diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2011-04-29 07:47:42 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2011-04-29 07:47:42 +0000 |
commit | efd5671a27e12dc8723be1d7b14fae45a8b0068b (patch) | |
tree | 9fe4522a6e90de6c5526a7727b719be15b6d75a7 | |
parent | e1bd40cfbd618e1ebeba288e844d424df10c601d (diff) | |
download | bcm5719-llvm-efd5671a27e12dc8723be1d7b14fae45a8b0068b.tar.gz bcm5719-llvm-efd5671a27e12dc8723be1d7b14fae45a8b0068b.zip |
Don't assume that the AST methods will only be invoked on C++ types.
Teaches isLiteralType and isTrivialType to behave plausibly and most
importantly not crash on normal RecordDecls.
Sadly I have no real way to test this. I stumbled onto it by
mis-implementing a warning.
llvm-svn: 130483
-rw-r--r-- | clang/lib/AST/Type.cpp | 49 |
1 files changed, 26 insertions, 23 deletions
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e75ce7dfe40..f4b34f0c063 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -891,22 +891,24 @@ bool Type::isLiteralType() const { if (BaseTy->isReferenceType()) return true; // -- a class type that has all of the following properties: if (const RecordType *RT = BaseTy->getAs<RecordType>()) { - const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl()); - // -- a trivial destructor, - if (!ClassDecl->hasTrivialDestructor()) return false; - // -- every constructor call and full-expression in the - // brace-or-equal-initializers for non-static data members (if any) - // is a constant expression, - // FIXME: C++0x: Clang doesn't yet support non-static data member - // declarations with initializers, or constexprs. - // -- it is an aggregate type or has at least one constexpr - // constructor or constructor template that is not a copy or move - // constructor, and - if (!ClassDecl->isAggregate() && - !ClassDecl->hasConstExprNonCopyMoveConstructor()) - return false; - // -- all non-static data members and base classes of literal types - if (ClassDecl->hasNonLiteralTypeFieldsOrBases()) return false; + if (const CXXRecordDecl *ClassDecl = + dyn_cast<CXXRecordDecl>(RT->getDecl())) { + // -- a trivial destructor, + if (!ClassDecl->hasTrivialDestructor()) return false; + // -- every constructor call and full-expression in the + // brace-or-equal-initializers for non-static data members (if any) + // is a constant expression, + // FIXME: C++0x: Clang doesn't yet support non-static data member + // declarations with initializers, or constexprs. + // -- it is an aggregate type or has at least one constexpr + // constructor or constructor template that is not a copy or move + // constructor, and + if (!ClassDecl->isAggregate() && + !ClassDecl->hasConstExprNonCopyMoveConstructor()) + return false; + // -- all non-static data members and base classes of literal types + if (ClassDecl->hasNonLiteralTypeFieldsOrBases()) return false; + } return true; } @@ -925,13 +927,14 @@ bool Type::isTrivialType() const { 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; + if (const CXXRecordDecl *ClassDecl = + dyn_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; } |