<commit_before>// RUN: clang-cc -fsyntax-only -verify %s

// This test creates cases where implicit instantiations of various entities
// would cause a diagnostic, but provides expliict specializations for those
// entities that avoid the diagnostic. The specializations are alternately
// declarations and definitions, and the intent of this test is to verify
// that we allow specializations only in the appropriate namespaces (and
// nowhere else).
struct NonDefaultConstructible {
  NonDefaultConstructible(int);
};


// C++ [temp.expl.spec]p1:
//   An explicit specialization of any of the following:

//     -- function template
namespace N0 {
  template<typename T> void f0(T) { // expected-note{{here}}
    T t;
  }

  template<> void f0(NonDefaultConstructible) { }

  void test_f0(NonDefaultConstructible NDC) {
    f0(NDC);
  }
  
  template<> void f0(int);
  template<> void f0(long);
}

template<> void N0::f0(int) { } // okay

namespace N1 {
  template<> void N0::f0(long) { } // expected-error{{not in a namespace enclosing}}
}

template<> void N0::f0(double) { } // expected-error{{originally be declared}}

struct X1 {
  template<typename T> void f(T);
  
  template<> void f(int); // expected-error{{in class scope}}
};

//     -- class template
namespace N0 {
  
template<typename T>
struct X0 { // expected-note 2{{here}}
  static T member; // expected-note{{here}}
  
  void f1(T t) { // expected-note{{explicitly specialized declaration is here}}
    t = 17;
  }
  
  struct Inner : public T { }; // expected-note 3{{here}}
  
  template<typename U>
  struct InnerTemplate : public T { };
  
  template<typename U>
  void ft1(T t, U u);
};

}

template<typename T> 
template<typename U>
void N0::X0<T>::ft1(T t, U u) {
  t = u;
}

template<typename T> T N0::X0<T>::member;

template<> struct N0::X0<void> { }; // expected-error{{originally}}
N0::X0<void> test_X0;

namespace N1 {
  template<> struct N0::X0<const void> { }; // expected-error{{originally}}
}

namespace N0 {
  template<> struct X0<volatile void>;
}

template<> struct N0::X0<volatile void> { 
  void f1(void *);
};

//     -- member function of a class template
template<> void N0::X0<void*>::f1(void *) { } // expected-error{{member function specialization}}

void test_spec(N0::X0<void*> xvp, void *vp) {
  xvp.f1(vp);
}

namespace N0 {
  template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}

  template<> void X0<const volatile void*>::f1(const volatile void*);
}

void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
  x0.f1(cvp); // okay: we've explicitly specialized
}

//     -- static data member of a class template
namespace N0 {
  // This actually tests p15; the following is a declaration, not a definition.
  template<> 
  NonDefaultConstructible X0<NonDefaultConstructible>::member;
  
  template<> long X0<long>::member = 17;

  template<> float X0<float>::member;
  
  template<> double X0<double>::member;
}

NonDefaultConstructible &get_static_member() {
  return N0::X0<NonDefaultConstructible>::member;
}

template<> int N0::X0<int>::member;  // expected-error{{originally}}

template<> float N0::X0<float>::member = 3.14f;

namespace N1 {
  template<> double N0::X0<double>::member = 3.14; // expected-error{{not in a namespace enclosing}}
}

//    -- member class of a class template
namespace N0 {
  
  template<>
  struct X0<void*>::Inner { };

  template<>
  struct X0<int>::Inner { };

  template<>
  struct X0<unsigned>::Inner;

  template<>
  struct X0<float>::Inner;

  template<>
  struct X0<double>::Inner; // expected-note{{forward declaration}}
}

template<>
struct N0::X0<long>::Inner { }; // expected-error{{originally}}

template<>
struct N0::X0<float>::Inner { };

namespace N1 {
  template<>
  struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}

  template<>
  struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
};

N0::X0<void*>::Inner inner0;
N0::X0<int>::Inner inner1;
N0::X0<long>::Inner inner2;
N0::X0<float>::Inner inner3;
N0::X0<double>::Inner inner4; // expected-error{{incomplete}}

#if 0
// FIXME: update the remainder of this test to check for scopes properly.
//    -- member class template of a class template
template<>
template<>
struct X0<void*>::InnerTemplate<int> { };

X0<void*>::InnerTemplate<int> inner_template0;

//    -- member function template of a class template
template<>
template<>
void X0<void*>::ft1(void*, const void*) { }

void test_func_template(X0<void *> xvp, void *vp, const void *cvp) {
  xvp.ft1(vp, cvp);
}
#endif<commit_msg>More testing for explicit specializations of member class templates<commit_after>// RUN: clang-cc -fsyntax-only -verify %s

// This test creates cases where implicit instantiations of various entities
// would cause a diagnostic, but provides expliict specializations for those
// entities that avoid the diagnostic. The specializations are alternately
// declarations and definitions, and the intent of this test is to verify
// that we allow specializations only in the appropriate namespaces (and
// nowhere else).
struct NonDefaultConstructible {
  NonDefaultConstructible(int);
};


