summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Type.h4
-rw-r--r--include/clang/Basic/TokenKinds.def3
-rw-r--r--include/clang/Basic/TypeTraits.h1
-rw-r--r--lib/AST/StmtPrinter.cpp1
-rw-r--r--lib/AST/Type.cpp31
-rw-r--r--lib/Lex/PPMacroExpansion.cpp1
-rw-r--r--lib/Parse/ParseExpr.cpp4
-rw-r--r--lib/Parse/ParseExprCXX.cpp1
-rw-r--r--lib/Parse/ParseTentative.cpp1
-rw-r--r--lib/Sema/SemaExprCXX.cpp3
-rw-r--r--test/Lexer/has_feature_type_traits.cpp5
-rw-r--r--test/SemaCXX/type-traits.cpp87
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)];