[cfe-commits] r75270 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/warn-reorder-ctor-initialization.cpp

Fariborz Jahanian fjahanian at apple.com
Fri Jul 10 13:13:23 PDT 2009


Author: fjahanian
Date: Fri Jul 10 15:13:23 2009
New Revision: 75270

URL: http://llvm.org/viewvc/llvm-project?rev=75270&view=rev
Log:
Patch to build list of inherited virtual base classes 
in their order of construction for each class and use it 
to to check on propery order of base class construction 
under -Wreorder option.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=75270&r1=75269&r2=75270&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Jul 10 15:13:23 2009
@@ -310,6 +310,12 @@
   /// 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
@@ -361,6 +367,15 @@
   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.

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=75270&r1=75269&r2=75270&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Jul 10 15:13:23 2009
@@ -30,7 +30,8 @@
     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 @@
 
   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 {

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=75270&r1=75269&r2=75270&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Jul 10 15:13:23 2009
@@ -825,14 +825,24 @@
                     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)

Modified: cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp?rev=75270&r1=75269&r2=75270&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp Fri Jul 10 15:13:23 2009
@@ -1,18 +1,76 @@
 // 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'}}
+};
+
+





More information about the cfe-commits mailing list