[cfe-commits] r99806 - in /cfe/trunk: lib/AST/DeclCXX.cpp test/SemaCXX/warn-reorder-ctor-initialization.cpp

Anders Carlsson andersca at mac.com
Sun Mar 28 22:13:12 PDT 2010


Author: andersca
Date: Mon Mar 29 00:13:12 2010
New Revision: 99806

URL: http://llvm.org/viewvc/llvm-project?rev=99806&view=rev
Log:
Fix a nasty bug in the virtual base computation which would lead to us initializing virtual bases in the wrong order.

Modified:
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=99806&r1=99805&r2=99806&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Mar 29 00:13:12 2010
@@ -83,9 +83,11 @@
   if (data().Bases)
     C.Deallocate(data().Bases);
 
-  int vbaseCount = 0;
-  llvm::SmallVector<const CXXBaseSpecifier*, 8> UniqueVbases;
-  bool hasDirectVirtualBase = false;
+  // The set of seen virtual base types.
+  llvm::SmallPtrSet<QualType, 8> SeenVBaseTypes;
+  
+  // The virtual bases of this class.
+  llvm::SmallVector<const CXXBaseSpecifier *, 8> VBases;
 
   data().Bases = new(C) CXXBaseSpecifier [NumBases];
   data().NumBases = NumBases;
@@ -99,58 +101,44 @@
       continue;
     CXXRecordDecl *BaseClassDecl
       = cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
-    if (Base->isVirtual())
-      hasDirectVirtualBase = true;
+
+    // Now go through all virtual bases of this base and add them.
     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;
-      }
+      // Add this base if it's not already in the list.
+      if (SeenVBaseTypes.insert(VBase->getType()))
+        VBases.push_back(VBase);
     }
-  }
-  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 j;
-      for (j = 0; j < vbaseCount; ++j)
-        if (UniqueVbases[j]->getType() == VBase->getType())
-          break;
-      if (j == vbaseCount) {
-        UniqueVbases.push_back(VBase);
-        ++vbaseCount;
-      }
+
+    if (Base->isVirtual()) {
+      // Add this base if it's not already in the list.
+      if (SeenVBaseTypes.insert(BaseType))
+          VBases.push_back(Base);
     }
+
   }
-  if (vbaseCount > 0) {
-    // build AST for inhireted, direct or indirect, virtual bases.
-    data().VBases = new (C) CXXBaseSpecifier [vbaseCount];
-    data().NumVBases = vbaseCount;
-    for (int i = 0; i < vbaseCount; i++) {
-      QualType QT = UniqueVbases[i]->getType();
-      // Skip dependent types; we can't do any checking on them now.
-      if (QT->isDependentType())
-        continue;
-      CXXRecordDecl *VBaseClassDecl
-        = cast<CXXRecordDecl>(QT->getAs<RecordType>()->getDecl());
-      data().VBases[i] =
-        CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
-                         VBaseClassDecl->getTagKind() == RecordDecl::TK_class,
-                         UniqueVbases[i]->getAccessSpecifier(), QT);
-    }
+  
+  if (VBases.empty())
+    return;
+
+  // Create base specifier for any direct or indirect virtual bases.
+  data().VBases = new (C) CXXBaseSpecifier[VBases.size()];
+  data().NumVBases = VBases.size();
+  for (int I = 0, E = VBases.size(); I != E; ++I) {
+    QualType VBaseType = VBases[I]->getType();
+    
+    // Skip dependent types; we can't do any checking on them now.
+    if (VBaseType->isDependentType())
+      continue;
+
+    CXXRecordDecl *VBaseClassDecl
+      = cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
+
+    data().VBases[I] =
+      CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
+                       VBaseClassDecl->getTagKind() == RecordDecl::TK_class,
+                       VBases[I]->getAccessSpecifier(), VBaseType);
   }
 }
 

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=99806&r1=99805&r2=99806&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-reorder-ctor-initialization.cpp Mon Mar 29 00:13:12 2010
@@ -87,3 +87,15 @@
   union {int a,b;};
   Anon3() : b(1) {}
 };
+
+namespace T1 {
+
+struct S1 { };
+struct S2: virtual S1 { };
+struct S3 { };
+
+struct S4: virtual S3, S2 {
+  S4() : S2(), // expected-warning {{base class 'T1::S2' will be initialized after}}
+    S3() { }; // expected-note {{base 'T1::S3'}}
+};
+}





More information about the cfe-commits mailing list