diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclCXX.cpp | 6 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 30 |
5 files changed, 43 insertions, 1 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index ffc35fe1f7..78ed3fcf4d 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -29,6 +29,7 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false), UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false), Aggregate(true), PlainOldData(true), Polymorphic(false), Abstract(false), + HasTrivialConstructor(true), Bases(0), NumBases(0), Conversions(DC, DeclarationName()), TemplateOrInstantiation() { } @@ -138,6 +139,11 @@ CXXRecordDecl::addedConstructor(ASTContext &Context, // A POD-struct is an aggregate class [...] PlainOldData = false; + // C++ [class.ctor]p5: + // A constructor is trivial if it is an implicitly-declared default + // constructor. + HasTrivialConstructor = false; + // Note when we have a user-declared copy constructor, which will // suppress the implicit declaration of a copy constructor. if (ConDecl->isCopyConstructor(Context)) diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index c2fcc5f9ee..3634c20356 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -170,6 +170,10 @@ bool UnaryTypeTraitExpr::EvaluateTrait() const { if (const RecordType *RT = QueriedType->getAsRecordType()) return cast<CXXRecordDecl>(RT->getDecl())->isAbstract(); return false; + case UTT_HasTrivialConstructor: + if (const RecordType *RT = QueriedType->getAsRecordType()) + return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialConstructor(); + return false; } } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 20a8359d1d..d41586ca91 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -481,7 +481,7 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) { /// '__has_nothrow_constructor' [TODO] /// '__has_trivial_assign' [TODO] /// '__has_trivial_copy' [TODO] -/// '__has_trivial_constructor' [TODO] +/// '__has_trivial_constructor' /// '__has_trivial_destructor' [TODO] /// '__has_virtual_destructor' [TODO] /// '__is_abstract' [TODO] @@ -771,6 +771,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___is_union: case tok::kw___is_polymorphic: case tok::kw___is_abstract: + case tok::kw___has_trivial_constructor: return ParseUnaryTypeTrait(); case tok::at: { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6233871c9e..6c4580df28 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2049,6 +2049,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, CurClass->setAggregate(false); CurClass->setPOD(false); CurClass->setPolymorphic(true); + CurClass->setHasTrivialConstructor(false); } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index cc70dc4a5c..ec1ed4668a 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -369,6 +369,18 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Class->setAggregate(false); Class->setPOD(false); + if (Virtual) { + // C++ [class.ctor]p5: + // A constructor is trivial if its class has no virtual base classes. + Class->setHasTrivialConstructor(false); + } else { + // C++ [class.ctor]p5: + // A constructor is trivial if all the direct base classes of its + // class have trivial constructors. + Class->setHasTrivialConstructor(cast<CXXRecordDecl>(BaseDecl)-> + hasTrivialConstructor()); + } + // Create the base specifier. // FIXME: Allocate via ASTContext? return new CXXBaseSpecifier(SpecifierRange, Virtual, @@ -940,6 +952,24 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, if (RD->isAbstract()) AbstractClassUsageDiagnoser(*this, RD); + if (RD->hasTrivialConstructor()) { + for (RecordDecl::field_iterator i = RD->field_begin(Context), + e = RD->field_end(Context); i != e; ++i) { + // All the nonstatic data members must have trivial constructors. + QualType FTy = i->getType(); + while (const ArrayType *AT = Context.getAsArrayType(FTy)) + FTy = AT->getElementType(); + + if (const RecordType *RT = FTy->getAsRecordType()) { + CXXRecordDecl *FieldRD = cast<CXXRecordDecl>(RT->getDecl()); + if (!FieldRD->hasTrivialConstructor()) { + RD->setHasTrivialConstructor(false); + break; + } + } + } + } + if (!Template) AddImplicitlyDeclaredMembersToClass(RD); } |