r368785 - Add __has_builtin support for builtin function-like type traits.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 13 19:30:12 PDT 2019
Author: rsmith
Date: Tue Aug 13 19:30:11 2019
New Revision: 368785
URL: http://llvm.org/viewvc/llvm-project?rev=368785&view=rev
Log:
Add __has_builtin support for builtin function-like type traits.
Summary:
Previously __has_builtin(__builtin_*) would return false for
__builtin_*s that we modeled as keywords rather than as functions
(because they take type arguments). With this patch, all builtins
that are called with function-call-like syntax return true from
__has_builtin (covering __builtin_* and also the __is_* and __has_* type
traits and the handful of similar builtins without such a prefix).
Update the documentation on __has_builtin and on type traits to match.
While doing this I noticed the type trait documentation was out of date
and incomplete; that's fixed here too.
Reviewers: aaron.ballman
Subscribers: jfb, kristina, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66100
Added:
cfe/trunk/test/Preprocessor/feature_tests.cpp
Modified:
cfe/trunk/docs/LanguageExtensions.rst
cfe/trunk/include/clang/Basic/Features.def
cfe/trunk/include/clang/Basic/TokenKinds.def
cfe/trunk/lib/Lex/PPMacroExpansion.cpp
cfe/trunk/test/Preprocessor/feature_tests.c
Modified: cfe/trunk/docs/LanguageExtensions.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=368785&r1=368784&r2=368785&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.rst (original)
+++ cfe/trunk/docs/LanguageExtensions.rst Tue Aug 13 19:30:11 2019
@@ -38,7 +38,9 @@ version checks".
-----------------
This function-like macro takes a single identifier argument that is the name of
-a builtin function. It evaluates to 1 if the builtin is supported or 0 if not.
+a builtin function, a builtin pseudo-function (taking one or more type
+arguments), or a builtin template.
+It evaluates to 1 if the builtin is supported or 0 if not.
It can be used like this:
.. code-block:: c++
@@ -55,6 +57,14 @@ It can be used like this:
#endif
...
+.. note::
+
+ Prior to Clang 10, ``__has_builtin`` could not be used to detect most builtin
+ pseudo-functions.
+
+ ``__has_builtin`` should not be used to detect support for a builtin macro;
+ use ``#ifdef`` instead.
+
.. _langext-__has_feature-__has_extension:
``__has_feature`` and ``__has_extension``
@@ -1041,8 +1051,8 @@ For example, compiling code with ``-fmod
More information could be found `here <https://clang.llvm.org/docs/Modules.html>`_.
-Checks for Type Trait Primitives
-================================
+Type Trait Primitives
+=====================
Type trait primitives are special builtin constant expressions that can be used
by the standard C++ library to facilitate or simplify the implementation of
@@ -1058,20 +1068,173 @@ the supported set of system headers, cur
Clang supports the `GNU C++ type traits
<https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html>`_ and a subset of the
-`Microsoft Visual C++ Type traits
-<https://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx>`_.
+`Microsoft Visual C++ type traits
+<https://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx>`_,
+as well as nearly all of the
+`Embarcadero C++ type traits
+<http://docwiki.embarcadero.com/RADStudio/Rio/en/Type_Trait_Functions_(C%2B%2B11)_Index>`_.
+
+The following type trait primitives are supported by Clang. Those traits marked
+(C++) provide implementations for type traits specified by the C++ standard;
+``__X(...)`` has the same semantics and constraints as the corresponding
+``std::X_t<...>`` or ``std::X_v<...>`` type trait.
+
+* ``__array_rank(type)`` (Embarcadero):
+ Returns the number of levels of array in the type ``type``:
+ ``0`` if ``type`` is not an array type, and
+ ``__array_rank(element) + 1`` if ``type`` is an array of ``element``.
+* ``__array_extent(type, dim)`` (Embarcadero):
+ The ``dim``'th array bound in the type ``type``, or ``0`` if
+ ``dim >= __array_rank(type)``.
+* ``__has_nothrow_assign`` (GNU, Microsoft, Embarcadero):
+ Deprecated, use ``__is_nothrow_assignable`` instead.
+* ``__has_nothrow_move_assign`` (GNU, Microsoft):
+ Deprecated, use ``__is_nothrow_assignable`` instead.
+* ``__has_nothrow_copy`` (GNU, Microsoft):
+ Deprecated, use ``__is_nothrow_constructible`` instead.
+* ``__has_nothrow_constructor`` (GNU, Microsoft):
+ Deprecated, use ``__is_nothrow_constructible`` instead.
+* ``__has_trivial_assign`` (GNU, Microsoft, Embarcadero):
+ Deprecated, use ``__is_trivially_assignable`` instead.
+* ``__has_trivial_move_assign`` (GNU, Microsoft):
+ Deprecated, use ``__is_trivially_assignable`` instead.
+* ``__has_trivial_copy`` (GNU, Microsoft):
+ Deprecated, use ``__is_trivially_constructible`` instead.
+* ``__has_trivial_constructor`` (GNU, Microsoft):
+ Deprecated, use ``__is_trivially_constructible`` instead.
+* ``__has_trivial_move_constructor`` (GNU, Microsoft):
+ Deprecated, use ``__is_trivially_constructible`` instead.
+* ``__has_trivial_destructor`` (GNU, Microsoft, Embarcadero):
+ Deprecated, use ``__is_trivially_destructible`` instead.
+* ``__has_unique_object_representations`` (C++, GNU)
+* ``__has_virtual_destructor`` (C++, GNU, Microsoft, Embarcadero)
+* ``__is_abstract`` (C++, GNU, Microsoft, Embarcadero)
+* ``__is_aggregate`` (C++, GNU, Microsoft)
+* ``__is_arithmetic`` (C++, Embarcadero)
+* ``__is_array`` (C++, Embarcadero)
+* ``__is_assignable`` (C++, MSVC 2015)
+* ``__is_base_of`` (C++, GNU, Microsoft, Embarcadero)
+* ``__is_class`` (C++, GNU, Microsoft, Embarcadero)
+* ``__is_complete_type(type)`` (Embarcadero):
+ Return ``true`` if ``type`` is a complete type.
+ Warning: this trait is dangerous because it can return different values at
+ different points in the same program.
+* ``__is_compound`` (C++, Embarcadero)
+* ``__is_const`` (C++, Embarcadero)
+* ``__is_constructible`` (C++, MSVC 2013)
+* ``__is_convertible`` (C++, Embarcadero)
+* ``__is_convertible_to`` (Microsoft):
+ Synonym for ``__is_convertible``.
+* ``__is_destructible`` (C++, MSVC 2013):
+ Only available in ``-fms-extensions`` mode.
+* ``__is_empty`` (C++, GNU, Microsoft, Embarcadero)
+* ``__is_enum`` (C++, GNU, Microsoft, Embarcadero)
+* ``__is_final`` (C++, GNU, Microsoft)
+* ``__is_floating_point`` (C++, Embarcadero)
+* ``__is_function`` (C++, Embarcadero)
+* ``__is_fundamental`` (C++, Embarcadero)
+* ``__is_integral`` (C++, Embarcadero)
+* ``__is_interface_class`` (Microsoft):
+ Returns ``false``, even for types defined with ``__interface``.
+* ``__is_literal`` (Clang):
+ Synonym for ``__is_literal_type``.
+* ``__is_literal_type`` (C++, GNU, Microsoft):
+ Note, the corresponding standard trait was deprecated in C++17
+ and removed in C++20.
+* ``__is_lvalue_reference`` (C++, Embarcadero)
+* ``__is_member_object_pointer`` (C++, Embarcadero)
+* ``__is_member_function_pointer`` (C++, Embarcadero)
+* ``__is_member_pointer`` (C++, Embarcadero)
+* ``__is_nothrow_assignable`` (C++, MSVC 2013)
+* ``__is_nothrow_constructible`` (C++, MSVC 2013)
+* ``__is_nothrow_destructible`` (C++, MSVC 2013)
+ Only available in ``-fms-extensions`` mode.
+* ``__is_object`` (C++, Embarcadero)
+* ``__is_pod`` (C++, GNU, Microsoft, Embarcadero):
+ Note, the corresponding standard trait was deprecated in C++20.
+* ``__is_pointer`` (C++, Embarcadero)
+* ``__is_polymorphic`` (C++, GNU, Microsoft, Embarcadero)
+* ``__is_reference`` (C++, Embarcadero)
+* ``__is_rvalue_reference`` (C++, Embarcadero)
+* ``__is_same`` (C++, Embarcadero)
+* ``__is_scalar`` (C++, Embarcadero)
+* ``__is_sealed`` (Microsoft):
+ Synonym for ``__is_final``.
+* ``__is_signed`` (C++, Embarcadero):
+ Note that this currently returns true for enumeration types if the underlying
+ type is signed, and returns false for floating-point types, in violation of
+ the requirements for ``std::is_signed``. This behavior is likely to change in
+ a future version of Clang.
+* ``__is_standard_layout`` (C++, GNU, Microsoft, Embarcadero)
+* ``__is_trivial`` (C++, GNU, Microsoft, Embarcadero)
+* ``__is_trivially_assignable`` (C++, GNU, Microsoft)
+* ``__is_trivially_constructible`` (C++, GNU, Microsoft)
+* ``__is_trivially_copyable`` (C++, GNU, Microsoft)
+* ``__is_trivially_destructible`` (C++, MSVC 2013)
+* ``__is_union`` (C++, GNU, Microsoft, Embarcadero)
+* ``__is_unsigned`` (C++, Embarcadero)
+ Note that this currently returns true for enumeration types if the underlying
+ type is unsigned, in violation of the requirements for ``std::is_unsigned``.
+ This behavior is likely to change in a future version of Clang.
+* ``__is_void`` (C++, Embarcadero)
+* ``__is_volatile`` (C++, Embarcadero)
+* ``__reference_binds_to_temporary(T, U)`` (Clang): Determines whether a
+ reference of type ``T`` bound to an expression of type ``U`` would bind to a
+ materialized temporary object. If ``T`` is not a reference type the result
+ is false. Note this trait will also return false when the initialization of
+ ``T`` from ``U`` is ill-formed.
+* ``__underlying_type`` (C++, GNU, Microsoft)
+
+In addition, the following expression traits are supported:
-Feature detection is supported only for some of the primitives at present. User
-code should not use these checks because they bear no direct relation to the
-actual set of type traits supported by the C++ standard library.
-
-For type trait ``__X``, ``__has_extension(X)`` indicates the presence of the
-type trait primitive in the compiler. A simplistic usage example as might be
-seen in standard C++ headers follows:
+* ``__is_lvalue_expr(e)`` (Embarcadero):
+ Returns true if ``e`` is an lvalue expression.
+ Deprecated, use ``__is_lvalue_reference(decltype((e)))`` instead.
+* ``__is_rvalue_expr(e)`` (Embarcadero):
+ Returns true if ``e`` is a prvalue expression.
+ Deprecated, use ``!__is_reference(decltype((e)))`` instead.
+
+There are multiple ways to detect support for a type trait ``__X`` in the
+compiler, depending on the oldest version of Clang you wish to support.
+
+* From Clang 10 onwards, ``__has_builtin(__X)`` can be used.
+* From Clang 6 onwards, ``!__is_identifier(__X)`` can be used.
+* From Clang 3 onwards, ``__has_feature(X)`` can be used, but only supports
+ the following traits:
+
+ * ``__has_nothrow_assign``
+ * ``__has_nothrow_copy``
+ * ``__has_nothrow_constructor``
+ * ``__has_trivial_assign``
+ * ``__has_trivial_copy``
+ * ``__has_trivial_constructor``
+ * ``__has_trivial_destructor``
+ * ``__has_virtual_destructor``
+ * ``__is_abstract``
+ * ``__is_base_of``
+ * ``__is_class``
+ * ``__is_constructible``
+ * ``__is_convertible_to``
+ * ``__is_empty``
+ * ``__is_enum``
+ * ``__is_final``
+ * ``__is_literal``
+ * ``__is_standard_layout``
+ * ``__is_pod``
+ * ``__is_polymorphic``
+ * ``__is_sealed``
+ * ``__is_trivial``
+ * ``__is_trivially_assignable``
+ * ``__is_trivially_constructible``
+ * ``__is_trivially_copyable``
+ * ``__is_union``
+ * ``__underlying_type``
+
+A simplistic usage example as might be seen in standard C++ headers follows:
.. code-block:: c++
- #if __has_extension(is_convertible_to)
+ #if __has_builtin(__is_convertible_to)
template<typename From, typename To>
struct is_convertible_to {
static const bool value = __is_convertible_to(From, To);
@@ -1080,54 +1243,6 @@ seen in standard C++ headers follows:
// Emulate type trait for compatibility with other compilers.
#endif
-The following type trait primitives are supported by Clang:
-
-* ``__has_nothrow_assign`` (GNU, Microsoft)
-* ``__has_nothrow_copy`` (GNU, Microsoft)
-* ``__has_nothrow_constructor`` (GNU, Microsoft)
-* ``__has_trivial_assign`` (GNU, Microsoft)
-* ``__has_trivial_copy`` (GNU, Microsoft)
-* ``__has_trivial_constructor`` (GNU, Microsoft)
-* ``__has_trivial_destructor`` (GNU, Microsoft)
-* ``__has_virtual_destructor`` (GNU, Microsoft)
-* ``__is_abstract`` (GNU, Microsoft)
-* ``__is_aggregate`` (GNU, Microsoft)
-* ``__is_base_of`` (GNU, Microsoft)
-* ``__is_class`` (GNU, Microsoft)
-* ``__is_convertible_to`` (Microsoft)
-* ``__is_empty`` (GNU, Microsoft)
-* ``__is_enum`` (GNU, Microsoft)
-* ``__is_interface_class`` (Microsoft)
-* ``__is_pod`` (GNU, Microsoft)
-* ``__is_polymorphic`` (GNU, Microsoft)
-* ``__is_union`` (GNU, Microsoft)
-* ``__is_literal(type)``: Determines whether the given type is a literal type
-* ``__is_final``: Determines whether the given type is declared with a
- ``final`` class-virt-specifier.
-* ``__underlying_type(type)``: Retrieves the underlying type for a given
- ``enum`` type. This trait is required to implement the C++11 standard
- library.
-* ``__is_trivially_assignable(totype, fromtype)``: Determines whether a value
- of type ``totype`` can be assigned to from a value of type ``fromtype`` such
- that no non-trivial functions are called as part of that assignment. This
- trait is required to implement the C++11 standard library.
-* ``__is_trivially_constructible(type, argtypes...)``: Determines whether a
- value of type ``type`` can be direct-initialized with arguments of types
- ``argtypes...`` such that no non-trivial functions are called as part of
- that initialization. This trait is required to implement the C++11 standard
- library.
-* ``__is_destructible`` (MSVC 2013)
-* ``__is_nothrow_destructible`` (MSVC 2013)
-* ``__is_nothrow_assignable`` (MSVC 2013, clang)
-* ``__is_constructible`` (MSVC 2013, clang)
-* ``__is_nothrow_constructible`` (MSVC 2013, clang)
-* ``__is_assignable`` (MSVC 2015, clang)
-* ``__reference_binds_to_temporary(T, U)`` (Clang): Determines whether a
- reference of type ``T`` bound to an expression of type ``U`` would bind to a
- materialized temporary object. If ``T`` is not a reference type the result
- is false. Note this trait will also return false when the initialization of
- ``T`` from ``U`` is ill-formed.
-
Blocks
======
Modified: cfe/trunk/include/clang/Basic/Features.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Features.def?rev=368785&r1=368784&r2=368785&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Features.def (original)
+++ cfe/trunk/include/clang/Basic/Features.def Tue Aug 13 19:30:11 2019
@@ -187,7 +187,7 @@ FEATURE(cxx_variable_templates, LangOpts
// 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.
+// Instead, they should be detected by has_builtin.
FEATURE(has_nothrow_assign, LangOpts.CPlusPlus)
FEATURE(has_nothrow_copy, LangOpts.CPlusPlus)
FEATURE(has_nothrow_constructor, LangOpts.CPlusPlus)
Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=368785&r1=368784&r2=368785&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Tue Aug 13 19:30:11 2019
@@ -449,16 +449,18 @@ TYPE_TRAIT_N(__is_nothrow_constructible,
// MSVC14.0 / VS2015 Type Traits
TYPE_TRAIT_2(__is_assignable, IsAssignable, KEYCXX)
+// MSVC Type Traits of unknown vintage
+TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX)
+TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYCXX)
+TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX)
+
// GNU and MS Type Traits
TYPE_TRAIT_1(__has_nothrow_assign, HasNothrowAssign, KEYCXX)
-TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX)
TYPE_TRAIT_1(__has_nothrow_copy, HasNothrowCopy, KEYCXX)
TYPE_TRAIT_1(__has_nothrow_constructor, HasNothrowConstructor, KEYCXX)
TYPE_TRAIT_1(__has_trivial_assign, HasTrivialAssign, KEYCXX)
-TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYCXX)
TYPE_TRAIT_1(__has_trivial_copy, HasTrivialCopy, KEYCXX)
TYPE_TRAIT_1(__has_trivial_constructor, HasTrivialDefaultConstructor, KEYCXX)
-TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX)
TYPE_TRAIT_1(__has_trivial_destructor, HasTrivialDestructor, KEYCXX)
TYPE_TRAIT_1(__has_virtual_destructor, HasVirtualDestructor, KEYCXX)
TYPE_TRAIT_1(__is_abstract, IsAbstract, KEYCXX)
@@ -475,17 +477,18 @@ TYPE_TRAIT_1(__is_literal, IsLiteral, KE
ALIAS("__is_literal_type", __is_literal, KEYCXX)
TYPE_TRAIT_1(__is_pod, IsPOD, KEYCXX)
TYPE_TRAIT_1(__is_polymorphic, IsPolymorphic, KEYCXX)
+TYPE_TRAIT_1(__is_standard_layout, IsStandardLayout, KEYCXX)
TYPE_TRAIT_1(__is_trivial, IsTrivial, KEYCXX)
+TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX)
+TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX)
+TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX)
TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
TYPE_TRAIT_1(__has_unique_object_representations,
HasUniqueObjectRepresentations, KEYCXX)
+KEYWORD(__underlying_type , KEYCXX)
// Clang-only C++ Type Traits
-TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX)
-TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX)
-TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX)
TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
-KEYWORD(__underlying_type , KEYCXX)
// Embarcadero Expression Traits
KEYWORD(__is_lvalue_expr , KEYCXX)
@@ -512,7 +515,6 @@ TYPE_TRAIT_1(__is_member_function_pointe
TYPE_TRAIT_1(__is_member_pointer, IsMemberPointer, KEYCXX)
TYPE_TRAIT_1(__is_const, IsConst, KEYCXX)
TYPE_TRAIT_1(__is_volatile, IsVolatile, KEYCXX)
-TYPE_TRAIT_1(__is_standard_layout, IsStandardLayout, KEYCXX)
TYPE_TRAIT_1(__is_signed, IsSigned, KEYCXX)
TYPE_TRAIT_1(__is_unsigned, IsUnsigned, KEYCXX)
Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=368785&r1=368784&r2=368785&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Tue Aug 13 19:30:11 2019
@@ -1617,21 +1617,38 @@ void Preprocessor::ExpandBuiltinMacro(To
return true;
}
return true;
+ } else if (II->getTokenID() != tok::identifier ||
+ II->hasRevertedTokenIDToIdentifier()) {
+ // Treat all keywords that introduce a custom syntax of the form
+ //
+ // '__some_keyword' '(' [...] ')'
+ //
+ // as being "builtin functions", even if the syntax isn't a valid
+ // function call (for example, because the builtin takes a type
+ // argument).
+ if (II->getName().startswith("__builtin_") ||
+ II->getName().startswith("__is_") ||
+ II->getName().startswith("__has_"))
+ return true;
+ return llvm::StringSwitch<bool>(II->getName())
+ .Case("__array_rank", true)
+ .Case("__array_extent", true)
+ .Case("__reference_binds_to_temporary", true)
+ .Case("__underlying_type", true)
+ .Default(false);
} else {
return llvm::StringSwitch<bool>(II->getName())
- .Case("__make_integer_seq", LangOpts.CPlusPlus)
- .Case("__type_pack_element", LangOpts.CPlusPlus)
- .Case("__builtin_available", true)
- .Case("__is_target_arch", true)
- .Case("__is_target_vendor", true)
- .Case("__is_target_os", true)
- .Case("__is_target_environment", true)
- .Case("__builtin_LINE", true)
- .Case("__builtin_FILE", true)
- .Case("__builtin_FUNCTION", true)
- .Case("__builtin_COLUMN", true)
- .Case("__builtin_bit_cast", true)
- .Default(false);
+ // Report builtin templates as being builtins.
+ .Case("__make_integer_seq", LangOpts.CPlusPlus)
+ .Case("__type_pack_element", LangOpts.CPlusPlus)
+ // Likewise for some builtin preprocessor macros.
+ // FIXME: This is inconsistent; we usually suggest detecting
+ // builtin macros via #ifdef. Don't add more cases here.
+ .Case("__is_target_arch", true)
+ .Case("__is_target_vendor", true)
+ .Case("__is_target_os", true)
+ .Case("__is_target_environment", true)
+ .Default(false);
}
});
} else if (II == Ident__is_identifier) {
Modified: cfe/trunk/test/Preprocessor/feature_tests.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/feature_tests.c?rev=368785&r1=368784&r2=368785&view=diff
==============================================================================
--- cfe/trunk/test/Preprocessor/feature_tests.c (original)
+++ cfe/trunk/test/Preprocessor/feature_tests.c Tue Aug 13 19:30:11 2019
@@ -25,10 +25,18 @@
#if !__has_builtin(__builtin_LINE) || \
!__has_builtin(__builtin_FILE) || \
!__has_builtin(__builtin_FUNCTION) || \
- !__has_builtin(__builtin_COLUMN)
+ !__has_builtin(__builtin_COLUMN) || \
+ !__has_builtin(__builtin_types_compatible_p)
#error Clang should have these
#endif
+// These are C++-only builtins.
+#if __has_builtin(__array_rank) || \
+ __has_builtin(__underlying_type) || \
+ __has_builtin(__is_trivial)
+#error Clang should not have these in C mode
+#endif
+
#if __has_builtin(__builtin_insanity)
#error Clang should not have this
#endif
Added: cfe/trunk/test/Preprocessor/feature_tests.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/feature_tests.cpp?rev=368785&view=auto
==============================================================================
--- cfe/trunk/test/Preprocessor/feature_tests.cpp (added)
+++ cfe/trunk/test/Preprocessor/feature_tests.cpp Tue Aug 13 19:30:11 2019
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -verify -DVERIFY
+// expected-no-diagnostics
+
+#ifndef __has_feature
+#error Should have __has_feature
+#endif
+
+#if __has_feature(something_we_dont_have)
+#error Bad
+#endif
+
+#if !__has_builtin(__builtin_huge_val) || \
+ !__has_builtin(__builtin_shufflevector) || \
+ !__has_builtin(__builtin_convertvector) || \
+ !__has_builtin(__builtin_trap) || \
+ !__has_builtin(__c11_atomic_init) || \
+ !__has_builtin(__builtin_launder) || \
+ !__has_feature(attribute_analyzer_noreturn) || \
+ !__has_feature(attribute_overloadable)
+#error Clang should have these
+#endif
+
+// These are technically implemented as keywords, but __has_builtin should
+// still return true.
+#if !__has_builtin(__builtin_LINE) || \
+ !__has_builtin(__builtin_FILE) || \
+ !__has_builtin(__builtin_FUNCTION) || \
+ !__has_builtin(__builtin_COLUMN) || \
+ !__has_builtin(__array_rank) || \
+ !__has_builtin(__underlying_type) || \
+ !__has_builtin(__is_trivial) || \
+ !__has_builtin(__has_unique_object_representations)
+#error Clang should have these
+#endif
+
+// This is a C-only builtin.
+#if __has_builtin(__builtin_types_compatible_p)
+#error Clang should not have this in C++ mode
+#endif
+
+#if __has_builtin(__builtin_insanity)
+#error Clang should not have this
+#endif
More information about the cfe-commits
mailing list