forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			1320 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1320 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C++
		
	
	
	
| // 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
 | |
| // For clang, "internal" is just an alias for "hidden". We could use it for some
 | |
| // optimization purposes on 32-bit x86, but it's not worth it.
 | |
| // RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -fvisibility internal -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 {
 | |
|     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
 | |
| }
 | |
| 
 | |
| 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<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 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
 | |
| // 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 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: @_ZTVN5Test63fooE = linkonce_odr hidden unnamed_addr constant
 | |
| 
 | |
| // CHECK-HIDDEN: @_ZTVN6Test161AIcEE = external unnamed_addr constant
 | |
| // CHECK-HIDDEN: @_ZTTN6Test161AIcEE = external unnamed_addr constant
 | |
| 
 | |
| // CHECK: @_ZZN6test681fC1EvE4test = linkonce_odr global
 | |
| // CHECK-HIDDEN: @_ZZN6test681fC1EvE4test = linkonce_odr hidden global
 | |
| 
 | |
| // CHECK: @_ZGVZN6test681fC1EvE4test = linkonce_odr global
 | |
| // CHECK-HIDDEN: @_ZGVZN6test681fC1EvE4test = linkonce_odr hidden global
 | |
| 
 | |
| // CHECK: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr global
 | |
| // CHECK-HIDDEN: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr hidden global
 | |
| 
 | |
| // CHECK: @_ZGVZN6Test193fooIiEEvvE1a = linkonce_odr global i64
 | |
| // CHECK-HIDDEN: @_ZGVZN6Test193fooIiEEvvE1a = linkonce_odr hidden global i64
 | |
| 
 | |
| namespace Test1 {
 | |
|   // CHECK-LABEL: 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-LABEL: 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-LABEL: define hidden void @_ZN5Test31A1B1fEv
 | |
|   void A::B::f() { }  
 | |
| }
 | |
| 
 | |
| namespace Test4 HIDDEN {
 | |
|   int VariableInHiddenNamespace = 10;
 | |
| 
 | |
|   // Test4::g is in a hidden namespace.
 | |
|   // CHECK-LABEL: define hidden void @_ZN5Test41gEv
 | |
|   void g() { } 
 | |
|   
 | |
|   struct DEFAULT A {
 | |
|     void f();
 | |
|   };
 | |
|   
 | |
|   // A has default visibility.
 | |
|   // CHECK-LABEL: define void @_ZN5Test41A1fEv
 | |
|   void A::f() { } 
 | |
| }
 | |
| 
 | |
