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:
Rafael Espindola 2012-07-13 14:25:36 +00:00
parent abbfe69356
commit c7c7ad5f7e
2 changed files with 60 additions and 29 deletions

View File

@ -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

View File

@ -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
}