From 607a1788d9529c8e8494ac528764aa2c678a1a97 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Wed, 8 Sep 2010 00:48:43 +0000 Subject: [PATCH] Allow (cv) void and incomplete arrays to be passed to the type traits. 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 | 8 ++++-- lib/Sema/SemaExprCXX.cpp | 8 ++++-- test/SemaCXX/type-traits-incomplete.cpp | 3 +- test/SemaCXX/type-traits.cpp | 38 +++++++++++++++++++++++-- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index ca10532e72..8e6aa23618 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -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(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(CanonicalType)->getElementType()->isPODType(); case Builtin: diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index de9b599907..7857ea9693 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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(); } diff --git a/test/SemaCXX/type-traits-incomplete.cpp b/test/SemaCXX/type-traits-incomplete.cpp index f959821579..c0a520e167 100644 --- a/test/SemaCXX/type-traits-incomplete.cpp +++ b/test/SemaCXX/type-traits-incomplete.cpp @@ -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}} } diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index b05dd07ec2..99ac5cd433 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -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 struct B : A { }; void f() { - int t01[T(!__has_trivial_destructor(A))]; - int t02[T(!__has_trivial_destructor(B))]; + int t01[F(__has_trivial_destructor(A))]; + int t02[F(__has_trivial_destructor(B))]; } 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))]; } -- 2.40.0