Author: Christopher Di Bella Date: 2022-10-11T00:13:58Z New Revision: bd3f48eefc11c2f1ef6eb034418697e24e9a965d
URL: https://github.com/llvm/llvm-project/commit/bd3f48eefc11c2f1ef6eb034418697e24e9a965d DIFF: https://github.com/llvm/llvm-project/commit/bd3f48eefc11c2f1ef6eb034418697e24e9a965d.diff LOG: [clang] adds `__is_bounded_array` and `__is_unbounded_array` as builtins This is information that the compiler already has, and should be exposed so that the library doesn't need to reimplement the exact same functionality. This was originally a part of D116280. Differential Revision: https://reviews.llvm.org/D135175 Added: Modified: clang/docs/LanguageExtensions.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Basic/TokenKinds.def clang/lib/Parse/ParseDeclCXX.cpp clang/lib/Parse/ParseExpr.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaType.cpp clang/test/SemaCXX/type-traits.cpp Removed: ################################################################################ diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index f680b1f1d2ad7..83f49d9bf13bd 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1392,6 +1392,7 @@ The following type trait primitives are supported by Clang. Those traits marked * ``__is_array`` (C++, Embarcadero) * ``__is_assignable`` (C++, MSVC 2015) * ``__is_base_of`` (C++, GNU, Microsoft, Embarcadero) +* ``__is_bounded_array`` (C++, GNU, Microsoft, Embarcadero) * ``__is_class`` (C++, GNU, Microsoft, Embarcadero) * ``__is_complete_type(type)`` (Embarcadero): Return ``true`` if ``type`` is a complete type. @@ -1454,6 +1455,7 @@ The following type trait primitives are supported by Clang. Those traits marked functionally equivalent to copying the underlying bytes and then dropping the source object on the floor. This is true of trivial types and types which were made trivially relocatable via the ``clang::trivial_abi`` attribute. +* ``__is_unbounded_array`` (C++, GNU, Microsoft, Embarcadero) * ``__is_union`` (C++, GNU, Microsoft, Embarcadero) * ``__is_unsigned`` (C++, Embarcadero): Returns false for enumeration types. Note, before Clang 13, returned true for @@ -4245,7 +4247,7 @@ The ``__declspec`` style syntax is also supported: #pragma clang attribute pop -A single push directive can contain multiple attributes, however, +A single push directive can contain multiple attributes, however, only one syntax style can be used within a single directive: .. code-block:: c++ @@ -4255,7 +4257,7 @@ only one syntax style can be used within a single directive: void function1(); // The function now has the [[noreturn]] and [[noinline]] attributes #pragma clang attribute pop - + #pragma clang attribute push (__attribute((noreturn, noinline)), apply_to = function) void function2(); // The function now has the __attribute((noreturn)) and __attribute((noinline)) attributes diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d6fbaed126d64..3e9fe53eea8ea 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -147,7 +147,7 @@ def ext_vla_folded_to_constant : ExtWarn< "variable length array folded to constant array as an extension">, InGroup<GNUFoldingConstant>; def err_vla_unsupported : Error< - "variable length arrays are not supported for the current target">; + "variable length arrays are not supported for %select{the current target|'%1'}0">; def note_vla_unsupported : Note< "variable length arrays are not supported for the current target">; diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 44a8c3181f142..747565e7fac4e 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -518,6 +518,8 @@ TYPE_TRAIT_1(__has_unique_object_representations, // Clang-only C++ Type Traits TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX) +TYPE_TRAIT_1(__is_bounded_array, IsBoundedArray, KEYCXX) +TYPE_TRAIT_1(__is_unbounded_array, IsUnboundedArray, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) // Embarcadero Expression Traits diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 639320c6bb474..4eeba4787b57d 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1579,6 +1579,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, tok::kw___is_array, tok::kw___is_assignable, tok::kw___is_base_of, + tok::kw___is_bounded_array, tok::kw___is_class, tok::kw___is_complete_type, tok::kw___is_compound, @@ -1620,6 +1621,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, tok::kw___is_trivially_assignable, tok::kw___is_trivially_constructible, tok::kw___is_trivially_copyable, + tok::kw___is_unbounded_array, tok::kw___is_union, tok::kw___is_unsigned, tok::kw___is_void, diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 89d3b3e88ef52..956361123f998 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1067,6 +1067,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, REVERTIBLE_TYPE_TRAIT(__is_arithmetic); REVERTIBLE_TYPE_TRAIT(__is_array); REVERTIBLE_TYPE_TRAIT(__is_assignable); + REVERTIBLE_TYPE_TRAIT(__is_bounded_array); REVERTIBLE_TYPE_TRAIT(__is_base_of); REVERTIBLE_TYPE_TRAIT(__is_class); REVERTIBLE_TYPE_TRAIT(__is_complete_type); @@ -1109,6 +1110,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, REVERTIBLE_TYPE_TRAIT(__is_trivially_assignable); REVERTIBLE_TYPE_TRAIT(__is_trivially_constructible); REVERTIBLE_TYPE_TRAIT(__is_trivially_copyable); + REVERTIBLE_TYPE_TRAIT(__is_unbounded_array); REVERTIBLE_TYPE_TRAIT(__is_union); REVERTIBLE_TYPE_TRAIT(__is_unsigned); REVERTIBLE_TYPE_TRAIT(__is_void); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 1f827a3ec49ef..b477ae02ecc74 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -21,11 +21,13 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/AlignedAllocation.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Basic/TypeTraits.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" @@ -4756,6 +4758,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_IsIntegral: case UTT_IsFloatingPoint: case UTT_IsArray: + case UTT_IsBoundedArray: case UTT_IsPointer: case UTT_IsLvalueReference: case UTT_IsRvalueReference: @@ -4782,6 +4785,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_IsConst: case UTT_IsVolatile: case UTT_IsSigned: + case UTT_IsUnboundedArray: case UTT_IsUnsigned: // This type trait always returns false, checking the type is moot. @@ -4901,6 +4905,22 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return T->isFloatingType(); case UTT_IsArray: return T->isArrayType(); + case UTT_IsBoundedArray: + if (!T->isVariableArrayType()) { + return T->isArrayType() && !T->isIncompleteArrayType(); + } + + Self.Diag(KeyLoc, diag::err_vla_unsupported) + << 1 << tok::kw___is_bounded_array; + return false; + case UTT_IsUnboundedArray: + if (!T->isVariableArrayType()) { + return T->isIncompleteArrayType(); + } + + Self.Diag(KeyLoc, diag::err_vla_unsupported) + << 1 << tok::kw___is_unbounded_array; + return false; case UTT_IsPointer: return T->isAnyPointerType(); case UTT_IsLvalueReference: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 006d4c3049fca..f49deaf80fbce 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2627,12 +2627,10 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, if (T->isVariableArrayType() && !Context.getTargetInfo().isVLASupported()) { // CUDA device code and some other targets don't support VLAs. - targetDiag(Loc, (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) - ? diag::err_cuda_vla - : diag::err_vla_unsupported) - << ((getLangOpts().CUDA && getLangOpts().CUDAIsDevice) - ? CurrentCUDATarget() - : CFT_InvalidTarget); + bool IsCUDADevice = (getLangOpts().CUDA && getLangOpts().CUDAIsDevice); + targetDiag(Loc, + IsCUDADevice ? diag::err_cuda_vla : diag::err_vla_unsupported) + << (IsCUDADevice ? CurrentCUDATarget() : 0); } // If this is not C99, diagnose array size modifiers on non-VLAs. diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index ab2a9f74090a4..e1f8a0c9373da 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -702,6 +702,70 @@ void is_array() int t31[F(__is_array(cvoid*))]; } +void is_bounded_array(int n) { + static_assert(__is_bounded_array(IntAr), ""); + static_assert(!__is_bounded_array(IntArNB), ""); + static_assert(__is_bounded_array(UnionAr), ""); + + static_assert(!__is_bounded_array(void), ""); + static_assert(!__is_bounded_array(cvoid), ""); + static_assert(!__is_bounded_array(float), ""); + static_assert(!__is_bounded_array(double), ""); + static_assert(!__is_bounded_array(long double), ""); + static_assert(!__is_bounded_array(bool), ""); + static_assert(!__is_bounded_array(char), ""); + static_assert(!__is_bounded_array(signed char), ""); + static_assert(!__is_bounded_array(unsigned char), ""); + static_assert(!__is_bounded_array(wchar_t), ""); + static_assert(!__is_bounded_array(short), ""); + static_assert(!__is_bounded_array(unsigned short), ""); + static_assert(!__is_bounded_array(int), ""); + static_assert(!__is_bounded_array(unsigned int), ""); + static_assert(!__is_bounded_array(long), ""); + static_assert(!__is_bounded_array(unsigned long), ""); + static_assert(!__is_bounded_array(Union), ""); + static_assert(!__is_bounded_array(Derives), ""); + static_assert(!__is_bounded_array(ClassType), ""); + static_assert(!__is_bounded_array(Enum), ""); + static_assert(!__is_bounded_array(void *), ""); + static_assert(!__is_bounded_array(cvoid *), ""); + + int t32[n]; + (void)__is_bounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_bounded_array'}} +} + +void is_unbounded_array(int n) { + static_assert(!__is_unbounded_array(IntAr), ""); + static_assert(__is_unbounded_array(IntArNB), ""); + static_assert(!__is_unbounded_array(UnionAr), ""); + + static_assert(!__is_unbounded_array(void), ""); + static_assert(!__is_unbounded_array(cvoid), ""); + static_assert(!__is_unbounded_array(float), ""); + static_assert(!__is_unbounded_array(double), ""); + static_assert(!__is_unbounded_array(long double), ""); + static_assert(!__is_unbounded_array(bool), ""); + static_assert(!__is_unbounded_array(char), ""); + static_assert(!__is_unbounded_array(signed char), ""); + static_assert(!__is_unbounded_array(unsigned char), ""); + static_assert(!__is_unbounded_array(wchar_t), ""); + static_assert(!__is_unbounded_array(short), ""); + static_assert(!__is_unbounded_array(unsigned short), ""); + static_assert(!__is_unbounded_array(int), ""); + static_assert(!__is_unbounded_array(unsigned int), ""); + static_assert(!__is_unbounded_array(long), ""); + static_assert(!__is_unbounded_array(unsigned long), ""); + static_assert(!__is_unbounded_array(Union), ""); + static_assert(!__is_unbounded_array(Derives), ""); + static_assert(!__is_unbounded_array(ClassType), ""); + static_assert(!__is_unbounded_array(Enum), ""); + static_assert(!__is_unbounded_array(void *), ""); + static_assert(!__is_unbounded_array(cvoid *), ""); + + int t32[n]; + (void)__is_unbounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_unbounded_array'}} +} + template <typename T> void tmpl_func(T&) {} template <typename T> struct type_wrapper { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits