208 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -pedantic -verify %s2 3struct X {4 using type = int;5 static constexpr int value = 1;6 class tclass {};7};8 9template <typename T>10void f() {11 // it is a qualified name in a type-id-only context (see below), or12 // [its smallest enclosing [/new/defining/]-type-id is]:13 // - a new-type-id14 auto *Ptr = new T::type();15 // - a defining-type-id16 class T::tclass Empty1;17 T::tclass Empty2; // expected-error{{missing 'typename'}}18 // - a trailing-return-type19 auto f()->T::type;20 // - default argument of a type-parameter of a template [see below]21 22 // - type-id of a23 // static_cast,24 auto StaticCast = static_cast<T::type>(1.2);25 // const_cast,26 const auto *ConstCast = const_cast<const T::type *>(Ptr);27 // reinterpret_cast,28 int ReinterpretCast = reinterpret_cast<T::type>(4);29 // dynamic_cast30 struct B {31 virtual ~B() = default;32 };33 struct D : T::tclass {};34 auto *Base = dynamic_cast<T::tclass *>(new B);35 36 T::type Invalid; // expected-error{{missing 'typename'}}37}38 39template void f<X>();40 41// As default argument.42template <typename T, typename = T::type>43struct DefaultArg {};44 45template struct DefaultArg<X>;46 47// it is a decl-specifier of the decl-specifier-seq of a48// - simple-declaration or a function-definition in namespace scope49template <typename T>50T::type VarTemp = 1;51 52template int VarTemp<X>;53 54template <typename T>55T::type FuncDef() { return 1; }56 57template int FuncDef<X>();58 59template <typename T>60T::type funcDecl();61 62template <typename T>63void FuncParam(T::type); // ok, but variable template64// expected-error@-1{{variable has incomplete type 'void'}}65 66template <typename T>67void FuncParam2(const T::type, int); // expected-error{{missing 'typename'}}68 69template <typename T>70struct MemberDecl {71 // member-declaration,72 T::type Member;73 74 // parameter-declaration in a member-declaration, unless that75 // parameter-declaration appears in a default argument76 void NoDefault(T::type);77 void Default(int A = T::value);78};79 80template struct MemberDecl<X>;81 82// parameter-declaration in a declarator of a function or function template83// declaration where the declarator-id is qualified, unless that84// parameter-declaration appears in a default argument,85struct QualifiedFunc {86 template <typename T>87 void foo(typename T::type);88 template <typename T>89 void bar(T::type);90};91 92template <typename T>93void QualifiedFunc::foo(T::type) {}94template <typename T>95void QualifiedFunc::bar(typename T::type) {}96 97template <typename T>98void g() {99 // parameter-declaration in a lambda-declarator, unless that100 // parameter-declaration appears in a default argument, or101 auto Lambda1 = [](T::type) {};102 auto Lambda2 = [](int A = T::value) {};103}104 105template void g<X>();106 107// parameter-declaration of a (non-type) template-parameter.108template <typename T, T::type>109void NonTypeArg() {}110 111template void NonTypeArg<X, 0>();112 113template <typename T>114void f(T::type) {} // expected-error {{missing 'typename'}}115 116namespace N {117 template <typename T>118 int f(typename T::type);119 template <typename T>120 extern int Var;121}122 123template <typename T>124int N::f(T::type); // ok, function125template <typename T>126int N::Var(T::value); // ok, variable127 128int h() {129 return N::f<X>(10) + N::Var<X>;130}131 132namespace NN {133 inline namespace A { template <typename T> int f(typename T::type); } // expected-note{{previous definition is here}}134 inline namespace B { template <typename T> int f(T::type); }135}136 137template <typename T>138int NN::f(T::type); // expected-error{{redefinition of 'f' as different kind of symbol}}139 140template <auto V>141struct videntity {142 static constexpr auto value = V;143};144 145template <typename T,146 bool = T::value,147 bool = bool(T::value),148 bool = videntity<bool(T::value)>::value>149void f(int = T::value) {}150 151template <typename> int test() = delete;152template <auto> int test();153 154template <typename T>155int Test = test<int(T::value)>();156template int Test<X>;157 158template<typename T> struct A {159 enum E : T::type {}; // expected-error{{missing 'typename'}}160 operator T::type() {} // expected-error{{missing 'typename'}}161 void f() { this->operator T::type(); } // expected-error{{missing 'typename'}}162};163 164template<typename T>165struct C {166 C(T::type); // implicit typename context167 friend C (T::fn)(); // not implicit typename context, declarator-id of friend declaration168 C(T::type::*x)[3]; // not implicit typename context, pointer-to-member type169};170 171template <typename T>172C<T>::C(T::type) {}173 174namespace GH63119 {175struct X {176 X(int);177 X(auto);178 void f(int);179};180template<typename T> struct S {181 friend X::X(T::type);182 friend X::X(T::type = (int)(void(*)(typename T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}}183 friend X::X(T::type = (int)(void(*)(T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}} \184 // expected-error {{expected expression}}185 friend void X::f(T::type);186};187}188 189namespace GH113324 {190template <typename = int> struct S1 {191 friend void f1(S1, int = 0); // expected-error {{friend declaration specifying a default argument must be a definition}}192 friend void f2(S1 a, S1 = decltype(a){}); // expected-error {{friend declaration specifying a default argument must be a definition}}193};194 195template <class T> using alias = int;196template <typename T> struct S2 {197 // FIXME: We miss diagnosing the default argument instantiation failure198 // (forming reference to void)199 friend void f3(S2, int a = alias<T &>(1)); // expected-error {{friend declaration specifying a default argument must be a definition}}200};201 202void test() {203 f1(S1<>{});204 f2(S1<>{});205 f3(S2<void>());206}207} // namespace GH113324208