forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			461 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			461 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
// RUN: %clang_cc1 -verify -fsyntax-only -Wno-c++11-extensions -Wno-c++1y-extensions %s -DPRECXX11
 | 
						|
// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s
 | 
						|
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s
 | 
						|
 | 
						|
#ifdef PRECXX11
 | 
						|
  #define CONST const
 | 
						|
#else
 | 
						|
  #define CONST constexpr
 | 
						|
#endif
 | 
						|
 | 
						|
template<typename T> 
 | 
						|
T pi = T(3.1415926535897932385); // expected-note {{template is declared here}}
 | 
						|
 | 
						|
template<typename T> 
 | 
						|
CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}}
 | 
						|
 | 
						|
template<typename T> extern CONST T vc;
 | 
						|
#ifndef PRECXX11
 | 
						|
// expected-error@-2 {{constexpr variable declaration must be a definition}}
 | 
						|
#endif
 | 
						|
 | 
						|
namespace use_in_top_level_funcs {
 | 
						|
 | 
						|
  void good() {
 | 
						|
    int ipi = pi<int>;
 | 
						|
    int icpi = cpi<int>;
 | 
						|
    double dpi = pi<double>;
 | 
						|
    double dcpi = cpi<double>;
 | 
						|
  }
 | 
						|
 | 
						|
  void no_deduce() {
 | 
						|
    // template arguments are not deduced for uses of variable templates.
 | 
						|
    int ipi = pi; // expected-error {{cannot refer to variable template 'pi' without a template argument list}}
 | 
						|
    int icpi = cpi; // expected-error {{cannot refer to variable template 'cpi' without a template argument list}}
 | 
						|
  }
 | 
						|
  
