Skip to content

Commit 2b2b797

Browse files
committed
goto-gcc: select default language standard depending on emulated compiler
This ensures that goto-cc with no `-std` explicitly specified will expect the same language standard as the underlying compiler's preprocessor -- so for example, using `goto-cc test.cpp`, which invokes `g++-7 -E` to perform preprocessing, will be able to parse the C++14 constructs in the standard library exposed because g++-6 and above enable C++14 support by default.
1 parent 8cc1848 commit 2b2b797

File tree

3 files changed

+89
-17
lines changed

3 files changed

+89
-17
lines changed

src/goto-cc/gcc_mode.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,11 @@ int gcc_modet::doit()
597597
if(std_string=="gnu++14" || std_string=="c++14")
598598
config.cpp.set_cpp14();
599599
}
600+
else
601+
{
602+
config.ansi_c.c_standard = gcc_version.default_c_standard;
603+
config.cpp.cpp_standard = gcc_version.default_cxx_standard;
604+
}
600605

601606
// gcc's default is 32 bits for wchar_t
602607
if(cmdline.isset("short-wchar"))

src/goto-cc/gcc_version.cpp

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ void gcc_versiont::get(const std::string &executable)
3131
"bcc 0 0 0\n"
3232
"#else\n"
3333
"gcc __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__\n"
34-
"#endif\n";
34+
"#endif\n"
35+
"default_c_standard __STDC_VERSION__\n";
3536
}
3637

3738
// some variants output stuff on stderr, say Apple LLVM,
@@ -52,23 +53,78 @@ void gcc_versiont::get(const std::string &executable)
5253
std::string line;
5354

5455
while(!in.fail() && std::getline(in, line))
55-
if(!line.empty() && line[0] != '#')
56-
break;
57-
58-
auto split = split_string(line, ' ');
56+
{
57+
if(line.empty() || line[0] == '#')
58+
continue;
59+
60+
auto split = split_string(line, ' ');
61+
62+
if(split.size() >= 4)
63+
{
64+
if(split[0] == "gcc")
65+
flavor = flavort::GCC;
66+
else if(split[0] == "bcc")
67+
flavor = flavort::BCC;
68+
else if(split[0] == "clang")
69+
flavor = flavort::CLANG;
70+
71+
v_major = unsafe_string2unsigned(split[1]);
72+
v_minor = unsafe_string2unsigned(split[2]);
73+
v_patchlevel = unsafe_string2unsigned(split[3]);
74+
}
75+
else if(split.size() == 2 && split[0] == "default_c_standard")
76+
{
77+
if(split[1] == "199901L")
78+
default_c_standard = configt::ansi_ct::c_standardt::C99;
79+
else if(split[1] == "201112L")
80+
default_c_standard = configt::ansi_ct::c_standardt::C11;
81+
}
82+
}
5983

60-
if(split.size() >= 4)
84+
if(flavor == flavort::GCC || flavor == flavort::CLANG)
6185
{
62-
if(split[0] == "gcc")
63-
flavor = flavort::GCC;
64-
else if(split[0] == "bcc")
65-
flavor = flavort::BCC;
66-
else if(split[0] == "clang")
67-
flavor = flavort::CLANG;
68-
69-
v_major = unsafe_string2unsigned(split[1]);
70-
v_minor = unsafe_string2unsigned(split[2]);
71-
v_patchlevel = unsafe_string2unsigned(split[3]);
86+
// Grab the default C++ standard. Unfortunately this requires another
87+
// run, as the compiler can't preprocess two files in one go.
88+
89+
temporary_filet cpp_in("goto-gcc.", ".cpp");
90+
temporary_filet cpp_out("goto-gcc.", ".out");
91+
temporary_filet cpp_err("goto-gcc.", ".err");
92+
93+
{
94+
std::ofstream out(cpp_in());
95+
out << "default_cxx_standard __cplusplus\n";
96+
}
97+
98+
int result = run(
99+
executable,
100+
{executable, "-E", "-x", "c++", "-", "-o", "-"},
101+
cpp_in(),
102+
cpp_out(),
103+
cpp_err());
104+
105+
if(result >= 0)
106+
{
107+
std::ifstream in(cpp_out());
108+
std::string line;
109+
110+
while(!in.fail() && std::getline(in, line))
111+
{
112+
if(line.empty() || line[0] == '#')
113+
continue;
114+
115+
auto split = split_string(line, ' ');
116+
117+
if(split.size() == 2 && split[0] == "default_cxx_standard")
118+
{
119+
if(split[1] == "199711L")
120+
default_cxx_standard = configt::cppt::cpp_standardt::CPP98;
121+
else if(split[1] == "201103L")
122+
default_cxx_standard = configt::cppt::cpp_standardt::CPP11;
123+
else if(split[1] == "201402L")
124+
default_cxx_standard = configt::cppt::cpp_standardt::CPP14;
125+
}
126+
}
127+
}
72128
}
73129
}
74130
}

src/goto-cc/gcc_version.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Date: May 2018
1414
#include <iosfwd>
1515
#include <string>
1616

17+
#include <util/config.h>
18+
1719
class gcc_versiont
1820
{
1921
public:
@@ -34,8 +36,17 @@ class gcc_versiont
3436
BCC
3537
} flavor;
3638

39+
configt::ansi_ct::c_standardt default_c_standard;
40+
configt::cppt::cpp_standardt default_cxx_standard;
41+
3742
gcc_versiont()
38-
: v_major(0), v_minor(0), v_patchlevel(0), flavor(flavort::UNKNOWN)
43+
:
44+
v_major(0),
45+
v_minor(0),
46+
v_patchlevel(0),
47+
flavor(flavort::UNKNOWN),
48+
default_c_standard(configt::ansi_ct::c_standardt::C89),
49+
default_cxx_standard(configt::cppt::cpp_standardt::CPP98)
3950
{
4051
}
4152
};

0 commit comments

Comments
 (0)