| namespace Test5 {
 | |
| 
 | |
|   namespace NS HIDDEN {
 | |
|     // f is in NS which is hidden.
 | |
|     // CHECK-LABEL: define hidden void @_ZN5Test52NS1fEv()
 | |
|     void f() { }
 | |
|   }
 | |
|   
 | |
|   namespace NS {
 | |
|     // g is in NS, but this NS decl is not hidden.
 | |
|     // CHECK-LABEL: 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-LABEL: define linkonce_odr hidden void @_ZN5Test74ArefIL_ZNS_1aEEE3fooEv()
 | |
|   void test() {
 | |
|     Aref<a>::foo();
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace Test8 {
 | |
|   void foo();
 | |
|   void bar() {}
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define void @test9_fun(
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define void @_ZN6Test101B3fooEPNS_1AE(
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define linkonce_odr void @_ZN6Test111A3fooEv(
 | |
|   // CHECK-LABEL: define linkonce_odr void @_ZN6Test111A3barEv(
 | |
|   // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6Test111A3fooEv(
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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 {
 | |
|     DEFAULT void foo() {}
 | |
|   };
 | |
| 
 | |
|   // CHECK-LABEL: 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-LABEL: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv()
 | |
|   // CHECK: declare void @_ZN6test221BINS_2A2EE3fooEv()
 | |
|   // CHECK-LABEL: define linkonce_odr void @_ZN6test221BINS_2A2EE3barEv()
 | |
|   // CHECK-HIDDEN: declare void @_ZN6test221BINS_2A1EE3fooEv()
 | |
|   // CHECK-HIDDEN-LABEL: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv()
 | |
|   // CHECK-HIDDEN: declare void @_ZN6test221BINS_2A2EE3fooEv()
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv
 | |
| 
 | |
|   struct zed {
 | |
|   };
 | |
|   template class foo::bar<zed>;
 | |
|   // CHECK-LABEL: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN7PR101133foo3barINS_3zedEE3zedEv
 | |
| }
 | |
| 
 | |
| namespace PR11690 {
 | |
|   template<class T> struct Class {
 | |
|     void size() const {
 | |
|     }
 | |
|   };
 | |
|   template class DEFAULT Class<char>;
 | |
|   // CHECK-LABEL: define weak_odr void @_ZNK7PR116905ClassIcE4sizeEv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr void @_ZNK7PR116905ClassIcE4sizeEv
 | |
| 
 | |
|   template<class T> void Method() {}
 | |
|   template  DEFAULT void Method<char>();
 | |
|   // CHECK-LABEL: define weak_odr void @_ZN7PR116906MethodIcEEvv
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
 | |
|   // CHECK-HIDDEN-LABEL: 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 <typename T>
 | |
|   struct X {
 | |
|     static void f() {
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   class DEFAULT A;
 | |
| 
 | |
|   void g() {
 | |
|     X<A> y;
 | |
|     y.f();
 | |
|   }
 | |
|   // CHECK-LABEL: define linkonce_odr void @_ZN6test231XINS_1AEE1fEv
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define linkonce_odr void @_ZN7PR120014BindINS_7VersionEEEvRKT_
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define linkonce_odr void @_ZN6test241S3memINS_1AEEEvv
 | |
|   // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test241S3memINS_1AEEEvv
 | |
| }
 | |
| 
 | |
| namespace test26 {
 | |
|   template<typename T>
 | |
|   class C {
 | |
|     DEFAULT  void f();
 | |
|   };
 | |
| 
 | |
|   template<>
 | |
|   void C<int>::f() { }
 | |
| 
 | |
|   // CHECK-LABEL: define void @_ZN6test261CIiE1fEv
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define void @_ZN6test321A1B3bazEv
 | |
|   // CHECK-HIDDEN-LABEL: define void @_ZN6test321A1B3bazEv
 | |
| }
 | |
| 
 | |
| namespace test33 {
 | |
|   template<typename T>
 | |
|   class foo {
 | |
|     void bar() {}
 | |
|   };
 | |
|   struct HIDDEN zed {
 | |
|   };
 | |
|   template class DEFAULT foo<zed>;
 | |
|   // CHECK-LABEL: define weak_odr void @_ZN6test333fooINS_3zedEE3barEv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test333fooINS_3zedEE3barEv
 | |
| }
 | |
| 
 | |
| namespace test34 {
 | |
|   struct foo {
 | |
|   };
 | |
|   template<class T>
 | |
|   void bar() {}
 | |
|   template DEFAULT void bar<foo>();
 | |
|   // CHECK-LABEL: define weak_odr void @_ZN6test343barINS_3fooEEEvv
 | |
|   // CHECK-HIDDEN-LABEL: 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<typename T>
 | |
|   struct DEFAULT foo {
 | |
|     void bar() {}
 | |
|   };
 | |
|   class zed;
 | |
|   template class foo<zed>;
 | |
|   class DEFAULT zed {
 | |
|   };
 | |
|   // CHECK-LABEL: define weak_odr void @_ZN6test353fooINS_3zedEE3barEv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr hidden 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-LABEL: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define weak_odr void @_ZN6test373barINS_3fooEEEvv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test373barINS_3fooEEEvv
 | |
| }
 | |
| 
 | |
| namespace test38 {
 | |
|   template<typename T>
 | |
|   class DEFAULT foo {
 | |
|     void bar() {}
 | |
|   };
 | |
|   struct HIDDEN zed {
 | |
|   };
 | |
|   template class foo<zed>;
 | |
|   // CHECK-LABEL: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv
 | |
|   // CHECK-LABEL: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv
 | |
|   // CHECK-LABEL: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv
 | |
| 
 | |
|   // GCC produces a default for this one. Why?
 | |
|   // CHECK-LABEL: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv
 | |
| 
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv
 | |
| 
 | |
|   // GCC produces a default for this one. Why?
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define void @_ZN6test423barINS_3fooEE3zedEv
 | |
|   // CHECK-HIDDEN-LABEL: define void @_ZN6test423barINS_3fooEE3zedEv
 | |
| }
 | |
| 
 | |
| namespace test43 {
 | |
|   struct HIDDEN foo {
 | |
|   };
 | |
|   template <class P>
 | |
|   void bar() {
 | |
|   }
 | |
|   template <>
 | |
|   DEFAULT void bar<foo>() {
 | |
|   }
 | |
|   // CHECK-LABEL: define void @_ZN6test433barINS_3fooEEEvv
 | |
|   // CHECK-HIDDEN-LABEL: define void @_ZN6test433barINS_3fooEEEvv
 | |
| }
 | |
| 
 | |
| namespace test44 {
 | |
|   template <typename T>
 | |
|   struct foo {
 | |
|     foo() {}
 | |
|   };
 | |
|   namespace {
 | |
|     struct bar;
 | |
|   }
 | |
|   template struct DEFAULT foo<bar>;
 | |
|   foo<bar> x;
 | |
|   // CHECK-LABEL: define internal void @_ZN6test443fooINS_12_GLOBAL__N_13barEEC1Ev
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define internal void @_ZN6test453fooIiE3barINS_12_GLOBAL__N_13zedEEC1Ev
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define internal void @_ZN6test463fooINS_12_GLOBAL__N_13barEEEvv
 | |
|   // CHECK-HIDDEN-LABEL: define internal void @_ZN6test463fooINS_12_GLOBAL__N_13barEEEvv
 | |
| }
 | |
| 
 | |
| namespace test47 {
 | |
|   struct foo {
 | |
|     template <typename T>
 | |
|     static void bar() {
 | |
|     }
 | |
|   };
 | |
|   namespace {
 | |
|     struct zed;
 | |
|   }
 | |
|   template DEFAULT void foo::bar<zed>();
 | |
|   void baz() {
 | |
|     foo::bar<zed>();
 | |
|   }
 | |
|   // CHECK-LABEL: define internal void @_ZN6test473foo3barINS_12_GLOBAL__N_13zedEEEvv
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define weak_odr hidden void @_ZN6test493bar3zedIXadL_ZNS_1xEEEEEvv
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define weak_odr hidden void @_ZN6test503barIXadL_ZNS_1xEEEE3zedEv
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define internal void @_ZN6test523zedILPNS_12_GLOBAL__N_13fooE0EEEvv
 | |
|   // CHECK-HIDDEN-LABEL: 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 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 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 DEFAULT bar {
 | |
|     static void zed() {
 | |
|     }
 | |
|   };
 | |
|   void bah() {
 | |
|     bar<foo>::zed();
 | |
|   }
 | |
| #pragma GCC visibility pop
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test583barINS_3fooEE3zedEv
 | |
|   // CHECK-HIDDEN-LABEL: 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-LABEL: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1gEvEEXadL_ZNS_1fEvEEEEvv
 | |
|     // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1gEvEEXadL_ZNS_1fEvEEEEvv
 | |
| 
 | |
|     test<&f, &g>();
 | |
|     // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1fEvEEXadL_ZNS_1gEvEEEEvv
 | |
|     // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1fEvEEXadL_ZNS_1gEvEEEEvv
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace test60 {
 | |
|   template<int i>
 | |
|   class HIDDEN a {};
 | |
|   template<int i>
 | |
|   class DEFAULT b {};
 | |
|   template<template<int> class x, template<int> class y>
 | |
|   void test() {}
 | |
|   void use() {
 | |
|     test<a, b>();
 | |
|     // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test604testINS_1aENS_1bEEEvv
 | |
|     // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test604testINS_1aENS_1bEEEvv
 | |
| 
 | |
|     test<b, a>();
 | |
|     // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test604testINS_1bENS_1aEEEvv
 | |
|     // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test604testINS_1bENS_1aEEEvv
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace test61 {
 | |
|   template <typename T1>
 | |
|   struct Class1
 | |
|   {
 | |
|     void f1() { f2(); }
 | |
|     inline void f2();
 | |
|   };
 | |
|   template<>
 | |
|   inline void Class1<int>::f2()
 | |
|   {
 | |
|   }
 | |
|   void g(Class1<int> *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<int>;
 | |
| }
 | |
| 
 | |
| namespace test62 {
 | |
|   template <typename T1>
 | |
|   struct Class1
 | |
|   {
 | |
|     void f1() { f2(); }
 | |
|     inline void f2() {}
 | |
|   };
 | |
|   template<>
 | |
|   inline void Class1<int>::f2()
 | |
|   {
 | |
|   }
 | |
|   void g(Class1<int> *x) {
 | |
|     x->f2();
 | |
|   }
 | |
| }
 | |
| namespace test62 {
 | |
|   template class HIDDEN Class1<int>;
 | |
|   // 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 <E> static void foo() {}
 | |
| 
 | |
|     template <E> struct B {
 | |
|       static void foo() {}
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   void test() {
 | |
|     A::foo<E0>();
 | |
|     A::B<E0>::foo();
 | |
|   }
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test631A3fooILNS_1EE0EEEvv()
 | |
|   // CHECK-LABEL: 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 <class P> struct B {
 | |
|     static DEFAULT void foo() {}
 | |
|   };
 | |
| 
 | |
|   template class B<A>;
 | |
|   // CHECK-LABEL: define weak_odr hidden void @_ZN6test641BINS_1AEE3fooEv()
 | |
| }
 | |
| 
 | |
| namespace test65 {
 | |
|   class HIDDEN A {};
 | |
|   template <class T> struct B {
 | |
|     static void func();
 | |
|     template <class U> static void funcT1();
 | |
|     template <class U> static void funcT2();
 | |
|     class Inner {};
 | |
|     template <class U> class InnerT {};
 | |
|   };
 | |
|   template <template <class T> class Temp> struct C {
 | |
|     static void foo() {}
 | |
|   };
 | |
| 
 | |
|   // CHECK-LABEL: define void @_ZN6test651BINS_1AEE4funcEv()
 | |
|   template <> DEFAULT void B<A>::func() {}
 | |
| 
 | |
|   // CHECK-LABEL: define void @_ZN6test651BINS_1AEE6funcT2IS1_EEvv()
 | |
|   template <> template <> DEFAULT void B<A>::funcT2<A>() {}
 | |
| 
 | |
|   // CHECK-LABEL: define linkonce_odr void @_ZN6test651BINS_1AEE6funcT1IiEEvv()
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test651BINS_1AEE6funcT1IS1_EEvv()
 | |
|   template <> template <class T> DEFAULT void B<A>::funcT1() {}
 | |
| 
 | |
|   // CHECK-LABEL: define linkonce_odr void @_ZN6test651BINS_1AEE5Inner3fooEv()
 | |
|   template <> struct DEFAULT B<A>::Inner {
 | |
|     static void foo() {}
 | |
|   };
 | |
| 
 | |
|   // CHECK-LABEL: define linkonce_odr void @_ZN6test651BINS_1AEE6InnerTIiE3fooEv()
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test651BINS_1AEE6InnerTIS1_E3fooEv()
 | |
|   template <> template <class U> struct DEFAULT B<A>::InnerT {
 | |
|     static void foo() {}
 | |
|   };
 | |
| 
 | |
|   void test() {
 | |
|     B<A>::funcT1<int>();
 | |
|     B<A>::funcT1<A>();
 | |
|     B<A>::Inner::foo();
 | |
|     B<A>::InnerT<int>::foo();
 | |
|     B<A>::InnerT<A>::foo();
 | |
|   }
 | |
| 
 | |
|   template class C<B<A>::InnerT>;
 | |
| }
 | |
| 
 | |
| namespace test66 {
 | |
|   template <typename T>
 | |
|   struct DEFAULT barT {
 | |
|     static void zed() {}
 | |
|   };
 | |
|   class foo;
 | |
|   class DEFAULT foo;
 | |
|   template struct barT<foo>;
 | |
|   // CHECK-LABEL: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
 | |
| 
 | |
|   template <int* I>
 | |
|   struct DEFAULT barI {
 | |
|     static void zed() {}
 | |
|   };
 | |
|   extern int I;
 | |
|   extern int I DEFAULT;
 | |
|   template struct barI<&I>;
 | |
|   // CHECK-LABEL: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
 | |
| 
 | |
|   typedef void (*fType)(void);
 | |
|   template<fType F>
 | |
|   struct DEFAULT barF {
 | |
|     static void zed() {}
 | |
|   };
 | |
|   void F();
 | |
|   void F() DEFAULT;
 | |
|   template struct barF<F>;
 | |
|   // CHECK-LABEL: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
 | |
| }
 | |
| 
 | |
| namespace test67 {
 | |
|   template <typename T>
 | |
|   struct DEFAULT bar {
 | |
|     static void zed() {}
 | |
|   };
 | |
| 
 | |
|   class foo;
 | |
|   class compute {
 | |
|     void f(foo *rootfoo);
 | |
|   };
 | |
|   class DEFAULT foo;
 | |
| 
 | |
|   template struct bar<foo>;
 | |
|   // CHECK-LABEL: define weak_odr void @_ZN6test673barINS_3fooEE3zedEv
 | |
|   // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test673barINS_3fooEE3zedEv
 | |
| }
 | |
| 
 | |
| namespace test68 {
 | |
|   class A { public: ~A(); };
 | |
|   class f {
 | |
|   public:
 | |
|     f() {
 | |
|       static A test;
 | |
|     }
 | |
|   };
 | |
|   void g() {
 | |
|     f a;
 | |
|   }
 | |
|   // Check lines at top of file.
 | |
| }
 | |
| 
 | |
| namespace test69 {
 | |
|   // PR18174
 | |
|   namespace foo {
 | |
|     void f();
 | |
|   }
 | |
|   namespace foo {
 | |
|     void f() {};
 | |
|   }
 | |
|   namespace foo __attribute__((visibility("hidden"))) {
 | |
|   }
 | |
|   // CHECK-LABEL: define void @_ZN6test693foo1fEv
 | |
|   // CHECK-HIDDEN-LABEL: define hidden void @_ZN6test693foo1fEv
 | |
| }
 |