// 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 struct X { }; H DEFAULT a; X<&a> b; // CHECK: _ZN6test301bE = global // CHECK-HIDDEN: _ZN6test301bE = hidden global } namespace test25 { template struct X { template struct definition { }; }; class DEFAULT A { }; X::definition a; // CHECK: @_ZN6test251aE = global // CHECK-HIDDEN: @_ZN6test251aE = hidden global } namespace test28 { class DEFAULT foo { }; foo myvec; // CHECK: @_ZN6test285myvecE = global // CHECK-HIDDEN: @_ZN6test285myvecE = hidden global } namespace test29 { #pragma GCC visibility push(hidden) struct RECT { int top; }; 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 struct foo { DEFAULT static int bar; }; template int foo::bar; template struct foo; // 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 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 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 // 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 class C { class DEFAULT D { void f(); }; }; template<> class C::D { virtual void g(); }; void C::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() { } } } // 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 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::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 struct Temp { struct Inner { static char buffer[0]; }; }; char *test() { return Temp::Inner::buffer; } } namespace Test16 { struct Base1 { virtual void foo(); }; struct Base2 : virtual Base1 { virtual void foo(); }; template struct A : virtual Base1, Base2 { virtual void foo(); }; extern template struct A; void test() { A 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 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::foo(); A::bar(); A::baz(); A::B::foo(); A::B::bar(); A::B::baz(); A::foo(); A::bar(); A::baz(); A::B::foo(); A::B::bar(); A::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 void foo() { static A a; } void test() { foo(); } } // Various things with class template specializations. namespace Test20 { template 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(); } // // But we should assume that an unknown specialization has the // explicit visibility settings of the template. template struct B { static void test4() {} static void test5(); }; // CHECK: define linkonce_odr hidden void @_ZN6Test201BINS_1AILj2EEEE5test4Ev() void test4() { B >::test4(); } // CHECK: declare hidden void @_ZN6Test201BINS_1AILj2EEEE5test5Ev() void test5() { B >::test5(); } } // PR9371 namespace test21 { enum En { en }; template struct A { DEFAULT void foo() {} }; // CHECK: define weak_odr void @_ZN6test211AILNS_2EnE0EE3fooEv( template void A::foo(); } // rdar://problem/9616154 // Visibility on explicit specializations should take precedence. namespace test22 { class A1 {}; class A2 {}; template struct B {}; template <> struct DEFAULT B { static void foo(); static void bar() {} }; template <> struct B { static void foo(); static void bar() {} }; void test() { B::foo(); B::bar(); B::foo(); B::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 class bar { void zed() {} }; } template class foo::bar; // CHECK: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv // CHECK-HIDDEN: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv struct zed { }; template class foo::bar; // CHECK: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv // CHECK-HIDDEN: define weak_odr hidden void @_ZN7PR101133foo3barINS_3zedEE3zedEv } namespace PR11690 { template struct Class { void size() const { } }; template class DEFAULT Class; // CHECK: define weak_odr void @_ZNK7PR116905ClassIcE4sizeEv // CHECK-HIDDEN: define weak_odr void @_ZNK7PR116905ClassIcE4sizeEv template void Method() {} template DEFAULT void Method(); // CHECK: define weak_odr void @_ZN7PR116906MethodIcEEvv // CHECK-HIDDEN: define weak_odr void @_ZN7PR116906MethodIcEEvv } namespace PR11690_2 { namespace foo DEFAULT { class bar; template class zed { void bar() { } }; } struct baz { }; template class foo::zed; // CHECK: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv // CHECK-HIDDEN: define weak_odr hidden void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv } namespace test23 { // Having a template argument that is explicitly visible should not make // the template instantiation visible. template struct X { static void f() { } }; class DEFAULT A; void g() { X y; y.f(); } // CHECK: define linkonce_odr void @_ZN6test231XINS_1AEE1fEv // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test231XINS_1AEE1fEv } namespace PR12001 { template 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 void mem() {} }; void test() { S s; s.mem(); } // CHECK: define linkonce_odr void @_ZN6test241S3memINS_1AEEEvv // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test241S3memINS_1AEEEvv } namespace test26 { template class C { DEFAULT void f(); }; template<> void C::f() { } // 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 class foo { void bar() {} }; struct HIDDEN zed { }; template class DEFAULT foo; // CHECK: define weak_odr void @_ZN6test333fooINS_3zedEE3barEv // CHECK-HIDDEN: define weak_odr void @_ZN6test333fooINS_3zedEE3barEv } namespace test34 { struct foo { }; template void bar() {} template DEFAULT void bar(); // 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. It's not really clear what we can do here, because we // produce the symbols before even seeing the DEFAULT definition of zed. // FIXME: Maybe the best thing to do here is error? It's certainly hard // to argue that this ought to be valid. template struct DEFAULT foo { void bar() {} }; class zed; template class foo; class DEFAULT zed { }; // CHECK: define weak_odr void @_ZN6test353fooINS_3zedEE3barEv // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test353fooINS_3zedEE3barEv } namespace test36 { template class foo { void bar() {} }; class DEFAULT S1 {}; struct HIDDEN S2 {}; template class foo; // 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 DEFAULT void bar() {} template DEFAULT void bar(); // CHECK: define weak_odr void @_ZN6test373barINS_3fooEEEvv // CHECK-HIDDEN: define weak_odr void @_ZN6test373barINS_3fooEEEvv } namespace test38 { template class DEFAULT foo { void bar() {} }; struct HIDDEN zed { }; template class foo; // 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 A { template class B { HIDDEN void hidden() {} void noattr() {} template void temp() {} }; }; template class DEFAULT A; template class DEFAULT A::B; template void A::B::temp(); template void A::B::temp(); // 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 struct bar { }; template <> struct HIDDEN bar { DEFAULT static void zed(); }; void bar::zed() { } // CHECK: define void @_ZN6test423barINS_3fooEE3zedEv // CHECK-HIDDEN: define void @_ZN6test423barINS_3fooEE3zedEv } namespace test43 { struct HIDDEN foo { }; template void bar() { } template <> DEFAULT void bar() { } // CHECK: define void @_ZN6test433barINS_3fooEEEvv // CHECK-HIDDEN: define void @_ZN6test433barINS_3fooEEEvv } namespace test44 { template struct foo { foo() {} }; namespace { struct bar; } template struct DEFAULT foo; foo x; // CHECK: define internal void @_ZN6test443fooINS_12_GLOBAL__N_13barEEC1Ev // CHECK-HIDDEN: define internal void @_ZN6test443fooINS_12_GLOBAL__N_13barEEC1Ev } namespace test45 { template struct foo { template struct bar { bar() {}; }; }; namespace { struct zed; } template struct DEFAULT foo::bar; foo::bar x; // CHECK: define internal void @_ZN6test453fooIiE3barINS_12_GLOBAL__N_13zedEEC1Ev // CHECK-HIDDEN: define internal void @_ZN6test453fooIiE3barINS_12_GLOBAL__N_13zedEEC1Ev } namespace test46 { template void foo() { } namespace { struct bar; } template DEFAULT void foo(); void zed() { foo(); } // CHECK: define internal void @_ZN6test463fooINS_12_GLOBAL__N_13barEEEvv // CHECK-HIDDEN: define internal void @_ZN6test463fooINS_12_GLOBAL__N_13barEEEvv } namespace test47 { struct foo { template static void bar() { } }; namespace { struct zed; } template DEFAULT void foo::bar(); void baz() { foo::bar(); } // 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 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 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 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 void zed() { } void f() { zed(); } // CHECK: define internal void @_ZN6test523zedILPNS_12_GLOBAL__N_13fooE0EEEvv // CHECK-HIDDEN: define internal void @_ZN6test523zedILPNS_12_GLOBAL__N_13fooE0EEEvv } namespace test53 { template 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 { static void _M_fill_insert(); }; void foo() { vector::_M_fill_insert(); vector::_M_fill_insert(); vector::_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 struct foo { static void bar(); }; #pragma GCC visibility push(hidden) class zed { zed(const zed &); }; void bah() { foo::bar(); } #pragma GCC visibility pop // CHECK: declare hidden void @_ZN6test543fooINS_3zedEE3barEv // CHECK-HIDDEN: declare hidden void @_ZN6test543fooINS_3zedEE3barEv } namespace test55 { template struct HIDDEN foo { static void bar(); }; template struct foo; void foobar() { foo::bar(); } // CHECK: declare hidden void @_ZN6test553fooIiE3barEv // CHECK-HIDDEN: declare hidden void @_ZN6test553fooIiE3barEv } namespace test56 { template struct foo; template struct HIDDEN foo { static void bar(); }; void foobar() { foo::bar(); } // CHECK: declare hidden void @_ZN6test563fooIiE3barEv // CHECK-HIDDEN: declare hidden void @_ZN6test563fooIiE3barEv } namespace test57 { #pragma GCC visibility push(hidden) template struct foo; void bar(foo*); template struct foo { static void zed(); }; void bah() { foo::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 struct DEFAULT bar { static void zed() { } }; void bah() { bar::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 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 class HIDDEN a {}; template class DEFAULT b {}; template class x, template class y> void test() {} void use() { test(); // CHECK: define linkonce_odr hidden void @_ZN6test604testINS_1aENS_1bEEEvv // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test604testINS_1aENS_1bEEEvv test(); // CHECK: define linkonce_odr hidden void @_ZN6test604testINS_1bENS_1aEEEvv // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test604testINS_1bENS_1aEEEvv } } namespace test61 { template struct Class1 { void f1() { f2(); } inline void f2(); }; template<> inline void Class1::f2() { } void g(Class1 *x) { x->f1(); } } namespace test61 { // Just test that we don't crash. Currently we apply this attribute. Current // gcc issues a warning about it being unused since "the type is already // defined". We should probably do the same. template class HIDDEN Class1; } namespace test62 { template struct Class1 { void f1() { f2(); } inline void f2() {} }; template<> inline void Class1::f2() { } void g(Class1 *x) { x->f2(); } } namespace test62 { template class HIDDEN Class1; // Just test that we don't crash. Currently we apply this attribute. Current // gcc issues a warning about it being unused since "the type is already // defined". We should probably do the same. } namespace test63 { enum HIDDEN E { E0 }; struct A { template static void foo() {} template struct B { static void foo() {} }; }; void test() { A::foo(); A::B::foo(); } // CHECK: define linkonce_odr hidden void @_ZN6test631A3fooILNS_1EE0EEEvv() // CHECK: define linkonce_odr hidden void @_ZN6test631A1BILNS_1EE0EE3fooEv() } // Don't ignore the visibility of template arguments just because we // explicitly instantiated something. namespace test64 { struct HIDDEN A {}; template struct B { static DEFAULT void foo() {} }; template class B; // CHECK: define weak_odr hidden void @_ZN6test641BINS_1AEE3fooEv() } namespace test65 { class HIDDEN A {}; template struct B { static void func(); template static void funcT1(); template static void funcT2(); class Inner {}; template class InnerT {}; }; template