Rename "hasTrivialConstructor" to "hasTrivialDefaultConstructor" and
modify the semantics slightly to accomodate default constructors (I
hope).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131087 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 5298745..68bc165 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -337,15 +337,21 @@
/// HasPublicFields - True when there are private non-static data members.
bool HasPublicFields : 1;
- /// HasTrivialConstructor - True when this class has a trivial constructor.
+ /// HasTrivialDefaultConstructor - True when this class has a trivial
+ /// default constructor.
///
- /// C++ [class.ctor]p5. A constructor is trivial if it is an
- /// implicitly-declared default constructor and if:
- /// * its class has no virtual functions and no virtual base classes, and
- /// * all the direct base classes of its class have trivial constructors, and
- /// * for all the nonstatic data members of its class that are of class type
- /// (or array thereof), each such class has a trivial constructor.
- bool HasTrivialConstructor : 1;
+ /// C++0x [class.ctor]p5
+ /// A default constructor is trivial if it is not user-provided and if
+ /// -- its class has no virtual functions and no virtual base classes,
+ /// and
+ /// -- no non-static data member of its class has a
+ /// brace-or-equal-initializer, and
+ /// -- all the direct base classes of its class have trivial
+ /// default constructors, and
+ /// -- for all the nonstatic data members of its class that are of class
+ /// type (or array thereof), each such class has a trivial
+ /// default constructor.
+ bool HasTrivialDefaultConstructor : 1;
/// HasConstExprNonCopyMoveConstructor - True when this class has at least
/// one constexpr constructor which is neither the copy nor move
@@ -357,7 +363,7 @@
///
/// C++0x [class.copy]p13:
/// A copy/move constructor for class X is trivial if it is neither
- /// user-provided nor deleted and if
+ /// user-provided and if
/// -- class X has no virtual functions and no virtual base classes, and
/// -- the constructor selected to copy/move each direct base class
/// subobject is trivial, and
@@ -372,7 +378,7 @@
///
/// C++0x [class.copy]p13:
/// A copy/move constructor for class X is trivial if it is neither
- /// user-provided nor deleted and if
+ /// user-provided and if
/// -- class X has no virtual functions and no virtual base classes, and
/// -- the constructor selected to copy/move each direct base class
/// subobject is trivial, and
@@ -800,9 +806,12 @@
/// (C++ [class]p7)
bool isStandardLayout() const { return data().IsStandardLayout; }
- // hasTrivialConstructor - Whether this class has a trivial constructor
- // (C++ [class.ctor]p5)
- bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
+ // hasTrivialDefaultConstructor - Whether this class has a trivial default
+ // constructor
+ // (C++0x [class.ctor]p5)
+ bool hasTrivialDefaultConstructor() const {
+ return data().HasTrivialDefaultConstructor;
+ }
// hasConstExprNonCopyMoveConstructor - Whether this class has at least one
// constexpr constructor other than the copy or move constructors
@@ -845,9 +854,18 @@
}
// isTriviallyCopyable - Whether this class is considered trivially copyable
- // (C++0x [class]p5).
+ // (C++0x [class]p6).
bool isTriviallyCopyable() const;
+ // isTrivial - Whether this class is considered trivial
+ //
+ // C++0x [class]p6
+ // A trivial class is a class that has a trivial default constructor and
+ // is trivially copiable.
+ bool isTrivial() const {
+ return isTriviallyCopyable() && hasTrivialDefaultConstructor();
+ }
+
/// \brief If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
///
diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
index 4a2a2c6..b9b94a6 100644
--- a/include/clang/Basic/TypeTraits.h
+++ b/include/clang/Basic/TypeTraits.h
@@ -23,7 +23,7 @@
UTT_HasNothrowConstructor,
UTT_HasTrivialAssign,
UTT_HasTrivialCopy,
- UTT_HasTrivialConstructor,
+ UTT_HasTrivialDefaultConstructor,
UTT_HasTrivialDestructor,
UTT_HasVirtualDestructor,
UTT_IsAbstract,
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 5271c90..379c13a 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -6149,10 +6149,13 @@
// Structs that have non-trivial constructors or destructors are required.
// FIXME: Handle references.
+ // FIXME: Be more selective about which constructors we care about.
if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- if (RD->hasDefinition() &&
- (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor()))
+ if (RD->hasDefinition() && !(RD->hasTrivialDefaultConstructor() &&
+ RD->hasTrivialCopyConstructor() &&
+ RD->hasTrivialMoveConstructor() &&
+ RD->hasTrivialDestructor()))
return true;
}
}
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 9099cd5..ab097e4 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -33,11 +33,11 @@
Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false),
- HasTrivialConstructor(true), HasConstExprNonCopyMoveConstructor(false),
- HasTrivialCopyConstructor(true), HasTrivialMoveConstructor(true),
- HasTrivialCopyAssignment(true), HasTrivialMoveAssignment(true),
- HasTrivialDestructor(true), HasNonLiteralTypeFieldsOrBases(false),
- ComputedVisibleConversions(false),
+ HasTrivialDefaultConstructor(true),
+ HasConstExprNonCopyMoveConstructor(false), HasTrivialCopyConstructor(true),
+ HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true),
+ HasTrivialMoveAssignment(true), HasTrivialDestructor(true),
+ HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false),
DeclaredCopyAssignment(false), DeclaredDestructor(false),
NumBases(0), NumVBases(0), Bases(), VBases(),
@@ -165,8 +165,9 @@
data().Empty = false;
// C++ [class.ctor]p5:
- // A constructor is trivial if its class has no virtual base classes.
- data().HasTrivialConstructor = false;
+ // A default constructor is trivial [...] if:
+ // -- its class has [...] no virtual bases
+ data().HasTrivialDefaultConstructor = false;
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if it is neither
@@ -188,10 +189,11 @@
data().IsStandardLayout = false;
} else {
// C++ [class.ctor]p5:
- // A constructor is trivial if all the direct base classes of its
- // class have trivial constructors.
- if (!BaseClassDecl->hasTrivialConstructor())
- data().HasTrivialConstructor = false;
+ // A default constructor is trivial [...] if:
+ // -- all the direct base classes of its class have trivial default
+ // constructors.
+ if (!BaseClassDecl->hasTrivialDefaultConstructor())
+ data().HasTrivialDefaultConstructor = false;
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if [...]
@@ -421,8 +423,10 @@
// polymorphic class.
data().Polymorphic = true;
- // None of the special member functions are trivial.
- data().HasTrivialConstructor = false;
+ // C++0x [class.ctor]p5
+ // A default constructor is trivial [...] if:
+ // -- its class has no virtual functions [...]
+ data().HasTrivialDefaultConstructor = false;
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if [...]
@@ -497,11 +501,10 @@
// A POD-struct is an aggregate class [...]
data().PlainOldData = false;
- // C++ [class.ctor]p5:
- // A constructor is trivial if it is an implicitly-declared default
- // constructor.
- // FIXME: C++0x: don't do this for "= default" default constructors.
- data().HasTrivialConstructor = false;
+ // C++0x [class.ctor]p5:
+ // A default constructor is trivial if it is not user-provided [...]
+ if (Constructor->isUserProvided())
+ data().HasTrivialDefaultConstructor = false;
// Note when we have a user-declared copy or move constructor, which will
// suppress the implicit declaration of those constructors.
@@ -511,16 +514,16 @@
data().DeclaredCopyConstructor = true;
// C++0x [class.copy]p13:
- // A copy/move constructor for class X is trivial if it is neither
- // user-provided nor deleted
- // FIXME: C++0x: don't do this for "= default" copy constructors.
- data().HasTrivialCopyConstructor = false;
+ // A copy/move constructor for class X is trivial if it is not
+ // user-provided [...]
+ if (Constructor->isUserProvided())
+ data().HasTrivialCopyConstructor = false;
} else if (Constructor->isMoveConstructor()) {
// C++0x [class.copy]p13:
- // A copy/move constructor for class X is trivial if it is neither
- // user-provided nor deleted
- // FIXME: C++0x: don't do this for "= default" move constructors.
- data().HasTrivialMoveConstructor = false;
+ // A copy/move constructor for class X is trivial if it is not
+ // user-provided [...]
+ if (Constructor->isUserProvided())
+ data().HasTrivialMoveConstructor = false;
}
}
if (Constructor->isConstExpr() &&
@@ -676,7 +679,7 @@
if (!T->isPODType())
data().PlainOldData = false;
if (T->isReferenceType()) {
- data().HasTrivialConstructor = false;
+ data().HasTrivialDefaultConstructor = false;
// C++0x [class]p7:
// A standard-layout class is a class that:
@@ -691,8 +694,13 @@
if (const RecordType *RecordTy = T->getAs<RecordType>()) {
CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
if (FieldRec->getDefinition()) {
- if (!FieldRec->hasTrivialConstructor())
- data().HasTrivialConstructor = false;
+ // C++0x [class.ctor]p5:
+ // A defulat constructor is trivial [...] if:
+ // -- for all the non-static data members of its class that are of
+ // class type (or array thereof), each such class has a trivial
+ // default constructor.
+ if (!FieldRec->hasTrivialDefaultConstructor())
+ data().HasTrivialDefaultConstructor = false;
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if [...]
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 0d13502..094864b 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1297,7 +1297,7 @@
case UTT_HasNothrowConstructor: return "__has_nothrow_constructor";
case UTT_HasNothrowCopy: return "__has_nothrow_copy";
case UTT_HasTrivialAssign: return "__has_trivial_assign";
- case UTT_HasTrivialConstructor: return "__has_trivial_constructor";
+ case UTT_HasTrivialDefaultConstructor: return "__has_trivial_constructor";
case UTT_HasTrivialCopy: return "__has_trivial_copy";
case UTT_HasTrivialDestructor: return "__has_trivial_destructor";
case UTT_HasVirtualDestructor: return "__has_virtual_destructor";
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index b0086d9..638c4dc 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -954,11 +954,7 @@
if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
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;
+ if (!ClassDecl->isTrivial()) return false;
}
return true;
@@ -1027,11 +1023,7 @@
dyn_cast<CXXRecordDecl>(RT->getDecl())) {
// C++11 [class]p10:
// A POD struct is a non-union class that is both a trivial class [...]
- // C++11 [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 (!ClassDecl->isTrivial()) return false;
// C++11 [class]p10:
// A POD struct is a non-union class that is both a trivial class and
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 29c7688..d8da642 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -642,7 +642,7 @@
if (const RecordType *RT = CGF.getContext()
.getBaseElementType(ElementType)->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- hasNonTrivialCXXConstructor = !RD->hasTrivialConstructor();
+ hasNonTrivialCXXConstructor = !RD->hasTrivialDefaultConstructor();
}
// FIXME: were we intentionally ignoring address spaces and GC attributes?
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 6ee9bc1..cef5d91 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -738,7 +738,7 @@
if (E->isArray()) {
if (CXXConstructorDecl *Ctor = E->getConstructor()) {
bool RequiresZeroInitialization = false;
- if (Ctor->getParent()->hasTrivialConstructor()) {
+ if (Ctor->getParent()->hasTrivialDefaultConstructor()) {
// If new expression did not specify value-initialization, then there
// is no initialization.
if (!E->hasInitializer() || Ctor->getParent()->isEmpty())
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 5b0d41e..5fc5759 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -292,7 +292,7 @@
const CXXRecordDecl *classDecl = IVART->getAsCXXRecordDecl();
if (PID->getGetterCXXConstructor() &&
- classDecl && !classDecl->hasTrivialConstructor()) {
+ classDecl && !classDecl->hasTrivialDefaultConstructor()) {
ReturnStmt *Stmt =
new (getContext()) ReturnStmt(SourceLocation(),
PID->getGetterCXXConstructor(),
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index eb491ef..c8f95ff 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1924,7 +1924,8 @@
case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
- case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
+ case tok::kw___has_trivial_constructor:
+ return UTT_HasTrivialDefaultConstructor;
case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 586a298..71bea3c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -7653,7 +7653,7 @@
CXXSpecialMember member = CXXInvalid;
if (!RDecl->hasTrivialCopyConstructor())
member = CXXCopyConstructor;
- else if (!RDecl->hasTrivialConstructor())
+ else if (!RDecl->hasTrivialDefaultConstructor())
member = CXXConstructor;
else if (!RDecl->hasTrivialCopyAssignment())
member = CXXCopyAssignment;
@@ -7758,7 +7758,7 @@
bool (CXXRecordDecl::*hasTrivial)() const;
switch (member) {
case CXXConstructor:
- hasTrivial = &CXXRecordDecl::hasTrivialConstructor; break;
+ hasTrivial = &CXXRecordDecl::hasTrivialDefaultConstructor; break;
case CXXCopyConstructor:
hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break;
case CXXCopyAssignment:
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index df08ed8..e96fb37 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5065,7 +5065,7 @@
/*isImplicitlyDeclared=*/true);
DefaultCon->setAccess(AS_public);
DefaultCon->setImplicit();
- DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
+ DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor());
// Note that we have declared this constructor.
++ASTContext::NumImplicitDefaultConstructorsDeclared;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 56abdfb..1597152 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -9854,7 +9854,7 @@
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
unsigned TypeQuals;
if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) {
- if (Constructor->getParent()->hasTrivialConstructor())
+ if (Constructor->getParent()->hasTrivialDefaultConstructor())
return;
if (!Constructor->isUsed(false))
DefineImplicitDefaultConstructor(Loc, Constructor);
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 4aaba56..b2a67aa 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2434,7 +2434,7 @@
case UTT_HasNothrowConstructor:
case UTT_HasNothrowCopy:
case UTT_HasTrivialAssign:
- case UTT_HasTrivialConstructor:
+ case UTT_HasTrivialDefaultConstructor:
case UTT_HasTrivialCopy:
case UTT_HasTrivialDestructor:
case UTT_HasVirtualDestructor:
@@ -2544,7 +2544,7 @@
//
// 1: http://gcc.gnu/.org/onlinedocs/gcc/Type-Traits.html
// 2: http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index
- case UTT_HasTrivialConstructor:
+ case UTT_HasTrivialDefaultConstructor:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
// If __is_pod (type) is true then the trait is true, else if type is
// a cv class or union type (or array thereof) with a trivial default
@@ -2553,7 +2553,7 @@
return true;
if (const RecordType *RT =
C.getBaseElementType(T)->getAs<RecordType>())
- return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialConstructor();
+ return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDefaultConstructor();
return false;
case UTT_HasTrivialCopy:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
@@ -2694,7 +2694,7 @@
return true;
if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (RD->hasTrivialConstructor())
+ if (RD->hasTrivialDefaultConstructor())
return true;
DeclContext::lookup_const_iterator Con, ConEnd;
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 4b45816..be3cd34 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -4020,7 +4020,8 @@
CXXRecordDecl *ClassDecl = Constructor->getParent();
assert(ClassDecl && "No parent class for constructor.");
if (Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
- ClassDecl->hasTrivialConstructor() && !Constructor->isUsed(false))
+ ClassDecl->hasTrivialDefaultConstructor() &&
+ !Constructor->isUsed(false))
S.DefineImplicitDefaultConstructor(Loc, Constructor);
}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 44b8c6a..c31e9e5 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -858,7 +858,7 @@
Data.HasPrivateFields = Record[Idx++];
Data.HasProtectedFields = Record[Idx++];
Data.HasPublicFields = Record[Idx++];
- Data.HasTrivialConstructor = Record[Idx++];
+ Data.HasTrivialDefaultConstructor = Record[Idx++];
Data.HasConstExprNonCopyMoveConstructor = Record[Idx++];
Data.HasTrivialCopyConstructor = Record[Idx++];
Data.HasTrivialMoveConstructor = Record[Idx++];
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 720f203..13b333d 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -3818,7 +3818,7 @@
Record.push_back(Data.HasPrivateFields);
Record.push_back(Data.HasProtectedFields);
Record.push_back(Data.HasPublicFields);
- Record.push_back(Data.HasTrivialConstructor);
+ Record.push_back(Data.HasTrivialDefaultConstructor);
Record.push_back(Data.HasConstExprNonCopyMoveConstructor);
Record.push_back(Data.HasTrivialCopyConstructor);
Record.push_back(Data.HasTrivialMoveConstructor);