/// 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);
/// 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
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(),
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
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;
}
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) {
void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) {
Method->setVirtualAsWritten(true);
- setAggregate(false);
- setPOD(false);
setEmpty(false);
setPolymorphic(true);
setHasTrivialConstructor(false);
}
}
- // 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
if (!InvalidDecl && getLangOptions().CPlusPlus) {
CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record);
- if (!T->isPODType())
- CXXRecord->setPOD(false);
if (!ZeroWidth)
CXXRecord->setEmpty(false);
if (T->isReferenceType())
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;
}