// C++ [temp.expl.spec]p1:
//   An explicit specialization of any of the following:

//     -- function template
namespace N0 {
  template<typename T> void f0(T) { // expected-note{{here}}
    T t;
  }

  template<> void f0(NonDefaultConstructible) { }

  void test_f0(NonDefaultConstructible NDC) {
    f0(NDC);
  }
  
  template<> void f0(int);
  template<> void f0(long);
}

template<> void N0::f0(int) { } // okay

namespace N1 {
  template<> void N0::f0(long) { } // expected-error{{not in a namespace enclosing}}
}

template<> void N0::f0(double) { } // expected-error{{originally be declared}}

struct X1 {
  template<typename T> void f(T);
  
  template<> void f(int); // expected-error{{in class scope}}
};

//     -- class template
namespace N0 {
  
template<typename T>
struct X0 { // expected-note 2{{here}}
  static T member; // expected-note{{here}}
  
  void f1(T t) { // expected-note{{explicitly specialized declaration is here}}
    t = 17;
  }
  
  struct Inner : public T { }; // expected-note 3{{here}}
  
  template<typename U>
  struct InnerTemplate : public T { }; // expected-note 2{{explicitly specialized}} \
   // expected-error{{base specifier}}
  
  template<typename U>
  void ft1(T t, U u);
};

}

template<typename T> 
template<typename U>
void N0::X0<T>::ft1(T t, U u) {
  t = u;
}

template<typename T> T N0::X0<T>::member;

template<> struct N0::X0<void> { }; // expected-error{{originally}}
N0::X0<void> test_X0;

namespace N1 {
  template<> struct N0::X0<const void> { }; // expected-error{{originally}}
}

namespace N0 {
  template<> struct X0<volatile void>;
}

template<> struct N0::X0<volatile void> { 
  void f1(void *);
};

//     -- member function of a class template
template<> void N0::X0<void*>::f1(void *) { } // expected-error{{member function specialization}}

void test_spec(N0::X0<void*> xvp, void *vp) {
  xvp.f1(vp);
}

namespace N0 {
  template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}

  template<> void X0<const volatile void*>::f1(const volatile void*);
}

void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
  x0.f1(cvp); // okay: we've explicitly specialized
}

//     -- static data member of a class template
namespace N0 {
  // This actually tests p15; the following is a declaration, not a definition.
  template<> 
  NonDefaultConstructible X0<NonDefaultConstructible>::member;
  
  template<> long X0<long>::member = 17;

  template<> float X0<float>::member;
  
  template<> double X0<double>::member;
}

NonDefaultConstructible &get_static_member() {
  return N0::X0<NonDefaultConstructible>::member;
}

template<> int N0::X0<int>::member;  // expected-error{{originally}}

template<> float N0::X0<float>::member = 3.14f;

namespace N1 {
  template<> double N0::X0<double>::member = 3.14; // expected-error{{not in a namespace enclosing}}
}

//    -- member class of a class template
namespace N0 {
  
  template<>
  struct X0<void*>::Inner { };

  template<>
  struct X0<int>::Inner { };

  template<>
  struct X0<unsigned>::Inner;

  template<>
  struct X0<float>::Inner;

  template<>
  struct X0<double>::Inner; // expected-note{{forward declaration}}
}

template<>
struct N0::X0<long>::Inner { }; // expected-error{{originally}}

template<>
struct N0::X0<float>::Inner { };

namespace N1 {
  template<>
  struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}

  template<>
  struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
};

N0::X0<void*>::Inner inner0;
N0::X0<int>::Inner inner1;
N0::X0<long>::Inner inner2;
N0::X0<float>::Inner inner3;
N0::X0<double>::Inner inner4; // expected-error{{incomplete}}

//    -- member class template of a class template
namespace N0 {
  template<>
  template<>
  struct X0<void*>::InnerTemplate<int> { };
  
  template<> template<>
  struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}

  template<> template<>
  struct X0<int>::InnerTemplate<long>;

  template<> template<>
  struct X0<int>::InnerTemplate<double>;
}

template<> template<>
struct N0::X0<int>::InnerTemplate<long> { }; // okay

template<> template<>
struct N0::X0<int>::InnerTemplate<float> { }; // expected-error{{class template specialization}}

namespace N1 {
  template<> template<>
  struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
}

N0::X0<void*>::InnerTemplate<int> inner_template0;
N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
N0::X0<int>::InnerTemplate<long> inner_template2;
N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}

#if 0
// FIXME: update the remainder of this test to check for scopes properly.
//    -- member function template of a class template
template<>
template<>
void X0<void*>::ft1(void*, const void*) { }

void test_func_template(X0<void *> xvp, void *vp, const void *cvp) {
  xvp.ft1(vp, cvp);
}
#endif
{'fraction_non_alphanumeric': 0.15678794992175274, 'fraction_numerical': 0.025821596244131457, 'mean_word_length': 4.270618556701031, 'pattern_counts': {'":': 0, '<': 197, '<?xml version=': 0, '>': 197, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2265027', 'n_tokens_mistral': 3420, 'n_tokens_neox': 3335, 'n_words': 908}