forked from OSchip/llvm-project
Fix marking of virtual members for nested classes whose first non-pure virtual function has a body inlined in the class
llvm-svn: 92855
This commit is contained in:
parent
2cdb806fd8
commit
ccecc1bb43
|
@ -1490,52 +1490,8 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
|
|||
return;
|
||||
}
|
||||
|
||||
llvm::GlobalVariable::LinkageTypes Linkage =
|
||||
llvm::GlobalVariable::InternalLinkage;
|
||||
if (RD->isInAnonymousNamespace() || !RD->hasLinkage())
|
||||
Linkage = llvm::GlobalVariable::InternalLinkage;
|
||||
else if (KeyFunction && !MD->isInlined()) {
|
||||
switch (MD->getTemplateSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
Linkage = llvm::GlobalVariable::ExternalLinkage;
|
||||
break;
|
||||
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
Linkage = llvm::GlobalVariable::WeakODRLinkage;
|
||||
break;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
// FIXME: Use available_externally linkage. However, this currently
|
||||
// breaks LLVM's build due to undefined symbols.
|
||||
// Linkage = llvm::GlobalVariable::AvailableExternallyLinkage;
|
||||
Linkage = llvm::GlobalVariable::WeakODRLinkage;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (KeyFunction)
|
||||
Linkage = llvm::GlobalVariable::WeakODRLinkage;
|
||||
else {
|
||||
Linkage = llvm::GlobalVariable::WeakODRLinkage;
|
||||
|
||||
switch (RD->getTemplateSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
break;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
// FIXME: Use available_externally linkage. However, this currently
|
||||
// breaks LLVM's build due to undefined symbols.
|
||||
// Linkage = llvm::GlobalVariable::AvailableExternallyLinkage;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the data.
|
||||
GenerateClassData(Linkage, RD);
|
||||
GenerateClassData(CGM.getVtableLinkage(RD), RD);
|
||||
|
||||
for (CXXRecordDecl::method_iterator i = RD->method_begin(),
|
||||
e = RD->method_end(); i != e; ++i) {
|
||||
|
|
|
@ -887,6 +887,60 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) {
|
|||
EmitGlobalVarDefinition(D);
|
||||
}
|
||||
|
||||
llvm::GlobalVariable::LinkageTypes
|
||||
CodeGenModule::getVtableLinkage(const CXXRecordDecl *RD) {
|
||||
// Get the key function.
|
||||
const CXXMethodDecl *KeyFunction = getContext().getKeyFunction(RD);
|
||||
|
||||
if (KeyFunction) {
|
||||
const FunctionDecl *Def = 0;
|
||||
if (KeyFunction->getBody(Def))
|
||||
KeyFunction = cast<CXXMethodDecl>(Def);
|
||||
}
|
||||
|
||||
if (RD->isInAnonymousNamespace() || !RD->hasLinkage())
|
||||
return llvm::GlobalVariable::InternalLinkage;
|
||||
else if (KeyFunction) {
|
||||
switch (KeyFunction->getTemplateSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
if (KeyFunction->isInlined())
|
||||
return llvm::GlobalVariable::WeakODRLinkage;
|
||||
|
||||
return llvm::GlobalVariable::ExternalLinkage;
|
||||
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return llvm::GlobalVariable::WeakODRLinkage;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
// FIXME: Use available_externally linkage. However, this currently
|
||||
// breaks LLVM's build due to undefined symbols.
|
||||
// return llvm::GlobalVariable::AvailableExternallyLinkage;
|
||||
return llvm::GlobalVariable::WeakODRLinkage;
|
||||
}
|
||||
} else if (KeyFunction) {
|
||||
return llvm::GlobalVariable::WeakODRLinkage;
|
||||
} else {
|
||||
switch (RD->getTemplateSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return llvm::GlobalVariable::WeakODRLinkage;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
// FIXME: Use available_externally linkage. However, this currently
|
||||
// breaks LLVM's build due to undefined symbols.
|
||||
// return llvm::GlobalVariable::AvailableExternallyLinkage;
|
||||
return llvm::GlobalVariable::WeakODRLinkage;
|
||||
}
|
||||
}
|
||||
|
||||
// Silence GCC warning.
|
||||
return llvm::GlobalVariable::WeakODRLinkage;
|
||||
}
|
||||
|
||||
static CodeGenModule::GVALinkage
|
||||
GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
|
||||
// Everything located semantically within an anonymous namespace is
|
||||
|
|
|
@ -407,6 +407,10 @@ public:
|
|||
GVA_TemplateInstantiation
|
||||
};
|
||||
|
||||
/// getVtableLinkage - Return the appropriate linkage for the vtable, VTT,
|
||||
/// and type information of the given class.
|
||||
llvm::GlobalVariable::LinkageTypes getVtableLinkage(const CXXRecordDecl *RD);
|
||||
|
||||
private:
|
||||
/// UniqueMangledName - Unique a name by (if necessary) inserting it into the
|
||||
/// MangledNames string map.
|
||||
|
|
|
@ -5693,14 +5693,40 @@ void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc,
|
|||
if (!RD->isDynamicClass())
|
||||
return;
|
||||
|
||||
// Only out-of-line definitions matter.
|
||||
if (!MD->isOutOfLine())
|
||||
// Ignore declarations that are not definitions.
|
||||
if (!MD->isThisDeclarationADefinition())
|
||||
return;
|
||||
|
||||
const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD);
|
||||
if (!KeyFunction || KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
|
||||
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;
|
||||
}
|
||||
|
||||
// We will need to mark all of the virtual members as referenced to build the
|
||||
// vtable.
|
||||
ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc));
|
||||
|
|
|
@ -41,3 +41,15 @@ struct Derived : Base<T> {
|
|||
|
||||
template struct Derived<int>; // expected-note{{instantiation}}
|
||||
|
||||
template<typename T>
|
||||
struct HasOutOfLineKey {
|
||||
HasOutOfLineKey() { } // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::f' requested here}}
|
||||
virtual T *f(float *fp);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue