aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2011-04-23 10:47:28 +0000
committerChandler Carruth <chandlerc@gmail.com>2011-04-23 10:47:28 +0000
commitb7e9589bce9852b4db9575f55ac9137572147eb5 (patch)
tree3ab7a514891d4caa02c7495fe18a66e85a87fb2c /lib
parent4e61ddd644e9c6293697a966d98d7c1905cf63a8 (diff)
Implement basic __is_trivial type-trait support, enough to close PR9472.
This introduces a few APIs on the AST to bundle up the standard-based logic so that programmatic clients have access to exactly the same behavior. There is only one serious FIXME here: checking for non-trivial move constructors and move assignment operators. Those bits need to be added to the declaration and accessors provided. This implementation should be enough for the uses of __is_trivial in libstdc++ 4.6's C++98 library implementation. Ideas for more thorough test cases or any edge cases missing would be appreciated. =D git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130057 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/DeclCXX.cpp17
-rw-r--r--lib/AST/StmtPrinter.cpp1
-rw-r--r--lib/AST/Type.cpp27
-rw-r--r--lib/Lex/PPMacroExpansion.cpp1
-rw-r--r--lib/Parse/ParseExpr.cpp2
-rw-r--r--lib/Parse/ParseExprCXX.cpp1
-rw-r--r--lib/Parse/ParseTentative.cpp1
-rw-r--r--lib/Sema/SemaExprCXX.cpp1
8 files changed, 51 insertions, 0 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 54c8c35986..015b49aed6 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -217,6 +217,23 @@ bool CXXRecordDecl::hasConstCopyConstructor(const ASTContext &Context) const {
return getCopyConstructor(Context, Qualifiers::Const) != 0;
}
+bool CXXRecordDecl::isTriviallyCopyable() const {
+ // C++0x [class]p5:
+ // A trivially copyable class is a class that:
+ // -- has no non-trivial copy constructors,
+ if (!hasTrivialCopyConstructor()) return false;
+ // -- has no non-trivial move constructors,
+ // FIXME: C++0x: Track and check trivial move constructors.
+ // -- has no non-trivial copy assignment operators,
+ if (!hasTrivialCopyAssignment()) return false;
+ // -- has no non-trivial move assignment operators, and
+ // FIXME: C++0x: Track and check trivial move assignment operators.
+ // -- has a trivial destructor.
+ if (!hasTrivialDestructor()) return false;
+
+ return true;
+}
+
/// \brief Perform a simplistic form of overload resolution that only considers
/// cv-qualifiers on a single parameter, and return the best overload candidate
/// (if there is one).
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 89631261dc..3591c32ad8 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1266,6 +1266,7 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) {
case UTT_IsEnum: return "__is_enum";
case UTT_IsPOD: return "__is_pod";
case UTT_IsPolymorphic: return "__is_polymorphic";
+ case UTT_IsTrivial: return "__is_trivial";
case UTT_IsUnion: return "__is_union";
}
return "";
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index ba3251b88b..a25f0331f4 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -902,6 +902,33 @@ bool Type::isLiteralType() const {
}
}
+bool Type::isTrivialType() const {
+ if (isIncompleteType())
+ return false;
+
+ // C++0x [basic.types]p9:
+ // Scalar types, trivial 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");
+ if (BaseTy->isScalarType()) return true;
+ if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
+ const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+
+ // C++0x [class]p5:
+ // A trivial class is a class that has a trivial default constructor
+ if (!ClassDecl->hasTrivialConstructor()) return false;
+ // and is trivially copyable.
+ if (!ClassDecl->isTriviallyCopyable()) return false;
+
+ return true;
+ }
+
+ // No other types can match.
+ return false;
+}
+
bool Type::isPromotableIntegerType() const {
if (const BuiltinType *BT = getAs<BuiltinType>())
switch (BT->getKind()) {
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 64b0baf383..0e38e39c26 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -590,6 +590,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("is_literal", LangOpts.CPlusPlus)
.Case("is_pod", LangOpts.CPlusPlus)
.Case("is_polymorphic", LangOpts.CPlusPlus)
+ .Case("is_trivial", 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 1a3290a43d..d218c79736 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -536,6 +536,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
/// '__is_enum'
/// '__is_pod'
/// '__is_polymorphic'
+/// '__is_trivial'
/// '__is_union'
///
/// binary-type-trait:
@@ -990,6 +991,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___is_literal:
case tok::kw___is_pod:
case tok::kw___is_polymorphic:
+ case tok::kw___is_trivial:
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 3c9ebc388b..38c074d1de 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1929,6 +1929,7 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
case tok::kw___is_literal: return UTT_IsLiteral;
case tok::kw___is_pod: return UTT_IsPOD;
case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
+ case tok::kw___is_trivial: return UTT_IsTrivial;
case tok::kw___is_union: return UTT_IsUnion;
}
}
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index cdfe8875d4..3e00a8c0db 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -662,6 +662,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw___is_literal:
case tok::kw___is_pod:
case tok::kw___is_polymorphic:
+ case tok::kw___is_trivial:
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 c6a8210911..27545d802e 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2362,6 +2362,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
default: assert(false && "Unknown type trait or not implemented");
case UTT_IsPOD: return T->isPODType();
case UTT_IsLiteral: return T->isLiteralType();
+ case UTT_IsTrivial: return T->isTrivialType();
case UTT_IsClass: // Fallthrough
case UTT_IsUnion:
if (const RecordType *Record = T->getAs<RecordType>()) {