cprover
gcc_version.cpp
Go to the documentation of this file.
1
/*******************************************************************\
2
3
Module: GCC Mode
4
5
Author: Daniel Kroening, 2018
6
7
\*******************************************************************/
8
9
#include "
gcc_version.h
"
10
11
#include <
util/prefix.h
>
12
#include <
util/run.h
>
13
#include <
util/string2int.h
>
14
#include <
util/string_utils.h
>
15
#include <
util/tempfile.h
>
16
17
#include <fstream>
18
19
void
gcc_versiont::get
(
const
std::string &executable)
20
{
21
temporary_filet
tmp_file_in(
"goto-gcc."
,
".in"
);
22
temporary_filet
tmp_file_out(
"goto-gcc."
,
".out"
);
23
temporary_filet
tmp_file_err(
"goto-gcc."
,
".err"
);
24
25
{
26
std::ofstream out(tmp_file_in());
27
28
out <<
"#if defined(__clang_major__)\n"
29
"clang __clang_major__ __clang_minor__ __clang_patchlevel__\n"
30
"#elif defined(__BCC__)\n"
31
"bcc 0 0 0\n"
32
"#else\n"
33
"gcc __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__\n"
34
"#endif\n"
35
"default_c_standard __STDC_VERSION__\n"
;
36
}
37
38
// some variants output stuff on stderr, say Apple LLVM,
39
// which we silence.
40
int
result =
run
(
41
executable,
42
{executable,
"-E"
,
"-"
,
"-o"
,
"-"
},
43
tmp_file_in(),
44
tmp_file_out(),
45
tmp_file_err());
46
47
v_major
=
v_minor
=
v_patchlevel
= 0;
48
flavor
=
flavort::UNKNOWN
;
49
50
if
(result >= 0)
51
{
52
std::ifstream in(tmp_file_out());
53
std::string line;
54
55
while
(!in.fail() && std::getline(in, 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
}
83
84
if
(
flavor
==
flavort::GCC
||
flavor
==
flavort::CLANG
)
85
{
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
}
128
}
129
}
130
}
131
132
bool
gcc_versiont::is_at_least
(
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
142
std::ostream &
operator<<
(std::ostream &out,
const
gcc_versiont
&v)
143
{
144
return
out << v.
v_major
<<
'.'
<< v.
v_minor
<<
'.'
<< v.
v_patchlevel
;
145
}
configt::cppt::cpp_standardt::CPP98
tempfile.h
gcc_versiont::get
void get(const std::string &executable)
Definition:
gcc_version.cpp:19
string_utils.h
gcc_version.h
prefix.h
run
int run(const std::string &what, const std::vector< std::string > &argv)
Definition:
run.cpp:47
run.h
gcc_versiont::default_cxx_standard
configt::cppt::cpp_standardt default_cxx_standard
Definition:
gcc_version.h:40
gcc_versiont::flavort::UNKNOWN
string2int.h
gcc_versiont::flavort::GCC
split_string
void split_string(const std::string &s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)
Given a string s, split into a sequence of substrings when separated by specified delimiter.
Definition:
string_utils.cpp:49
gcc_versiont::flavor
enum gcc_versiont::flavort flavor
gcc_versiont::v_major
unsigned v_major
Definition:
gcc_version.h:22
gcc_versiont::is_at_least
bool is_at_least(unsigned v_major, unsigned v_minor=0, unsigned v_patchlevel=0) const
Definition:
gcc_version.cpp:132
gcc_versiont::flavort::CLANG
configt::ansi_ct::c_standardt::C99
gcc_versiont
Definition:
gcc_version.h:19
configt::ansi_ct::c_standardt::C11
gcc_versiont::v_minor
unsigned v_minor
Definition:
gcc_version.h:22
gcc_versiont::default_c_standard
configt::ansi_ct::c_standardt default_c_standard
Definition:
gcc_version.h:39
unsafe_string2unsigned
unsigned unsafe_string2unsigned(const std::string &str, int base)
Definition:
string2int.cpp:69
operator<<
std::ostream & operator<<(std::ostream &out, const gcc_versiont &v)
Definition:
gcc_version.cpp:142
configt::cppt::cpp_standardt::CPP14
configt::cppt::cpp_standardt::CPP11
gcc_versiont::flavort::BCC
gcc_versiont::v_patchlevel
unsigned v_patchlevel
Definition:
gcc_version.h:22
temporary_filet
Definition:
tempfile.h:23
goto-cc
gcc_version.cpp
Generated by
1.8.16