 | 
						|
  template<typename T>
 | 
						|
  T circular_area(T r) {
 | 
						|
    return pi<T> * r * r;
 | 
						|
  }
 | 
						|
 | 
						|
  template<typename T>
 | 
						|
  CONST T const_circular_area(T r) {
 | 
						|
    return cpi<T> * r * r;
 | 
						|
  }
 | 
						|
 | 
						|
  double use_circular_area(double r) {
 | 
						|
    CONST float t = const_circular_area(2.0) - 12;
 | 
						|
#ifndef PRECXX11
 | 
						|
    static_assert(const_circular_area(2) == 12, "");
 | 
						|
    CONST int test = (t > 0) && (t < 1);
 | 
						|
    static_assert(test, "");
 | 
						|
#endif
 | 
						|
    return circular_area(r);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace shadow {
 | 
						|
  void foo() {
 | 
						|
    int ipi0 = pi<int>;
 | 
						|
    int pi;
 | 
						|
    int a = pi;
 | 
						|
    int ipi = pi<int>;  // expected-error {{expected '(' for function-style cast or type construction}} \
 | 
						|
                        // expected-error {{expected expression}}
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace odr_tmpl {
 | 
						|
  namespace pv_cvt {
 | 
						|
    int v;   // expected-note {{previous definition is here}}
 | 
						|
    template<typename T> T v; // expected-error {{redefinition of 'v' as different kind of symbol}}
 | 
						|
  }
 | 
						|
  namespace pvt_cv {
 | 
						|
    template<typename T> T v; // expected-note {{previous definition is here}}
 | 
						|
    int v;   // expected-error {{redefinition of 'v' as different kind of symbol}}
 | 
						|
  }
 | 
						|
  namespace pvt_cvt {
 | 
						|
    template<typename T> T v0; // expected-note {{previous definition is here}}
 | 
						|
    template<typename T> T v0; // expected-error {{redefinition of 'v0'}}
 | 
						|
 | 
						|
    template<typename T> T v; // expected-note {{previous definition is here}}
 | 
						|
    template<typename T> int v; // expected-error {{redefinition of 'v'}}
 | 
						|
    
 | 
						|
    template<typename T> extern int v1; // expected-note {{previous template declaration is here}}
 | 
						|
    template<int I> int v1;      // expected-error {{template parameter has a different kind in template redeclaration}}
 | 
						|
  }
 | 
						|
  namespace pvt_use {
 | 
						|
    template<typename T> T v;
 | 
						|
    v = 10;  // expected-error {{C++ requires a type specifier for all declarations}}
 | 
						|
  }
 | 
						|
 | 
						|
  namespace pvt_diff_params {
 | 
						|
    template<typename T, typename> T v;   // expected-note {{previous template declaration is here}}
 | 
						|
    template<typename T> T v;   // expected-error {{too few template parameters in template redeclaration}} expected-note {{previous template declaration is here}}
 | 
						|
    template<typename T, typename, typename> T v; // expected-error {{too many template parameters in template redeclaration}}
 | 
						|
  }
 | 
						|
 | 
						|
  namespace pvt_extern {
 | 
						|
    template<typename T> T v = T();
 | 
						|
    template<typename T> extern T v;      // redeclaration is allowed \
 | 
						|
                                          // expected-note {{previous definition is here}}
 | 
						|
    template<typename T> extern int v;    // expected-error {{redefinition of 'v' with a different type: 'int' vs 'T'}}
 | 
						|
 | 
						|
#ifndef PRECXX11
 | 
						|
    template<typename T> extern auto v;   // expected-error {{declaration of variable 'v' with type 'auto' requires an initializer}}
 | 
						|
#endif
 | 
						|
 | 
						|
    template<typename T> T var = T();     // expected-note {{previous definition is here}}
 | 
						|
    extern int var;                       // expected-error {{redefinition of 'var' as different kind of symbol}}
 | 
						|
  }
 | 
						|
 | 
						|
#ifndef PRECXX11
 | 
						|
  namespace pvt_auto {
 | 
						|
    template<typename T> auto v0; // expected-error {{declaration of variable 'v0' with type 'auto' requires an initializer}}
 | 
						|
    template<typename T> auto v1 = T();  // expected-note {{previous definition is here}}
 | 
						|
    template<typename T> int v1;   // expected-error {{redefinition of 'v1' with a different type: 'int' vs 'auto'}}
 | 
						|
    template<typename T> auto v2 = T();  // expected-note {{previous definition is here}}
 | 
						|
    template<typename T> T v2;   // expected-error {{redefinition of 'v2'}}
 | 
						|
    template<typename T> auto v3 = T();   // expected-note {{previous definition is here}}
 | 
						|
    template<typename T> extern T v3;     // expected-error {{redefinition of 'v3' with a different type: 'T' vs 'auto'}}
 | 
						|
    template<typename T> auto v4 = T();
 | 
						|
    template<typename T> extern auto v4;   // expected-error {{declaration of variable 'v4' with type 'auto' requires an initializer}}
 | 
						|
  }
 | 
						|
#endif
 | 
						|
  
 | 
						|
}
 | 
						|
 | 
						|
namespace explicit_instantiation {
 | 
						|
  template<typename T> 
 | 
						|
  T pi0a = T(3.1415926535897932385);  // expected-note {{variable template 'pi0a' declared here}}
 | 
						|
  template float pi0a<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0a' does not match expected type 'int'}}
 | 
						|
 | 
						|
  template<typename T> 
 | 
						|
  T pi0b = T(3.1415926535897932385);  // expected-note {{variable template 'pi0b' declared here}}
 | 
						|
  template CONST int pi0b<int>; // expected-error {{type 'const int' of explicit instantiation of 'pi0b' does not match expected type 'int'}}
 | 
						|
 | 
						|
  template<typename T> 
 | 
						|
  T pi0c = T(3.1415926535897932385);  // expected-note {{variable template 'pi0c' declared here}}
 | 
						|
  template int pi0c<const int>;  // expected-error {{type 'int' of explicit instantiation of 'pi0c' does not match expected type 'const int'}}
 | 
						|
 | 
						|
  template<typename T> 
 | 
						|
  T pi0 = T(3.1415926535897932385);
 | 
						|
  template int pi0<int>;   // expected-note {{previous explicit instantiation is here}}
 | 
						|
  template int pi0<int>;   // expected-error {{duplicate explicit instantiation of 'pi0<int>'}}
 | 
						|
 | 
						|
  template<typename T> 
 | 
						|
  CONST T pi1a = T(3.1415926535897932385);  // expected-note {{variable template 'pi1a' declared here}}
 | 
						|
  template int pi1a<int>; // expected-error {{type 'int' of explicit instantiation of 'pi1a' does not match expected type 'const int'}}
 | 
						|
 | 
						|
  template<typename T> 
 | 
						|
  CONST T pi1b = T(3.1415926535897932385);  // expected-note {{variable template 'pi1b' declared here}}
 | 
						|
  template int pi1b<const int>;  // expected-error {{type 'int' of explicit instantiation of 'pi1b' does not match expected type 'const const int'}}
 | 
						|
 | 
						|
  template<typename T> 
 | 
						|
  CONST T pi1 = T(3.1415926535897932385);
 | 
						|
  template CONST int pi1<int>;   // expected-note {{previous explicit instantiation is here}}
 | 
						|
  template CONST int pi1<int>;   // expected-error {{duplicate explicit instantiation of 'pi1<int>'}}
 | 
						|
 | 
						|
#ifndef PRECXX11
 | 
						|
  namespace auto_var {
 | 
						|
    template<typename T> auto var0 = T();
 | 
						|
    template auto var0<int>;    // expected-error {{'auto' variable template instantiation is not allowed}}
 | 
						|
    
 | 
						|
    template<typename T> auto var = T();
 | 
						|
    template int var<int>;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  template<typename=int> int missing_args; // expected-note {{here}}
 | 
						|
  template int missing_args; // expected-error {{must specify a template argument list}}
 | 
						|
 | 
						|
  namespace extern_var {
 | 
						|
    // TODO:
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace explicit_specialization {
 | 
						|
 | 
						|
  namespace good {
 | 
						|
    template<typename T1, typename T2>
 | 
						|
    CONST int pi2 = 1;
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    CONST int pi2<T,int> = 2;
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    CONST int pi2<int,T> = 3;
 | 
						|
 | 
						|
    template<> CONST int pi2<int,int> = 4;
 | 
						|
 | 
						|
#ifndef PRECXX11   
 | 
						|
    void foo() {
 | 
						|
      static_assert(pi2<int,int> == 4, "");
 | 
						|
      static_assert(pi2<float,int> == 2, "");
 | 
						|
      static_assert(pi2<int,float> == 3, "");
 | 
						|
      static_assert(pi2<int,float> == pi2<int,double>, "");
 | 
						|
      static_assert(pi2<float,float> == 1, "");
 | 
						|
      static_assert(pi2<float,float> == pi2<float,double>, "");
 | 
						|
    }
 | 
						|
#endif
 | 
						|
  }
 | 
						|
 | 
						|
  namespace ambiguous {
 | 
						|
 | 
						|
    template<typename T1, typename T2>
 | 
						|
    CONST int pi2 = 1;
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    CONST int pi2<T,int> = 2; // expected-note {{partial specialization matches [with T = int]}}
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    CONST int pi2<int,T> = 3; // expected-note {{partial specialization matches [with T = int]}}
 | 
						|
    
 | 
						|
    void foo() {
 | 
						|
      int a = pi2<int,int>;  // expected-error {{ambiguous partial specializations of 'pi2<int, int>'}}
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  namespace type_changes {
 | 
						|
 | 
						|
    template<typename T> 
 | 
						|
    T pi0 = T(3.1415926535897932385);
 | 
						|
 | 
						|
    template<> float pi0<int> = 10;
 | 
						|
    template<> int pi0<const int> = 10;
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    T pi1 = T(3.1415926535897932385);
 | 
						|
    template<> CONST int pi1<int> = 10;
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    T pi2 = T(3.1415926535897932385);
 | 
						|
    template<> int pi2<const int> = 10;
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    CONST T pi4 = T(3.1415926535897932385);
 | 
						|
    template<> int pi4<int> = 10;
 | 
						|
  }
 | 
						|
 | 
						|
  namespace redefinition {
 | 
						|
    template<typename T>
 | 
						|
    T pi0 = T(3.1415926535897932385);
 | 
						|
 | 
						|
    template<> int pi0<int> = 10;   // expected-note 3{{previous definition is here}}
 | 
						|
#ifndef PRECXX11
 | 
						|
// expected-note@-2 {{previous definition is here}}
 | 
						|
#endif
 | 
						|
    template<> int pi0<int> = 10;   // expected-error {{redefinition of 'pi0<int>'}}
 | 
						|
    template<> CONST int pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'const int' vs 'int'}}
 | 
						|
    template<> float pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'float' vs 'int'}}
 | 
						|
#ifndef PRECXX11
 | 
						|
    template<> auto pi0<int> = 10;  // expected-error {{redefinition of 'pi0<int>'}}
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
    template<typename T> 
 | 
						|
    CONST T pi1 = T(3.1415926535897932385);
 | 
						|
 | 
						|
    template<> CONST int pi1<int> = 10;   // expected-note {{previous definition is here}}
 | 
						|
    template<> CONST int pi1<int> = 10;   // expected-error {{redefinition of 'pi1<int>'}}
 | 
						|
  }
 | 
						|
  
 | 
						|
  namespace before_instantiation {
 | 
						|
    template<typename T> 
 | 
						|
    T pi0 = T(3.1415926535897932385);   // expected-note {{variable template 'pi0' declared here}}
 | 
						|
 | 
						|
    template<> int pi0<int> = 10;
 | 
						|
    template int pi0<int>;
 | 
						|
    template float pi0<int>;    // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}}
 | 
						|
 | 
						|
    template<typename T1, typename T2>
 | 
						|
    CONST int pi2 = 1;
 | 
						|
 | 
						|
    template<typename T> CONST int pi2<T,int> = 2;
 | 
						|
    template CONST int pi2<int,int>;
 | 
						|
  }
 | 
						|
  namespace after_instantiation {
 | 
						|
    template<typename T> 
 | 
						|
    T pi0 = T(3.1415926535897932385);
 | 
						|
 | 
						|
    template int pi0<int>;   // expected-note 2{{explicit instantiation first required here}}
 | 
						|
    template<> int pi0<int> = 10; // expected-error {{explicit specialization of 'pi0' after instantiation}}
 | 
						|
    template<> float pi0<int>;    // expected-error {{explicit specialization of 'pi0' after instantiation}}
 | 
						|
 | 
						|
    template<typename T1, typename T2>
 | 
						|
    CONST int pi2 = 1;
 | 
						|
 | 
						|
    template CONST int pi2<int,int>;
 | 
						|
    template<typename T> CONST int pi2<T,int> = 2;
 | 
						|
  }
 | 
						|
 | 
						|
#ifndef PRECXX11
 | 
						|
  namespace auto_var {
 | 
						|
    template<typename T, typename> auto var0 = T();
 | 
						|
    template<typename T> auto var0<T,int> = T();
 | 
						|
    template<> auto var0<int,int> = 7;
 | 
						|
 | 
						|
    template<typename T, typename> auto var = T();
 | 
						|
    template<typename T> T var<T,int> = T(5);
 | 
						|
    template<> int var<int,int> = 7;
 | 
						|
 | 
						|
    void foo() {
 | 
						|
      int i0 = var0<int,int>;
 | 
						|
      int b = var<int,int>;
 | 
						|
    }
 | 
						|
  }
 | 
						|
#endif
 | 
						|
  
 | 
						|
  namespace extern_var {
 | 
						|
    // TODO:
 | 
						|
  }
 | 
						|
  
 | 
						|
  namespace diff_type {
 | 
						|
    // TODO:
 | 
						|
    template<typename T> T* var = new T();
 | 
						|
#ifndef PRECXX11
 | 
						|
    template<typename T> auto var<T*> = T();  // expected-note {{previous definition is here}}
 | 
						|
    template<typename T> T var<T*> = T();     // expected-error {{redefinition of 'var' with a different type: 'T' vs 'auto'}}
 | 
						|
#endif
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace narrowing {
 | 
						|
  template<typename T> T v = {1234};  // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1234 to}}
 | 
						|
#ifndef PRECXX11
 | 
						|
  // expected-error@-2 {{constant expression evaluates to 1234 which cannot be narrowed to type 'char'}}\
 | 
						|
  // expected-note@-2 {{insert an explicit cast to silence this issue}}
 | 
						|
#endif
 | 
						|
  int k = v<char>;        // expected-note {{in instantiation of variable template specialization 'narrowing::v<char>' requested here}}
 | 
						|
}
 | 
						|
 | 
						|
namespace use_in_structs {
 | 
						|
  // TODO:
 | 
						|
}
 | 
						|
 | 
						|
namespace attributes {
 | 
						|
  // TODO:
 | 
						|
}
 | 
						|
 | 
						|
#ifndef PRECXX11
 | 
						|
namespace arrays {
 | 
						|
  template<typename T>
 | 
						|
  T* arr = new T[10]{T(10), T(23)};
 | 
						|
 | 
						|
  float f = 10.5;
 | 
						|
  template<> float* arr<float> = &f;
 | 
						|
  
 | 
						|
  void bar() {
 | 
						|
    int *iarr = arr<int>;
 | 
						|
    iarr[0] = 1;
 | 
						|
    iarr[2] = 3;
 | 
						|
    iarr[6] = -2;
 | 
						|
 | 
						|
    float ff = *arr<float>;
 | 
						|
    float nof = arr<float>[3];  // No bounds-check in C++
 | 
						|
  }
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
namespace nested {
 | 
						|
  
 | 
						|
  namespace n0a {
 | 
						|
    template<typename T> 
 | 
						|
    T pi0a = T(3.1415926535897932385);
 | 
						|
  }
 | 
						|
  
 | 
						|
  using namespace n0a;
 | 
						|
  int i0a = pi0a<int>;
 | 
						|
  
 | 
						|
  template float pi0a<float>;
 | 
						|
  float f0a = pi0a<float>;
 | 
						|
  
 | 
						|
  template<> double pi0a<double> = 5.2;
 | 
						|
  double d0a = pi0a<double>;
 | 
						|
 | 
						|
  namespace n0b {
 | 
						|
    template<typename T> 
 | 
						|
    T pi0b = T(3.1415926535897932385);
 | 
						|
  }
 | 
						|
  
 | 
						|
  int i0b = n0b::pi0b<int>;
 | 
						|
  
 | 
						|
  template float n0b::pi0b<float>;
 | 
						|
  float f0b = n0b::pi0b<float>;
 | 
						|
  
 | 
						|
  template<> double n0b::pi0b<double> = 5.2;
 | 
						|
  double d0b = n0b::pi0b<double>;
 | 
						|
  
 | 
						|
  namespace n1 {
 | 
						|
    template<typename T> 
 | 
						|
    T pi1a = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}}
 | 
						|
#ifndef PRECXX11
 | 
						|
// expected-note@-2 {{explicit instantiation refers here}}
 | 
						|
#endif
 | 
						|
 | 
						|
    template<typename T> 
 | 
						|
    T pi1b = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}}
 | 
						|
#ifndef PRECXX11
 | 
						|
// expected-note@-2 {{explicit instantiation refers here}}
 | 
						|
#endif
 | 
						|
  }
 | 
						|
  
 | 
						|
  namespace use_n1a {
 | 
						|
    using namespace n1;
 | 
						|
    int i1 = pi1a<int>;
 | 
						|
 | 
						|
    template float pi1a<float>;
 | 
						|
#ifndef PRECXX11
 | 
						|
// expected-error@-2 {{explicit instantiation of 'pi1a<float>' not in a namespace enclosing 'n1'}}
 | 
						|
#endif
 | 
						|
    float f1 = pi1a<float>;
 | 
						|
    
 | 
						|
    template<> double pi1a<double> = 5.2;  // expected-error {{variable template specialization of 'pi1a' must originally be declared in namespace 'n1'}}
 | 
						|
    double d1 = pi1a<double>;
 | 
						|
  }
 | 
						|
  
 | 
						|
  namespace use_n1b {
 | 
						|
    int i1 = n1::pi1b<int>;
 | 
						|
    
 | 
						|
    template float n1::pi1b<float>;
 | 
						|
#ifndef PRECXX11
 | 
						|
// expected-error@-2 {{explicit instantiation of 'pi1b<float>' not in a namespace enclosing 'n1'}}
 | 
						|
#endif
 | 
						|
    float f1 = n1::pi1b<float>;
 | 
						|
    
 | 
						|
    template<> double n1::pi1b<double> = 5.2;  // expected-error {{cannot define or redeclare 'pi1b' here because namespace 'use_n1b' does not enclose namespace 'n1'}} \
 | 
						|
                                               // expected-error {{variable template specialization of 'pi1b' must originally be declared in namespace 'n1'}}
 | 
						|
    double d1 = n1::pi1b<double>;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace nested_name {
 | 
						|
  template<typename T> int a; // expected-note {{variable template 'a' declared here}}
 | 
						|
  a<int>::b c; // expected-error {{qualified name refers into a specialization of variable template 'a'}}
 | 
						|
 | 
						|
  class a<int> {}; // expected-error {{identifier followed by '<' indicates a class template specialization but 'a' refers to a variable template}}
 | 
						|
  enum a<int> {}; // expected-error {{expected identifier or '{'}} expected-warning {{does not declare anything}}
 | 
						|
}
 | 
						|
 | 
						|
namespace PR18530 {
 | 
						|
  template<typename T> int a;
 | 
						|
  int a<int>; // expected-error {{requires 'template<>'}}
 | 
						|
}
 | 
						|
 | 
						|
namespace PR19152 {
 | 
						|
#ifndef PRECXX11
 | 
						|
  template<typename T> const auto x = 1;
 | 
						|
  static_assert(x<int> == 1, "");
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
namespace PR19169 {
 | 
						|
  template <typename T> int* f();
 | 
						|
  template <typename T> void f();
 | 
						|
  template<> int f<double>; // expected-error {{no variable template matches specialization; did you mean to use 'f' as function template instead?}}
 | 
						|
  
 | 
						|
  template <typename T> void g();
 | 
						|
  template<> int g<double>; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}}
 | 
						|
}
 | 
						|
 |