]> granicus.if.org Git - clang/commitdiff
[AST] correct the behavior of -fvisibility-inlines-hidden option (don't make static...
authorHiroshi Inoue <inouehrs@jp.ibm.com>
Wed, 22 Aug 2018 05:43:27 +0000 (05:43 +0000)
committerHiroshi Inoue <inouehrs@jp.ibm.com>
Wed, 22 Aug 2018 05:43:27 +0000 (05:43 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@340386 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Decl.cpp
test/CodeGenCXX/visibility-inlines-hidden-staticvar.cpp [new file with mode: 0644]

index b6d35f4260c73844be18c415ab213a6bf5d5a05e..272e49a7997fbb5dbad8d6179bf5b235125ae07a 100644 (file)
@@ -1262,6 +1262,16 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
         !isTemplateInstantiation(FD->getTemplateSpecializationKind()))
       return LinkageInfo::none();
 
+    // If a function is hidden by -fvisibility-inlines-hidden option and
+    // is not explicitly attributed as a hidden function,
+    // we should not make static local variables in the function hidden.
+    if (isa<VarDecl>(D) && useInlineVisibilityHidden(FD) &&
+        !(!hasExplicitVisibilityAlready(computation) &&
+          getExplicitVisibility(FD, computation))) {
+      assert(cast<VarDecl>(D)->isStaticLocal());
+      return LinkageInfo(VisibleNoLinkage, DefaultVisibility, false);
+    }
+
     LV = getLVForDecl(FD, computation);
   }
   if (!isExternallyVisible(LV.getLinkage()))
diff --git a/test/CodeGenCXX/visibility-inlines-hidden-staticvar.cpp b/test/CodeGenCXX/visibility-inlines-hidden-staticvar.cpp
new file mode 100644 (file)
index 0000000..0b62527
--- /dev/null
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s
+// 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
+
+// When a function is hidden due to -fvisibility-inlines-hidden option, static local variables of the function should not be hidden by the option.
+
+// CHECK-DAG: @_ZZ4funcvE3var = internal global i32 0
+// CHECK-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
+// CHECK-DAG: @_ZZ12default_funcvE3var = internal global i32 0
+// CHECK-DAG: @_ZZ11inline_funcvE3var = linkonce_odr global i32 0, comdat
+// CHECK-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
+// CHECK-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
+// CHECK-DAG: define i32 @_Z4funcv()
+// CHECK-DAG: define hidden i32 @_Z11hidden_funcv()
+// CHECK-DAG: define i32 @_Z12default_funcv()
+// CHECK-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv()
+// CHECK-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
+// CHECK-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
+
+// CHECK-NO-VIH-DAG: @_ZZ4funcvE3var = internal global i32 0
+// CHECK-NO-VIH-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
+// CHECK-NO-VIH-DAG: @_ZZ12default_funcvE3var = internal global i32 0
+// CHECK-NO-VIH-DAG: @_ZZ11inline_funcvE3var = linkonce_odr global i32 0, comdat
+// CHECK-NO-VIH-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
+// CHECK-NO-VIH-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
+// CHECK-NO-VIH-DAG: define i32 @_Z4funcv()
+// CHECK-NO-VIH-DAG: define hidden i32 @_Z11hidden_funcv()
+// CHECK-NO-VIH-DAG: define i32 @_Z12default_funcv()
+// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_Z11inline_funcv()
+// CHECK-NO-VIH-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
+// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
+
+
+int func(void) {
+  static int var = 0;
+  return var++;
+}
+inline int inline_func(void) {
+  static int var = 0;
+  return var++;
+}
+int __attribute__((visibility("hidden"))) hidden_func(void) {
+  static int var = 0;
+  return var++;
+}
+inline int __attribute__((visibility("hidden"))) inline_hidden_func(void) {
+  static int var = 0;
+  return var++;
+}
+int __attribute__((visibility("default"))) default_func(void) {
+  static int var = 0;
+  return var++;
+}
+inline int __attribute__((visibility("default"))) inline_default_func(void) {
+  static int var = 0;
+  return var++;
+}
+void bar(void) {
+  func();
+  inline_func();
+  hidden_func();
+  inline_hidden_func();
+  default_func();
+  inline_default_func();
+}
+