forked from OSchip/llvm-project
Use -fvisibility-inlines-hidden in inline functions too. This matches gcc
behavior since gcc pr30066. Thanks to Benjamin Kramer for pointing it out. llvm-svn: 160174
This commit is contained in:
parent
abbfe69356
commit
c7c7ad5f7e
|
@ -168,6 +168,35 @@ shouldConsiderTemplateVis(const ClassTemplateSpecializationDecl *d) {
|
|||
return !d->hasAttr<VisibilityAttr>() || d->isExplicitSpecialization();
|
||||
}
|
||||
|
||||
static bool useInlineVisibilityHidden(const NamedDecl *D) {
|
||||
// FIXME: we should warn if -fvisibility-inlines-hidden is used with c.
|
||||
ASTContext &Context = D->getASTContext();
|
||||
if (!Context.getLangOpts().CPlusPlus)
|
||||
return false;
|
||||
|
||||
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
|
||||
if (!FD)
|
||||
return false;
|
||||
|
||||
TemplateSpecializationKind TSK = TSK_Undeclared;
|
||||
if (FunctionTemplateSpecializationInfo *spec
|
||||
= FD->getTemplateSpecializationInfo()) {
|
||||
TSK = spec->getTemplateSpecializationKind();
|
||||
} else if (MemberSpecializationInfo *MSI =
|
||||
FD->getMemberSpecializationInfo()) {
|
||||
TSK = MSI->getTemplateSpecializationKind();
|
||||
}
|
||||
|
||||
const FunctionDecl *Def = 0;
|
||||
// InlineVisibilityHidden only applies to definitions, and
|
||||
// isInlined() only gives meaningful answers on definitions
|
||||
// anyway.
|
||||
return TSK != TSK_ExplicitInstantiationDeclaration &&
|
||||
TSK != TSK_ExplicitInstantiationDefinition &&
|
||||
FD->getASTContext().getLangOpts().InlineVisibilityHidden &&
|
||||
FD->hasBody(Def) && Def->isInlined();
|
||||
}
|
||||
|
||||
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
|
||||
bool OnlyTemplate) {
|
||||
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
|
||||
|
@ -266,8 +295,13 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|||
}
|
||||
}
|
||||
|
||||
if (!OnlyTemplate)
|
||||
if (!OnlyTemplate) {
|
||||
LV.mergeVisibility(Context.getLangOpts().getVisibilityMode());
|
||||
// If we're paying attention to global visibility, apply
|
||||
// -finline-visibility-hidden if this is an inline method.
|
||||
if (!LV.visibilityExplicit() && useInlineVisibilityHidden(D))
|
||||
LV.mergeVisibility(HiddenVisibility, true);
|
||||
}
|
||||
|
||||
// C++ [basic.link]p4:
|
||||
|
||||
|
@ -473,6 +507,13 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, bool OnlyTemplate) {
|
|||
if (!OnlyTemplate) {
|
||||
if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility())
|
||||
LV.mergeVisibility(*Vis, true);
|
||||
// If we're paying attention to global visibility, apply
|
||||
// -finline-visibility-hidden if this is an inline method.
|
||||
//
|
||||
// Note that we do this before merging information about
|
||||
// the class visibility.
|
||||
if (!LV.visibilityExplicit() && useInlineVisibilityHidden(D))
|
||||
LV.mergeVisibility(HiddenVisibility, true);
|
||||
}
|
||||
|
||||
// If this class member has an explicit visibility attribute, the only
|
||||
|
@ -480,34 +521,6 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, bool OnlyTemplate) {
|
|||
// only look for them when processing the the class.
|
||||
bool ClassOnlyTemplate = LV.visibilityExplicit() ? true : OnlyTemplate;
|
||||
|
||||
// If we're paying attention to global visibility, apply
|
||||
// -finline-visibility-hidden if this is an inline method.
|
||||
//
|
||||
// Note that we do this before merging information about
|
||||
// the class visibility.
|
||||
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
|
||||
TemplateSpecializationKind TSK = TSK_Undeclared;
|
||||
if (FunctionTemplateSpecializationInfo *spec
|
||||
= MD->getTemplateSpecializationInfo()) {
|
||||
TSK = spec->getTemplateSpecializationKind();
|
||||
} else if (MemberSpecializationInfo *MSI =
|
||||
MD->getMemberSpecializationInfo()) {
|
||||
TSK = MSI->getTemplateSpecializationKind();
|
||||
}
|
||||
|
||||
const FunctionDecl *Def = 0;
|
||||
// InlineVisibilityHidden only applies to definitions, and
|
||||
// isInlined() only gives meaningful answers on definitions
|
||||
// anyway.
|
||||
if (TSK != TSK_ExplicitInstantiationDeclaration &&
|
||||
TSK != TSK_ExplicitInstantiationDefinition &&
|
||||
!OnlyTemplate &&
|
||||
!LV.visibilityExplicit() &&
|
||||
MD->getASTContext().getLangOpts().InlineVisibilityHidden &&
|
||||
MD->hasBody(Def) && Def->isInlined())
|
||||
LV.mergeVisibility(HiddenVisibility, true);
|
||||
}
|
||||
|
||||
// If this member has an visibility attribute, ClassF will exclude
|
||||
// attributes on the class or command line options, keeping only information
|
||||
// about the template instantiation. If the member has no visibility
|
||||
|
|
|
@ -108,3 +108,21 @@ namespace PR11642 {
|
|||
template class Foo<int>;
|
||||
// CHECK: define weak_odr i32 @_ZN7PR116423FooIiE3fooEi
|
||||
}
|
||||
|
||||
// Test that clang implements the new gcc behaviour for inline functions.
|
||||
// GCC PR30066.
|
||||
namespace test3 {
|
||||
inline void foo(void) {
|
||||
}
|
||||
template<typename T>
|
||||
inline void zed() {
|
||||
}
|
||||
template void zed<float>();
|
||||
void bar(void) {
|
||||
foo();
|
||||
zed<int>();
|
||||
}
|
||||
// CHECK: define weak_odr void @_ZN5test33zedIfEEvv
|
||||
// CHECK: define linkonce_odr hidden void @_ZN5test33fooEv
|
||||
// CHECK: define linkonce_odr hidden void @_ZN5test33zedIiEEvv
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue