Centralize the management of CXXRecordDecl::DefinitionData's

HasTrivialConstructor, HasTrivialCopyConstructor,
HasTrivialCopyAssignment, and HasTrivialDestructor bits in
CXXRecordDecl's methods. This completes all but the Abstract bit and
the set of conversion functions, both of which will require a bit of
extra work. The majority of <rdar://problem/8459981> is now
implemented (but not all of it).

llvm-svn: 114929
This commit is contained in:
Douglas Gregor 2010-09-28 00:00:00 +00:00
parent 8fd3244af3
commit 1f93ffb3e6
7 changed files with 69 additions and 113 deletions

View File

@ -688,10 +688,6 @@ public:
/// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
bool isAggregate() const { return data().Aggregate; }
/// setMethodAsVirtual - Make input method virtual and set the necesssary
/// special function bits and other bits accordingly.
void setMethodAsVirtual(FunctionDecl *Method);
/// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class
/// that is an aggregate that has no non-static non-POD data members, no
/// reference data members, no user-defined copy assignment operator and no
@ -719,42 +715,22 @@ public:
// (C++ [class.ctor]p5)
bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
// setHasTrivialConstructor - Set whether this class has a trivial constructor
// (C++ [class.ctor]p5)
void setHasTrivialConstructor(bool TC) { data().HasTrivialConstructor = TC; }
// hasTrivialCopyConstructor - Whether this class has a trivial copy
// constructor (C++ [class.copy]p6)
bool hasTrivialCopyConstructor() const {
return data().HasTrivialCopyConstructor;
}
// setHasTrivialCopyConstructor - Set whether this class has a trivial
// copy constructor (C++ [class.copy]p6)
void setHasTrivialCopyConstructor(bool TC) {
data().HasTrivialCopyConstructor = TC;
}
// hasTrivialCopyAssignment - Whether this class has a trivial copy
// assignment operator (C++ [class.copy]p11)
bool hasTrivialCopyAssignment() const {
return data().HasTrivialCopyAssignment;
}
// setHasTrivialCopyAssignment - Set whether this class has a
// trivial copy assignment operator (C++ [class.copy]p11)
void setHasTrivialCopyAssignment(bool TC) {
data().HasTrivialCopyAssignment = TC;
}
// hasTrivialDestructor - Whether this class has a trivial destructor
// (C++ [class.dtor]p3)
bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
// setHasTrivialDestructor - Set whether this class has a trivial destructor
// (C++ [class.dtor]p3)
void setHasTrivialDestructor(bool TC) { data().HasTrivialDestructor = TC; }
/// \brief If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
///

View File

@ -2584,13 +2584,6 @@ public:
bool Virtual, AccessSpecifier Access,
TypeSourceInfo *TInfo);
/// SetClassDeclAttributesFromBase - Copies class decl traits
/// (such as whether the class has a trivial constructor,
/// trivial destructor etc) from the given base class.
void SetClassDeclAttributesFromBase(CXXRecordDecl *Class,
const CXXRecordDecl *BaseClass,
bool BaseIsVirtual);
BaseResult ActOnBaseSpecifier(Decl *classdecl,
SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,

View File

@ -134,7 +134,45 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// T is a class type, but not a union type, with ... no virtual base
// classes
data().Empty = false;
// C++ [class.ctor]p5:
// A constructor is trivial if its class has no virtual base classes.
data().HasTrivialConstructor = false;
// C++ [class.copy]p6:
// A copy constructor is trivial if its class has no virtual base
// classes.
data().HasTrivialCopyConstructor = false;
// C++ [class.copy]p11:
// A copy assignment operator is trivial if its class has no virtual
// base classes.
data().HasTrivialCopyAssignment = 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;
// C++ [class.copy]p6:
// A copy constructor is trivial if all the direct base classes of its
// class have trivial copy constructors.
if (!BaseClassDecl->hasTrivialCopyConstructor())
data().HasTrivialCopyConstructor = false;
// C++ [class.copy]p11:
// A copy assignment operator is trivial if all the direct base classes
// of its class have trivial copy assignment operators.
if (!BaseClassDecl->hasTrivialCopyAssignment())
data().HasTrivialCopyAssignment = false;
}
// C++ [class.ctor]p3:
// A destructor is trivial if all the direct base classes of its class
// have trivial destructors.
if (!BaseClassDecl->hasTrivialDestructor())
data().HasTrivialDestructor = false;
}
if (VBases.empty())
@ -309,6 +347,12 @@ CXXRecordDecl::addedMember(Decl *D) {
// A class that declares or inherits a virtual function is called a
// polymorphic class.
data().Polymorphic = true;
// None of the special member functions are trivial.
data().HasTrivialConstructor = false;
data().HasTrivialCopyConstructor = false;
data().HasTrivialCopyAssignment = false;
// FIXME: Destructor?
}
}
@ -384,6 +428,13 @@ CXXRecordDecl::addedMember(Decl *D) {
// destructor.
data().PlainOldData = false;
// C++ [class.dtor]p3:
// A destructor is trivial if it is an implicitly-declared destructor and
// [...].
//
// FIXME: C++0x: don't do this for "= default" destructors
data().HasTrivialDestructor = false;
return;
}
@ -453,6 +504,22 @@ CXXRecordDecl::addedMember(Decl *D) {
QualType T = Context.getBaseElementType(Field->getType());
if (!T->isPODType())
data().PlainOldData = false;
if (T->isReferenceType())
data().HasTrivialConstructor = false;
if (const RecordType *RecordTy = T->getAs<RecordType>()) {
CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
if (FieldRec->getDefinition()) {
if (!FieldRec->hasTrivialConstructor())
data().HasTrivialConstructor = false;
if (!FieldRec->hasTrivialCopyConstructor())
data().HasTrivialCopyConstructor = false;
if (!FieldRec->hasTrivialCopyAssignment())
data().HasTrivialCopyAssignment = false;
if (!FieldRec->hasTrivialDestructor())
data().HasTrivialDestructor = false;
}
}
// If this is not a zero-length bit-field, then the class is not empty.
if (data().Empty) {
@ -649,13 +716,6 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) {
llvm_unreachable("conversion not found in set!");
}
void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) {
Method->setVirtualAsWritten(true);
setHasTrivialConstructor(false);
setHasTrivialCopyConstructor(false);
setHasTrivialCopyAssignment(false);
}
CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const {
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom());

