Skip to content

Commit c4c4115

Browse files
committed
Merging r340386 and r344190:
------------------------------------------------------------------------ r340386 | inouehrs | 2018-08-21 22:43:27 -0700 (Tue, 21 Aug 2018) | 10 lines [AST] correct the behavior of -fvisibility-inlines-hidden option (don't make static local variables hidden) The command line option -fvisibility-inlines-hidden makes inlined method hidden, but it is expected not to affect the visibility of static local variables in the function. However, Clang makes the static local variables in the function also hidden as reported in PR37595. This problem causes LLVM bootstarp failure on Fedora 28 if configured with -DBUILD_SHARED_LIBS=ON. This patch makes the behavior of -fvisibility-inlines-hidden option to be consistent with that of gcc; the option does not change the visibility of the static local variables if the containing function does not associated with explicit visibility attribute and becomes hidden due to this option. Differential Revision: https://reviews.llvm.org/D50968 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r344190 | rnk | 2018-10-10 14:59:56 -0700 (Wed, 10 Oct 2018) | 19 lines [AST] Use -fvisibility value when ignoring -fv-i-h* inline static locals Summary: In r340386 we added code to give static locals in inline functions default visibility. Instead, we should use the "default" visibility passed on the command line, which could be hidden or protected, as GCC does. Some code bases use both -fvisibility=hidden and -fvisibility-inlines-hidden to hide inline functions of classes that are explicitly marked with default visibility. Fixes PR39236 Reviewers: hans, thakis Subscribers: eraman, llvm-commits Differential Revision: https://reviews.llvm.org/D53052 ------------------------------------------------------------------------ llvm-svn: 348554
1 parent b7096f7 commit c4c4115

File tree

2 files changed

+133
-2
lines changed

2 files changed

+133
-2
lines changed

clang/lib/AST/Decl.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
725725
// If we're paying attention to global visibility, apply
726726
// -finline-visibility-hidden if this is an inline method.
727727
if (useInlineVisibilityHidden(D))
728-
LV.mergeVisibility(HiddenVisibility, true);
728+
LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
729729
}
730730
}
731731

@@ -915,7 +915,7 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
915915
// Note that we do this before merging information about
916916
// the class visibility.
917917
if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D))
918-
LV.mergeVisibility(HiddenVisibility, true);
918+
LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
919919
}
920920

921921
// If this class member has an explicit visibility attribute, the only
@@ -1262,7 +1262,27 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
12621262
!isTemplateInstantiation(FD->getTemplateSpecializationKind()))
12631263
return LinkageInfo::none();
12641264

