From 018a088b3b30e500efa9173f7cd4b1b1f6a065a8 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sat, 30 Apr 2011 10:31:50 +0000 Subject: [PATCH] Switch the type-trait like APIs on the AST to only check for incomplete types after looking through arrays. Arrays with an unknown bound seem to be specifically allowed in the library type traits in C++0x, and GCC's builtin __is_trivial returns 'true' for the type 'int[]'. Now Clang agrees with GCC about __is_trivial here. Also hardens these methods against dependent types by just returning false. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130605 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/Type.cpp | 33 ++++++++++++++++++++++++++++----- test/SemaCXX/type-traits.cpp | 4 ++-- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index d359265090..ae52ff06fa 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -869,7 +869,7 @@ bool Type::isPODType() const { } bool Type::isLiteralType() const { - if (isIncompleteType()) + if (isDependentType()) return false; // C++0x [basic.types]p10: @@ -878,11 +878,16 @@ bool Type::isLiteralType() const { // -- an array of literal type // Extension: variable arrays cannot be literal types, since they're // runtime-sized. - if (isArrayType() && !isConstantArrayType()) + if (isVariableArrayType()) return false; const Type *BaseTy = getBaseElementTypeUnsafe(); assert(BaseTy && "NULL element type"); + // Return false for incomplete types after skipping any incomplete array + // types; those are expressly allowed by the standard and thus our API. + if (BaseTy->isIncompleteType()) + return false; + // C++0x [basic.types]p10: // A type is a literal type if it is: // -- a scalar type; or @@ -916,7 +921,7 @@ bool Type::isLiteralType() const { } bool Type::isTrivialType() const { - if (isIncompleteType()) + if (isDependentType()) return false; // C++0x [basic.types]p9: @@ -925,6 +930,12 @@ bool Type::isTrivialType() const { // types. const Type *BaseTy = getBaseElementTypeUnsafe(); assert(BaseTy && "NULL element type"); + + // Return false for incomplete types after skipping any incomplete array + // types which are expressly allowed by the standard and thus our API. + if (BaseTy->isIncompleteType()) + return false; + if (BaseTy->isScalarType()) return true; if (const RecordType *RT = BaseTy->getAs()) { if (const CXXRecordDecl *ClassDecl = @@ -944,7 +955,7 @@ bool Type::isTrivialType() const { } bool Type::isStandardLayoutType() const { - if (isIncompleteType()) + if (isDependentType()) return false; // C++0x [basic.types]p9: @@ -953,6 +964,12 @@ bool Type::isStandardLayoutType() const { // standard-layout types. const Type *BaseTy = getBaseElementTypeUnsafe(); assert(BaseTy && "NULL element type"); + + // Return false for incomplete types after skipping any incomplete array + // types which are expressly allowed by the standard and thus our API. + if (BaseTy->isIncompleteType()) + return false; + if (BaseTy->isScalarType()) return true; if (const RecordType *RT = BaseTy->getAs()) { if (const CXXRecordDecl *ClassDecl = @@ -974,7 +991,7 @@ bool Type::isStandardLayoutType() const { // isStandardLayoutType. We implement it dircetly to avoid redundant // conversions from a type to a CXXRecordDecl. bool Type::isCXX11PODType() const { - if (isIncompleteType()) + if (isDependentType()) return false; // C++11 [basic.types]p9: @@ -982,6 +999,12 @@ bool Type::isCXX11PODType() const { // versions of these types are collectively called trivial types. const Type *BaseTy = getBaseElementTypeUnsafe(); assert(BaseTy && "NULL element type"); + + // Return false for incomplete types after skipping any incomplete array + // types which are expressly allowed by the standard and thus our API. + if (BaseTy->isIncompleteType()) + return false; + if (BaseTy->isScalarType()) return true; if (const RecordType *RT = BaseTy->getAs()) { if (const CXXRecordDecl *ClassDecl = diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 1dec7f923a..c45adecf66 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -1429,12 +1429,14 @@ void is_trivial() { int arr[T(__is_trivial(POD))]; } { int arr[T(__is_trivial(Int))]; } { int arr[T(__is_trivial(IntAr))]; } + { int arr[T(__is_trivial(IntArNB))]; } { int arr[T(__is_trivial(Statics))]; } { int arr[T(__is_trivial(Empty))]; } { int arr[T(__is_trivial(EmptyUnion))]; } { int arr[T(__is_trivial(Union))]; } { int arr[T(__is_trivial(Derives))]; } { int arr[T(__is_trivial(DerivesAr))]; } + { int arr[T(__is_trivial(DerivesArNB))]; } { int arr[T(__is_trivial(DerivesEmpty))]; } { int arr[T(__is_trivial(HasFunc))]; } { int arr[T(__is_trivial(HasOp))]; } @@ -1459,8 +1461,6 @@ void is_trivial() { int arr[F(__is_trivial(DerivesHasDest))]; } { int arr[F(__is_trivial(DerivesHasRef))]; } { int arr[F(__is_trivial(DerivesHasVirt))]; } - { int arr[F(__is_trivial(IntArNB))]; } - { int arr[F(__is_trivial(DerivesArNB))]; } { int arr[F(__is_trivial(void))]; } { int arr[F(__is_trivial(cvoid))]; } } -- 2.50.1