diff options
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 48 | ||||
-rw-r--r-- | test/SemaCXX/abstract.cpp | 13 |
2 files changed, 39 insertions, 22 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 30975bc1a4..9a74b53da9 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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; + } + } } diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp index 20b35da83d..f5ec9ab6ba 100644 --- a/test/SemaCXX/abstract.cpp +++ b/test/SemaCXX/abstract.cpp @@ -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; |