[clang] bd3f48e - [clang] adds `__is_bounded_array` and `__is_unbounded_array` as builtins

Christopher Di Bella via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 10 17:39:11 PDT 2022


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 {


        


More information about the cfe-commits mailing list