Add basic C++20 support
This commit is contained in:
parent
019163b585
commit
ce218dfb8a
4 changed files with 73 additions and 25 deletions
|
|
@ -22,8 +22,10 @@ enum class cpp_standard
|
|||
cpp_03,
|
||||
cpp_11,
|
||||
cpp_14,
|
||||
|
||||
cpp_1z, //< Upcoming C++17 (experimental).
|
||||
cpp_1z,
|
||||
cpp_17,
|
||||
cpp_2a,
|
||||
cpp_20,
|
||||
|
||||
cpp_latest = cpp_standard::cpp_14, //< The latest supported C++ standard.
|
||||
};
|
||||
|
|
@ -44,6 +46,12 @@ inline const char* to_string(cpp_standard standard) noexcept
|
|||
return "c++14";
|
||||
case cpp_standard::cpp_1z:
|
||||
return "c++1z";
|
||||
case cpp_standard::cpp_17:
|
||||
return "c++17";
|
||||
case cpp_standard::cpp_2a:
|
||||
return "c++2a";
|
||||
case cpp_standard::cpp_20:
|
||||
return "c++20";
|
||||
}
|
||||
|
||||
DEBUG_UNREACHABLE(detail::assert_handler{});
|
||||
|
|
|
|||
|
|
@ -248,8 +248,8 @@ namespace
|
|||
{
|
||||
bool is_valid_binary(const std::string& binary)
|
||||
{
|
||||
tpl::Process process(binary + " -v", "", [](const char*, std::size_t) {},
|
||||
[](const char*, std::size_t) {});
|
||||
tpl::Process process(
|
||||
binary + " -v", "", [](const char*, std::size_t) {}, [](const char*, std::size_t) {});
|
||||
return process.get_exit_status() == 0;
|
||||
}
|
||||
|
||||
|
|
@ -262,11 +262,10 @@ bool is_valid_binary(const std::string& binary)
|
|||
void add_default_include_dirs(libclang_compile_config& config)
|
||||
{
|
||||
std::string verbose_output;
|
||||
tpl::Process process(detail::libclang_compile_config_access::clang_binary(config)
|
||||
+ " -x c++ -v -",
|
||||
"", [](const char*, std::size_t) {},
|
||||
[&](const char* str, std::size_t n) { verbose_output.append(str, n); },
|
||||
true);
|
||||
tpl::Process process(
|
||||
detail::libclang_compile_config_access::clang_binary(config) + " -x c++ -v -", "",
|
||||
[](const char*, std::size_t) {},
|
||||
[&](const char* str, std::size_t n) { verbose_output.append(str, n); }, true);
|
||||
process.write("", 1);
|
||||
process.close_stdin();
|
||||
process.get_exit_status();
|
||||
|
|
@ -326,7 +325,9 @@ bool libclang_compile_config::set_clang_binary(std::string binary)
|
|||
// first search in current directory, then in PATH
|
||||
static const char* paths[]
|
||||
= {"./clang++", "clang++", "./clang++-4.0", "clang++-4.0", "./clang++-5.0",
|
||||
"clang++-5.0", "./clang++-6.0", "clang++-6.0", "./clang-7", "clang-7"};
|
||||
"clang++-5.0", "./clang++-6.0", "clang++-6.0", "./clang-7", "clang-7",
|
||||
"./clang-8", "clang-8", "./clang-9", "clang-9", "./clang-10",
|
||||
"clang-10", "./clang-11", "clang-11"};
|
||||
for (auto& p : paths)
|
||||
if (is_valid_binary(p))
|
||||
{
|
||||
|
|
@ -373,6 +374,39 @@ void libclang_compile_config::do_set_flags(cpp_standard standard, compile_flags
|
|||
else
|
||||
add_flag("-std=c++1z");
|
||||
break;
|
||||
case cpp_standard::cpp_17:
|
||||
if (libclang_parser::libclang_minor_version() >= 43)
|
||||
{ // Corresponds to Clang version 5
|
||||
if (flags & compile_flag::gnu_extensions)
|
||||
add_flag("-std=gnu++17");
|
||||
else
|
||||
add_flag("-std=c++17");
|
||||
break;
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("c++17 is not yet supported for current version of clang");
|
||||
case cpp_standard::cpp_2a:
|
||||
if (libclang_parser::libclang_minor_version() >= 59)
|
||||
{ // Corresponds to Clang version 9
|
||||
if (flags & compile_flag::gnu_extensions)
|
||||
add_flag("-std=gnu++2a");
|
||||
else
|
||||
add_flag("-std=c++2a");
|
||||
break;
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("c++2a is not yet supported for current version of clang");
|
||||
case cpp_standard::cpp_20:
|
||||
if (libclang_parser::libclang_minor_version() >= 60)
|
||||
{ // Corresponds to Clang version 10
|
||||
if (flags & compile_flag::gnu_extensions)
|
||||
add_flag("-std=gnu++20");
|
||||
else
|
||||
add_flag("-std=c++20");
|
||||
break;
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("c++20 is not yet supported for current version of clang");
|
||||
}
|
||||
|
||||
if (flags & compile_flag::ms_compatibility)
|
||||
|
|
@ -559,7 +593,8 @@ unsigned get_line_no(const CXCursor& cursor)
|
|||
}
|
||||
} // namespace
|
||||
std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx, std::string path,
|
||||
const compile_config& c) const try
|
||||
const compile_config& c) const
|
||||
try
|
||||
{
|
||||
DEBUG_ASSERT(std::strcmp(c.name(), "libclang") == 0, detail::precondition_error_handler{},
|
||||
"config has mismatched type");
|
||||
|
|
|
|||
|
|
@ -23,21 +23,18 @@ inline void write_file(const char* name, const char* code)
|
|||
file << code;
|
||||
}
|
||||
|
||||
inline cppast::libclang_compile_config make_test_config()
|
||||
{
|
||||
using namespace cppast;
|
||||
|
||||
libclang_compile_config config;
|
||||
config.set_flags(cpp_standard::cpp_latest);
|
||||
return config;
|
||||
}
|
||||
|
||||
inline std::unique_ptr<cppast::cpp_file> parse_file(const cppast::cpp_entity_index& idx,
|
||||
const char* name,
|
||||
bool fast_preprocessing = false)
|
||||
bool fast_preprocessing = false,
|
||||
cppast::cpp_standard standard
|
||||
= cppast::cpp_standard::cpp_latest)
|
||||
{
|
||||
using namespace cppast;
|
||||
static auto config = make_test_config();
|
||||
|
||||
// Creating a config is expensive, so we remember a default one.
|
||||
static auto default_config = libclang_compile_config();
|
||||
auto config = default_config;
|
||||
config.set_flags(standard);
|
||||
config.fast_preprocessing(fast_preprocessing);
|
||||
|
||||
libclang_parser p(default_logger());
|
||||
|
|
@ -50,10 +47,12 @@ inline std::unique_ptr<cppast::cpp_file> parse_file(const cppast::cpp_entity_ind
|
|||
|
||||
inline std::unique_ptr<cppast::cpp_file> parse(const cppast::cpp_entity_index& idx,
|
||||
const char* name, const char* code,
|
||||
bool fast_preprocessing = false)
|
||||
bool fast_preprocessing = false,
|
||||
cppast::cpp_standard standard
|
||||
= cppast::cpp_standard::cpp_latest)
|
||||
{
|
||||
write_file(name, code);
|
||||
return parse_file(idx, name, fast_preprocessing);
|
||||
return parse_file(idx, name, fast_preprocessing, standard);
|
||||
}
|
||||
|
||||
class test_generator : public cppast::code_generator
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ int main(int argc, char* argv[]) try
|
|||
cxxopts::value<std::string>())
|
||||
("database_file", "set the file name whose configuration will be used regardless of the current file name",
|
||||
cxxopts::value<std::string>())
|
||||
("std", "set the C++ standard (c++98, c++03, c++11, c++14, c++1z (experimental))",
|
||||
("std", "set the C++ standard (c++98, c++03, c++11, c++14, c++1z (experimental), c++17, c++2a, c++20)",
|
||||
cxxopts::value<std::string>()->default_value(cppast::to_string(cppast::cpp_standard::cpp_latest)))
|
||||
("I,include_directory", "add directory to include search path",
|
||||
cxxopts::value<std::vector<std::string>>())
|
||||
|
|
@ -304,6 +304,12 @@ int main(int argc, char* argv[]) try
|
|||
config.set_flags(cppast::cpp_standard::cpp_14, flags);
|
||||
else if (options["std"].as<std::string>() == "c++1z")
|
||||
config.set_flags(cppast::cpp_standard::cpp_1z, flags);
|
||||
else if (options["std"].as<std::string>() == "c++17")
|
||||
config.set_flags(cppast::cpp_standard::cpp_17, flags);
|
||||
else if (options["std"].as<std::string>() == "c++2a")
|
||||
config.set_flags(cppast::cpp_standard::cpp_2a, flags);
|
||||
else if (options["std"].as<std::string>() == "c++20")
|
||||
config.set_flags(cppast::cpp_standard::cpp_20, flags);
|
||||
else
|
||||
{
|
||||
print_error("invalid value '" + options["std"].as<std::string>() + "' for std flag");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue