forked from OSchip/llvm-project
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. llvm-svn: 97589
This commit is contained in:
parent
f61e34d120
commit
70e040d552
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
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;
|
||||
return false;
|
||||
|
||||
CXXRecordDecl *RD = MD->getParent();
|
||||
|
||||
// Ignore classes without a vtable.
|
||||
if (!RD->isDynamicClass())
|
||||
return false;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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}}
|
||||
|
|
Loading…
Reference in New Issue