/// NumBases - The number of base class specifiers in Bases.
unsigned NumBases;
+ /// VBases - direct and indirect virtual base classes of this class.
+ CXXBaseSpecifier *VBases;
+
+ /// NumVBases - The number of virtual base class specifiers in VBases.
+ unsigned NumVBases;
+
/// Conversions - Overload set containing the conversion functions
/// of this C++ class (but not its inherited conversion
/// functions). Each of the entries in this overload set is a
base_class_const_iterator bases_begin() const { return Bases; }
base_class_iterator bases_end() { return Bases + NumBases; }
base_class_const_iterator bases_end() const { return Bases + NumBases; }
+
+ /// getNumVBases - Retrieves the number of virtual base classes of this
+ /// class.
+ unsigned getNumVBases() const { return NumVBases; }
+
+ base_class_iterator vbases_begin() { return VBases; }
+ base_class_const_iterator vbases_begin() const { return VBases; }
+ base_class_iterator vbases_end() { return VBases + NumVBases; }
+ base_class_const_iterator vbases_end() const { return VBases + NumVBases; }
/// hasConstCopyConstructor - Determines whether this class has a
/// copy constructor that accepts a const-qualified argument.
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,
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 {
NumMemInits);
// Also issue warning if order of ctor-initializer list does not match order
// of 1) base class declarations and 2) order of non-static data members.
- // FIXME. proper handling in the presense of virtual base class.
llvm::SmallVector<const void*, 32> AllBaseOrMembers;
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(Constructor->getDeclContext());
+ // Push virtual bases before others.
+ for (CXXRecordDecl::base_class_iterator VBase =
+ ClassDecl->vbases_begin(),
+ E = ClassDecl->vbases_end(); VBase != E; ++VBase)
+ AllBaseOrMembers.push_back(VBase->getType()->getAsRecordType());
+
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base)
+ E = ClassDecl->bases_end(); Base != E; ++Base) {
+ // Virtuals are alread in the virtual base list and are constructed
+ // first.
+ if (Base->isVirtual())
+ continue;
AllBaseOrMembers.push_back(Base->getType()->getAsRecordType());
+ }
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
E = ClassDecl->field_end(); Field != E; ++Field)
// RUN: clang-cc -fsyntax-only -Wreorder -verify %s
-struct B {};
+struct BB {};
-struct B1 {};
+struct BB1 {};
-class complex : public B, B1 {
+class complex : public BB, BB1 {
public:
complex() : s2(1), // expected-warning {{member 's2' will be initialized after}}
s1(1) , // expected-note {{field s1}}
s3(3), // expected-warning {{member 's3' will be initialized after}}
- B1(), // expected-note {{base 'struct B1'}} \
- // expected-warning {{base class 'struct B1' will be initialized after}}
- B() {} // expected-note {{base 'struct B'}}
+ BB1(), // expected-note {{base 'struct BB1'}} \
+ // expected-warning {{base class 'struct BB1' will be initialized after}}
+ BB() {} // expected-note {{base 'struct BB'}}
int s1;
int s2;
int s3;
};
+
+
+// testing virtual bases.
+
+
+struct V {
+ V();
+};
+
+struct A : public virtual V {
+ A();
+};
+
+struct B : public virtual V {
+ B();
+};
+
+struct Diamond : public A, public B {
+ Diamond() : A(), B() {}
+};
+
+
+struct C : public A, public B, private virtual V {
+ C() { }
+};
+
+
+struct D : public A, public B {
+ D() : A(), V() { } // expected-warning {{base class 'struct A' will be initialized after}} \
+ // expected-note {{base 'struct V'}}
+};
+
+
+struct E : public A, public B, private virtual V {
+ E() : A(), V() { } // expected-warning {{base class 'struct A' will be initialized after}} \
+ // expected-note {{base 'struct V'}}
+};
+
+
+struct A1 {
+ A1();
+};
+
+struct B1 {
+ B1();
+};
+
+struct F : public A1, public B1, private virtual V {
+ F() : A1(), V() { } // expected-warning {{base class 'struct A1' will be initialized after}} \
+ // expected-note {{base 'struct V'}}
+};
+
+struct X : public virtual A, virtual V, public virtual B {
+ X(): A(), V(), B() {} // expected-warning {{base class 'struct A' will be initialized after}} \
+ // expected-note {{base 'struct V'}}
+};
+
+