View File

@ -3425,8 +3425,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
<< FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc());
} else {
// Okay: Add virtual to the method.
CXXRecordDecl *CurClass = cast<CXXRecordDecl>(DC);
CurClass->setMethodAsVirtual(NewFD);
NewFD->setVirtualAsWritten(true);
}
}
@ -3927,11 +3926,6 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
return NewFD->setInvalidDecl();
}
}
// C++ [class.dtor]p3: A destructor is trivial if it is an implicitly-
// declared destructor.
// FIXME: C++0x: don't do this for "= default" destructors
Record->setHasTrivialDestructor(false);
} else if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(NewFD)) {
ActOnConversionDeclarator(Conversion);
@ -6185,23 +6179,9 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
}
if (!InvalidDecl && getLangOptions().CPlusPlus) {
CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record);
if (T->isReferenceType())
CXXRecord->setHasTrivialConstructor(false);
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
if (RDecl->getDefinition()) {
if (!RDecl->hasTrivialConstructor())
CXXRecord->setHasTrivialConstructor(false);
if (!RDecl->hasTrivialCopyConstructor())
CXXRecord->setHasTrivialCopyConstructor(false);
if (!RDecl->hasTrivialCopyAssignment())
CXXRecord->setHasTrivialCopyAssignment(false);
if (!RDecl->hasTrivialDestructor())
CXXRecord->setHasTrivialDestructor(false);
// C++ 9.5p1: An object of a class with a non-trivial
// constructor, a non-trivial copy constructor, a non-trivial
// destructor, or a non-trivial copy assignment operator

View File

@ -502,8 +502,6 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
return 0;
}
SetClassDeclAttributesFromBase(Class, CXXBaseDecl, Virtual);
if (BaseDecl->isInvalidDecl())
Class->setInvalidDecl();
@ -513,49 +511,6 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
Access, TInfo);
}
void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class,
const CXXRecordDecl *BaseClass,
bool BaseIsVirtual) {
if (BaseIsVirtual) {
// C++ [class.ctor]p5:
// A constructor is trivial if its class has no virtual base classes.
Class->setHasTrivialConstructor(false);
// C++ [class.copy]p6:
// A copy constructor is trivial if its class has no virtual base classes.
Class->setHasTrivialCopyConstructor(false);
// C++ [class.copy]p11:
// A copy assignment operator is trivial if its class has no virtual
// base classes.
Class->setHasTrivialCopyAssignment(false);
} else {
// C++ [class.ctor]p5:
// A constructor is trivial if all the direct base classes of its
// class have trivial constructors.
if (!BaseClass->hasTrivialConstructor())
Class->setHasTrivialConstructor(false);
// C++ [class.copy]p6:
// A copy constructor is trivial if all the direct base classes of its
// class have trivial copy constructors.
if (!BaseClass->hasTrivialCopyConstructor())
Class->setHasTrivialCopyConstructor(false);
// C++ [class.copy]p11:
// A copy assignment operator is trivial if all the direct base classes
// of its class have trivial copy assignment operators.
if (!BaseClass->hasTrivialCopyAssignment())
Class->setHasTrivialCopyAssignment(false);
}
// C++ [class.ctor]p3:
// A destructor is trivial if all the direct base classes of its class
// have trivial destructors.
if (!BaseClass->hasTrivialDestructor())
Class->setHasTrivialDestructor(false);
}
/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is
/// one entry in the base class list of a class specifier, for
/// example:

View File

@ -1091,13 +1091,6 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end();
Base != BaseEnd; ++Base) {
if (!Base->getType()->isDependentType()) {
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
// Make sure to set the attributes from the base.
SetClassDeclAttributesFromBase(Instantiation, BaseDecl,
Base->isVirtual());
InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base));
continue;
}

View File

@ -1996,10 +1996,9 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
if (InitFunctionInstantiation(New, Tmpl))
return true;
CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
New->setAccess(Tmpl->getAccess());
if (Tmpl->isVirtualAsWritten())
Record->setMethodAsVirtual(New);
New->setVirtualAsWritten(true);
// FIXME: attributes
// FIXME: New needs a pointer to Tmpl