cprover
Loading...
Searching...
No Matches
gcc_version.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: GCC Mode
4
5Author: Daniel Kroening, 2018
6
7\*******************************************************************/
8
9#include "gcc_version.h"
10
11#include <util/run.h>
12#include <util/string2int.h>
13#include <util/string_utils.h>
14#include <util/tempfile.h>
15
16#include <fstream>
17
18void gcc_versiont::get(const std::string &executable)
19{
20 temporary_filet tmp_file_in("goto-gcc.", ".in");
21 temporary_filet tmp_file_out("goto-gcc.", ".out");
22 temporary_filet tmp_file_err("goto-gcc.", ".err");
23
24 {
25 std::ofstream out(tmp_file_in());
26
27 out << "#if defined(__clang_major__)\n"
28 "clang __clang_major__ __clang_minor__ __clang_patchlevel__\n"
29 "#elif defined(__BCC__)\n"
30 "bcc 0 0 0\n"
31 "#else\n"
32 "gcc __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__\n"
33 "#endif\n"
34 "default_c_standard __STDC_VERSION__\n";
35 }
36
37 // some variants output stuff on stderr, say Apple LLVM,
38 // which we silence.
39 int result = run(
40 executable,
41 {executable, "-E", "-", "-o", "-"},
42 tmp_file_in(),
43 tmp_file_out(),
44 tmp_file_err());
45
48
49 if(result >= 0)
50 {
51 std::ifstream in(tmp_file_out());
52 std::string line;
53
54 while(!in.fail() && std::getline(in, line))
55 {
56 if(line.empty() || line[0] == '#')
57 continue;
58
59 auto split = split_string(line, ' ');
60
61 if(split.size() >= 4)
62 {
63 if(split[0] == "gcc")
65 else if(split[0] == "bcc")
67 else if(split[0] == "clang")
69
73 }
74 else if(split.size() == 2 && split[0] == "default_c_standard")
75 {
76 if(split[1] == "199901L")
78 else if(split[1] == "201112L")
80 }
81 }
82
84 {
85 // Grab the default C++ standard. Unfortunately this requires another
86 // run, as the compiler can't preprocess two files in one go.
87
88 temporary_filet cpp_in("goto-gcc.", ".cpp");
89 temporary_filet cpp_out("goto-gcc.", ".out");
90 temporary_filet cpp_err("goto-gcc.", ".err");
91
92 {
93 std::ofstream out(cpp_in());
94 out << "default_cxx_standard __cplusplus\n";
95 }
96
97 result = run(
98 executable,
99 {executable, "-E", "-x", "c++", "-", "-o", "-"},
100 cpp_in(),
101 cpp_out(),
102 cpp_err());
103
104 if(result >= 0)
105 {
106 std::ifstream in2(cpp_out());
107
108 while(!in2.fail() && std::getline(in2, line))
109 {
110 if(line.empty() || line[0] == '#')
111 continue;
112
113 auto split = split_string(line, ' ');
114
115 if(split.size() == 2 && split[0] == "default_cxx_standard")
116 {
117 if(split[1] == "199711L")
119 else if(split[1] == "201103L")
121 else if(split[1] == "201402L")
123 else if(split[1] == "201703L")
125 }
126 }
127 }
128 }
129 }
130}
131
133 unsigned _major,
134 unsigned _minor,
135 unsigned _patchlevel) const
136{
137 return v_major > _major || (v_major == _major && v_minor > _minor) ||
138 (v_major == _major && v_minor == _minor &&
139 v_patchlevel >= _patchlevel);
140}
141
142std::ostream &operator<<(std::ostream &out, const gcc_versiont &v)
143{
144 return out << v.v_major << '.' << v.v_minor << '.' << v.v_patchlevel;
145}
146
147void configure_gcc(const gcc_versiont &gcc_version)
148{
149 // ISO/IEC TS 18661-3:2015 support was introduced with gcc 7.0
150 if(
151 gcc_version.flavor == gcc_versiont::flavort::GCC &&
152 gcc_version.is_at_least(7u))
153 {
155 }
156
157 const auto gcc_float128_minor_version =
158 config.ansi_c.arch == "x86_64" ? 3u : 5u;
159
160 // __float128 exists (as a typedef) since gcc 4.5 everywhere,
161 // and since 4.3 on x86_64
163 gcc_version.flavor == gcc_versiont::flavort::GCC &&
164 gcc_version.is_at_least(4u, gcc_float128_minor_version);
165
167 (gcc_version.flavor == gcc_versiont::flavort::GCC &&
168 gcc_version.is_at_least(12u)) ||
169 (gcc_version.flavor == gcc_versiont::flavort::CLANG &&
170 gcc_version.is_at_least(15u));
171
173 (gcc_version.flavor == gcc_versiont::flavort::GCC &&
174 gcc_version.is_at_least(13u)) ||
175 (gcc_version.flavor == gcc_versiont::flavort::CLANG &&
176 gcc_version.is_at_least(15u));
177}
configt config
Definition config.cpp:25
struct configt::ansi_ct ansi_c
bool is_at_least(unsigned v_major, unsigned v_minor=0, unsigned v_patchlevel=0) const
void get(const std::string &executable)
configt::cppt::cpp_standardt default_cxx_standard
Definition gcc_version.h:40
configt::ansi_ct::c_standardt default_c_standard
Definition gcc_version.h:39
unsigned v_patchlevel
Definition gcc_version.h:22
unsigned v_minor
Definition gcc_version.h:22
unsigned v_major
Definition gcc_version.h:22
enum gcc_versiont::flavort flavor
std::ostream & operator<<(std::ostream &out, const gcc_versiont &v)
void configure_gcc(const gcc_versiont &gcc_version)
int run(const std::string &what, const std::vector< std::string > &argv)
Definition run.cpp:48
unsigned unsafe_string2unsigned(const std::string &str, int base)
void split_string(const std::string &s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)
bool float16_type
Definition config.h:151
bool ts_18661_3_Floatn_types
Definition config.h:149
bool gcc__float128_type
Definition config.h:150
irep_idt arch
Definition config.h:218