]> granicus.if.org Git - clang/commitdiff
Rewrite PureVirtualMethodCollector to use the overridden methods. Fixes <rdar://probl...
authorAnders Carlsson <andersca@mac.com>
Sun, 17 May 2009 00:00:05 +0000 (00:00 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 17 May 2009 00:00:05 +0000 (00:00 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71970 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/abstract.cpp

index 30975bc1a4c4051e61fc4fce60eb67f1fdece818..9a74b53da9592b428f07d72b30db075b7fa22e5a 100644 (file)
@@ -786,34 +786,38 @@ namespace {
     }
     
     // Next, zero out any pure virtual methods that this class overrides.
-    for (size_t i = 0, e = Methods.size(); i != e; ++i) {
-      const CXXMethodDecl *VMD = dyn_cast_or_null<CXXMethodDecl>(Methods[i]);
-      if (!VMD)
-        continue;
-      
-      DeclContext::lookup_const_iterator I, E;
-      for (llvm::tie(I, E) = RD->lookup(Context, VMD->getDeclName()); 
-           I != E; ++I) {
-        if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*I)) {
-          if (Context.getCanonicalType(MD->getType()) == 
-              Context.getCanonicalType(VMD->getType())) {
-            // We did find a matching method, which means that this is not a
-            // pure virtual method in the current class. Zero it out.
-            Methods[i] = 0;
-          }
-        }
-      }
-    }
-    
-    // Finally, add pure virtual methods from this class.
+    typedef llvm::SmallPtrSet<const CXXMethodDecl*, 4> MethodSetTy;
+  
+    MethodSetTy OverriddenMethods;
+    size_t MethodsSize = Methods.size();
+
     for (RecordDecl::decl_iterator i = RD->decls_begin(Context), 
-                                   e = RD->decls_end(Context); 
+         e = RD->decls_end(Context); 
          i != e; ++i) {
+      // Traverse the record, looking for methods.
       if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*i)) {
-        if (MD->isPure())
+        // If the method is pre virtual, add it to the methods vector.
+        if (MD->isPure()) {
           Methods.push_back(MD);
+          continue;
+        }
+        
+        // Otherwise, record all the overridden methods in our set.
+        for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+             E = MD->end_overridden_methods(); I != E; ++I) {
+          // Keep track of the overridden methods.
+          OverriddenMethods.insert(*I);
+        }
       }
     }
+    
+    // Now go through the methods and zero out all the ones we know are 
+    // overridden.
+    for (size_t i = 0, e = MethodsSize; i != e; ++i) {
+      if (OverriddenMethods.count(Methods[i]))
+        Methods[i] = 0;
+    }
+    
   }
 }
 
index 20b35da83dbef1be1608b036105d10be5270c060..f5ec9ab6ba4289fa0a5d0d164347b9e862d6163e 100644 (file)
@@ -82,3 +82,16 @@ namespace N {
 class Abstract {
  virtual void f() = 0; // expected-note {{pure virtual function 'f'}}
 };
+
+// <rdar://problem/6854087>
+class foo {
+public:
+       virtual foo *getFoo() = 0;
+};
+
+class bar : public foo {
+public:
+       virtual bar *getFoo();
+};
+
+bar x;