]> granicus.if.org Git - clang/commitdiff
Allow (cv) void and incomplete arrays to be passed to the type traits.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Wed, 8 Sep 2010 00:48:43 +0000 (00:48 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Wed, 8 Sep 2010 00:48:43 +0000 (00:48 +0000)
Fixes PR8110, and thus PR8109, PR8097, and parts of PR8101, PR8105 and PR8107. Only a few traits have tests for incomplete arrays, since I'm not yet clear what the result for them should be; Howards wants to file a DR to change the standard.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113326 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Type.cpp
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/type-traits-incomplete.cpp
test/SemaCXX/type-traits.cpp

index ca10532e729e1729e58379da3fd765a709f94bab..8e6aa23618c5ee9fbdaf9da553096ac72984d3c6 100644 (file)
@@ -678,7 +678,11 @@ bool Type::isIncompleteType() const {
 /// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10)
 bool Type::isPODType() const {
   // The compiler shouldn't query this for incomplete types, but the user might.
-  // We return false for that case.
+  // We return false for that case. Except for incomplete arrays of PODs, which
+  // are PODs according to the standard.
+  if (isIncompleteArrayType() &&
+      cast<ArrayType>(CanonicalType)->getElementType()->isPODType())
+    return true;
   if (isIncompleteType())
     return false;
 
@@ -687,7 +691,7 @@ bool Type::isPODType() const {
   default: return false;
   case VariableArray:
   case ConstantArray:
-    // IncompleteArray is caught by isIncompleteType() above.
+    // IncompleteArray is handled above.
     return cast<ArrayType>(CanonicalType)->getElementType()->isPODType();
 
   case Builtin:
index de9b59990726c5aaf5003d5acac07293107bb753..7857ea969357c33622811fcd06e2eb0f2cc12196 100644 (file)
@@ -1956,9 +1956,13 @@ ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
 
   // According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
   // all traits except __is_class, __is_enum and __is_union require a the type
-  // to be complete.
+  // to be complete, an array of unknown bound, or void.
   if (OTT != UTT_IsClass && OTT != UTT_IsEnum && OTT != UTT_IsUnion) {
-    if (RequireCompleteType(KWLoc, T,
+    QualType E = T;
+    if (T->isIncompleteArrayType())
+      E = Context.getAsArrayType(T)->getElementType();
+    if (!T->isVoidType() &&
+        RequireCompleteType(KWLoc, E,
                             diag::err_incomplete_type_used_in_type_trait_expr))
       return ExprError();
   }
index f95982157900f848308faa5367dd43cd3145dc3c..c0a520e167698afabe14f3782eaed93c835817eb 100644 (file)
@@ -1,7 +1,8 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s 
 
-struct S; // expected-note{{forward declaration of 'S'}}
+struct S; // expected-note 2 {{forward declaration of 'S'}}
 
 void f() {
   __is_pod(S); // expected-error{{incomplete type 'S' used in type trait expression}}
+  __is_pod(S[]); // expected-error{{incomplete type 'S' used in type trait expression}}
 }
index b05dd07ec2ec4431d8c549096c556b17460d9612..99ac5cd433c71ebdef4a1972e6f58b903f4f9695 100644 (file)
@@ -11,6 +11,7 @@ struct Empty {};
 typedef Empty EmptyAr[10];
 typedef int Int;
 typedef Int IntAr[10];
+typedef Int IntArNB[];
 class Statics { static int priv; static NonPOD np; };
 union EmptyUnion {};
 union Union { int i; float f; };
@@ -20,6 +21,7 @@ struct HasConv { operator int(); };
 struct HasAssign { void operator =(int); };
 
 // Not PODs
+typedef const void cvoid;
 struct Derives : POD {};
 struct DerivesEmpty : Empty {};
 struct HasCons { HasCons(int); };
@@ -32,6 +34,7 @@ struct HasNonPOD { NonPOD np; };
 struct HasVirt { virtual void Virt() {}; };
 typedef Derives NonPODAr[10];
 typedef HasVirt VirtAr[10];
+typedef HasCons NonPODArNB[];
 union NonPODUnion { int i; Derives n; };
 
 struct HasNoThrowCopyAssign {
@@ -80,6 +83,7 @@ void is_pod()
   int t11[T(__is_pod(HasOp))];
   int t12[T(__is_pod(HasConv))];
   int t13[T(__is_pod(HasAssign))];
+  int t14[T(__is_pod(IntArNB))];
 
   int t21[F(__is_pod(Derives))];
   int t22[F(__is_pod(HasCons))];
@@ -92,6 +96,9 @@ void is_pod()
   int t29[F(__is_pod(HasVirt))];
   int t30[F(__is_pod(NonPODAr))];
   int t31[F(__is_pod(DerivesEmpty))];
+  int t32[F(__is_pod(void))];
+  int t33[F(__is_pod(cvoid))];
+  int t34[F(__is_pod(NonPODArNB))];
  // int t32[F(__is_pod(NonPODUnion))];
 }
 
@@ -122,6 +129,8 @@ void is_empty()
   int t25[F(__is_empty(HasRef))];
   int t26[F(__is_empty(HasVirt))];
   int t27[F(__is_empty(BitOnly))];
+  int t28[F(__is_empty(void))];
+  int t29[F(__is_empty(IntArNB))];
 //  int t27[F(__is_empty(DerivesVirt))];
 }
 
@@ -139,6 +148,8 @@ void is_class()
   int t14[F(__is_class(IntAr))];
   int t15[F(__is_class(NonPODAr))];
   int t16[F(__is_class(Union))];
+  int t17[F(__is_class(cvoid))];
+  int t18[F(__is_class(IntArNB))];
 }
 
 typedef Union UnionAr[10];
@@ -154,6 +165,8 @@ void is_union()
   int t13[F(__is_union(Int))];
   int t14[F(__is_union(IntAr))];
   int t15[F(__is_union(UnionAr))];
+  int t16[F(__is_union(cvoid))];
+  int t17[F(__is_union(IntArNB))];
 }
 
 typedef Enum EnumType;
@@ -170,6 +183,8 @@ void is_enum()
   int t15[F(__is_enum(UnionAr))];
   int t16[F(__is_enum(Derives))];
   int t17[F(__is_enum(ClassType))];
+  int t18[F(__is_enum(cvoid))];
+  int t19[F(__is_enum(IntArNB))];
 }
 
 typedef HasVirt Polymorph;
@@ -188,6 +203,8 @@ void is_polymorphic()
   int t16[F(__is_polymorphic(Derives))];
   int t17[F(__is_polymorphic(ClassType))];
   int t18[F(__is_polymorphic(Enum))];
+  int t19[F(__is_polymorphic(cvoid))];
+  int t20[F(__is_polymorphic(IntArNB))];
 }
 
 typedef Int& IntRef;
@@ -217,6 +234,8 @@ void has_trivial_default_constructor() {
   int t16[T(__has_trivial_constructor(const Int))];
   int t17[T(__has_trivial_constructor(NonPODAr))];
   int t18[F(__has_trivial_constructor(VirtAr))];
+  int t19[F(__has_trivial_constructor(void))];
+  int t20[F(__has_trivial_constructor(cvoid))];
 }
 
 void has_trivial_copy_constructor() {
@@ -238,6 +257,8 @@ void has_trivial_copy_constructor() {
   int t16[T(__has_trivial_copy(const Int))];
   int t17[F(__has_trivial_copy(NonPODAr))];
   int t18[F(__has_trivial_copy(VirtAr))];
+  int t19[F(__has_trivial_copy(void))];
+  int t20[F(__has_trivial_copy(cvoid))];
 }
 
 void has_trivial_copy_assignment() {
@@ -259,6 +280,8 @@ void has_trivial_copy_assignment() {
   int t16[F(__has_trivial_assign(const Int))];
   int t17[F(__has_trivial_assign(NonPODAr))];
   int t18[F(__has_trivial_assign(VirtAr))];
+  int t19[F(__has_trivial_assign(void))];
+  int t20[F(__has_trivial_assign(cvoid))];
 }
 
 void has_trivial_destructor() {
@@ -280,14 +303,16 @@ void has_trivial_destructor() {
   int t16[T(__has_trivial_destructor(const Int))];
   int t17[T(__has_trivial_destructor(NonPODAr))];
   int t18[T(__has_trivial_destructor(VirtAr))];
+  int t19[F(__has_trivial_destructor(void))];
+  int t20[F(__has_trivial_destructor(cvoid))];
 }
 
 struct A { ~A() {} };
 template<typename> struct B : A { };
 
 void f() {
-  int t01[T(!__has_trivial_destructor(A))];
-  int t02[T(!__has_trivial_destructor(B<int>))];
+  int t01[F(__has_trivial_destructor(A))];
+  int t02[F(__has_trivial_destructor(B<int>))];
 }
 
 void has_nothrow_assign() {
@@ -309,10 +334,11 @@ void has_nothrow_assign() {
   int t16[F(__has_nothrow_assign(const Int))];
   int t17[F(__has_nothrow_assign(NonPODAr))];
   int t18[F(__has_nothrow_assign(VirtAr))];
-
   int t19[T(__has_nothrow_assign(HasNoThrowCopyAssign))];
   int t20[F(__has_nothrow_assign(HasMultipleCopyAssign))];
   int t21[T(__has_nothrow_assign(HasMultipleNoThrowCopyAssign))];
+  int t22[F(__has_nothrow_assign(void))];
+  int t23[F(__has_nothrow_assign(cvoid))];
 }
 
 void has_nothrow_copy() {
@@ -338,6 +364,8 @@ void has_nothrow_copy() {
   int t19[T(__has_nothrow_copy(HasNoThrowCopy))];
   int t20[F(__has_nothrow_copy(HasMultipleCopy))];
   int t21[T(__has_nothrow_copy(HasMultipleNoThrowCopy))];
+  int t22[F(__has_nothrow_copy(void))];
+  int t23[F(__has_nothrow_copy(cvoid))];
 }
 
 void has_nothrow_constructor() {
@@ -362,6 +390,8 @@ void has_nothrow_constructor() {
 
   int t19[T(__has_nothrow_constructor(HasNoThrowConstructor))];
   int t20[F(__has_nothrow_constructor(HasNoThrowConstructorWithArgs))];
+  int t21[F(__has_nothrow_constructor(void))];
+  int t22[F(__has_nothrow_constructor(cvoid))];
 }
 
 void has_virtual_destructor() {
@@ -387,4 +417,6 @@ void has_virtual_destructor() {
   int t19[T(__has_virtual_destructor(HasVirtDest))];
   int t20[T(__has_virtual_destructor(DerivedVirtDest))];
   int t21[F(__has_virtual_destructor(VirtDestAr))];
+  int t22[F(__has_virtual_destructor(void))];
+  int t23[F(__has_virtual_destructor(cvoid))];
 }