1265+
// If a function is hidden by -fvisibility-inlines-hidden option and
1266+
// is not explicitly attributed as a hidden function,
1267+
// we should not make static local variables in the function hidden.
12651268
LV = getLVForDecl(FD, computation);
1269+
if (isa<VarDecl>(D) && useInlineVisibilityHidden(FD) &&
1270+
!LV.isVisibilityExplicit()) {
1271+
assert(cast<VarDecl>(D)->isStaticLocal());
1272+
// If this was an implicitly hidden inline method, check again for
1273+
// explicit visibility on the parent class, and use that for static locals
1274+
// if present.
1275+
if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
1276+
LV = getLVForDecl(MD->getParent(), computation);
1277+
if (!LV.isVisibilityExplicit()) {
1278+
Visibility globalVisibility =
1279+
computation.isValueVisibility()
1280+
? Context.getLangOpts().getValueVisibilityMode()
1281+
: Context.getLangOpts().getTypeVisibilityMode();
1282+
return LinkageInfo(VisibleNoLinkage, globalVisibility,
1283+
/*visibilityExplicit=*/false);
1284+
}
1285+
}
12661286
}
12671287
if (!isExternallyVisible(LV.getLinkage()))
12681288
return LinkageInfo::none();
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s
2+
// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck -check-prefixes=CHECK-NO-VIH %s
3+
// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility hidden -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s --check-prefix=CHECK-VIS-HIDDEN
4+
// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility protected -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s --check-prefix=CHECK-VIS-PROTECTED
5+
6+
// When a function is hidden due to -fvisibility-inlines-hidden option, static local variables of the function should not be hidden by the option.
7+
8+
// CHECK-DAG: @_ZZ4funcvE3var = internal global i32 0
9+
// CHECK-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
10+
// CHECK-DAG: @_ZZ12default_funcvE3var = internal global i32 0
11+
// CHECK-DAG: @_ZZ11inline_funcvE3var = linkonce_odr global i32 0, comdat
12+
// CHECK-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
13+
// CHECK-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
14+
// CHECK-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
15+
// CHECK-DAG: define i32 @_Z4funcv()
16+
// CHECK-DAG: define hidden i32 @_Z11hidden_funcv()
17+
// CHECK-DAG: define i32 @_Z12default_funcv()
18+
// CHECK-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv()
19+
// CHECK-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
20+
// CHECK-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
21+
// CHECK-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
22+
// CHECK-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
23+
24+
// CHECK-NO-VIH-DAG: @_ZZ4funcvE3var = internal global i32 0
25+
// CHECK-NO-VIH-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
26+
// CHECK-NO-VIH-DAG: @_ZZ12default_funcvE3var = internal global i32 0
27+
// CHECK-NO-VIH-DAG: @_ZZ11inline_funcvE3var = linkonce_odr global i32 0, comdat
28+
// CHECK-NO-VIH-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
29+
// CHECK-NO-VIH-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
30+
// CHECK-NO-VIH-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
31+
// CHECK-NO-VIH-DAG: define i32 @_Z4funcv()
32+
// CHECK-NO-VIH-DAG: define hidden i32 @_Z11hidden_funcv()
33+
// CHECK-NO-VIH-DAG: define i32 @_Z12default_funcv()
34+
// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_Z11inline_funcv()
35+
// CHECK-NO-VIH-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
36+
// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
37+
// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
38+
// CHECK-NO-VIH-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
39+
40+
// CHECK-VIS-HIDDEN-DAG: @_ZZ4funcvE3var = internal global i32 0
41+
// CHECK-VIS-HIDDEN-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
42+
// CHECK-VIS-HIDDEN-DAG: @_ZZ12default_funcvE3var = internal global i32 0
43+
// CHECK-VIS-HIDDEN-DAG: @_ZZ11inline_funcvE3var = linkonce_odr hidden global i32 0, comdat
44+
// CHECK-VIS-HIDDEN-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
45+
// CHECK-VIS-HIDDEN-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
46+
// CHECK-VIS-HIDDEN-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
47+
// CHECK-VIS-HIDDEN-DAG: define hidden i32 @_Z4funcv()
48+
// CHECK-VIS-HIDDEN-DAG: define hidden i32 @_Z11hidden_funcv()
49+
// CHECK-VIS-HIDDEN-DAG: define i32 @_Z12default_funcv()
50+
// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv()
51+
// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
52+
// CHECK-VIS-HIDDEN-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
53+
// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
54+
// CHECK-VIS-HIDDEN-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
55+
56+
// CHECK-VIS-PROTECTED-DAG: @_ZZ4funcvE3var = internal global i32 0
57+
// CHECK-VIS-PROTECTED-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
58+
// CHECK-VIS-PROTECTED-DAG: @_ZZ12default_funcvE3var = internal global i32 0
59+
// CHECK-VIS-PROTECTED-DAG: @_ZZ11inline_funcvE3var = linkonce_odr protected global i32 0, comdat
60+
// CHECK-VIS-PROTECTED-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
61+
// CHECK-VIS-PROTECTED-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
62+
// CHECK-VIS-PROTECTED-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
63+
// CHECK-VIS-PROTECTED-DAG: define protected i32 @_Z4funcv()
64+
// CHECK-VIS-PROTECTED-DAG: define hidden i32 @_Z11hidden_funcv()
65+
// CHECK-VIS-PROTECTED-DAG: define i32 @_Z12default_funcv()
66+
// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv()
67+
// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
68+
// CHECK-VIS-PROTECTED-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
69+
// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
70+
// CHECK-VIS-PROTECTED-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
71+
72+
int func(void) {
73+
static int var = 0;
74+
return var++;
75+
}
76+
inline int inline_func(void) {
77+
static int var = 0;
78+
return var++;
79+
}
80+
int __attribute__((visibility("hidden"))) hidden_func(void) {
81+
static int var = 0;
82+
return var++;
83+
}
84+
inline int __attribute__((visibility("hidden"))) inline_hidden_func(void) {
85+
static int var = 0;
86+
return var++;
87+
}
88+
int __attribute__((visibility("default"))) default_func(void) {
89+
static int var = 0;
90+
return var++;
91+
}
92+
inline int __attribute__((visibility("default"))) inline_default_func(void) {
93+
static int var = 0;
94+
return var++;
95+
}
96+
struct __attribute__((visibility("default"))) ExportedClass {
97+
int inl_method() {
98+
static int var = 0;
99+
return var++;
100+
}
101+
int ext_method();
102+
};
103+
int ExportedClass::ext_method() { return inl_method(); }
104+
void bar(void) {
105+
func();
106+
inline_func();
107+
hidden_func();
108+
inline_hidden_func();
109+
default_func();
110+
inline_default_func();
111+
}

0 commit comments

Comments
 (0)