Skip to content

Clang reports that __is_array(T[0]) is true #54705

@ldionne

Description

@ldionne

Clang currently reports that __is_array(T[0]) is true, which leads to std::is_array<T[0]> being true as well.

Since it's ill-formed, I guess Clang is technically conforming, however it still leads to code like this surprisingly compiling with Clang:

static_assert(!std::is_bounded_array_v<T[0]>);
static_assert(!std::is_unbounded_array_v<T[0]>);
static_assert(std::is_array_v<T[0]>);

So it looks like T[0] is neither a bounded array nor an unbounded array, but it is an array, which is quite confusing. I would suggest Clang either:

  1. Errors out when we try to form T[0] since it's ill-formed, or
  2. At least not report that T[0] is an array from its __is_array builtin (patch provided for this)

Also note that Clang will not match a partial specialization like template <class T, size_t N> struct foo<T[N]> { ... }; when instantiating it with T[0], which seems to support the fact that we really don't want to treat T[0] as an array type.

Here's a potential patch that changes __is_array(T[0]) to false, but I suspect we may want a deeper fix in the compiler.

diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index f360dc6e1a23..c7178e097213 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4870,6 +4870,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
   case UTT_IsFloatingPoint:
     return T->isFloatingType();
   case UTT_IsArray:
+    // We don't want to report T[0] as being an array type.
+    if (ConstantArrayType const* CAT = C.getAsConstantArrayType(T))
+      return CAT->getSize() != 0;
     return T->isArrayType();
   case UTT_IsPointer:
     return T->isAnyPointerType();
diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp
index d576e4388d6f..ce45d1857179 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -23,6 +23,7 @@ typedef Empty EmptyArMB[1][2];
 typedef int Int;
 typedef Int IntAr[10];
 typedef Int IntArNB[];
+typedef Int IntArZero[0];
 class Statics { static int priv; static NonPOD np; };
 union EmptyUnion {};
 union IncompleteUnion; // expected-note {{forward declaration of 'IncompleteUnion'}}
@@ -673,7 +674,8 @@ void is_array()
 {
   int t01[T(__is_array(IntAr))];
   int t02[T(__is_array(IntArNB))];
-  int t03[T(__is_array(UnionAr))];
+  int t03[F(__is_array(IntArZero))];
+  int t04[T(__is_array(UnionAr))];
 
   int t10[F(__is_array(void))];
   int t11[F(__is_array(cvoid))];

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions