From 16ed8dd823a4c2282425d081e1817d9dc205775e Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 31 May 2018 13:57:09 +0000 Subject: [PATCH] Add a new driver mode to dump compiler feature and extension options. Add the ability to dump compiler option-related information to a JSON file via the -compiler-options-dump option. Specifically, it dumps the features/extensions lists -- however, this output could be extended to other information should it be useful. In order to support features and extensions, I moved them into a .def file so that we could build the various lists we care about from them without a significant increase in maintenance burden. llvm-svn: 333653 --- clang/include/clang/Basic/Features.def | 238 ++++++++++++++++++ clang/include/clang/Driver/CC1Options.td | 2 + .../include/clang/Frontend/FrontendActions.h | 12 + .../include/clang/Frontend/FrontendOptions.h | 3 + clang/lib/Frontend/CompilerInvocation.cpp | 3 + clang/lib/Frontend/FrontendActions.cpp | 48 ++++ .../ExecuteCompilerInvocation.cpp | 2 + clang/lib/Lex/PPMacroExpansion.cpp | 216 +--------------- clang/test/Frontend/compiler-options-dump.cpp | 25 ++ 9 files changed, 342 insertions(+), 207 deletions(-) create mode 100644 clang/include/clang/Basic/Features.def create mode 100644 clang/test/Frontend/compiler-options-dump.cpp diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def new file mode 100644 index 000000000000..a0e0ce4560ab --- /dev/null +++ b/clang/include/clang/Basic/Features.def @@ -0,0 +1,238 @@ +//===--- Features.def - Features and Extensions database --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines features exposed via __has_feature and extensions exposed +// via __has_extension. Users of this file must either define the FEATURE or +// EXTENSION macros (or both) to make use of this information. Note that these +// macros expect the following declarations to be available for the Predicate: +// +// const LangOptions &LangOpts; +// const Preprocessor &PP; +// +// The Predicate field dictates the conditions under which the feature or +// extension will be made available. +//===----------------------------------------------------------------------===// + +#if !defined(FEATURE) && !defined(EXTENSION) +# error Define either the FEATURE or EXTENSION macro to handle features +#endif + +#ifndef FEATURE +#define FEATURE(Name, Predicate) +#endif + +#ifndef EXTENSION +#define EXTENSION(Name, Predicate) +#endif + +FEATURE(address_sanitizer, + LangOpts.Sanitize.hasOneOf(SanitizerKind::Address | + SanitizerKind::KernelAddress)) +FEATURE(hwaddress_sanitizer, + LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress | + SanitizerKind::KernelHWAddress)) +FEATURE(assume_nonnull, true) +FEATURE(attribute_analyzer_noreturn, true) +FEATURE(attribute_availability, true) +FEATURE(attribute_availability_with_message, true) +FEATURE(attribute_availability_app_extension, true) +FEATURE(attribute_availability_with_version_underscores, true) +FEATURE(attribute_availability_tvos, true) +FEATURE(attribute_availability_watchos, true) +FEATURE(attribute_availability_with_strict, true) +FEATURE(attribute_availability_with_replacement, true) +FEATURE(attribute_availability_in_templates, true) +FEATURE(attribute_cf_returns_not_retained, true) +FEATURE(attribute_cf_returns_retained, true) +FEATURE(attribute_cf_returns_on_parameters, true) +FEATURE(attribute_deprecated_with_message, true) +FEATURE(attribute_deprecated_with_replacement, true) +FEATURE(attribute_ext_vector_type, true) +FEATURE(attribute_ns_returns_not_retained, true) +FEATURE(attribute_ns_returns_retained, true) +FEATURE(attribute_ns_consumes_self, true) +FEATURE(attribute_ns_consumed, true) +FEATURE(attribute_cf_consumed, true) +FEATURE(attribute_objc_ivar_unused, true) +FEATURE(attribute_objc_method_family, true) +FEATURE(attribute_overloadable, true) +FEATURE(attribute_unavailable_with_message, true) +FEATURE(attribute_unused_on_fields, true) +FEATURE(attribute_diagnose_if_objc, true) +FEATURE(blocks, LangOpts.Blocks) +FEATURE(c_thread_safety_attributes, true) +FEATURE(cxx_exceptions, LangOpts.CXXExceptions) +FEATURE(cxx_rtti, LangOpts.RTTI &&LangOpts.RTTIData) +FEATURE(enumerator_attributes, true) +FEATURE(nullability, true) +FEATURE(nullability_on_arrays, true) +FEATURE(memory_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Memory)) +FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread)) +FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow)) +FEATURE(efficiency_sanitizer, + LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) +FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) +// Objective-C features +FEATURE(objc_arr, LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? +FEATURE(objc_arc, LangOpts.ObjCAutoRefCount) +FEATURE(objc_arc_fields, true) +FEATURE(objc_arc_weak, LangOpts.ObjCWeak) +FEATURE(objc_default_synthesize_properties, LangOpts.ObjC2) +FEATURE(objc_fixed_enum, LangOpts.ObjC2) +FEATURE(objc_instancetype, LangOpts.ObjC2) +FEATURE(objc_kindof, LangOpts.ObjC2) +FEATURE(objc_modules, LangOpts.ObjC2 &&LangOpts.Modules) +FEATURE(objc_nonfragile_abi, LangOpts.ObjCRuntime.isNonFragile()) +FEATURE(objc_property_explicit_atomic, true) +FEATURE(objc_protocol_qualifier_mangling, true) +FEATURE(objc_weak_class, LangOpts.ObjCRuntime.hasWeakClassImport()) +FEATURE(ownership_holds, true) +FEATURE(ownership_returns, true) +FEATURE(ownership_takes, true) +FEATURE(objc_bool, true) +FEATURE(objc_subscripting, LangOpts.ObjCRuntime.isNonFragile()) +FEATURE(objc_array_literals, LangOpts.ObjC2) +FEATURE(objc_dictionary_literals, LangOpts.ObjC2) +FEATURE(objc_boxed_expressions, LangOpts.ObjC2) +FEATURE(objc_boxed_nsvalue_expressions, LangOpts.ObjC2) +FEATURE(arc_cf_code_audited, true) +FEATURE(objc_bridge_id, true) +FEATURE(objc_bridge_id_on_typedefs, true) +FEATURE(objc_generics, LangOpts.ObjC2) +FEATURE(objc_generics_variance, LangOpts.ObjC2) +FEATURE(objc_class_property, LangOpts.ObjC2) +// C11 features +FEATURE(c_alignas, LangOpts.C11) +FEATURE(c_alignof, LangOpts.C11) +FEATURE(c_atomic, LangOpts.C11) +FEATURE(c_generic_selections, LangOpts.C11) +FEATURE(c_static_assert, LangOpts.C11) +FEATURE(c_thread_local, LangOpts.C11 &&PP.getTargetInfo().isTLSSupported()) +// C++11 features +FEATURE(cxx_access_control_sfinae, LangOpts.CPlusPlus11) +FEATURE(cxx_alias_templates, LangOpts.CPlusPlus11) +FEATURE(cxx_alignas, LangOpts.CPlusPlus11) +FEATURE(cxx_alignof, LangOpts.CPlusPlus11) +FEATURE(cxx_atomic, LangOpts.CPlusPlus11) +FEATURE(cxx_attributes, LangOpts.CPlusPlus11) +FEATURE(cxx_auto_type, LangOpts.CPlusPlus11) +FEATURE(cxx_constexpr, LangOpts.CPlusPlus11) +FEATURE(cxx_constexpr_string_builtins, LangOpts.CPlusPlus11) +FEATURE(cxx_decltype, LangOpts.CPlusPlus11) +FEATURE(cxx_decltype_incomplete_return_types, LangOpts.CPlusPlus11) +FEATURE(cxx_default_function_template_args, LangOpts.CPlusPlus11) +FEATURE(cxx_defaulted_functions, LangOpts.CPlusPlus11) +FEATURE(cxx_delegating_constructors, LangOpts.CPlusPlus11) +FEATURE(cxx_deleted_functions, LangOpts.CPlusPlus11) +FEATURE(cxx_explicit_conversions, LangOpts.CPlusPlus11) +FEATURE(cxx_generalized_initializers, LangOpts.CPlusPlus11) +FEATURE(cxx_implicit_moves, LangOpts.CPlusPlus11) +FEATURE(cxx_inheriting_constructors, LangOpts.CPlusPlus11) +FEATURE(cxx_inline_namespaces, LangOpts.CPlusPlus11) +FEATURE(cxx_lambdas, LangOpts.CPlusPlus11) +FEATURE(cxx_local_type_template_args, LangOpts.CPlusPlus11) +FEATURE(cxx_nonstatic_member_init, LangOpts.CPlusPlus11) +FEATURE(cxx_noexcept, LangOpts.CPlusPlus11) +FEATURE(cxx_nullptr, LangOpts.CPlusPlus11) +FEATURE(cxx_override_control, LangOpts.CPlusPlus11) +FEATURE(cxx_range_for, LangOpts.CPlusPlus11) +FEATURE(cxx_raw_string_literals, LangOpts.CPlusPlus11) +FEATURE(cxx_reference_qualified_functions, LangOpts.CPlusPlus11) +FEATURE(cxx_rvalue_references, LangOpts.CPlusPlus11) +FEATURE(cxx_strong_enums, LangOpts.CPlusPlus11) +FEATURE(cxx_static_assert, LangOpts.CPlusPlus11) +FEATURE(cxx_thread_local, + LangOpts.CPlusPlus11 &&PP.getTargetInfo().isTLSSupported()) +FEATURE(cxx_trailing_return, LangOpts.CPlusPlus11) +FEATURE(cxx_unicode_literals, LangOpts.CPlusPlus11) +FEATURE(cxx_unrestricted_unions, LangOpts.CPlusPlus11) +FEATURE(cxx_user_literals, LangOpts.CPlusPlus11) +FEATURE(cxx_variadic_templates, LangOpts.CPlusPlus11) +// C++14 features +FEATURE(cxx_aggregate_nsdmi, LangOpts.CPlusPlus14) +FEATURE(cxx_binary_literals, LangOpts.CPlusPlus14) +FEATURE(cxx_contextual_conversions, LangOpts.CPlusPlus14) +FEATURE(cxx_decltype_auto, LangOpts.CPlusPlus14) +FEATURE(cxx_generic_lambdas, LangOpts.CPlusPlus14) +FEATURE(cxx_init_captures, LangOpts.CPlusPlus14) +FEATURE(cxx_relaxed_constexpr, LangOpts.CPlusPlus14) +FEATURE(cxx_return_type_deduction, LangOpts.CPlusPlus14) +FEATURE(cxx_variable_templates, LangOpts.CPlusPlus14) +// NOTE: For features covered by SD-6, it is preferable to provide *only* +// the SD-6 macro and not a __has_feature check. + +// C++ TSes +// FEATURE(cxx_runtime_arrays, LangOpts.CPlusPlusTSArrays) +// FEATURE(cxx_concepts, LangOpts.CPlusPlusTSConcepts) +// FIXME: Should this be __has_feature or __has_extension? +// FEATURE(raw_invocation_type, LangOpts.CPlusPlus) +// Type traits +// N.B. Additional type traits should not be added to the following list. +// Instead, they should be detected by has_extension. +FEATURE(has_nothrow_assign, LangOpts.CPlusPlus) +FEATURE(has_nothrow_copy, LangOpts.CPlusPlus) +FEATURE(has_nothrow_constructor, LangOpts.CPlusPlus) +FEATURE(has_trivial_assign, LangOpts.CPlusPlus) +FEATURE(has_trivial_copy, LangOpts.CPlusPlus) +FEATURE(has_trivial_constructor, LangOpts.CPlusPlus) +FEATURE(has_trivial_destructor, LangOpts.CPlusPlus) +FEATURE(has_virtual_destructor, LangOpts.CPlusPlus) +FEATURE(is_abstract, LangOpts.CPlusPlus) +FEATURE(is_base_of, LangOpts.CPlusPlus) +FEATURE(is_class, LangOpts.CPlusPlus) +FEATURE(is_constructible, LangOpts.CPlusPlus) +FEATURE(is_convertible_to, LangOpts.CPlusPlus) +FEATURE(is_empty, LangOpts.CPlusPlus) +FEATURE(is_enum, LangOpts.CPlusPlus) +FEATURE(is_final, LangOpts.CPlusPlus) +FEATURE(is_literal, LangOpts.CPlusPlus) +FEATURE(is_standard_layout, LangOpts.CPlusPlus) +FEATURE(is_pod, LangOpts.CPlusPlus) +FEATURE(is_polymorphic, LangOpts.CPlusPlus) +FEATURE(is_sealed, LangOpts.CPlusPlus &&LangOpts.MicrosoftExt) +FEATURE(is_trivial, LangOpts.CPlusPlus) +FEATURE(is_trivially_assignable, LangOpts.CPlusPlus) +FEATURE(is_trivially_constructible, LangOpts.CPlusPlus) +FEATURE(is_trivially_copyable, LangOpts.CPlusPlus) +FEATURE(is_union, LangOpts.CPlusPlus) +FEATURE(modules, LangOpts.Modules) +FEATURE(safe_stack, LangOpts.Sanitize.has(SanitizerKind::SafeStack)) +FEATURE(shadow_call_stack, + LangOpts.Sanitize.has(SanitizerKind::ShadowCallStack)) +FEATURE(tls, PP.getTargetInfo().isTLSSupported()) +FEATURE(underlying_type, LangOpts.CPlusPlus) + +// C11 features supported by other languages as extensions. +EXTENSION(c_alignas, true) +EXTENSION(c_alignof, true) +EXTENSION(c_atomic, true) +EXTENSION(c_generic_selections, true) +EXTENSION(c_static_assert, true) +EXTENSION(c_thread_local, PP.getTargetInfo().isTLSSupported()) +// C++11 features supported by other languages as extensions. +EXTENSION(cxx_atomic, LangOpts.CPlusPlus) +EXTENSION(cxx_deleted_functions, LangOpts.CPlusPlus) +EXTENSION(cxx_explicit_conversions, LangOpts.CPlusPlus) +EXTENSION(cxx_inline_namespaces, LangOpts.CPlusPlus) +EXTENSION(cxx_local_type_template_args, LangOpts.CPlusPlus) +EXTENSION(cxx_nonstatic_member_init, LangOpts.CPlusPlus) +EXTENSION(cxx_override_control, LangOpts.CPlusPlus) +EXTENSION(cxx_range_for, LangOpts.CPlusPlus) +EXTENSION(cxx_reference_qualified_functions, LangOpts.CPlusPlus) +EXTENSION(cxx_rvalue_references, LangOpts.CPlusPlus) +EXTENSION(cxx_variadic_templates, LangOpts.CPlusPlus) +// C++14 features supported by other languages as extensions. +EXTENSION(cxx_binary_literals, true) +EXTENSION(cxx_init_captures, LangOpts.CPlusPlus11) +EXTENSION(cxx_variable_templates, LangOpts.CPlusPlus) +// Miscellaneous language extensions +EXTENSION(overloadable_unmarked, true) + +#undef EXTENSION +#undef FEATURE diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 5d56b4264b95..18d0483a79ca 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -563,6 +563,8 @@ def rewrite_macros : Flag<["-"], "rewrite-macros">, HelpText<"Expand macros without full preprocessing">; def migrate : Flag<["-"], "migrate">, HelpText<"Migrate source code">; +def compiler_options_dump : Flag<["-"], "compiler-options-dump">, + HelpText<"Dump the compiler configuration options">; } def emit_llvm_uselists : Flag<["-"], "emit-llvm-uselists">, diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index 4d64892acc0d..20f1b3e11bdb 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -35,6 +35,18 @@ public: bool usesPreprocessorOnly() const override { return false; } }; +class DumpCompilerOptionsAction : public FrontendAction { + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override { + return nullptr; + } + + void ExecuteAction() override; + +public: + bool usesPreprocessorOnly() const override { return true; } +}; + //===----------------------------------------------------------------------===// // AST Consumer Actions //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 75f97ba7caff..fa79a36eb2f7 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -43,6 +43,9 @@ enum ActionKind { /// Parse ASTs and view them in Graphviz. ASTView, + /// Dump the compiler configuration. + DumpCompilerOptions, + /// Dump out raw tokens. DumpRawTokens, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 594164332eca..b5396dd758f2 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1396,6 +1396,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::ASTPrint; break; case OPT_ast_view: Opts.ProgramAction = frontend::ASTView; break; + case OPT_compiler_options_dump: + Opts.ProgramAction = frontend::DumpCompilerOptions; break; case OPT_dump_raw_tokens: Opts.ProgramAction = frontend::DumpRawTokens; break; case OPT_dump_tokens: @@ -2788,6 +2790,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::MigrateSource: return false; + case frontend::DumpCompilerOptions: case frontend::DumpRawTokens: case frontend::DumpTokens: case frontend::InitOnly: diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 13f053717182..602fee1fdcae 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -756,3 +756,51 @@ void PrintPreambleAction::ExecuteAction() { llvm::outs().write((*Buffer)->getBufferStart(), Preamble); } } + +void DumpCompilerOptionsAction::ExecuteAction() { + CompilerInstance &CI = getCompilerInstance(); + std::unique_ptr OSP = + CI.createDefaultOutputFile(false, getCurrentFile()); + if (!OSP) + return; + + raw_ostream &OS = *OSP; + const Preprocessor &PP = CI.getPreprocessor(); + const LangOptions &LangOpts = PP.getLangOpts(); + + // FIXME: Rather than manually format the JSON (which is awkward due to + // needing to remove trailing commas), this should make use of a JSON library. + // FIXME: Instead of printing enums as an integral value and specifying the + // type as a separate field, use introspection to print the enumerator. + + OS << "{\n"; + OS << "\n\"features\" : [\n"; + { + llvm::SmallString<128> Str; +#define FEATURE(Name, Predicate) \ + ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \ + .toVector(Str); +#include "clang/Basic/Features.def" +#undef FEATURE + // Remove the newline and comma from the last entry to ensure this remains + // valid JSON. + OS << Str.substr(0, Str.size() - 2); + } + OS << "\n],\n"; + + OS << "\n\"extensions\" : [\n"; + { + llvm::SmallString<128> Str; +#define EXTENSION(Name, Predicate) \ + ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \ + .toVector(Str); +#include "clang/Basic/Features.def" +#undef EXTENSION + // Remove the newline and comma from the last entry to ensure this remains + // valid JSON. + OS << Str.substr(0, Str.size() - 2); + } + OS << "\n]\n"; + + OS << "}"; +} diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 1bb939a6fad7..ac2ee50a1e4b 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -45,6 +45,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) { case ASTDump: return llvm::make_unique(); case ASTPrint: return llvm::make_unique(); case ASTView: return llvm::make_unique(); + case DumpCompilerOptions: + return llvm::make_unique(); case DumpRawTokens: return llvm::make_unique(); case DumpTokens: return llvm::make_unique(); case EmitAssembly: return llvm::make_unique(); diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 21b338618888..d9992e00f8c0 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1099,187 +1099,11 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) { if (Feature.startswith("__") && Feature.endswith("__") && Feature.size() >= 4) Feature = Feature.substr(2, Feature.size() - 4); +#define FEATURE(Name, Predicate) .Case(#Name, Predicate) return llvm::StringSwitch(Feature) - .Case("address_sanitizer", - LangOpts.Sanitize.hasOneOf(SanitizerKind::Address | - SanitizerKind::KernelAddress)) - .Case("hwaddress_sanitizer", - LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress | - SanitizerKind::KernelHWAddress)) - .Case("assume_nonnull", true) - .Case("attribute_analyzer_noreturn", true) - .Case("attribute_availability", true) - .Case("attribute_availability_with_message", true) - .Case("attribute_availability_app_extension", true) - .Case("attribute_availability_with_version_underscores", true) - .Case("attribute_availability_tvos", true) - .Case("attribute_availability_watchos", true) - .Case("attribute_availability_with_strict", true) - .Case("attribute_availability_with_replacement", true) - .Case("attribute_availability_in_templates", true) - .Case("attribute_cf_returns_not_retained", true) - .Case("attribute_cf_returns_retained", true) - .Case("attribute_cf_returns_on_parameters", true) - .Case("attribute_deprecated_with_message", true) - .Case("attribute_deprecated_with_replacement", true) - .Case("attribute_ext_vector_type", true) - .Case("attribute_ns_returns_not_retained", true) - .Case("attribute_ns_returns_retained", true) - .Case("attribute_ns_consumes_self", true) - .Case("attribute_ns_consumed", true) - .Case("attribute_cf_consumed", true) - .Case("attribute_objc_ivar_unused", true) - .Case("attribute_objc_method_family", true) - .Case("attribute_overloadable", true) - .Case("attribute_unavailable_with_message", true) - .Case("attribute_unused_on_fields", true) - .Case("attribute_diagnose_if_objc", true) - .Case("blocks", LangOpts.Blocks) - .Case("c_thread_safety_attributes", true) - .Case("cxx_exceptions", LangOpts.CXXExceptions) - .Case("cxx_rtti", LangOpts.RTTI && LangOpts.RTTIData) - .Case("enumerator_attributes", true) - .Case("nullability", true) - .Case("nullability_on_arrays", true) - .Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory)) - .Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread)) - .Case("dataflow_sanitizer", - LangOpts.Sanitize.has(SanitizerKind::DataFlow)) - .Case("efficiency_sanitizer", - LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) - .Case("scudo", LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) - // Objective-C features - .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? - .Case("objc_arc", LangOpts.ObjCAutoRefCount) - .Case("objc_arc_fields", true) - .Case("objc_arc_weak", LangOpts.ObjCWeak) - .Case("objc_default_synthesize_properties", LangOpts.ObjC2) - .Case("objc_fixed_enum", LangOpts.ObjC2) - .Case("objc_instancetype", LangOpts.ObjC2) - .Case("objc_kindof", LangOpts.ObjC2) - .Case("objc_modules", LangOpts.ObjC2 && LangOpts.Modules) - .Case("objc_nonfragile_abi", LangOpts.ObjCRuntime.isNonFragile()) - .Case("objc_property_explicit_atomic", - true) // Does clang support explicit "atomic" keyword? - .Case("objc_protocol_qualifier_mangling", true) - .Case("objc_weak_class", LangOpts.ObjCRuntime.hasWeakClassImport()) - .Case("ownership_holds", true) - .Case("ownership_returns", true) - .Case("ownership_takes", true) - .Case("objc_bool", true) - .Case("objc_subscripting", LangOpts.ObjCRuntime.isNonFragile()) - .Case("objc_array_literals", LangOpts.ObjC2) - .Case("objc_dictionary_literals", LangOpts.ObjC2) - .Case("objc_boxed_expressions", LangOpts.ObjC2) - .Case("objc_boxed_nsvalue_expressions", LangOpts.ObjC2) - .Case("arc_cf_code_audited", true) - .Case("objc_bridge_id", true) - .Case("objc_bridge_id_on_typedefs", true) - .Case("objc_generics", LangOpts.ObjC2) - .Case("objc_generics_variance", LangOpts.ObjC2) - .Case("objc_class_property", LangOpts.ObjC2) - // C11 features - .Case("c_alignas", LangOpts.C11) - .Case("c_alignof", LangOpts.C11) - .Case("c_atomic", LangOpts.C11) - .Case("c_generic_selections", LangOpts.C11) - .Case("c_static_assert", LangOpts.C11) - .Case("c_thread_local", - LangOpts.C11 && PP.getTargetInfo().isTLSSupported()) - // C++11 features - .Case("cxx_access_control_sfinae", LangOpts.CPlusPlus11) - .Case("cxx_alias_templates", LangOpts.CPlusPlus11) - .Case("cxx_alignas", LangOpts.CPlusPlus11) - .Case("cxx_alignof", LangOpts.CPlusPlus11) - .Case("cxx_atomic", LangOpts.CPlusPlus11) - .Case("cxx_attributes", LangOpts.CPlusPlus11) - .Case("cxx_auto_type", LangOpts.CPlusPlus11) - .Case("cxx_constexpr", LangOpts.CPlusPlus11) - .Case("cxx_constexpr_string_builtins", LangOpts.CPlusPlus11) - .Case("cxx_decltype", LangOpts.CPlusPlus11) - .Case("cxx_decltype_incomplete_return_types", LangOpts.CPlusPlus11) - .Case("cxx_default_function_template_args", LangOpts.CPlusPlus11) - .Case("cxx_defaulted_functions", LangOpts.CPlusPlus11) - .Case("cxx_delegating_constructors", LangOpts.CPlusPlus11) - .Case("cxx_deleted_functions", LangOpts.CPlusPlus11) - .Case("cxx_explicit_conversions", LangOpts.CPlusPlus11) - .Case("cxx_generalized_initializers", LangOpts.CPlusPlus11) - .Case("cxx_implicit_moves", LangOpts.CPlusPlus11) - .Case("cxx_inheriting_constructors", LangOpts.CPlusPlus11) - .Case("cxx_inline_namespaces", LangOpts.CPlusPlus11) - .Case("cxx_lambdas", LangOpts.CPlusPlus11) - .Case("cxx_local_type_template_args", LangOpts.CPlusPlus11) - .Case("cxx_nonstatic_member_init", LangOpts.CPlusPlus11) - .Case("cxx_noexcept", LangOpts.CPlusPlus11) - .Case("cxx_nullptr", LangOpts.CPlusPlus11) - .Case("cxx_override_control", LangOpts.CPlusPlus11) - .Case("cxx_range_for", LangOpts.CPlusPlus11) - .Case("cxx_raw_string_literals", LangOpts.CPlusPlus11) - .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus11) - .Case("cxx_rvalue_references", LangOpts.CPlusPlus11) - .Case("cxx_strong_enums", LangOpts.CPlusPlus11) - .Case("cxx_static_assert", LangOpts.CPlusPlus11) - .Case("cxx_thread_local", - LangOpts.CPlusPlus11 && PP.getTargetInfo().isTLSSupported()) - .Case("cxx_trailing_return", LangOpts.CPlusPlus11) - .Case("cxx_unicode_literals", LangOpts.CPlusPlus11) - .Case("cxx_unrestricted_unions", LangOpts.CPlusPlus11) - .Case("cxx_user_literals", LangOpts.CPlusPlus11) - .Case("cxx_variadic_templates", LangOpts.CPlusPlus11) - // C++14 features - .Case("cxx_aggregate_nsdmi", LangOpts.CPlusPlus14) - .Case("cxx_binary_literals", LangOpts.CPlusPlus14) - .Case("cxx_contextual_conversions", LangOpts.CPlusPlus14) - .Case("cxx_decltype_auto", LangOpts.CPlusPlus14) - .Case("cxx_generic_lambdas", LangOpts.CPlusPlus14) - .Case("cxx_init_captures", LangOpts.CPlusPlus14) - .Case("cxx_relaxed_constexpr", LangOpts.CPlusPlus14) - .Case("cxx_return_type_deduction", LangOpts.CPlusPlus14) - .Case("cxx_variable_templates", LangOpts.CPlusPlus14) - // NOTE: For features covered by SD-6, it is preferable to provide *only* - // the SD-6 macro and not a __has_feature check. - - // C++ TSes - //.Case("cxx_runtime_arrays", LangOpts.CPlusPlusTSArrays) - //.Case("cxx_concepts", LangOpts.CPlusPlusTSConcepts) - // FIXME: Should this be __has_feature or __has_extension? - //.Case("raw_invocation_type", LangOpts.CPlusPlus) - // Type traits - // N.B. Additional type traits should not be added to the following list. - // Instead, they should be detected by has_extension. - .Case("has_nothrow_assign", LangOpts.CPlusPlus) - .Case("has_nothrow_copy", LangOpts.CPlusPlus) - .Case("has_nothrow_constructor", LangOpts.CPlusPlus) - .Case("has_trivial_assign", LangOpts.CPlusPlus) - .Case("has_trivial_copy", LangOpts.CPlusPlus) - .Case("has_trivial_constructor", LangOpts.CPlusPlus) - .Case("has_trivial_destructor", LangOpts.CPlusPlus) - .Case("has_virtual_destructor", LangOpts.CPlusPlus) - .Case("is_abstract", LangOpts.CPlusPlus) - .Case("is_base_of", LangOpts.CPlusPlus) - .Case("is_class", LangOpts.CPlusPlus) - .Case("is_constructible", LangOpts.CPlusPlus) - .Case("is_convertible_to", LangOpts.CPlusPlus) - .Case("is_empty", LangOpts.CPlusPlus) - .Case("is_enum", LangOpts.CPlusPlus) - .Case("is_final", LangOpts.CPlusPlus) - .Case("is_literal", LangOpts.CPlusPlus) - .Case("is_standard_layout", LangOpts.CPlusPlus) - .Case("is_pod", LangOpts.CPlusPlus) - .Case("is_polymorphic", LangOpts.CPlusPlus) - .Case("is_sealed", LangOpts.CPlusPlus && LangOpts.MicrosoftExt) - .Case("is_trivial", LangOpts.CPlusPlus) - .Case("is_trivially_assignable", LangOpts.CPlusPlus) - .Case("is_trivially_constructible", LangOpts.CPlusPlus) - .Case("is_trivially_copyable", LangOpts.CPlusPlus) - .Case("is_union", LangOpts.CPlusPlus) - .Case("modules", LangOpts.Modules) - .Case("safe_stack", LangOpts.Sanitize.has(SanitizerKind::SafeStack)) - .Case("shadow_call_stack", - LangOpts.Sanitize.has(SanitizerKind::ShadowCallStack)) - .Case("tls", PP.getTargetInfo().isTLSSupported()) - .Case("underlying_type", LangOpts.CPlusPlus) +#include "clang/Basic/Features.def" .Default(false); +#undef FEATURE } /// HasExtension - Return true if we recognize and implement the feature @@ -1302,35 +1126,13 @@ static bool HasExtension(const Preprocessor &PP, StringRef Extension) { Extension.size() >= 4) Extension = Extension.substr(2, Extension.size() - 4); - // Because we inherit the feature list from HasFeature, this string switch - // must be less restrictive than HasFeature's. + // Because we inherit the feature list from HasFeature, this string switch + // must be less restrictive than HasFeature's. +#define EXTENSION(Name, Predicate) .Case(#Name, Predicate) return llvm::StringSwitch(Extension) - // C11 features supported by other languages as extensions. - .Case("c_alignas", true) - .Case("c_alignof", true) - .Case("c_atomic", true) - .Case("c_generic_selections", true) - .Case("c_static_assert", true) - .Case("c_thread_local", PP.getTargetInfo().isTLSSupported()) - // C++11 features supported by other languages as extensions. - .Case("cxx_atomic", LangOpts.CPlusPlus) - .Case("cxx_deleted_functions", LangOpts.CPlusPlus) - .Case("cxx_explicit_conversions", LangOpts.CPlusPlus) - .Case("cxx_inline_namespaces", LangOpts.CPlusPlus) - .Case("cxx_local_type_template_args", LangOpts.CPlusPlus) - .Case("cxx_nonstatic_member_init", LangOpts.CPlusPlus) - .Case("cxx_override_control", LangOpts.CPlusPlus) - .Case("cxx_range_for", LangOpts.CPlusPlus) - .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus) - .Case("cxx_rvalue_references", LangOpts.CPlusPlus) - .Case("cxx_variadic_templates", LangOpts.CPlusPlus) - // C++14 features supported by other languages as extensions. - .Case("cxx_binary_literals", true) - .Case("cxx_init_captures", LangOpts.CPlusPlus11) - .Case("cxx_variable_templates", LangOpts.CPlusPlus) - // Miscellaneous language extensions - .Case("overloadable_unmarked", true) - .Default(false); +#include "clang/Basic/Features.def" + .Default(false); +#undef EXTENSION } /// EvaluateHasIncludeCommon - Process a '__has_include("path")' diff --git a/clang/test/Frontend/compiler-options-dump.cpp b/clang/test/Frontend/compiler-options-dump.cpp new file mode 100644 index 000000000000..daa8bb18549a --- /dev/null +++ b/clang/test/Frontend/compiler-options-dump.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -compiler-options-dump -std=c++03 %s -o - | FileCheck %s --check-prefix=CXX03 +// RUN: %clang_cc1 -compiler-options-dump -std=c++17 %s -o - | FileCheck %s --check-prefix=CXX17 +// RUN: %clang_cc1 -compiler-options-dump -std=c99 -x c %s -o - | FileCheck %s --check-prefix=C99 + +// CXX03: "features" +// CXX03: "cxx_auto_type" : false +// CXX03: "cxx_range_for" : false +// CXX03: "extensions" +// CXX03: "cxx_range_for" : true + +// CXX17: "features" +// CXX17: "cxx_auto_type" : true +// CXX17: "cxx_range_for" : true +// CXX17: "extensions" +// CXX17: "cxx_range_for" : true + +// C99: "features" +// C99: "c_alignas" : false +// C99: "c_atomic" : false +// C99: "cxx_auto_type" : false +// C99: "cxx_range_for" : false +// C99: "extensions" +// C99: "c_alignas" : true +// C99: "c_atomic" : true +// C99: "cxx_range_for" : false