diff options
| author | Anders Carlsson <andersca@mac.com> | 2009-12-07 08:24:59 +0000 |
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2009-12-07 08:24:59 +0000 |
| commit | 82fccd014a4f2e1fcbde11ed1c39c7fc70f28752 (patch) | |
| tree | 5f295851790b782a5493ec036d49f7b82b050c30 /clang/lib/Sema/SemaDeclCXX.cpp | |
| parent | e1b3e6292a355dafc4757d7cd2f2e04ca71927fa (diff) | |
| download | bcm5719-llvm-82fccd014a4f2e1fcbde11ed1c39c7fc70f28752.tar.gz bcm5719-llvm-82fccd014a4f2e1fcbde11ed1c39c7fc70f28752.zip | |
Rework how virtual member functions are marked. If a class has no key function, we now wait until the end of the translation unit to mark its virtual member functions as references. This lays the groundwork for fixing PR5557.
llvm-svn: 90752
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 59 |
1 files changed, 51 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 1e96bf525ae..bd191ab8c96 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -3163,8 +3163,6 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, } else { Constructor->setUsed(); } - - MaybeMarkVirtualImplicitMembersReferenced(CurrentLocation, Constructor); } void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, @@ -5083,8 +5081,8 @@ Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { return Dcl; } -void Sema::MaybeMarkVirtualImplicitMembersReferenced(SourceLocation Loc, - CXXMethodDecl *MD) { +void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc, + CXXMethodDecl *MD) { // Ignore dependent types. if (MD->isDependentContext()) return; @@ -5095,6 +5093,16 @@ void Sema::MaybeMarkVirtualImplicitMembersReferenced(SourceLocation Loc, if (!RD->isDynamicClass()) return; + if (!MD->isOutOfLine()) { + // The only inline functions we care about are constructors. We also defer + // marking the virtual members as referenced until we've reached the end + // of the translation unit. We do this because we need to know the key + // function of the class in order to determine the key function. + if (isa<CXXConstructorDecl>(MD)) + ClassesWithUnmarkedVirtualMembers.insert(std::make_pair(RD, Loc)); + return; + } + const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); if (!KeyFunction) { @@ -5107,10 +5115,45 @@ void Sema::MaybeMarkVirtualImplicitMembersReferenced(SourceLocation Loc, return; } - if (CXXDestructorDecl *Dtor = RD->getDestructor(Context)) { - if (Dtor->isImplicit() && Dtor->isVirtual()) - MarkDeclarationReferenced(Loc, Dtor); + // Mark the members as referenced. + MarkVirtualMembersReferenced(Loc, RD); + ClassesWithUnmarkedVirtualMembers.erase(RD); +} + +bool Sema::ProcessPendingClassesWithUnmarkedVirtualMembers() { + if (ClassesWithUnmarkedVirtualMembers.empty()) + return false; + + for (std::map<CXXRecordDecl *, SourceLocation>::iterator i = + ClassesWithUnmarkedVirtualMembers.begin(), + e = ClassesWithUnmarkedVirtualMembers.end(); i != e; ++i) { + CXXRecordDecl *RD = i->first; + + const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); + if (KeyFunction) { + // We know that the class has a key function. If the key function was + // declared in this translation unit, then it the class decl would not + // have been in the ClassesWithUnmarkedVirtualMembers map. + continue; + } + + SourceLocation Loc = i->second; + MarkVirtualMembersReferenced(Loc, RD); } - // FIXME: Need to handle the virtual assignment operator here too. + ClassesWithUnmarkedVirtualMembers.clear(); + return true; } + +void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, CXXRecordDecl *RD) { + for (CXXRecordDecl::method_iterator i = RD->method_begin(), + e = RD->method_end(); i != e; ++i) { + CXXMethodDecl *MD = *i; + + // C++ [basic.def.odr]p2: + // [...] A virtual member function is used if it is not pure. [...] + if (MD->isVirtual() && !MD->isPure()) + MarkDeclarationReferenced(Loc, MD); + } +} + |

