diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2011-04-23 10:47:28 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2011-04-23 10:47:28 +0000 |
commit | a3e1f9a02c6aeecb97009d5786713163f46cedce (patch) | |
tree | 1e2e67c6ec8f271b75b5600a36817a2ac8987eee /clang/lib | |
parent | 7980348fcf3a0f1da7352728493f00ff78852afb (diff) | |
download | bcm5719-llvm-a3e1f9a02c6aeecb97009d5786713163f46cedce.tar.gz bcm5719-llvm-a3e1f9a02c6aeecb97009d5786713163f46cedce.zip |
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
llvm-svn: 130057
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 17 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 1 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 1 |
8 files changed, 51 insertions, 0 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 54c8c359863..015b49aed6f 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/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/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 89631261dcc..3591c32ad82 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/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/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index ba3251b88b8..a25f0331f44 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/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/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 64b0baf3832..0e38e39c26a 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/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/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 1a3290a43db..d218c797360 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/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/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 3c9ebc388bc..38c074d1de6 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/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/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index cdfe8875d4c..3e00a8c0db5 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/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/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c6a82109115..27545d802e4 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/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>()) { |