aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/DeclCXX.cpp6
-rw-r--r--lib/AST/ExprCXX.cpp4
-rw-r--r--lib/Parse/ParseExpr.cpp3
-rw-r--r--lib/Sema/SemaDecl.cpp1
-rw-r--r--lib/Sema/SemaDeclCXX.cpp30
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);
}