diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2010-03-02 21:28:26 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2010-03-02 21:28:26 +0000 |
commit | 7b9a5aa7c0d76f577699d25ce6afe21ecccb60b7 (patch) | |
tree | 8070e7af00c3aba3ee672785c5e8110998a7324f | |
parent | 0268181bf8e1e561e2a51474ffad9f46b1c3f85d (diff) |
During codegen assert that any copy assignment, destructor or constructor that
we need to synthesize has been marked as used by Sema.
Change Sema to avoid these asserts.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97589 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 118 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 12 | ||||
-rw-r--r-- | test/SemaCXX/implicit-virtual-member-functions.cpp | 4 | ||||
-rw-r--r-- | test/SemaTemplate/virtual-member-functions.cpp | 8 |
5 files changed, 102 insertions, 52 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 5236619088..91c7322c67 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -752,14 +752,20 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, // A called constructor which has no definition or declaration need be // synthesized. else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { - if (CD->isImplicit()) + if (CD->isImplicit()) { + assert (CD->isUsed()); DeferredDeclsToEmit.push_back(D); + } } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) { - if (DD->isImplicit()) + if (DD->isImplicit()) { + assert (DD->isUsed()); DeferredDeclsToEmit.push_back(D); + } } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { - if (MD->isCopyAssignment() && MD->isImplicit()) + if (MD->isCopyAssignment() && MD->isImplicit()) { + assert (MD->isUsed()); DeferredDeclsToEmit.push_back(D); + } } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 20a8303ba4..574b225027 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1638,8 +1638,22 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, new (Context) CXXBaseOrMemberInitializer*[NumInitializers]; Constructor->setBaseOrMemberInitializers(baseOrMemberInitializers); - for (unsigned Idx = 0; Idx < NumInitializers; ++Idx) - baseOrMemberInitializers[Idx] = AllToInit[Idx]; + for (unsigned Idx = 0; Idx < NumInitializers; ++Idx) { + CXXBaseOrMemberInitializer *Member = AllToInit[Idx]; + baseOrMemberInitializers[Idx] = Member; + if (!Member->isBaseInitializer()) + continue; + const Type *BaseType = Member->getBaseClass(); + const RecordType *RT = BaseType->getAs<RecordType>(); + if (!RT) + continue; + CXXRecordDecl *BaseClassDecl = + cast<CXXRecordDecl>(RT->getDecl()); + if (BaseClassDecl->hasTrivialDestructor()) + continue; + CXXDestructorDecl *DD = BaseClassDecl->getDestructor(Context); + MarkDeclarationReferenced(Constructor->getLocation(), DD); + } } return HadError; @@ -5791,55 +5805,74 @@ Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { return Dcl; } -void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc, - CXXMethodDecl *MD) { +static bool needsVtable(CXXMethodDecl *MD, ASTContext &Context) { // Ignore dependent types. if (MD->isDependentContext()) - return; - + return false; + + // Ignore declarations that are not definitions. + if (!MD->isThisDeclarationADefinition()) + return false; + CXXRecordDecl *RD = MD->getParent(); - + // Ignore classes without a vtable. if (!RD->isDynamicClass()) - return; + return false; - // Ignore declarations that are not definitions. - if (!MD->isThisDeclarationADefinition()) - return; - - if (isa<CXXConstructorDecl>(MD)) { - switch (MD->getParent()->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - // Classes that aren't instantiations of templates don't need their - // virtual methods marked until we see the definition of the key - // function. - return; - - case TSK_ImplicitInstantiation: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - // This is a constructor of a class template; mark all of the virtual - // members as referenced to ensure that they get instantiatied. - break; - } - } else if (!MD->isOutOfLine()) { - // Consider only out-of-line definitions of member functions. When we see - // an inline definition, it's too early to compute the key function. - return; - } else if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD)) { - // If this is not the key function, we don't need to mark virtual members. - if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) - return; - } else { - // The class has no key function, so we've already noted that we need to - // mark the virtual members of this class. - return; + switch (MD->getParent()->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + // Classes that aren't instantiations of templates don't need their + // virtual methods marked until we see the definition of the key + // function. + break; + + case TSK_ImplicitInstantiation: + // This is a constructor of a class template; mark all of the virtual + // members as referenced to ensure that they get instantiatied. + if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) + return true; + break; + + case TSK_ExplicitInstantiationDeclaration: + return true; //FIXME: This looks wrong. + + case TSK_ExplicitInstantiationDefinition: + // This is method of a explicit instantiation; mark all of the virtual + // members as referenced to ensure that they get instantiatied. + return true; } - + + // Consider only out-of-line definitions of member functions. When we see + // an inline definition, it's too early to compute the key function. + if (!MD->isOutOfLine()) + return false; + + const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); + + // If there is no key function, we will need a copy of the vtable. + if (!KeyFunction) + return true; + + // If this is the key function, we need to mark virtual members. + if (KeyFunction->getCanonicalDecl() == MD->getCanonicalDecl()) + return true; + + return false; +} + +void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc, + CXXMethodDecl *MD) { + CXXRecordDecl *RD = MD->getParent(); + // We will need to mark all of the virtual members as referenced to build the // vtable. - ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc)); + // We actually call MarkVirtualMembersReferenced instead of adding to + // ClassesWithUnmarkedVirtualMembers because this marking is needed by + // codegen that will happend before we finish parsing the file. + if (needsVtable(MD, Context)) + MarkVirtualMembersReferenced(Loc, RD); } bool Sema::ProcessPendingClassesWithUnmarkedVirtualMembers() { @@ -5867,4 +5900,3 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, CXXRecordDecl *RD) { MarkDeclarationReferenced(Loc, MD); } } - diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 23d52adf91..5f4601961c 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -426,6 +426,18 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { : diag::err_throw_incomplete) << E->getSourceRange())) return true; + + // FIXME: This is just a hack to mark the copy constructor referenced. + // This should go away when the next FIXME is fixed. + const RecordType *RT = Ty->getAs<RecordType>(); + if (!RT) + return false; + + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (RD->hasTrivialCopyConstructor()) + return false; + CXXConstructorDecl *CopyCtor = RD->getCopyConstructor(Context, 0); + MarkDeclarationReferenced(ThrowLoc, CopyCtor); } // FIXME: Construct a temporary here. diff --git a/test/SemaCXX/implicit-virtual-member-functions.cpp b/test/SemaCXX/implicit-virtual-member-functions.cpp index 4ae9eae3b3..1bb5adbb86 100644 --- a/test/SemaCXX/implicit-virtual-member-functions.cpp +++ b/test/SemaCXX/implicit-virtual-member-functions.cpp @@ -15,9 +15,9 @@ void B::f() { // expected-note {{implicit default destructor for 'struct B' firs struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}} C(); void operator delete(void *, int); // expected-note {{'operator delete' declared here}} -}; // expected-note {{implicit default destructor for 'struct C' first required here}} +}; -C::C() { } +C::C() { } // expected-note {{implicit default destructor for 'struct C' first required here}} struct D : A { // expected-error {{no suitable member 'operator delete' in 'D'}} void operator delete(void *, int); // expected-note {{'operator delete' declared here}} diff --git a/test/SemaTemplate/virtual-member-functions.cpp b/test/SemaTemplate/virtual-member-functions.cpp index db243130bb..58ac08c0b2 100644 --- a/test/SemaTemplate/virtual-member-functions.cpp +++ b/test/SemaTemplate/virtual-member-functions.cpp @@ -14,7 +14,7 @@ template<class T> int A<T>::a(T x) { } void f(A<int> x) { - x.anchor(); + x.anchor(); // expected-note{{in instantiation of member function 'PR5557::A<int>::anchor' requested here}} } template<typename T> @@ -36,10 +36,10 @@ struct Base { template<typename T> struct Derived : Base<T> { - virtual void foo() { } + virtual void foo() { } // expected-note {{in instantiation of member function 'Base<int>::~Base' requested here}} }; -template struct Derived<int>; // expected-note{{instantiation}} +template struct Derived<int>; template<typename T> struct HasOutOfLineKey { @@ -52,4 +52,4 @@ T *HasOutOfLineKey<T>::f(float *fp) { return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}} } -HasOutOfLineKey<int> out_of_line; +HasOutOfLineKey<int> out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::HasOutOfLineKey' requested here}} |