Extract a common structure for holding information about the definition
of a C++ record. Exposed a lot of problems where various routines were
silently doing The Wrong Thing (or The Acceptable Thing in The Wrong Order)
when presented with a non-definition. Also cuts down on memory usage.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95330 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 3d690d1..02ad36d 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -25,18 +25,23 @@
// Decl Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//
-CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
- SourceLocation L, IdentifierInfo *Id,
- CXXRecordDecl *PrevDecl,
- SourceLocation TKL)
- : RecordDecl(K, TK, DC, L, Id, PrevDecl, TKL),
- UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
+CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
+ : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
Abstract(false), HasTrivialConstructor(true),
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialDestructor(true), ComputedVisibleConversions(false),
Bases(0), NumBases(0), VBases(0), NumVBases(0),
+ Definition(D) {
+}
+
+CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ CXXRecordDecl *PrevDecl,
+ SourceLocation TKL)
+ : RecordDecl(K, TK, DC, L, Id, PrevDecl, TKL),
+ DefinitionData(PrevDecl ? PrevDecl->DefinitionData : 0),
TemplateOrInstantiation() { }
CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -57,8 +62,11 @@
}
void CXXRecordDecl::Destroy(ASTContext &C) {
- C.Deallocate(Bases);
- C.Deallocate(VBases);
+ if (data().Definition == this) {
+ C.Deallocate(data().Bases);
+ C.Deallocate(data().VBases);
+ C.Deallocate(&data());
+ }
this->RecordDecl::Destroy(C);
}
@@ -69,19 +77,19 @@
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with [...]
// no base classes [...].
- Aggregate = false;
+ data().Aggregate = false;
- if (this->Bases)
- C.Deallocate(this->Bases);
+ if (data().Bases)
+ C.Deallocate(data().Bases);
int vbaseCount = 0;
llvm::SmallVector<const CXXBaseSpecifier*, 8> UniqueVbases;
bool hasDirectVirtualBase = false;
- this->Bases = new(C) CXXBaseSpecifier [NumBases];
- this->NumBases = NumBases;
+ data().Bases = new(C) CXXBaseSpecifier [NumBases];
+ data().NumBases = NumBases;
for (unsigned i = 0; i < NumBases; ++i) {
- this->Bases[i] = *Bases[i];
+ data().Bases[i] = *Bases[i];
// Keep track of inherited vbases for this base class.
const CXXBaseSpecifier *Base = Bases[i];
QualType BaseType = Base->getType();
@@ -130,13 +138,13 @@
}
if (vbaseCount > 0) {
// build AST for inhireted, direct or indirect, virtual bases.
- this->VBases = new (C) CXXBaseSpecifier [vbaseCount];
- this->NumVBases = vbaseCount;
+ data().VBases = new (C) CXXBaseSpecifier [vbaseCount];
+ data().NumVBases = vbaseCount;
for (int i = 0; i < vbaseCount; i++) {
QualType QT = UniqueVbases[i]->getType();
CXXRecordDecl *VBaseClassDecl
= cast<CXXRecordDecl>(QT->getAs<RecordType>()->getDecl());
- this->VBases[i] =
+ data().VBases[i] =
CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
VBaseClassDecl->getTagKind() == RecordDecl::TK_class,
UniqueVbases[i]->getAccessSpecifier(), QT);
@@ -239,32 +247,32 @@
CXXConstructorDecl *ConDecl) {
assert(!ConDecl->isImplicit() && "addedConstructor - not for implicit decl");
// Note that we have a user-declared constructor.
- UserDeclaredConstructor = true;
+ data().UserDeclaredConstructor = true;
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with no
// user-declared constructors (12.1) [...].
- Aggregate = false;
+ data().Aggregate = false;
// C++ [class]p4:
// A POD-struct is an aggregate class [...]
- PlainOldData = false;
+ 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.
- HasTrivialConstructor = false;
+ data().HasTrivialConstructor = false;
// Note when we have a user-declared copy constructor, which will
// suppress the implicit declaration of a copy constructor.
if (ConDecl->isCopyConstructor()) {
- UserDeclaredCopyConstructor = true;
+ data().UserDeclaredCopyConstructor = true;
// C++ [class.copy]p6:
// A copy constructor is trivial if it is implicitly declared.
// FIXME: C++0x: don't do this for "= default" copy constructors.
- HasTrivialCopyConstructor = false;
+ data().HasTrivialCopyConstructor = false;
}
}
@@ -295,17 +303,17 @@
OpDecl->setCopyAssignment(true);
// Suppress the implicit declaration of a copy constructor.
- UserDeclaredCopyAssignment = true;
+ data().UserDeclaredCopyAssignment = true;
// C++ [class.copy]p11:
// A copy assignment operator is trivial if it is implicitly declared.
// FIXME: C++0x: don't do this for "= default" copy operators.
- HasTrivialCopyAssignment = false;
+ data().HasTrivialCopyAssignment = false;
// C++ [class]p4:
// A POD-struct is an aggregate class that [...] has no user-defined copy
// assignment operator [...].
- PlainOldData = false;
+ data().PlainOldData = false;
}
void
@@ -415,42 +423,42 @@
const UnresolvedSetImpl *CXXRecordDecl::getVisibleConversionFunctions() {
// If root class, all conversions are visible.
if (bases_begin() == bases_end())
- return &Conversions;
+ return &data().Conversions;
// If visible conversion list is already evaluated, return it.
- if (ComputedVisibleConversions)
- return &VisibleConversions;
+ if (data().ComputedVisibleConversions)
+ return &data().VisibleConversions;
llvm::SmallPtrSet<CanQualType, 8> TopConversionsTypeSet;
collectConversionFunctions(TopConversionsTypeSet);
getNestedVisibleConversionFunctions(this, TopConversionsTypeSet,
TopConversionsTypeSet);
- ComputedVisibleConversions = true;
- return &VisibleConversions;
+ data().ComputedVisibleConversions = true;
+ return &data().VisibleConversions;
}
void CXXRecordDecl::addVisibleConversionFunction(
CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
- VisibleConversions.addDecl(ConvDecl);
+ data().VisibleConversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addVisibleConversionFunction(
FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");
- VisibleConversions.addDecl(ConvDecl);
+ data().VisibleConversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addConversionFunction(CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
- Conversions.addDecl(ConvDecl);
+ data().Conversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addConversionFunction(FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");
- Conversions.addDecl(ConvDecl);
+ data().Conversions.addDecl(ConvDecl);
}