Centralize the management of CXXRecordDecl::DefinitionData's Aggregate

and PlainOldData bits in CXXRecordDecl itself. Another milepost on the
road toward <rdar://problem/8459981>.

llvm-svn: 114921
This commit is contained in:
Douglas Gregor 2010-09-27 23:16:44 +00:00
parent 185051cb8e
commit 1be93f5143
4 changed files with 48 additions and 35 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; }
/// setAggregate - Set whether this class is an aggregate (C++
/// [dcl.init.aggr]).
void setAggregate(bool Agg) { data().Aggregate = Agg; }
/// setMethodAsVirtual - Make input method virtual and set the necesssary
/// special function bits and other bits accordingly.
void setMethodAsVirtual(FunctionDecl *Method);
@ -702,9 +698,6 @@ public:
/// user-defined destructor.
bool isPOD() const { return data().PlainOldData; }
/// setPOD - Set whether this class is a POD-type (C++ [class]p4).
void setPOD(bool POD) { data().PlainOldData = POD; }
/// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which
/// means it has a virtual function, virtual base, data member (other than
/// 0-width bit-field) or inherits from a non-empty class. Does NOT include

View File

@ -97,6 +97,14 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
// C++ [dcl.init.aggr]p1:
// An aggregate is [...] a class with [...] no base classes [...].
data().Aggregate = false;
// C++ [class]p4:
// A POD-struct is an aggregate class...
data().PlainOldData = false;
// Now go through all virtual bases of this base and add them.
for (CXXRecordDecl::base_class_iterator VBase =
BaseClassDecl->vbases_begin(),
@ -268,6 +276,18 @@ CXXRecordDecl::addedMember(Decl *D) {
if (FunTmpl)
D = FunTmpl->getTemplatedDecl();
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
if (Method->isVirtual()) {
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class with [...] no virtual functions.
data().Aggregate = false;
// C++ [class]p4:
// A POD-struct is an aggregate class...
data().PlainOldData = false;
}
}
if (D->isImplicit()) {
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
// If this is the implicit default constructor, note that we have now
@ -334,6 +354,12 @@ CXXRecordDecl::addedMember(Decl *D) {
if (isa<CXXDestructorDecl>(D)) {
data().DeclaredDestructor = true;
data().UserDeclaredDestructor = true;
// C++ [class]p4:
// A POD-struct is an aggregate class that has [...] no user-defined
// destructor.
data().PlainOldData = false;
return;
}
@ -382,6 +408,28 @@ CXXRecordDecl::addedMember(Decl *D) {
return;
}
// Handle non-static data members.
if (FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with [...] no
// private or protected non-static data members (clause 11).
//
// A POD must be an aggregate.
if (D->getAccess() == AS_private || D->getAccess() == AS_protected) {
data().Aggregate = false;
data().PlainOldData = false;
}
// C++ [class]p9:
// A POD struct is a class that is both a trivial class and a
// standard-layout class, and has no non-static data members of type
// non-POD struct, non-POD union (or array of such types).
ASTContext &Context = getASTContext();
QualType T = Context.getBaseElementType(Field->getType());
if (!T->isPODType())
data().PlainOldData = false;
}
}
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
@ -566,8 +614,6 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) {
void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) {
Method->setVirtualAsWritten(true);
setAggregate(false);
setPOD(false);
setEmpty(false);
setPolymorphic(true);
setHasTrivialConstructor(false);

View File

@ -3931,10 +3931,6 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
}
// C++ [class]p4: A POD-struct is an aggregate class that has [...] no
// user-defined destructor.
Record->setPOD(false);
// 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
@ -6194,8 +6190,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
if (!InvalidDecl && getLangOptions().CPlusPlus) {
CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record);
if (!T->isPODType())
CXXRecord->setPOD(false);
if (!ZeroWidth)
CXXRecord->setEmpty(false);
if (T->isReferenceType())
@ -6235,18 +6229,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
Diag(Loc, diag::warn_attribute_weak_on_field);
NewFD->setAccess(AS);
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with [...] no
// private or protected non-static data members (clause 11).
// A POD must be an aggregate.
if (getLangOptions().CPlusPlus &&
(AS == AS_private || AS == AS_protected)) {
CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record);
CXXRecord->setAggregate(false);
CXXRecord->setPOD(false);
}
return NewFD;
}

View File

@ -527,14 +527,6 @@ void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class,
if (BaseClass->isPolymorphic())
Class->setPolymorphic(true);
// C++ [dcl.init.aggr]p1:
// An aggregate is [...] a class with [...] no base classes [...].
Class->setAggregate(false);
// C++ [class]p4:
// A POD-struct is an aggregate class...
Class->setPOD(false);
if (BaseIsVirtual) {
// C++ [class.ctor]p5:
// A constructor is trivial if its class has no virtual base classes.