@@ -82,7 +82,7 @@ libclang_compile_config::libclang_compile_config() : libclang_compile_config(CPP
8282
8383libclang_compile_config::libclang_compile_config (std::string clang_binary)
8484: compile_config({}), write_preprocessed_(false ), fast_preprocessing_(false ),
85- remove_comments_in_macro_(false )
85+ remove_comments_in_macro_(false ), use_c_( false )
8686{
8787 // set given clang binary
8888 set_clang_binary (clang_binary);
@@ -226,6 +226,11 @@ cppast::libclang_compile_config::libclang_compile_config(
226226 for (auto i = 0u ; i != size; ++i)
227227 {
228228 auto cmd = clang_CompileCommands_getCommand (commands.get (), i);
229+
230+ // If ++ exists within the compiler name (e.g. clang++, g++, etc), use C++
231+ std::string exe (clang_getCString (clang_CompileCommand_getArg (cmd, 0 )));
232+ use_c_ = (exe.find (" ++" , 0 ) == std::string::npos);
233+
229234 auto dir = detail::cxstring (clang_CompileCommand_getDirectory (cmd));
230235 parse_flags (cmd, [&](std::string flag, std::string args) {
231236 if (flag == " -I" )
@@ -243,11 +248,21 @@ cppast::libclang_compile_config::libclang_compile_config(
243248 add_flag (std::move (flag));
244249 }
245250 else if (flag == " -std" )
246- // standard
251+ {
252+ use_c_ = (args.find (" ++" ) == std::string::npos);
247253 add_flag (std::move (flag) + " =" + std::move (args));
254+ }
248255 else if (flag == " -f" )
249256 // other options
250257 add_flag (std::move (flag) + std::move (args));
258+ else if (flag == " -x" )
259+ {
260+ // language
261+ if (args == " c" )
262+ use_c_ = true ;
263+ else
264+ use_c_ = false ;
265+ }
251266 });
252267 }
253268}
@@ -270,8 +285,9 @@ bool is_valid_binary(const std::string& binary)
270285void add_default_include_dirs (libclang_compile_config& config)
271286{
272287 std::string verbose_output;
288+ std::string language = config.use_c () ? " -xc" : " -xc++" ;
273289 tpl::Process process (
274- detail::libclang_compile_config_access::clang_binary (config) + " -x c++ -v -" , " " ,
290+ detail::libclang_compile_config_access::clang_binary (config) + " " + language + " -v -" , " " ,
275291 [](const char *, std::size_t ) {},
276292 [&](const char * str, std::size_t n) { verbose_output.append (str, n); }, true );
277293 process.write (" " , 1 );
@@ -424,6 +440,57 @@ void libclang_compile_config::do_set_flags(cpp_standard standard, compile_flags
424440 add_flag (" -std=c++2a" );
425441 break ;
426442 }
443+ else
444+ throw std::invalid_argument (" c++2b is not yet supported for current version of clang" );
445+ case cpp_standard::c_89:
446+ if (flags & compile_flag::gnu_extensions)
447+ add_flag (" -std=gnu89" );
448+ else
449+ add_flag (" -std=c89" );
450+ break ;
451+ case cpp_standard::c_99:
452+ if (flags & compile_flag::gnu_extensions)
453+ add_flag (" -std=gnu99" );
454+ else
455+ add_flag (" -std=c99" );
456+ break ;
457+ case cpp_standard::c_11:
458+ if (flags & compile_flag::gnu_extensions)
459+ add_flag (" -std=gnu11" );
460+ else
461+ add_flag (" -std=c11" );
462+ break ;
463+ case cpp_standard::c_17:
464+ if (libclang_parser::libclang_minor_version () >= 45 )
465+ { // Corresponds to Clang version 6
466+ if (flags & compile_flag::gnu_extensions)
467+ add_flag (" -std=gnu17" );
468+ else
469+ add_flag (" -std=c17" );
470+ break ;
471+ }
472+ else
473+ throw std::invalid_argument (" c17 is not yet supported for current version of clang" );
474+ case cpp_standard::c_2x:
475+ if (libclang_parser::libclang_minor_version () >= 59 )
476+ { // Corresponds to Clang version 9
477+ if (flags & compile_flag::gnu_extensions)
478+ add_flag (" -std=gnu2x" );
479+ else
480+ add_flag (" -std=c2x" );
481+ break ;
482+ }
483+ else
484+ throw std::invalid_argument (" c2x is not yet supported for current version of clang" );
485+ }
486+
487+ // Add language flag for C or C++
488+ if (is_c_standard (standard)) {
489+ add_flag (" -xc" );
490+ use_c_ = true ;
491+ } else {
492+ add_flag (" -xc++" );
493+ use_c_ = false ;
427494 }
428495
429496 if (flags & compile_flag::ms_compatibility)
@@ -461,6 +528,11 @@ void libclang_compile_config::do_remove_macro_definition(std::string name)
461528 add_flag (" -U" + std::move (name));
462529}
463530
531+ bool libclang_compile_config::do_use_c () const noexcept
532+ {
533+ return use_c_;
534+ }
535+
464536type_safe::optional<libclang_compile_config> cppast::find_config_for (
465537 const libclang_compilation_database& database, std::string file_name)
466538{
@@ -474,7 +546,7 @@ type_safe::optional<libclang_compile_config> cppast::find_config_for(
474546 if (database.has_config (file_name))
475547 return libclang_compile_config (database, std::move (file_name));
476548 static const char * extensions[]
477- = {" .h" , " .hpp" , " .cpp" , " .h++" , " .c++" , " .hxx" , " .cxx" , " .hh" , " .cc" , " .H" , " .C" };
549+ = {" .h" , " .hpp" , " .cpp" , " .h++" , " .c++" , " .hxx" , " .cxx" , " .hh" , " .cc" , " .H" , " .C" , " .c " };
478550 for (auto ext : extensions)
479551 {
480552 auto name = file_name + ext;
@@ -511,8 +583,8 @@ namespace
511583std::vector<const char *> get_arguments (const libclang_compile_config& config)
512584{
513585 std::vector<const char *> args
514- // TODO: Why? and Why?
515- = {" -x " , " c++ " , " - I." }; // force C++ and enable current directory for include search
586+ // TODO: Why?
587+ = {" -I." }; // enable current directory for include search
516588 for (auto & flag : detail::libclang_compile_config_access::flags (config))
517589 args.push_back (flag.c_str ());
518590 return args;
0 commit comments