diff options
-rw-r--r-- | include/clang/AST/Type.h | 4 | ||||
-rw-r--r-- | include/clang/Basic/TokenKinds.def | 3 | ||||
-rw-r--r-- | include/clang/Basic/TypeTraits.h | 1 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 1 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 31 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 3 | ||||
-rw-r--r-- | test/Lexer/has_feature_type_traits.cpp | 5 | ||||
-rw-r--r-- | test/SemaCXX/type-traits.cpp | 87 |
12 files changed, 142 insertions, 0 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 9fc776d051..b883002f9f 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1189,6 +1189,10 @@ public: /// (C++0x [basic.types]p9) bool isTrivialType() const; + /// isTriviallyCopyableType - Return true if this is a trivially copyable type + /// (C++0x [basic.types]p9 + bool isTriviallyCopyableType() const; + /// \brief Test if this type is a standard-layout type. /// (C++0x [basic.type]p9) bool isStandardLayoutType() const; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 131bfe3afe..239c5b83e1 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -346,6 +346,9 @@ KEYWORD(__is_polymorphic , KEYCXX) KEYWORD(__is_trivial , KEYCXX) KEYWORD(__is_union , KEYCXX) +// Clang-only C++ Type Traits +KEYWORD(__is_trivially_copyable , KEYCXX) + // Embarcadero Expression Traits KEYWORD(__is_lvalue_expr , KEYCXX) KEYWORD(__is_rvalue_expr , KEYCXX) diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index b9b94a6f75..a7a45bded8 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -54,6 +54,7 @@ namespace clang { UTT_IsSigned, UTT_IsStandardLayout, UTT_IsTrivial, + UTT_IsTriviallyCopyable, UTT_IsUnion, UTT_IsUnsigned, UTT_IsVoid, diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 094864b1eb..1ef601c09b 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1329,6 +1329,7 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) { case UTT_IsSigned: return "__is_signed"; case UTT_IsStandardLayout: return "__is_standard_layout"; case UTT_IsTrivial: return "__is_trivial"; + case UTT_IsTriviallyCopyable: return "__is_trivially_copyable"; case UTT_IsUnion: return "__is_union"; case UTT_IsUnsigned: return "__is_unsigned"; case UTT_IsVoid: return "__is_void"; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 638c4dcf28..1e78393341 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -964,6 +964,37 @@ bool Type::isTrivialType() const { return false; } +bool Type::isTriviallyCopyableType() const { + if (isDependentType()) + return false; + + // C++0x [basic.types]p9 + // Scalar types, trivially copyable class types, arrays of such types, and + // cv-qualified 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; + + // As an extension, Clang treats vector types as Scalar types. + if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; + if (const RecordType *RT = BaseTy->getAs<RecordType>()) { + if (const CXXRecordDecl *ClassDecl = + dyn_cast<CXXRecordDecl>(RT->getDecl())) { + if (!ClassDecl->isTriviallyCopyable()) return false; + } + + return true; + } + + // No other types can match. + return false; +} + bool Type::isStandardLayoutType() const { if (isDependentType()) return false; diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index ce7acf7806..bc3c9b5a59 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -597,6 +597,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("is_pod", LangOpts.CPlusPlus) .Case("is_polymorphic", LangOpts.CPlusPlus) .Case("is_trivial", LangOpts.CPlusPlus) + .Case("is_trivially_copyable", LangOpts.CPlusPlus) .Case("is_union", LangOpts.CPlusPlus) .Case("tls", PP.getTargetInfo().isTLSSupported()) .Default(false); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 91fe1e1935..25d505c2c5 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -566,6 +566,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// '__is_trivial' /// '__is_union' /// +/// [Clang] unary-type-trait: +/// '__trivially_copyable' +/// /// binary-type-trait: /// [GNU] '__is_base_of' /// [MS] '__is_convertible_to' @@ -1060,6 +1063,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___is_pod: case tok::kw___is_polymorphic: case tok::kw___is_trivial: + case tok::kw___is_trivially_copyable: case tok::kw___is_union: case tok::kw___has_trivial_constructor: case tok::kw___has_trivial_copy: diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index c8f95ff4f6..7410dbecf1 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1958,6 +1958,7 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { case tok::kw___is_signed: return UTT_IsSigned; case tok::kw___is_standard_layout: return UTT_IsStandardLayout; case tok::kw___is_trivial: return UTT_IsTrivial; + case tok::kw___is_trivially_copyable: return UTT_IsTriviallyCopyable; case tok::kw___is_union: return UTT_IsUnion; case tok::kw___is_unsigned: return UTT_IsUnsigned; case tok::kw___is_void: return UTT_IsVoid; diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 1c4e2b3ddc..12152c36cc 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -664,6 +664,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___is_pod: case tok::kw___is_polymorphic: case tok::kw___is_trivial: + case tok::kw___is_trivially_copyable: case tok::kw___is_union: case tok::kw___uuidof: return TPResult::True(); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index a843ba4284..f0faa8c29c 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2436,6 +2436,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, // C++0x [meta.unary.prop] Table 49 requires the following traits to be // applied to a complete type. case UTT_IsTrivial: + case UTT_IsTriviallyCopyable: case UTT_IsStandardLayout: case UTT_IsPOD: case UTT_IsLiteral: @@ -2532,6 +2533,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, return T.isVolatileQualified(); case UTT_IsTrivial: return T->isTrivialType(); + case UTT_IsTriviallyCopyable: + return T->isTriviallyCopyableType(); case UTT_IsStandardLayout: return T->isStandardLayoutType(); case UTT_IsPOD: diff --git a/test/Lexer/has_feature_type_traits.cpp b/test/Lexer/has_feature_type_traits.cpp index c887563c2d..5da845f065 100644 --- a/test/Lexer/has_feature_type_traits.cpp +++ b/test/Lexer/has_feature_type_traits.cpp @@ -94,3 +94,8 @@ int is_literal(); int is_standard_layout(); #endif // CHECK: int is_standard_layout(); + +#if __has_feature(is_trivially_copyable) +int is_trivially_copyable(); +#endif +// CHECK: int is_trivially_copyable(); diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 96e9696a04..c3470d4c16 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -870,6 +870,15 @@ struct NonTrivialStruct { } }; +struct SuperNonTrivialStruct { + SuperNonTrivialStruct() { } + ~SuperNonTrivialStruct() { } +}; + +struct NonTCStruct { + NonTCStruct(const NonTCStruct&) {} +}; + void is_trivial2() { int t01[T(__is_trivial(char))]; @@ -897,6 +906,39 @@ void is_trivial2() int t30[F(__is_trivial(void))]; int t31[F(__is_trivial(NonTrivialStruct))]; + int t32[F(__is_trivial(SuperNonTrivialStruct))]; + int t33[F(__is_trivial(NonTCStruct))]; +} + +void is_trivially_copyable2() +{ + int t01[T(__is_trivially_copyable(char))]; + int t02[T(__is_trivially_copyable(int))]; + int t03[T(__is_trivially_copyable(long))]; + int t04[T(__is_trivially_copyable(short))]; + int t05[T(__is_trivially_copyable(signed char))]; + int t06[T(__is_trivially_copyable(wchar_t))]; + int t07[T(__is_trivially_copyable(bool))]; + int t08[T(__is_trivially_copyable(float))]; + int t09[T(__is_trivially_copyable(double))]; + int t10[T(__is_trivially_copyable(long double))]; + int t11[T(__is_trivially_copyable(unsigned char))]; + int t12[T(__is_trivially_copyable(unsigned int))]; + int t13[T(__is_trivially_copyable(unsigned long long))]; + int t14[T(__is_trivially_copyable(unsigned long))]; + int t15[T(__is_trivially_copyable(unsigned short))]; + int t16[T(__is_trivially_copyable(ClassType))]; + int t17[T(__is_trivially_copyable(Derives))]; + int t18[T(__is_trivially_copyable(Enum))]; + int t19[T(__is_trivially_copyable(IntAr))]; + int t20[T(__is_trivially_copyable(Union))]; + int t21[T(__is_trivially_copyable(UnionAr))]; + int t22[T(__is_trivially_copyable(TrivialStruct))]; + int t23[T(__is_trivially_copyable(NonTrivialStruct))]; + + int t30[F(__is_trivially_copyable(void))]; + int t32[F(__is_trivially_copyable(SuperNonTrivialStruct))]; + int t31[F(__is_trivially_copyable(NonTCStruct))]; } struct CStruct { @@ -1474,6 +1516,51 @@ void is_trivial() { int arr[F(__is_trivial(cvoid))]; } } +void is_trivially_copyable() +{ + { int arr[T(__is_trivially_copyable(int))]; } + { int arr[T(__is_trivially_copyable(Enum))]; } + { int arr[T(__is_trivially_copyable(POD))]; } + { int arr[T(__is_trivially_copyable(Int))]; } + { int arr[T(__is_trivially_copyable(IntAr))]; } + { int arr[T(__is_trivially_copyable(IntArNB))]; } + { int arr[T(__is_trivially_copyable(Statics))]; } + { int arr[T(__is_trivially_copyable(Empty))]; } + { int arr[T(__is_trivially_copyable(EmptyUnion))]; } + { int arr[T(__is_trivially_copyable(Union))]; } + { int arr[T(__is_trivially_copyable(Derives))]; } + { int arr[T(__is_trivially_copyable(DerivesAr))]; } + { int arr[T(__is_trivially_copyable(DerivesArNB))]; } + { int arr[T(__is_trivially_copyable(DerivesEmpty))]; } + { int arr[T(__is_trivially_copyable(HasFunc))]; } + { int arr[T(__is_trivially_copyable(HasOp))]; } + { int arr[T(__is_trivially_copyable(HasConv))]; } + { int arr[T(__is_trivially_copyable(HasAssign))]; } + { int arr[T(__is_trivially_copyable(HasAnonymousUnion))]; } + { int arr[T(__is_trivially_copyable(HasPriv))]; } + { int arr[T(__is_trivially_copyable(HasProt))]; } + { int arr[T(__is_trivially_copyable(DerivesHasPriv))]; } + { int arr[T(__is_trivially_copyable(DerivesHasProt))]; } + { int arr[T(__is_trivially_copyable(Vector))]; } + { int arr[T(__is_trivially_copyable(VectorExt))]; } + { int arr[T(__is_trivially_copyable(HasCons))]; } + { int arr[T(__is_trivially_copyable(HasRef))]; } + { int arr[T(__is_trivially_copyable(HasNonPOD))]; } + { int arr[T(__is_trivially_copyable(DerivesHasCons))]; } + { int arr[T(__is_trivially_copyable(DerivesHasRef))]; } + + { int arr[F(__is_trivially_copyable(HasCopyAssign))]; } + { int arr[F(__is_trivially_copyable(HasMoveAssign))]; } + { int arr[F(__is_trivially_copyable(HasDest))]; } + { int arr[F(__is_trivially_copyable(HasVirt))]; } + { int arr[F(__is_trivially_copyable(DerivesHasCopyAssign))]; } + { int arr[F(__is_trivially_copyable(DerivesHasMoveAssign))]; } + { int arr[F(__is_trivially_copyable(DerivesHasDest))]; } + { int arr[F(__is_trivially_copyable(DerivesHasVirt))]; } + { int arr[F(__is_trivially_copyable(void))]; } + { int arr[F(__is_trivially_copyable(cvoid))]; } +} + void array_rank() { int t01[T(__array_rank(IntAr) == 1)]; int t02[T(__array_rank(ConstIntArAr) == 2)]; |