diff options
| author | Anders Carlsson <andersca@mac.com> | 2009-12-02 17:15:43 +0000 |
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2009-12-02 17:15:43 +0000 |
| commit | f98849eb8aa991668e5c47eeb7b2899772af3810 (patch) | |
| tree | 11966ec08d59ff029272b1a82e0237c433a1589d /clang/lib/Sema | |
| parent | fffbc0c5d92deee5304a4e0b560e15f36f07b944 (diff) | |
| download | bcm5719-llvm-f98849eb8aa991668e5c47eeb7b2899772af3810.tar.gz bcm5719-llvm-f98849eb8aa991668e5c47eeb7b2899772af3810.zip | |
In Sema, whenever we think that a function is going to cause a vtable to be generated, we mark any virtual implicit member functions as referenced.
llvm-svn: 90327
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 11 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 37 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 5 |
4 files changed, 47 insertions, 14 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 98880e9d5f8..2b48efb4952 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1932,8 +1932,7 @@ public: QualType Argument); bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, - DeclarationName Name, FunctionDecl* &Operator, - bool Diagnose=true); + DeclarationName Name, FunctionDecl* &Operator); /// ActOnCXXDelete - Parsed a C++ 'delete' expression virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc, @@ -2128,6 +2127,12 @@ public: /// as referenced. void MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor); + /// MaybeMarkVirtualImplicitMembersReferenced - If the passed in method is the + /// key function of the record decl, will mark virtual member functions as + /// referenced. + void MaybeMarkVirtualImplicitMembersReferenced(SourceLocation Loc, + CXXMethodDecl *MD); + void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl); virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, @@ -2160,7 +2165,7 @@ public: void CheckConstructor(CXXConstructorDecl *Constructor); QualType CheckDestructorDeclarator(Declarator &D, FunctionDecl::StorageClass& SC); - bool CheckDestructor(CXXDestructorDecl *Destructor, bool Diagnose=true); + bool CheckDestructor(CXXDestructorDecl *Destructor); void CheckConversionDeclarator(Declarator &D, QualType &R, FunctionDecl::StorageClass& SC); DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 76b726fe339..5a7d0060433 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4085,12 +4085,14 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, if (!FD->isInvalidDecl()) DiagnoseUnusedParameters(FD->param_begin(), FD->param_end()); - // C++ [basic.def.odr]p2: - // [...] A virtual member function is used if it is not pure. [...] - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) { + // C++ [basic.def.odr]p2: + // [...] A virtual member function is used if it is not pure. [...] if (Method->isVirtual() && !Method->isPure()) MarkDeclarationReferenced(Method->getLocation(), Method); + MaybeMarkVirtualImplicitMembersReferenced(Method->getLocation(), Method); + } assert(FD == getCurFunctionDecl() && "Function parsing confused"); } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) { assert(MD == getCurMethodDecl() && "Method parsing confused"); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 7df86ee66c3..4db769bd91a 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -15,6 +15,7 @@ #include "Lookup.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/TypeOrdering.h" @@ -2172,7 +2173,6 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { ClassDecl->addDecl(Destructor); AddOverriddenMethods(ClassDecl, Destructor); - CheckDestructor(Destructor, false); } } @@ -2371,7 +2371,7 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { /// CheckDestructor - Checks a fully-formed destructor for well-formedness, /// issuing any diagnostics required. Returns true on error. -bool Sema::CheckDestructor(CXXDestructorDecl *Destructor, bool Diagnose) { +bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { CXXRecordDecl *RD = Destructor->getParent(); if (Destructor->isVirtual()) { @@ -2386,7 +2386,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor, bool Diagnose) { FunctionDecl *OperatorDelete = 0; DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete); - if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete, Diagnose)) + if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) return true; Destructor->setOperatorDelete(OperatorDelete); @@ -3083,7 +3083,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, } else { Constructor->setUsed(); } - return; + + MaybeMarkVirtualImplicitMembersReferenced(CurrentLocation, Constructor); } void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, @@ -4994,3 +4995,31 @@ Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { VD->setDeclaredInCondition(true); return Dcl; } + +void Sema::MaybeMarkVirtualImplicitMembersReferenced(SourceLocation Loc, + CXXMethodDecl *MD) { + // Ignore dependent types. + if (MD->isDependentContext()) + return; + + CXXRecordDecl *RD = MD->getParent(); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + const CXXMethodDecl *KeyFunction = Layout.getKeyFunction(); + + if (!KeyFunction) { + // This record does not have a key function, so we assume that the vtable + // will be emitted when it's used by the constructor. + if (!isa<CXXConstructorDecl>(MD)) + return; + } else if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) { + // We don't have the right key function. + return; + } + + if (CXXDestructorDecl *Dtor = RD->getDestructor(Context)) { + if (Dtor->isImplicit() && Dtor->isVirtual()) + MarkDeclarationReferenced(Loc, Dtor); + } + + // FIXME: Need to handle the virtual assignment operator here too. +} diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f5f712a0a5e..148dc639449 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -775,8 +775,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, DeclarationName Name, - FunctionDecl* &Operator, - bool Diagnose) { + FunctionDecl* &Operator) { LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName); // Try to find operator delete/operator delete[] in class scope. LookupQualifiedName(Found, RD); @@ -796,8 +795,6 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, // We did find operator delete/operator delete[] declarations, but // none of them were suitable. if (!Found.empty()) { - if (!Diagnose) - return true; Diag(StartLoc, diag::err_no_suitable_delete_member_function_found) << Name << RD; |

