summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/DeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/DeclCXX.cpp')
-rw-r--r--clang/lib/AST/DeclCXX.cpp72
1 files changed, 69 insertions, 3 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index f525667ad0a..b7051f8d2c5 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -30,7 +30,8 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
Aggregate(true), PlainOldData(true), Polymorphic(false), Abstract(false),
HasTrivialConstructor(true), HasTrivialDestructor(true),
- Bases(0), NumBases(0), Conversions(DC, DeclarationName()),
+ Bases(0), NumBases(0), VBases(0), NumVBases(0),
+ Conversions(DC, DeclarationName()),
TemplateOrInstantiation() { }
CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -62,11 +63,76 @@ CXXRecordDecl::setBases(ASTContext &C,
if (this->Bases)
C.Deallocate(this->Bases);
-
+
+ int vbaseCount = 0;
+ llvm::SmallVector<const CXXBaseSpecifier*, 8> UniqueVbases;
+ bool hasDirectVirtualBase = false;
+
this->Bases = new(C) CXXBaseSpecifier [NumBases];
this->NumBases = NumBases;
- for (unsigned i = 0; i < NumBases; ++i)
+ for (unsigned i = 0; i < NumBases; ++i) {
this->Bases[i] = *Bases[i];
+ // Keep track of inherited vbases for this base class.
+ const CXXBaseSpecifier *Base = Bases[i];
+ QualType BaseType = Base->getType();
+ // Skip template types.
+ // FIXME. This means that this list must be rebuilt during template
+ // instantiation.
+ if (BaseType->isDependentType())
+ continue;
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(BaseType->getAsRecordType()->getDecl());
+ if (Base->isVirtual())
+ hasDirectVirtualBase = true;
+ for (CXXRecordDecl::base_class_iterator VBase =
+ BaseClassDecl->vbases_begin(),
+ E = BaseClassDecl->vbases_end(); VBase != E; ++VBase) {
+ // Add this vbase to the array of vbases for current class if it is
+ // not already in the list.
+ // FIXME. Note that we do a linear search as number of such classes are
+ // very few.
+ int i;
+ for (i = 0; i < vbaseCount; ++i)
+ if (UniqueVbases[i]->getType() == VBase->getType())
+ break;
+ if (i == vbaseCount) {
+ UniqueVbases.push_back(VBase);
+ ++vbaseCount;
+ }
+ }
+ }
+ if (hasDirectVirtualBase) {
+ // Iterate one more time through the direct bases and add the virtual
+ // base to the list of vritual bases for current class.
+ for (unsigned i = 0; i < NumBases; ++i) {
+ const CXXBaseSpecifier *VBase = Bases[i];
+ if (!VBase->isVirtual())
+ continue;
+ int i;
+ for (i = 0; i < vbaseCount; ++i)
+ if (UniqueVbases[i]->getType() == VBase->getType())
+ break;
+ if (i == vbaseCount) {
+ UniqueVbases.push_back(VBase);
+ ++vbaseCount;
+ }
+ }
+ }
+ if (vbaseCount > 0) {
+ // build AST for inhireted, direct or indirect, virtual bases.
+ this->VBases = new(C) CXXBaseSpecifier [vbaseCount];
+ this->NumVBases = vbaseCount;
+ for (int i = 0; i < vbaseCount; i++) {
+ QualType QT = UniqueVbases[i]->getType();
+ CXXRecordDecl *VBaseClassDecl
+ = cast<CXXRecordDecl>(QT->getAsRecordType()->getDecl());
+ this->VBases[i] =
+ *new CXXBaseSpecifier(
+ VBaseClassDecl->getSourceRange(), true,
+ VBaseClassDecl->getTagKind() == RecordDecl::TK_class,
+ UniqueVbases[i]->getAccessSpecifier(), QT);
+ }
+ }
}
bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
OpenPOWER on IntegriCloud