On Sat, Apr 30, 2011 at 08:08:06PM +0200, Jean-Daniel Dupas wrote: > > Le 29 avr. 2011 à 20:07, Douglas Gregor a écrit : > > > > > On Apr 29, 2011, at 10:44 AM, Peter Collingbourne wrote: > >> OK, I am fine with introducing a c_ prefix, for the reasons you > >> point out. But the way I understand it is that __has_feature in fact > >> has 2 semi-orthogonal purposes: > >> > >> 1) To test for support for Clang-specific extensions to the language. > >> This is the purpose of the non-language-prefixed feature test > >> identifiers. > >> > >> 2) To test for Clang support for language features which have been > >> standardised in the current language. This is the purpose of the > >> language-prefixed feature test identifiers. > >> > >> However, there is a gap here in that there is no way to test for > >> the existence of Clang-specific language extensions which have been > >> standardised in other languages. For example, generic selections > >> can be used to implement an OpenCL runtime library using Clang. > >> Since OpenCL is based on C99, generic selections would be classified > >> as an extension. This makes it impossible to test for that extension. > >> > >> One solution to this problem is to have 2 feature test identifiers > >> for each standardised feature (e.g. "c_generic_selections" and > >> "generic_selections"), each serving the 2 purposes mentioned above. > >> The disadvantage of this approach would obviously be the doubling up of > >> language feature identifiers. Also, as you point out "static_assert" > >> would be ambiguous. > >> > >> An alternative solution would be to introduce another macro, say > >> __has_extension, which takes the same feature test identifiers > >> as __has_feature. __has_extension would test the features of > >> the compiler alone (approximately serving purpose 1) while > >> __has_feature tests the features of the compiler together > >> with the current language (approximately serving purpose 2). > >> > >> So for example __has_feature(c_generic_selections) could be > >> used to test for support for generic selections in C1X while > >> __has_extension(c_generic_selections) could be used in any language. > >> I would imagine that __has_extension should act identically to > >> __has_feature if -pedantic-errors (or perhaps -pedantic) is enabled. > >> > >> Please let me know what you think. > > > > I think that __has_extension is an *excellent* idea! > > I tried to implements this new suggestion. > The has_feature variants are bound to the selected language and returns true > only when compiling as C1X, and has_extension always returns true. > Is this what you had in mind ?
__has_extension should be a superset of __has_feature, so it should also include the C++ and C++0x features, as well as the Clang specific extensions. This can be done trivially by calling HasFeature from HasExtension. I began an implementation (see patch), but this is incomplete since it includes no tests. I also haven't surveyed all of the C++0x features to see which are supported as extensions to C++98. If you like, you can extend the patch to add the correct set of C++0x features as well as tests. I also wonder whether we should stop adding new non-standardised features to __has_feature (strictly speaking, under the new regime __has_feature(X) should always be 0 if X is a non-standardised feature, but we shouldn't do this for existing features for backwards compatibility reasons). That is the way I wrote the documentation in my patch, but I suppose an argument can also be made for maintaining the existing behaviour of __has_feature and continuing to add non-standardised features. Thanks, -- Peter
>From 6d8fd218942488d67d4921c509b4071ecf6ee769 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne <[email protected]> Date: Sat, 30 Apr 2011 03:20:56 +0100 Subject: [PATCH] __has_extension --- docs/LanguageExtensions.html | 247 +++++++++++++++++++++++--------------- include/clang/Basic/Diagnostic.h | 1 + include/clang/Lex/Preprocessor.h | 1 + lib/Lex/PPMacroExpansion.cpp | 44 ++++++- 4 files changed, 192 insertions(+), 101 deletions(-) diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html index f86835a..cfb0305 100644 --- a/docs/LanguageExtensions.html +++ b/docs/LanguageExtensions.html @@ -32,28 +32,35 @@ td { </ul> <li><a href="#checking_upcoming_features">Checks for Upcoming Standard Language Features</a></li> <ul> - <li><a href="#cxx_attributes">C++0x attributes</a></li> - <li><a href="#cxx_decltype">C++0x <tt>decltype()</tt></a></li> - <li><a href="#cxx_default_function_template_args">C++0x default template arguments in function templates</a></li> - <li><a href="#cxx_deleted_functions">C++0x deleted functions</a></li> - <li><a href="#cxx_lambdas">C++0x lambdas</a></li> - <li><a href="#cxx_nullptr">C++0x nullptr</a></li> - <li><a href="#cxx_override_control">C++0x override control</a></li> - <li><a href="#cxx_range_for">C++0x range-based for loop</a></li> - <li><a href="#cxx_rvalue_references">C++0x rvalue references</a></li> - <li><a href="#cxx_reference_qualified_functions">C++0x reference-qualified functions</a></li> - <li><a href="#cxx_static_assert">C++0x <tt>static_assert()</tt></a></li> - <li><a href="#cxx_auto_type">C++0x type inference</a></li> - <li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li> - <li><a href="#cxx_inline_namespaces">C++0x inline namespaces</a></li> - <li><a href="#cxx_strong_enums">C++0x strongly-typed enumerations</a></li> - <li><a href="#cxx_trailing_return">C++0x trailing return type</a></li> - <li><a href="#cxx_noexcept">C++0x noexcept specification</a></li> + <li><a href="#cxx0x">C++0x</a> + <ul> + <li><a href="#cxx_attributes">C++0x attributes</a></li> + <li><a href="#cxx_decltype">C++0x <tt>decltype()</tt></a></li> + <li><a href="#cxx_default_function_template_args">C++0x default template arguments in function templates</a></li> + <li><a href="#cxx_deleted_functions">C++0x deleted functions</a></li> + <li><a href="#cxx_lambdas">C++0x lambdas</a></li> + <li><a href="#cxx_nullptr">C++0x nullptr</a></li> + <li><a href="#cxx_override_control">C++0x override control</a></li> + <li><a href="#cxx_range_for">C++0x range-based for loop</a></li> + <li><a href="#cxx_rvalue_references">C++0x rvalue references</a></li> + <li><a href="#cxx_reference_qualified_functions">C++0x reference-qualified functions</a></li> + <li><a href="#cxx_static_assert">C++0x <tt>static_assert()</tt></a></li> + <li><a href="#cxx_auto_type">C++0x type inference</a></li> + <li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li> + <li><a href="#cxx_inline_namespaces">C++0x inline namespaces</a></li> + <li><a href="#cxx_strong_enums">C++0x strongly-typed enumerations</a></li> + <li><a href="#cxx_trailing_return">C++0x trailing return type</a></li> + <li><a href="#cxx_noexcept">C++0x noexcept specification</a></li> + </ul> + <li><a href="#c1x">C1X</a> + <ul> + <li><a href="#c_generic_selections">C1X generic selections</a></li> + <li><a href="#c_static_assert">C1X <tt>_Static_assert()</tt></a></li> + </ul> </ul> <li><a href="#checking_type_traits">Checks for Type Traits</a></li> <li><a href="#blocks">Blocks</a></li> <li><a href="#overloading-in-c">Function Overloading in C</a></li> -<li><a href="#generic-selections">Generic Selections</a></li> <li><a href="#builtins">Builtin Functions</a> <ul> <li><a href="#__builtin_shufflevector">__builtin_shufflevector</a></li> @@ -115,28 +122,42 @@ not. It can be used like this:</p> <!-- ======================================================================= --> -<h3 id="__has_feature">__has_feature</h3> +<h3 id="__has_feature_extension">__has_feature and __has_extension</h3> <!-- ======================================================================= --> -<p>This function-like macro takes a single identifier argument that is the name -of a feature. It evaluates to 1 if the feature is supported or 0 if not. It -can be used like this:</p> +<p>These function-like macros take a single identifier argument that is the +name of a feature. <code>__has_feature</code> evaluates to 1 if the feature +is both supported by Clang and standardized in the current language standard +or 0 if not, while <code>__has_extension</code> evaluates to 1 if the feature +is supported by Clang in the current language (either as a language extension +or a standard language feature) or 0 if not. They can be used like this:</p> <blockquote> <pre> #ifndef __has_feature // Optional of course. #define __has_feature(x) 0 // Compatibility with non-clang compilers. #endif +#ifndef __has_extension + #define __has_extension(x) 0 +#endif ... -#if __has_feature(attribute_overloadable) || \ - __has_feature(blocks) -... +#if __has_feature(cxx_rvalue_references) +// This code will only be compiled with the -std=c++0x and -std=gnu++0x +// options, because rvalue references are only standardized in C++0x. +#endif + +#if __has_extension(cxx_rvalue_references) +// This code will be compiled with the -std=c++0x, -std=gnu++0x, -std=c++98 +// and -std=gnu++98 options, because rvalue references are supported as a +// language extension in C++98. #endif -... </pre> </blockquote> +<p>If the <code>-pedantic-errors</code> option is given, +<code>__has_extension</code> is equivalent to <code>__has_feature</code>.</p> + <p>The feature tag is described along with the language feature below.</p> <!-- ======================================================================= --> @@ -293,7 +314,7 @@ float4 foo(float2 a, float2 b) { </pre> </blockquote> -<p>Query for this feature with __has_feature(attribute_ext_vector_type).</p> +<p>Query for this feature with __has_extension(attribute_ext_vector_type).</p> <p>See also <a href="#__builtin_shufflevector">__builtin_shufflevector</a>.</p> @@ -318,8 +339,8 @@ will be incorporated into the appropriate diagnostic:</p> </blockquote> <p>Query for this feature -with <tt>__has_feature(attribute_deprecated_with_message)</tt> -and <tt>__has_feature(attribute_unavailable_with_message)</tt>.</p> +with <tt>__has_extension(attribute_deprecated_with_message)</tt> +and <tt>__has_extension(attribute_unavailable_with_message)</tt>.</p> <!-- ======================================================================= --> <h2 id="attributes-on-enumerators">Attributes on Enumerators</h2> @@ -342,7 +363,7 @@ initializer, like so:</p> <p>Attributes on the <tt>enum</tt> declaration do not apply to individual enumerators.</p> -<p>Query for this feature with <tt>__has_feature(enumerator_attributes)</tt>.</p> +<p>Query for this feature with <tt>__has_extension(enumerator_attributes)</tt>.</p> <!-- ======================================================================= --> <h2 id="checking_language_features">Checks for Standard Language Features</h2> @@ -365,106 +386,156 @@ compiling code with <tt>-fno-rtti</tt> disables the use of RTTI.</p> <h2 id="checking_upcoming_features">Checks for Upcoming Standard Language Features</h2> <!-- ======================================================================= --> -<p>The <tt>__has_feature</tt> macro can be used to query if certain upcoming -standard language features are enabled. Those features are listed here.</p> +<p>The <tt>__has_feature</tt> or <tt>__has_extension</tt> macros can be used +to query if certain upcoming standard language features are enabled. Those +features are listed here. Features that are not yet implemented will be +noted.</p> -<p>Currently, all features listed here are slated for inclusion in the upcoming -C++0x standard. As a result, all the features that clang supports are enabled -with the <tt>-std=c++0x</tt> option when compiling C++ code. Features that are -not yet implemented will be noted.</p> +<h3 id="cxx0x">C++0x</h3> -<h3 id="cxx_decltype">C++0x <tt>decltype()</tt></h3> +<p>The features listed below are slated for inclusion in the upcoming +C++0x standard. As a result, all these features are enabled +with the <tt>-std=c++0x</tt> option when compiling C++ code.</p> -<p>Use <tt>__has_feature(cxx_decltype)</tt> to determine if support for the +<h4 id="cxx_decltype">C++0x <tt>decltype()</tt></h3> + +<p>Use <tt>__has_feature(cxx_decltype)</tt> or +<tt>__has_extension(cxx_decltype)</tt> to determine if support for the <tt>decltype()</tt> specifier is enabled.</p> -<h3 id="cxx_attributes">C++0x attributes</h3> +<h4 id="cxx_attributes">C++0x attributes</h3> -<p>Use <tt>__has_feature(cxx_attributes)</tt> to determine if support for -attribute parsing with C++0x's square bracket notation is enabled.</p> +<p>Use <tt>__has_feature(cxx_attributes)</tt> or +<tt>__has_extension(cxx_attributes)</tt> to determine if support for attribute +parsing with C++0x's square bracket notation is enabled.</p> -<h3 id="cxx_default_function_template_args">C++0x default template arguments in function templates</h3> +<h4 id="cxx_default_function_template_args">C++0x default template arguments in function templates</h3> -<p>Use <tt>__has_feature(cxx_default_function_template_args)</tt> to determine if support for default template arguments in function templates is enabled.</p> +<p>Use <tt>__has_feature(cxx_default_function_template_args)</tt> or +<tt>__has_extension(cxx_default_function_template_args)</tt> to determine +if support for default template arguments in function templates is enabled.</p> -<h3 id="cxx_deleted_functions">C++0x deleted functions</tt></h3> +<h4 id="cxx_deleted_functions">C++0x deleted functions</tt></h3> -<p>Use <tt>__has_feature(cxx_deleted_functions)</tt> to determine if support for +<p>Use <tt>__has_feature(cxx_deleted_functions)</tt> or +<tt>__has_extension(cxx_deleted_functions)</tt> to determine if support for deleted function definitions (with <tt>= delete</tt>) is enabled.</p> -<h3 id="cxx_lambdas">C++0x lambdas</h3> +<h4 id="cxx_lambdas">C++0x lambdas</h3> -<p>Use <tt>__has_feature(cxx_lambdas)</tt> to determine if support for -lambdas is enabled. clang does not currently implement this feature.</p> +<p>Use <tt>__has_feature(cxx_lambdas)</tt> or +<tt>__has_extension(cxx_lambdas)</tt> to determine if support for lambdas +is enabled. clang does not currently implement this feature.</p> -<h3 id="cxx_nullptr">C++0x <tt>nullptr</tt></h3> +<h4 id="cxx_nullptr">C++0x <tt>nullptr</tt></h3> -<p>Use <tt>__has_feature(cxx_nullptr)</tt> to determine if support for +<p>Use <tt>__has_feature(cxx_nullptr)</tt> or +<tt>__has_extension(cxx_nullptr)</tt> to determine if support for <tt>nullptr</tt> is enabled. clang does not yet fully implement this feature.</p> -<h3 id="cxx_override_control">C++0x <tt>override control</tt></h3> +<h4 id="cxx_override_control">C++0x <tt>override control</tt></h3> -<p>Use <tt>__has_feature(cxx_override_control)</tt> to determine if support for +<p>Use <tt>__has_feature(cxx_override_control)</tt> or +<tt>__has_extension(cxx_override_control)</tt> to determine if support for the override control keywords is enabled.</p> -<h3 id="cxx_reference_qualified_functions">C++0x reference-qualified functions</h3> -<p>Use <tt>__has_feature(cxx_reference_qualified_functions)</tt> to determine if support for reference-qualified functions (e.g., member functions with <code>&</code> or <code>&&</code> applied to <code>*this</code>) is enabled.</p> +<h4 id="cxx_reference_qualified_functions">C++0x reference-qualified functions</h3> +<p>Use <tt>__has_feature(cxx_reference_qualified_functions)</tt> or +<tt>__has_extension(cxx_reference_qualified_functions)</tt> to determine +if support for reference-qualified functions (e.g., member functions with +<code>&</code> or <code>&&</code> applied to <code>*this</code>) +is enabled.</p> -<h3 id="cxx_range_for">C++0x range-based for loop</tt></h3> +<h4 id="cxx_range_for">C++0x range-based for loop</tt></h3> -<p>Use <tt>__has_feature(cxx_range_for)</tt> to determine if support for -the range-based for loop is enabled. </p> +<p>Use <tt>__has_feature(cxx_range_for)</tt> or +<tt>__has_extension(cxx_range_for)</tt> to determine if support for the +range-based for loop is enabled. </p> -<h3 id="cxx_rvalue_references">C++0x rvalue references</tt></h3> +<h4 id="cxx_rvalue_references">C++0x rvalue references</tt></h3> -<p>Use <tt>__has_feature(cxx_rvalue_references)</tt> to determine if support for +<p>Use <tt>__has_feature(cxx_rvalue_references)</tt> or +<tt>__has_extension(cxx_rvalue_references)</tt> to determine if support for rvalue references is enabled. </p> -<h3 id="cxx_static_assert">C++0x <tt>static_assert()</tt></h3> +<h4 id="cxx_static_assert">C++0x <tt>static_assert()</tt></h3> -<p>Use <tt>__has_feature(cxx_static_assert)</tt> to determine if support for +<p>Use <tt>__has_feature(cxx_static_assert)</tt> or +<tt>__has_extension(cxx_static_assert)</tt> to determine if support for compile-time assertions using <tt>static_assert</tt> is enabled.</p> -<h3 id="cxx_auto_type">C++0x type inference</h3> +<h4 id="cxx_auto_type">C++0x type inference</h3> -<p>Use <tt>__has_feature(cxx_auto_type)</tt> to determine C++0x type inference -is supported using the <tt>auto</tt> specifier. If this is disabled, -<tt>auto</tt> will instead be a storage class specifier, as in C or C++98.</p> +<p>Use <tt>__has_feature(cxx_auto_type)</tt> or +<tt>__has_extension(cxx_auto_type)</tt> to determine C++0x type inference is +supported using the <tt>auto</tt> specifier. If this is disabled, <tt>auto</tt> +will instead be a storage class specifier, as in C or C++98.</p> -<h3 id="cxx_variadic_templates">C++0x variadic templates</h3> +<h4 id="cxx_variadic_templates">C++0x variadic templates</h3> -<p>Use <tt>__has_feature(cxx_variadic_templates)</tt> to determine if support +<p>Use <tt>__has_feature(cxx_variadic_templates)</tt> or +<tt>__has_extension(cxx_variadic_templates)</tt> to determine if support for variadic templates is enabled.</p> -<h3 id="cxx_inline_namespaces">C++0x inline namespaces</h3> +<h4 id="cxx_inline_namespaces">C++0x inline namespaces</h3> -<p>Use <tt>__has_feature(cxx_inline_namespaces)</tt> to determine if support for +<p>Use <tt>__has_feature(cxx_inline_namespaces)</tt> or +<tt>__has_extension(cxx_inline_namespaces)</tt> to determine if support for inline namespaces is enabled.</p> -<h3 id="cxx_trailing_return">C++0x trailing return type</h3> +<h4 id="cxx_trailing_return">C++0x trailing return type</h3> -<p>Use <tt>__has_feature(cxx_trailing_return)</tt> to determine if support for -the alternate function declaration syntax with trailing return type is enabled.</p> +<p>Use <tt>__has_feature(cxx_trailing_return)</tt> or +<tt>__has_extension(cxx_trailing_return)</tt> to determine if support for the +alternate function declaration syntax with trailing return type is enabled.</p> -<h3 id="cxx_noexcept">C++0x noexcept</h3> +<h4 id="cxx_noexcept">C++0x noexcept</h3> -<p>Use <tt>__has_feature(cxx_noexcept)</tt> to determine if support for -noexcept exception specifications is enabled.</p> +<p>Use <tt>__has_feature(cxx_noexcept)</tt> or +<tt>__has_extension(cxx_noexcept)</tt> to determine if support for noexcept +exception specifications is enabled.</p> -<h3 id="cxx_strong_enums">C++0x strongly typed enumerations</h3> +<h4 id="cxx_strong_enums">C++0x strongly typed enumerations</h3> -<p>Use <tt>__has_feature(cxx_strong_enums)</tt> to determine if support for +<p>Use <tt>__has_feature(cxx_strong_enums)</tt> or +<tt>__has_extension(cxx_strong_enums)</tt> to determine if support for strongly typed, scoped enumerations is enabled.</p> +<h3 id="c1x">C1X</h3> + +<p>The features listed below are slated for inclusion in the upcoming +C1X standard. As a result, all these features are enabled +with the <tt>-std=c1x</tt> option when compiling C code.</p> + +<h4 id="c_generic_selections">C1X generic selections</h2> + +<p>Use <tt>__has_feature(c_generic_selections)</tt> or +<tt>__has_extension(c_generic_selections)</tt> to determine if support for +generic selections is enabled.</p> + +<p>As an extension, the C1X generic selection expression is available in all +languages supported by Clang. The syntax is the same as that given in the +C1X draft standard.</p> + +<p>In C, type compatibility is decided according to the rules given in the +appropriate standard, but in C++, which lacks the type compatibility rules +used in C, types are considered compatible only if they are equivalent.</p> + +<h4 id="c_static_assert">C1X <tt>_Static_assert()</tt></h3> + +<p>Use <tt>__has_feature(c_static_assert)</tt> or +<tt>__has_extension(c_static_assert)</tt> to determine if support for +compile-time assertions using <tt>_Static_assert</tt> is enabled.</p> + <!-- ======================================================================= --> <h2 id="checking_type_traits">Checks for Type Traits</h2> <!-- ======================================================================= --> -<p>Clang supports the <a hef="http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html">GNU C++ type traits</a> and a subset of the <a href="http://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx">Microsoft Visual C++ Type traits</a>. For each supported type trait <code>__X</code>, <code>__has_feature(X)</code> indicates the presence of the type trait. For example: +<p>Clang supports the <a hef="http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html">GNU C++ type traits</a> and a subset of the <a href="http://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx">Microsoft Visual C++ Type traits</a>. For each supported type trait <code>__X</code>, <code>__has_extension(X)</code> indicates the presence of the type trait. For example: <blockquote> <pre> -#if __has_feature(is_convertible_to) +#if __has_extension(is_convertible_to) template<typename From, typename To> struct is_convertible_to { static const bool value = __is_convertible_to(From, To); @@ -507,7 +578,7 @@ details for the clang implementation are in <a href="Block-ABI-Apple.txt">Block-ABI-Apple.txt</a>.</p> -<p>Query for this feature with __has_feature(blocks).</p> +<p>Query for this feature with __has_extension(blocks).</p> <!-- ======================================================================= --> <h2 id="overloading-in-c">Function Overloading in C</h2> @@ -607,22 +678,8 @@ caveats to this use of name mangling:</p> C.</li> </ul> -<p>Query for this feature with __has_feature(attribute_overloadable).</p> - - -<!-- ======================================================================= --> -<h2 id="generic-selections">Generic Selections</h2> -<!-- ======================================================================= --> - -<p>The C1X generic selection expression is available in all languages -supported by Clang. The syntax is the same as that given in the C1X draft -standard.</p> - -<p>In C, type compatibility is decided according to the rules given in the -appropriate standard, but in C++, which lacks the type compatibility rules -used in C, types are considered compatible only if they are equivalent.</p> +<p>Query for this feature with __has_extension(attribute_overloadable).</p> -<p>Query for this feature with __has_feature(generic_selections).</p> <!-- ======================================================================= --> <h2 id="builtins">Builtin Functions</h2> diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 7fc400f..3c8a933 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -400,6 +400,7 @@ public: void setExtensionHandlingBehavior(ExtensionHandling H) { ExtBehavior = H; } + ExtensionHandling getExtensionHandlingBehavior() const { return ExtBehavior; } /// AllExtensionsSilenced - This is a counter bumped when an __extension__ /// block is encountered. When non-zero, all extension diagnostics are diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 616507a..a26c15f 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -84,6 +84,7 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__ IdentifierInfo *Ident__has_feature; // __has_feature + IdentifierInfo *Ident__has_extension; // __has_extension IdentifierInfo *Ident__has_builtin; // __has_builtin IdentifierInfo *Ident__has_attribute; // __has_attribute IdentifierInfo *Ident__has_include; // __has_include diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index bacd624..3059428 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -85,6 +85,7 @@ void Preprocessor::RegisterBuiltinMacros() { // Clang Extensions. Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature"); + Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension"); Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin"); Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute"); Ident__has_include = RegisterBuiltinMacro(*this, "__has_include"); @@ -525,8 +526,8 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, } -/// HasFeature - Return true if we recognize and implement the specified feature -/// specified by the identifier. +/// HasFeature - Return true if we recognize and implement the feature +/// specified by the identifier as a standard language feature. static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { const LangOptions &LangOpts = PP.getLangOptions(); @@ -550,12 +551,14 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("cxx_exceptions", LangOpts.Exceptions) .Case("cxx_rtti", LangOpts.RTTI) .Case("enumerator_attributes", true) - .Case("generic_selections", true) .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI) .Case("objc_weak_class", LangOpts.ObjCNonFragileABI) .Case("ownership_holds", true) .Case("ownership_returns", true) .Case("ownership_takes", true) + // C1X features + .Case("c_generic_selections", LangOpts.C1X) + .Case("c_static_assert", LangOpts.C1X) // C++0x features .Case("cxx_attributes", LangOpts.CPlusPlus0x) .Case("cxx_auto_type", LangOpts.CPlusPlus0x) @@ -598,6 +601,32 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Default(false); } +/// HasExtension - Return true if we recognize and implement the feature +/// specified by the identifier, either as an extension or a standard language +/// feature. +static bool HasExtension(const Preprocessor &PP, const IdentifierInfo *II) { + if (HasFeature(PP, II)) + return true; + + // If the use of an extension results in an error diagnostic, extensions are + // effectively unavailable, so just return false here. + if (PP.getDiagnostics().getExtensionHandlingBehavior()==Diagnostic::Ext_Error) + return false; + + const LangOptions &LangOpts = PP.getLangOptions(); + + // Because we inherit the feature list from HasFeature, this string switch + // must be less restrictive than HasFeature's. + return llvm::StringSwitch<bool>(II->getName()) + // C1X features supported by other languages as extensions. + .Case("c_generic_selections", true) + .Case("c_static_assert", true) + // C++0x features supported by other languages as extensions. + .Case("cxx_override_control", LangOpts.CPlusPlus) + .Case("cxx_rvalue_references", LangOpts.CPlusPlus) + .Default(false); +} + /// HasAttribute - Return true if we recognize and implement the attribute /// specified by the given identifier. static bool HasAttribute(const IdentifierInfo *II) { @@ -846,10 +875,11 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { // __COUNTER__ expands to a simple numeric value. OS << CounterValue++; Tok.setKind(tok::numeric_constant); - } else if (II == Ident__has_feature || - II == Ident__has_builtin || + } else if (II == Ident__has_feature || + II == Ident__has_extension || + II == Ident__has_builtin || II == Ident__has_attribute) { - // The argument to these two builtins should be a parenthesized identifier. + // The argument to these builtins should be a parenthesized identifier. SourceLocation StartLoc = Tok.getLocation(); bool IsValid = false; @@ -878,6 +908,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { Value = FeatureII->getBuiltinID() != 0; } else if (II == Ident__has_attribute) Value = HasAttribute(FeatureII); + else if (II == Ident__has_extension) + Value = HasExtension(*this, FeatureII); else { assert(II == Ident__has_feature && "Must be feature check"); Value = HasFeature(*this, FeatureII); -- 1.7.1
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
