summaryrefslogtreecommitdiff
path: root/clang/test/CodeGenCXX/visibility.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CodeGenCXX/visibility.cpp')
-rw-r--r--clang/test/CodeGenCXX/visibility.cpp607
1 files changed, 607 insertions, 0 deletions
diff --git a/clang/test/CodeGenCXX/visibility.cpp b/clang/test/CodeGenCXX/visibility.cpp
new file mode 100644
index 0000000..59fd7c2
--- /dev/null
+++ b/clang/test/CodeGenCXX/visibility.cpp
@@ -0,0 +1,607 @@
+// 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
+
+#define HIDDEN __attribute__((visibility("hidden")))
+#define PROTECTED __attribute__((visibility("protected")))
+#define DEFAULT __attribute__((visibility("default")))
+
+namespace test25 {
+ template<typename T>
+ struct X {
+ template<typename U>
+ struct definition {
+ };
+ };
+
+ class DEFAULT A { };
+
+ X<int>::definition<A> a;
+ // CHECK: @_ZN6test251aE = global
+ // CHECK-HIDDEN: @_ZN6test251aE = hidden global
+}
+
+namespace test28 {
+ class DEFAULT foo {
+ };
+ foo myvec;
+ // CHECK: @_ZN6test285myvecE = global
+ // CHECK-HIDDEN: @_ZN6test285myvecE = hidden global
+}
+
+// CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10
+// CHECK: @_ZN5Test71aE = hidden global
+// CHECK: @_ZN5Test71bE = global
+// CHECK: @test9_var = global
+// CHECK-HIDDEN: @test9_var = global
+// CHECK: @_ZN6Test121A6hiddenE = external hidden global
+// CHECK: @_ZN6Test121A7visibleE = external global
+// CHECK-HIDDEN: @_ZN6Test121A6hiddenE = external hidden global
+// CHECK-HIDDEN: @_ZN6Test121A7visibleE = external global
+// CHECK: @_ZN6Test131B1aE = hidden global
+// CHECK: @_ZN6Test131C1aE = global
+// CHECK-HIDDEN: @_ZN6Test131B1aE = hidden global
+// CHECK-HIDDEN: @_ZN6Test131C1aE = global
+// CHECK: @_ZN6Test143varE = external global
+// CHECK-HIDDEN: @_ZN6Test143varE = external global
+// CHECK: @_ZN6Test154TempINS_1AEE5Inner6bufferE = external global [0 x i8]
+// CHECK-HIDDEN: @_ZN6Test154TempINS_1AEE5Inner6bufferE = external global [0 x i8]
+
+namespace test27 {
+ template<typename T>
+ class C {
+ class __attribute__((visibility("default"))) D {
+ void f();
+ };
+ };
+
+ template<>
+ class C<int>::D {
+ virtual void g();
+ };
+
+ void C<int>::D::g() {
+ }
+ // CHECK: _ZTVN6test271CIiE1DE = unnamed_addr constant
+ // CHECK-HIDDEN: _ZTVN6test271CIiE1DE = unnamed_addr constant
+}
+
+// CHECK: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr global
+// CHECK: @_ZGVZN6Test193fooIiEEvvE1a = linkonce_odr global i64
+// CHECK-HIDDEN: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr hidden global
+// CHECK-HIDDEN: @_ZGVZN6Test193fooIiEEvvE1a = linkonce_odr hidden global i64
+// CHECK-HIDDEN: @_ZTVN6Test161AIcEE = external unnamed_addr constant
+// CHECK-HIDDEN: @_ZTTN6Test161AIcEE = external unnamed_addr constant
+// CHECK: @_ZTVN5Test63fooE = linkonce_odr hidden unnamed_addr constant
+
+namespace Test1 {
+ // CHECK: define hidden void @_ZN5Test11fEv
+ void HIDDEN f() { }
+
+}
+
+namespace Test2 {
+ struct HIDDEN A {
+ void f();
+ };
+
+ // A::f is a member function of a hidden class.
+ // CHECK: define hidden void @_ZN5Test21A1fEv
+ void A::f() { }
+}
+
+namespace Test3 {
+ struct HIDDEN A {
+ struct B {
+ void f();
+ };
+ };
+
+ // B is a nested class where its parent class is hidden.
+ // CHECK: define hidden void @_ZN5Test31A1B1fEv
+ void A::B::f() { }
+}
+
+namespace Test4 HIDDEN {
+ int VariableInHiddenNamespace = 10;
+
+ // Test4::g is in a hidden namespace.
+ // CHECK: define hidden void @_ZN5Test41gEv
+ void g() { }
+
+ struct DEFAULT A {
+ void f();
+ };
+
+ // A has default visibility.
+ // CHECK: define void @_ZN5Test41A1fEv
+ void A::f() { }
+}
+
+namespace Test5 {
+
+ namespace NS HIDDEN {
+ // f is in NS which is hidden.
+ // CHECK: define hidden void @_ZN5Test52NS1fEv()
+ void f() { }
+ }
+
+ namespace NS {
+ // g is in NS, but this NS decl is not hidden.
+ // CHECK: define void @_ZN5Test52NS1gEv
+ void g() { }
+ }
+}
+
+// <rdar://problem/8091955>
+namespace Test6 {
+ struct HIDDEN foo {
+ foo() { }
+ void bonk();
+ virtual void bar() = 0;
+
+ virtual void zonk() {}
+ };
+
+ struct barc : public foo {
+ barc();
+ virtual void bar();
+ };
+
+ barc::barc() {}
+}
+
+namespace Test7 {
+ class HIDDEN A {};
+ A a; // top of file
+
+ template <A&> struct Aref {
+ static void foo() {}
+ };
+
+ class B : public A {};
+ B b; // top of file
+
+ // CHECK: define linkonce_odr hidden void @_ZN5Test74ArefILZNS_1aEEE3fooEv()
+ void test() {
+ Aref<a>::foo();
+ }
+}
+
+namespace Test8 {
+ void foo();
+ void bar() {}
+ // CHECK-HIDDEN: define hidden void @_ZN5Test83barEv()
+ // CHECK-HIDDEN: declare void @_ZN5Test83fooEv()
+
+ void test() {
+ foo();
+ bar();
+ }
+}
+
+// PR8457
+namespace Test9 {
+ extern "C" {
+ struct A { int field; };
+ void DEFAULT test9_fun(struct A *a) { }
+ struct A DEFAULT test9_var; // above
+ }
+ // CHECK: define void @test9_fun(
+ // CHECK-HIDDEN: define void @test9_fun(
+
+ void test() {
+ A a = test9_var;
+ test9_fun(&a);
+ }
+}
+
+// PR8478
+namespace Test10 {
+ struct A;
+
+ class DEFAULT B {
+ void foo(A*);
+ };
+
+ // CHECK: define void @_ZN6Test101B3fooEPNS_1AE(
+ // CHECK-HIDDEN: define void @_ZN6Test101B3fooEPNS_1AE(
+ void B::foo(A*) {}
+}
+
+// PR8492
+namespace Test11 {
+ struct A {
+ void foo() {}
+ void DEFAULT bar() {}
+ };
+
+ void test() {
+ A a;
+ a.foo();
+ a.bar();
+ }
+
+ // CHECK: define linkonce_odr void @_ZN6Test111A3fooEv(
+ // CHECK: define linkonce_odr void @_ZN6Test111A3barEv(
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6Test111A3fooEv(
+ // CHECK-HIDDEN: define linkonce_odr void @_ZN6Test111A3barEv(
+}
+
+// Tested at top of file.
+namespace Test12 {
+ struct A {
+ // This is hidden in all cases: the explicit attribute takes
+ // priority over -fvisibility on the parent.
+ static int hidden HIDDEN;
+
+ // This is default in all cases because it's only a declaration.
+ static int visible;
+ };
+
+ void test() {
+ A::hidden = 0;
+ A::visible = 0;
+ }
+}
+
+// Tested at top of file.
+namespace Test13 {
+ struct HIDDEN A {};
+
+ // Should be hidden in all cases.
+ struct B {
+ static A a;
+ };
+ A B::a;
+
+ // Should be default in all cases.
+ struct DEFAULT C {
+ static A a;
+ };
+ A C::a;
+};
+
+// Tested at top of file.
+namespace Test14 {
+ // Neither the visibility of the type nor -fvisibility=hidden should
+ // apply to declarations.
+ extern struct A *var;
+
+ struct A *test() { return var; }
+}
+
+// rdar://problem/8613093
+namespace Test15 {
+ struct A {};
+ template <class T> struct Temp {
+ struct Inner {
+ static char buffer[0];
+ };
+ };
+
+ char *test() {
+ return Temp<A>::Inner::buffer;
+ }
+}
+
+namespace Test16 {
+ struct Base1 { virtual void foo(); };
+ struct Base2 : virtual Base1 { virtual void foo(); };
+ template <class T> struct A : virtual Base1, Base2 {
+ virtual void foo();
+ };
+ extern template struct A<char>;
+
+ void test() {
+ A<char> a;
+ a.foo();
+ }
+}
+
+namespace Test17 {
+ struct HIDDEN A {
+ static void foo();
+ static void DEFAULT bar();
+ static void HIDDEN baz();
+
+ struct DEFAULT B {
+ static void foo();
+ static void DEFAULT bar();
+ static void HIDDEN baz();
+ };
+ };
+
+ void test() {
+ A::foo();
+ A::bar();
+ A::baz();
+ A::B::foo();
+ A::B::bar();
+ A::B::baz();
+ }
+ // CHECK: declare hidden void @_ZN6Test171A3fooEv()
+ // CHECK: declare void @_ZN6Test171A3barEv()
+ // CHECK: declare hidden void @_ZN6Test171A3bazEv()
+ // CHECK: declare void @_ZN6Test171A1B3fooEv()
+ // CHECK: declare void @_ZN6Test171A1B3barEv()
+ // CHECK: declare hidden void @_ZN6Test171A1B3bazEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test171A3fooEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test171A3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test171A3bazEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test171A1B3fooEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test171A1B3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test171A1B3bazEv()
+}
+
+namespace Test18 {
+ template <class T> struct HIDDEN A {
+ static void foo();
+ static void DEFAULT bar();
+ static void HIDDEN baz();
+
+ struct DEFAULT B {
+ static void foo();
+ static void DEFAULT bar();
+ static void HIDDEN baz();
+ };
+ };
+ struct HIDDEN H;
+
+ void test() {
+ A<int>::foo();
+ A<int>::bar();
+ A<int>::baz();
+ A<int>::B::foo();
+ A<int>::B::bar();
+ A<int>::B::baz();
+ A<H>::foo();
+ A<H>::bar();
+ A<H>::baz();
+ A<H>::B::foo();
+ A<H>::B::bar();
+ A<H>::B::baz();
+ }
+ // CHECK: declare hidden void @_ZN6Test181AIiE3fooEv()
+ // CHECK: declare void @_ZN6Test181AIiE3barEv()
+ // CHECK: declare hidden void @_ZN6Test181AIiE3bazEv()
+ // CHECK: declare void @_ZN6Test181AIiE1B3fooEv()
+ // CHECK: declare void @_ZN6Test181AIiE1B3barEv()
+ // CHECK: declare hidden void @_ZN6Test181AIiE1B3bazEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE3fooEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE3barEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE3bazEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE1B3fooEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE1B3barEv()
+ // CHECK: declare hidden void @_ZN6Test181AINS_1HEE1B3bazEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AIiE3fooEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test181AIiE3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AIiE3bazEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test181AIiE1B3fooEv()
+ // CHECK-HIDDEN: declare void @_ZN6Test181AIiE1B3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AIiE1B3bazEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE3fooEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE3bazEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE1B3fooEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE1B3barEv()
+ // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE1B3bazEv()
+}
+
+namespace Test19 {
+ struct A { A(); ~A(); };
+
+ // Tested at top of file.
+ template <class T> void foo() {
+ static A a;
+ }
+
+ void test() {
+ foo<int>();
+ }
+}
+
+// Various things with class template specializations.
+namespace Test20 {
+ template <unsigned> struct HIDDEN A {};
+
+ // An explicit specialization inherits the explicit visibility of
+ // the template.
+ template <> struct A<0> {
+ static void test0();
+ static void test1();
+ };
+
+ // CHECK: define hidden void @_ZN6Test201AILj0EE5test0Ev()
+ void A<0>::test0() {}
+
+ // CHECK: declare hidden void @_ZN6Test201AILj0EE5test1Ev()
+ void test1() {
+ A<0>::test1();
+ }
+
+ // ...unless that's explicitly overridden.
+ template <> struct DEFAULT A<1> {
+ static void test2();
+ static void test3();
+ };
+
+ // CHECK: define void @_ZN6Test201AILj1EE5test2Ev()
+ void A<1>::test2() {}
+
+ // CHECK: declare void @_ZN6Test201AILj1EE5test3Ev()
+ void test3() {
+ A<1>::test3();
+ }
+
+ // <rdar://problem/8778497>
+ // But we should assume that an unknown specialization has the
+ // explicit visibility settings of the template.
+ template <class T> struct B {
+ static void test4() {}
+ static void test5();
+ };
+
+ // CHECK: define linkonce_odr hidden void @_ZN6Test201BINS_1AILj2EEEE5test4Ev()
+ void test4() {
+ B<A<2> >::test4();
+ }
+
+ // CHECK: declare hidden void @_ZN6Test201BINS_1AILj2EEEE5test5Ev()
+ void test5() {
+ B<A<2> >::test5();
+ }
+}
+
+// PR9371
+namespace test21 {
+ enum En { en };
+ template<En> struct A {
+ __attribute__((visibility("default"))) void foo() {}
+ };
+
+ // CHECK: define weak_odr void @_ZN6test211AILNS_2EnE0EE3fooEv(
+ template void A<en>::foo();
+}
+
+// rdar://problem/9616154
+// Visibility on explicit specializations should take precedence.
+namespace test22 {
+ class A1 {};
+ class A2 {};
+
+ template <class T> struct B {};
+ template <> struct DEFAULT B<A1> {
+ static void foo();
+ static void bar() {}
+ };
+ template <> struct B<A2> {
+ static void foo();
+ static void bar() {}
+ };
+
+ void test() {
+ B<A1>::foo();
+ B<A1>::bar();
+ B<A2>::foo();
+ B<A2>::bar();
+ }
+ // CHECK: declare void @_ZN6test221BINS_2A1EE3fooEv()
+ // CHECK: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv()
+ // CHECK: declare void @_ZN6test221BINS_2A2EE3fooEv()
+ // CHECK: define linkonce_odr void @_ZN6test221BINS_2A2EE3barEv()
+ // CHECK-HIDDEN: declare void @_ZN6test221BINS_2A1EE3fooEv()
+ // CHECK-HIDDEN: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv()
+ // CHECK-HIDDEN: declare void @_ZN6test221BINS_2A2EE3fooEv()
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test221BINS_2A2EE3barEv()
+}
+
+namespace PR10113 {
+ namespace foo DEFAULT {
+ template<typename T>
+ class bar {
+ void zed() {}
+ };
+ }
+ template class foo::bar<char>;
+ // CHECK: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv
+
+ struct zed {
+ };
+ template class foo::bar<zed>;
+ // CHECK: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv
+}
+
+namespace PR11690 {
+ template<class T> struct Class {
+ void size() const {
+ }
+ };
+ template class DEFAULT Class<char>;
+ // CHECK: define weak_odr void @_ZNK7PR116905ClassIcE4sizeEv
+ // CHECK-HIDDEN: define weak_odr void @_ZNK7PR116905ClassIcE4sizeEv
+
+ template<class T> void Method() {}
+ template DEFAULT void Method<char>();
+ // CHECK: define weak_odr void @_ZN7PR116906MethodIcEEvv
+ // CHECK-HIDDEN: define weak_odr void @_ZN7PR116906MethodIcEEvv
+}
+
+namespace PR11690_2 {
+ namespace foo DEFAULT {
+ class bar;
+ template<typename T1, typename T2 = bar>
+ class zed {
+ void bar() {
+ }
+ };
+ }
+ struct baz {
+ };
+ template class foo::zed<baz>;
+ // CHECK: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
+}
+
+namespace test23 {
+ // Having a template argument that is explicitly visible should not make
+ // the template instantiation visible.
+ template <typename T>
+ struct X {
+ static void f() {
+ }
+ };
+
+ class DEFAULT A;
+
+ void g() {
+ X<A> y;
+ y.f();
+ }
+ // CHECK: define linkonce_odr void @_ZN6test231XINS_1AEE1fEv
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test231XINS_1AEE1fEv
+}
+
+namespace PR12001 {
+ template <typename P1>
+ void Bind(const P1& p1) {
+ }
+
+ class DEFAULT Version { };
+
+ void f() {
+ Bind(Version());
+ }
+ // CHECK: define linkonce_odr void @_ZN7PR120014BindINS_7VersionEEEvRKT_
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN7PR120014BindINS_7VersionEEEvRKT_
+}
+
+namespace test24 {
+ class DEFAULT A { };
+
+ struct S {
+ template <typename T>
+ void mem() {}
+ };
+
+ void test() {
+ S s;
+ s.mem<A>();
+ }
+ // CHECK: define linkonce_odr void @_ZN6test241S3memINS_1AEEEvv
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test241S3memINS_1AEEEvv
+}
+
+namespace test26 {
+ template<typename T>
+ class C {
+ __attribute__((visibility("default"))) void f();
+ };
+
+ template<>
+ void C<int>::f() { }
+
+ // CHECK: define void @_ZN6test261CIiE1fEv
+ // CHECK-HIDDEN: define void @_ZN6test261CIiE1fEv
+}