From b04b73122064641d3acd637c26ea76bd3573041b Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 13 Jul 2012 14:25:36 +0000 Subject: [PATCH] Use -fvisibility-inlines-hidden in inline functions too. This matches gcc behavior since gcc pr30066. Thanks to Benjamin Kramer for pointing it out. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160174 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/Decl.cpp | 71 +++++++++++-------- test/CodeGenCXX/visibility-inlines-hidden.cpp | 18 +++++ 2 files changed, 60 insertions(+), 29 deletions(-) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 33826cbb46..7ca8d397f1 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -168,6 +168,35 @@ shouldConsiderTemplateVis(const ClassTemplateSpecializationDecl *d) { return !d->hasAttr() || 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(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 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(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 diff --git a/test/CodeGenCXX/visibility-inlines-hidden.cpp b/test/CodeGenCXX/visibility-inlines-hidden.cpp index d660b1b410..2bb13485e9 100644 --- a/test/CodeGenCXX/visibility-inlines-hidden.cpp +++ b/test/CodeGenCXX/visibility-inlines-hidden.cpp @@ -108,3 +108,21 @@ namespace PR11642 { template class Foo; // 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 + inline void zed() { + } + template void zed(); + void bar(void) { + foo(); + zed(); + } + // CHECK: define weak_odr void @_ZN5test33zedIfEEvv + // CHECK: define linkonce_odr hidden void @_ZN5test33fooEv + // CHECK: define linkonce_odr hidden void @_ZN5test33zedIiEEvv +} -- 2.40.0