summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/visibility.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX/visibility.cpp')
-rw-r--r--test/CodeGenCXX/visibility.cpp511
1 files changed, 509 insertions, 2 deletions
diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp
index 59fd7c2..0145039 100644
--- a/test/CodeGenCXX/visibility.cpp
+++ b/test/CodeGenCXX/visibility.cpp
@@ -1,10 +1,24 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fvisibility hidden -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-HIDDEN
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -fvisibility hidden -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-HIDDEN
#define HIDDEN __attribute__((visibility("hidden")))
#define PROTECTED __attribute__((visibility("protected")))
#define DEFAULT __attribute__((visibility("default")))
+namespace test30 {
+ // When H is hidden, it should make X hidden, even if the template argument
+ // is not.
+ struct H {
+ };
+ template<H *T>
+ struct X {
+ };
+ H DEFAULT a;
+ X<&a> b;
+ // CHECK: _ZN6test301bE = global
+ // CHECK-HIDDEN: _ZN6test301bE = hidden global
+}
+
namespace test25 {
template<typename T>
struct X {
@@ -28,6 +42,62 @@ namespace test28 {
// CHECK-HIDDEN: @_ZN6test285myvecE = hidden global
}
+namespace test29 {
+#pragma GCC visibility push(hidden)
+ struct RECT {
+ int top;
+ };
+ __attribute__ ((visibility ("default"))) extern RECT data_rect;
+ RECT data_rect = { -1};
+#pragma GCC visibility pop
+ // CHECK: @_ZN6test299data_rectE = global
+ // CHECK-HIDDEN: @_ZN6test299data_rectE = global
+}
+
+namespace test40 {
+ template<typename T>
+ struct foo {
+ DEFAULT static int bar;
+ };
+ template<typename T>
+ int foo<T>::bar;
+ template struct foo<int>;
+ // CHECK: _ZN6test403fooIiE3barE = weak_odr global
+ // CHECK-HIDDEN: _ZN6test403fooIiE3barE = weak_odr global
+}
+
+namespace test41 {
+ // Unlike gcc we propagate the information that foo not only is hidden, but
+ // has been explicitly marked as so. This lets us produce a hidden undefined
+ // reference to bar.
+ struct __attribute__((visibility("hidden"))) foo {};
+ extern foo bar;
+ foo *zed() {
+ return &bar;
+ }
+ // CHECK: @_ZN6test413barE = external hidden global
+ // CHECK-HIDDEN: @_ZN6test413barE = external hidden global
+}
+
+namespace test48 {
+ // Test that we use the visibility of struct foo when instantiating the
+ // template. Note that is a case where we disagree with gcc, it produces
+ // a default symbol.
+ struct HIDDEN foo {
+ };
+ DEFAULT foo x;
+
+ struct bar {
+ template<foo *z>
+ struct zed {
+ };
+ };
+
+ bar::zed<&x> y;
+ // CHECK: _ZN6test481yE = hidden global
+ // CHECK-HIDDEN: _ZN6test481yE = hidden global
+}
+
// CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10
// CHECK: @_ZN5Test71aE = hidden global
// CHECK: @_ZN5Test71bE = global
@@ -510,6 +580,8 @@ namespace PR10113 {
};
template class foo::bar<zed>;
// CHECK: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv
+
+ // FIXME: This should be hidden as zed is hidden.
// CHECK-HIDDEN: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv
}
@@ -541,6 +613,8 @@ namespace PR11690_2 {
};
template class foo::zed<baz>;
// CHECK: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
+
+ // FIXME: This should be hidden as baz is hidden.
// CHECK-HIDDEN: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
}
@@ -605,3 +679,436 @@ namespace test26 {
// CHECK: define void @_ZN6test261CIiE1fEv
// CHECK-HIDDEN: define void @_ZN6test261CIiE1fEv
}
+
+namespace test31 {
+ struct A {
+ struct HIDDEN B {
+ static void DEFAULT baz();
+ };
+ };
+ void f() {
+ A::B::baz();
+ }
+ // CHECK: declare void @_ZN6test311A1B3bazEv()
+ // CHECK-HIDDEN: declare void @_ZN6test311A1B3bazEv()
+}
+
+namespace test32 {
+ struct HIDDEN A {
+ struct DEFAULT B {
+ void DEFAULT baz();
+ };
+ };
+ void A::B::baz() {
+ }
+ // CHECK: define void @_ZN6test321A1B3bazEv
+ // CHECK-HIDDEN: define void @_ZN6test321A1B3bazEv
+}
+
+namespace test33 {
+ template<typename T>
+ class foo {
+ void bar() {}
+ };
+ struct HIDDEN zed {
+ };
+ template class DEFAULT foo<zed>;
+ // CHECK: define weak_odr void @_ZN6test333fooINS_3zedEE3barEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN6test333fooINS_3zedEE3barEv
+}
+
+namespace test34 {
+ struct foo {
+ };
+ template<class T>
+ void bar() {}
+ template DEFAULT void bar<foo>();
+ // CHECK: define weak_odr void @_ZN6test343barINS_3fooEEEvv
+ // CHECK-HIDDEN: define weak_odr void @_ZN6test343barINS_3fooEEEvv
+}
+
+namespace test35 {
+ // This is a really ugly testcase. GCC propagates the DEFAULT in zed's
+ // definition. What we do instead is be conservative about merging
+ // implicit visibilities.
+ // FIXME: Maybe the best thing to do here is error? The test at least
+ // makes sure we don't produce a hidden symbol for foo<zed>::bar.
+ template<typename T>
+ struct DEFAULT foo {
+ void bar() {}
+ };
+ class zed;
+ template class foo<zed>;
+ class DEFAULT zed {
+ };
+ // CHECK: define weak_odr void @_ZN6test353fooINS_3zedEE3barEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN6test353fooINS_3zedEE3barEv
+}
+
+namespace test36 {
+ template<typename T1, typename T2>
+ class foo {
+ void bar() {}
+ };
+ class DEFAULT S1 {};
+ struct HIDDEN S2 {};
+ template class foo<S1, S2>;
+ // CHECK: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv
+ // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv
+}
+
+namespace test37 {
+ struct HIDDEN foo {
+ };
+ template<class T>
+ DEFAULT void bar() {}
+ template DEFAULT void bar<foo>();
+ // CHECK: define weak_odr void @_ZN6test373barINS_3fooEEEvv
+ // CHECK-HIDDEN: define weak_odr void @_ZN6test373barINS_3fooEEEvv
+}
+
+namespace test38 {
+ template<typename T>
+ class DEFAULT foo {
+ void bar() {}
+ };
+ struct HIDDEN zed {
+ };
+ template class foo<zed>;
+ // CHECK: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv
+ // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv
+}
+
+namespace test39 {
+ class DEFAULT default_t;
+ class HIDDEN hidden_t;
+ template <class T> class A {
+ template <class U> class B {
+ HIDDEN void hidden() {}
+ void noattr() {}
+ template <class V> void temp() {}
+ };
+ };
+ template class DEFAULT A<hidden_t>;
+ template class DEFAULT A<hidden_t>::B<hidden_t>;
+ template void A<hidden_t>::B<hidden_t>::temp<default_t>();
+ template void A<hidden_t>::B<hidden_t>::temp<hidden_t>();
+
+ // CHECK: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv
+ // CHECK: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv
+ // CHECK: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv
+
+ // GCC produces a default for this one. Why?
+ // CHECK: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv
+
+ // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv
+
+ // GCC produces a default for this one. Why?
+ // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv
+}
+
+namespace test42 {
+ struct HIDDEN foo {
+ };
+ template <class P>
+ struct bar {
+ };
+ template <>
+ struct HIDDEN bar<foo> {
+ DEFAULT static void zed();
+ };
+ void bar<foo>::zed() {
+ }
+ // CHECK: define hidden void @_ZN6test423barINS_3fooEE3zedEv
+ // CHECK-HIDDEN: define hidden void @_ZN6test423barINS_3fooEE3zedEv
+}
+
+namespace test43 {
+ struct HIDDEN foo {
+ };
+ template <class P>
+ void bar() {
+ }
+ template <>
+ DEFAULT void bar<foo>() {
+ }
+ // CHECK: define hidden void @_ZN6test433barINS_3fooEEEvv
+ // CHECK-HIDDEN: define hidden void @_ZN6test433barINS_3fooEEEvv
+}
+
+namespace test44 {
+ template <typename T>
+ struct foo {
+ foo() {}
+ };
+ namespace {
+ struct bar;
+ }
+ template struct DEFAULT foo<bar>;
+ foo<bar> x;
+ // CHECK: define internal void @_ZN6test443fooINS_12_GLOBAL__N_13barEEC1Ev
+ // CHECK-HIDDEN: define internal void @_ZN6test443fooINS_12_GLOBAL__N_13barEEC1Ev
+}
+
+namespace test45 {
+ template <typename T>
+ struct foo {
+ template <typename T2>
+ struct bar {
+ bar() {};
+ };
+ };
+ namespace {
+ struct zed;
+ }
+ template struct DEFAULT foo<int>::bar<zed>;
+ foo<int>::bar<zed> x;
+ // CHECK: define internal void @_ZN6test453fooIiE3barINS_12_GLOBAL__N_13zedEEC1Ev
+ // CHECK-HIDDEN: define internal void @_ZN6test453fooIiE3barINS_12_GLOBAL__N_13zedEEC1Ev
+}
+
+namespace test46 {
+ template <typename T>
+ void foo() {
+ }
+ namespace {
+ struct bar;
+ }
+ template DEFAULT void foo<bar>();
+ void zed() {
+ foo<bar>();
+ }
+ // CHECK: define internal void @_ZN6test463fooINS_12_GLOBAL__N_13barEEEvv
+ // CHECK-HIDDEN: define internal void @_ZN6test463fooINS_12_GLOBAL__N_13barEEEvv
+}
+
+namespace test47 {
+ struct foo {
+ template <typename T>
+ static void bar() {
+ }
+ };
+ namespace {
+ struct zed;
+ }
+ template __attribute__((visibility("default"))) void foo::bar<zed>();
+ void baz() {
+ foo::bar<zed>();
+ }
+ // CHECK: define internal void @_ZN6test473foo3barINS_12_GLOBAL__N_13zedEEEvv
+ // CHECK-HIDDEN: define internal void @_ZN6test473foo3barINS_12_GLOBAL__N_13zedEEEvv
+}
+
+namespace test49 {
+ // Test that we use the visibility of struct foo when instantiating the
+ // template. Note that is a case where we disagree with gcc, it produces
+ // a default symbol.
+
+ struct HIDDEN foo {
+ };
+
+ DEFAULT foo x;
+
+ struct bar {
+ template<foo *z>
+ void zed() {
+ }
+ };
+
+ template void bar::zed<&x>();
+ // CHECK: define weak_odr hidden void @_ZN6test493bar3zedIXadL_ZNS_1xEEEEEvv
+ // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test493bar3zedIXadL_ZNS_1xEEEEEvv
+}
+
+namespace test50 {
+ // Test that we use the visibility of struct foo when instantiating the
+ // template. Note that is a case where we disagree with gcc, it produces
+ // a default symbol.
+
+ struct HIDDEN foo {
+ };
+ DEFAULT foo x;
+ template<foo *z>
+ struct DEFAULT bar {
+ void zed() {
+ }
+ };
+ template void bar<&x>::zed();
+ // CHECK: define weak_odr hidden void @_ZN6test503barIXadL_ZNS_1xEEEE3zedEv
+ // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test503barIXadL_ZNS_1xEEEE3zedEv
+}
+
+namespace test51 {
+ // Test that we use the visibility of struct foo when instantiating the
+ // template. Note that is a case where we disagree with gcc, it produces
+ // a default symbol.
+
+ struct HIDDEN foo {
+ };
+ DEFAULT foo x;
+ template<foo *z>
+ void DEFAULT zed() {
+ }
+ template void zed<&x>();
+ // CHECK: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv
+ // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv
+}
+
+namespace test52 {
+ // Test that we use the linkage of struct foo when instantiating the
+ // template. Note that is a case where we disagree with gcc, it produces
+ // an external symbol.
+
+ namespace {
+ struct foo {
+ };
+ }
+ template<foo *x>
+ void zed() {
+ }
+ void f() {
+ zed<nullptr>();
+ }
+ // CHECK: define internal void @_ZN6test523zedILPNS_12_GLOBAL__N_13fooE0EEEvv
+ // CHECK-HIDDEN: define internal void @_ZN6test523zedILPNS_12_GLOBAL__N_13fooE0EEEvv
+}
+
+namespace test53 {
+ template<typename _Tp > struct vector {
+ static void _M_fill_insert();
+ };
+#pragma GCC visibility push(hidden)
+ // GCC doesn't seem to use the visibility of enums at all, we do.
+ enum zed {v1};
+
+ // GCC fails to mark this specialization hidden, we mark it.
+ template<>
+ struct vector<int> {
+ static void _M_fill_insert();
+ };
+ void foo() {
+ vector<unsigned>::_M_fill_insert();
+ vector<int>::_M_fill_insert();
+ vector<zed>::_M_fill_insert();
+ }
+#pragma GCC visibility pop
+ // CHECK: declare void @_ZN6test536vectorIjE14_M_fill_insertEv
+ // CHECK-HIDDEN: declare void @_ZN6test536vectorIjE14_M_fill_insertEv
+ // CHECK: declare hidden void @_ZN6test536vectorIiE14_M_fill_insertEv
+ // CHECK-HIDDEN: declare hidden void @_ZN6test536vectorIiE14_M_fill_insertEv
+ // CHECK: declare hidden void @_ZN6test536vectorINS_3zedEE14_M_fill_insertEv
+ // CHECK-HIDDEN: declare hidden void @_ZN6test536vectorINS_3zedEE14_M_fill_insertEv
+}
+
+namespace test54 {
+ template <class T>
+ struct foo {
+ static void bar();
+ };
+#pragma GCC visibility push(hidden)
+ class zed {
+ zed(const zed &);
+ };
+ void bah() {
+ foo<zed>::bar();
+ }
+#pragma GCC visibility pop
+ // CHECK: declare hidden void @_ZN6test543fooINS_3zedEE3barEv
+ // CHECK-HIDDEN: declare hidden void @_ZN6test543fooINS_3zedEE3barEv
+}
+
+namespace test55 {
+ template <class T>
+ struct __attribute__((visibility("hidden"))) foo {
+ static void bar();
+ };
+ template <class T> struct foo;
+ void foobar() {
+ foo<int>::bar();
+ }
+ // CHECK: declare hidden void @_ZN6test553fooIiE3barEv
+ // CHECK-HIDDEN: declare hidden void @_ZN6test553fooIiE3barEv
+}
+
+namespace test56 {
+ template <class T> struct foo;
+ template <class T>
+ struct __attribute__((visibility("hidden"))) foo {
+ static void bar();
+ };
+ void foobar() {
+ foo<int>::bar();
+ }
+ // CHECK: declare hidden void @_ZN6test563fooIiE3barEv
+ // CHECK-HIDDEN: declare hidden void @_ZN6test563fooIiE3barEv
+}
+
+namespace test57 {
+#pragma GCC visibility push(hidden)
+ template <class T>
+ struct foo;
+ void bar(foo<int>*);
+ template <class T>
+ struct foo {
+ static void zed();
+ };
+ void bah() {
+ foo<int>::zed();
+ }
+#pragma GCC visibility pop
+ // CHECK: declare hidden void @_ZN6test573fooIiE3zedEv
+ // CHECK-HIDDEN: declare hidden void @_ZN6test573fooIiE3zedEv
+}
+
+namespace test58 {
+#pragma GCC visibility push(hidden)
+ struct foo;
+ template<typename T>
+ struct __attribute__((visibility("default"))) bar {
+ static void zed() {
+ }
+ };
+ void bah() {
+ bar<foo>::zed();
+ }
+#pragma GCC visibility pop
+ // CHECK: define linkonce_odr hidden void @_ZN6test583barINS_3fooEE3zedEv
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test583barINS_3fooEE3zedEv
+}
+
+namespace test59 {
+ DEFAULT int f();
+ HIDDEN int g();
+ typedef int (*foo)();
+ template<foo x, foo y>
+ void test() {}
+ void use() {
+ test<&g, &f>();
+ // CHECK: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1gEvEEXadL_ZNS_1fEvEEEEvv
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1gEvEEXadL_ZNS_1fEvEEEEvv
+
+ test<&f, &g>();
+ // CHECK: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1fEvEEXadL_ZNS_1gEvEEEEvv
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1fEvEEXadL_ZNS_1gEvEEEEvv
+ }
+}
+
+namespace test60 {
+ template<int i>
+ class __attribute__((visibility("hidden"))) a {};
+ template<int i>
+ class __attribute__((visibility("default"))) b {};
+ template<template<int> class x, template<int> class y>
+ void test() {}
+ void use() {
+ test<a, b>();
+ // CHECK: define linkonce_odr hidden void @_ZN6test604testINS_1aENS_1bEEEvv
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test604testINS_1aENS_1bEEEvv
+
+ test<b, a>();
+ // CHECK: define linkonce_odr hidden void @_ZN6test604testINS_1bENS_1aEEEvv
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test604testINS_1bENS_1aEEEvv
+ }
+}
OpenPOWER on IntegriCloud