xref: /llvm-project/clang/test/CXX/temp/temp.res/p4.cpp (revision 9daf10ff8f29ba3a88a105aaa9d2379c21b77d35)
14848f3bfSNicolas Lesser // RUN: %clang_cc1 -std=c++20 -pedantic -verify %s
24848f3bfSNicolas Lesser 
34848f3bfSNicolas Lesser struct X {
44848f3bfSNicolas Lesser   using type = int;
54848f3bfSNicolas Lesser   static constexpr int value = 1;
64848f3bfSNicolas Lesser   class tclass {};
74848f3bfSNicolas Lesser };
84848f3bfSNicolas Lesser 
94848f3bfSNicolas Lesser template <typename T>
104848f3bfSNicolas Lesser void f() {
114848f3bfSNicolas Lesser   // it is a qualified name in a type-id-only context (see below), or
124848f3bfSNicolas Lesser   // [its smallest enclosing [/new/defining/]-type-id is]:
134848f3bfSNicolas Lesser   // - a new-type-id
144848f3bfSNicolas Lesser   auto *Ptr = new T::type();
154848f3bfSNicolas Lesser   // - a defining-type-id
164848f3bfSNicolas Lesser   class T::tclass Empty1;
174848f3bfSNicolas Lesser   T::tclass Empty2; // expected-error{{missing 'typename'}}
184848f3bfSNicolas Lesser   // - a trailing-return-type
194848f3bfSNicolas Lesser   auto f()->T::type;
204848f3bfSNicolas Lesser   // - default argument of a type-parameter of a template [see below]
214848f3bfSNicolas Lesser 
224848f3bfSNicolas Lesser   // - type-id of a
234848f3bfSNicolas Lesser   // static_cast,
244848f3bfSNicolas Lesser   auto StaticCast = static_cast<T::type>(1.2);
254848f3bfSNicolas Lesser   // const_cast,
264848f3bfSNicolas Lesser   const auto *ConstCast = const_cast<const T::type *>(Ptr);
274848f3bfSNicolas Lesser   // reinterpret_cast,
284848f3bfSNicolas Lesser   int ReinterpretCast = reinterpret_cast<T::type>(4);
294848f3bfSNicolas Lesser   // dynamic_cast
304848f3bfSNicolas Lesser   struct B {
314848f3bfSNicolas Lesser     virtual ~B() = default;
324848f3bfSNicolas Lesser   };
334848f3bfSNicolas Lesser   struct D : T::tclass {};
344848f3bfSNicolas Lesser   auto *Base = dynamic_cast<T::tclass *>(new B);
354848f3bfSNicolas Lesser 
364848f3bfSNicolas Lesser   T::type Invalid; // expected-error{{missing 'typename'}}
374848f3bfSNicolas Lesser }
384848f3bfSNicolas Lesser 
394848f3bfSNicolas Lesser template void f<X>();
404848f3bfSNicolas Lesser 
414848f3bfSNicolas Lesser // As default argument.
424848f3bfSNicolas Lesser template <typename T, typename = T::type>
434848f3bfSNicolas Lesser struct DefaultArg {};
444848f3bfSNicolas Lesser 
454848f3bfSNicolas Lesser template struct DefaultArg<X>;
464848f3bfSNicolas Lesser 
474848f3bfSNicolas Lesser // it is a decl-specifier of the decl-specifier-seq of a
484848f3bfSNicolas Lesser // - simple-declaration or a function-definition in namespace scope
494848f3bfSNicolas Lesser template <typename T>
504848f3bfSNicolas Lesser T::type VarTemp = 1;
514848f3bfSNicolas Lesser 
524848f3bfSNicolas Lesser template int VarTemp<X>;
534848f3bfSNicolas Lesser 
544848f3bfSNicolas Lesser template <typename T>
554848f3bfSNicolas Lesser T::type FuncDef() { return 1; }
564848f3bfSNicolas Lesser 
574848f3bfSNicolas Lesser template int FuncDef<X>();
584848f3bfSNicolas Lesser 
594848f3bfSNicolas Lesser template <typename T>
604848f3bfSNicolas Lesser T::type funcDecl();
614848f3bfSNicolas Lesser 
624848f3bfSNicolas Lesser template <typename T>
634848f3bfSNicolas Lesser void FuncParam(T::type); // ok, but variable template
644848f3bfSNicolas Lesser // expected-error@-1{{variable has incomplete type 'void'}}
654848f3bfSNicolas Lesser 
664848f3bfSNicolas Lesser template <typename T>
674848f3bfSNicolas Lesser void FuncParam2(const T::type, int); // expected-error{{missing 'typename'}}
684848f3bfSNicolas Lesser 
694848f3bfSNicolas Lesser template <typename T>
704848f3bfSNicolas Lesser struct MemberDecl {
714848f3bfSNicolas Lesser   // member-declaration,
724848f3bfSNicolas Lesser   T::type Member;
734848f3bfSNicolas Lesser 
744848f3bfSNicolas Lesser   // parameter-declaration in a member-declaration, unless that
754848f3bfSNicolas Lesser   // parameter-declaration appears in a default argument
764848f3bfSNicolas Lesser   void NoDefault(T::type);
774848f3bfSNicolas Lesser   void Default(int A = T::value);
784848f3bfSNicolas Lesser };
794848f3bfSNicolas Lesser 
804848f3bfSNicolas Lesser template struct MemberDecl<X>;
814848f3bfSNicolas Lesser 
824848f3bfSNicolas Lesser // parameter-declaration in a declarator of a function or function template
834848f3bfSNicolas Lesser // declaration where the declarator-id is qualified, unless that
844848f3bfSNicolas Lesser // parameter-declaration appears in a default argument,
854848f3bfSNicolas Lesser struct QualifiedFunc {
864848f3bfSNicolas Lesser   template <typename T>
874848f3bfSNicolas Lesser   void foo(typename T::type);
884848f3bfSNicolas Lesser   template <typename T>
894848f3bfSNicolas Lesser   void bar(T::type);
904848f3bfSNicolas Lesser };
914848f3bfSNicolas Lesser 
924848f3bfSNicolas Lesser template <typename T>
934848f3bfSNicolas Lesser void QualifiedFunc::foo(T::type) {}
944848f3bfSNicolas Lesser template <typename T>
954848f3bfSNicolas Lesser void QualifiedFunc::bar(typename T::type) {}
964848f3bfSNicolas Lesser 
974848f3bfSNicolas Lesser template <typename T>
984848f3bfSNicolas Lesser void g() {
994848f3bfSNicolas Lesser   // parameter-declaration in a lambda-declarator, unless that
1004848f3bfSNicolas Lesser   // parameter-declaration appears in a default argument, or
1014848f3bfSNicolas Lesser   auto Lambda1 = [](T::type) {};
1024848f3bfSNicolas Lesser   auto Lambda2 = [](int A = T::value) {};
1034848f3bfSNicolas Lesser }
1044848f3bfSNicolas Lesser 
1054848f3bfSNicolas Lesser template void g<X>();
1064848f3bfSNicolas Lesser 
1074848f3bfSNicolas Lesser // parameter-declaration of a (non-type) template-parameter.
1084848f3bfSNicolas Lesser template <typename T, T::type>
1094848f3bfSNicolas Lesser void NonTypeArg() {}
1104848f3bfSNicolas Lesser 
1114848f3bfSNicolas Lesser template void NonTypeArg<X, 0>();
1124848f3bfSNicolas Lesser 
1134848f3bfSNicolas Lesser template <typename T>
1144848f3bfSNicolas Lesser void f(T::type) {} // expected-error {{missing 'typename'}}
1154848f3bfSNicolas Lesser 
1164848f3bfSNicolas Lesser namespace N {
1174848f3bfSNicolas Lesser   template <typename T>
1184848f3bfSNicolas Lesser   int f(typename T::type);
1194848f3bfSNicolas Lesser   template <typename T>
1204848f3bfSNicolas Lesser   extern int Var;
1214848f3bfSNicolas Lesser }
1224848f3bfSNicolas Lesser 
1234848f3bfSNicolas Lesser template <typename T>
1244848f3bfSNicolas Lesser int N::f(T::type); // ok, function
1254848f3bfSNicolas Lesser template <typename T>
1264848f3bfSNicolas Lesser int N::Var(T::value); // ok, variable
1274848f3bfSNicolas Lesser 
1284848f3bfSNicolas Lesser int h() {
1294848f3bfSNicolas Lesser   return N::f<X>(10) + N::Var<X>;
1304848f3bfSNicolas Lesser }
1314848f3bfSNicolas Lesser 
1324848f3bfSNicolas Lesser namespace NN {
1334848f3bfSNicolas Lesser   inline namespace A { template <typename T> int f(typename T::type); } // expected-note{{previous definition is here}}
1344848f3bfSNicolas Lesser   inline namespace B { template <typename T> int f(T::type); }
1354848f3bfSNicolas Lesser }
1364848f3bfSNicolas Lesser 
1374848f3bfSNicolas Lesser template <typename T>
1384848f3bfSNicolas Lesser int NN::f(T::type); // expected-error{{redefinition of 'f' as different kind of symbol}}
1394848f3bfSNicolas Lesser 
1404848f3bfSNicolas Lesser template <auto V>
1414848f3bfSNicolas Lesser struct videntity {
1424848f3bfSNicolas Lesser   static constexpr auto value = V;
1434848f3bfSNicolas Lesser };
1444848f3bfSNicolas Lesser 
1454848f3bfSNicolas Lesser template <typename T,
1464848f3bfSNicolas Lesser     bool = T::value,
1474848f3bfSNicolas Lesser     bool = bool(T::value),
1484848f3bfSNicolas Lesser     bool = videntity<bool(T::value)>::value>
1494848f3bfSNicolas Lesser void f(int = T::value) {}
1504848f3bfSNicolas Lesser 
1514848f3bfSNicolas Lesser template <typename> int test() = delete;
1524848f3bfSNicolas Lesser template <auto> int test();
1534848f3bfSNicolas Lesser 
1544848f3bfSNicolas Lesser template <typename T>
1554848f3bfSNicolas Lesser int Test = test<int(T::value)>();
1564848f3bfSNicolas Lesser template int Test<X>;
1574848f3bfSNicolas Lesser 
1584848f3bfSNicolas Lesser template<typename T> struct A {
1594848f3bfSNicolas Lesser   enum E : T::type {}; // expected-error{{missing 'typename'}}
1604848f3bfSNicolas Lesser   operator T::type() {} // expected-error{{missing 'typename'}}
1614848f3bfSNicolas Lesser   void f() { this->operator T::type(); } // expected-error{{missing 'typename'}}
1624848f3bfSNicolas Lesser };
1634848f3bfSNicolas Lesser 
1644848f3bfSNicolas Lesser template<typename T>
1654848f3bfSNicolas Lesser struct C {
1664848f3bfSNicolas Lesser   C(T::type); // implicit typename context
1674848f3bfSNicolas Lesser   friend C (T::fn)(); // not implicit typename context, declarator-id of friend declaration
1684848f3bfSNicolas Lesser   C(T::type::*x)[3]; // not implicit typename context, pointer-to-member type
1694848f3bfSNicolas Lesser };
1704848f3bfSNicolas Lesser 
1714848f3bfSNicolas Lesser template <typename T>
1724848f3bfSNicolas Lesser C<T>::C(T::type) {}
173d9be8a8aSCorentin Jabot 
174d9be8a8aSCorentin Jabot namespace GH63119 {
175d9be8a8aSCorentin Jabot struct X {
176d9be8a8aSCorentin Jabot     X(int);
177d9be8a8aSCorentin Jabot     X(auto);
178d9be8a8aSCorentin Jabot     void f(int);
179d9be8a8aSCorentin Jabot };
180d9be8a8aSCorentin Jabot template<typename T> struct S {
181d9be8a8aSCorentin Jabot   friend X::X(T::type);
182d9be8a8aSCorentin Jabot   friend X::X(T::type = (int)(void(*)(typename T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}}
183d9be8a8aSCorentin Jabot   friend X::X(T::type = (int)(void(*)(T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}} \
184d9be8a8aSCorentin Jabot                                                            // expected-error {{expected expression}}
185d9be8a8aSCorentin Jabot   friend void X::f(T::type);
186d9be8a8aSCorentin Jabot };
187d9be8a8aSCorentin Jabot }
188*9daf10ffSOleksandr T. 
189*9daf10ffSOleksandr T. namespace GH113324 {
190*9daf10ffSOleksandr T. template <typename = int> struct S1 {
191*9daf10ffSOleksandr T.   friend void f1(S1, int = 0); // expected-error {{friend declaration specifying a default argument must be a definition}}
192*9daf10ffSOleksandr T.   friend void f2(S1 a, S1 = decltype(a){}); // expected-error {{friend declaration specifying a default argument must be a definition}}
193*9daf10ffSOleksandr T. };
194*9daf10ffSOleksandr T. 
195*9daf10ffSOleksandr T. template <class T> using alias = int;
196*9daf10ffSOleksandr T. template <typename T> struct S2 {
197*9daf10ffSOleksandr T.   // FIXME: We miss diagnosing the default argument instantiation failure
198*9daf10ffSOleksandr T.   // (forming reference to void)
199*9daf10ffSOleksandr T.   friend void f3(S2, int a = alias<T &>(1)); // expected-error {{friend declaration specifying a default argument must be a definition}}
200*9daf10ffSOleksandr T. };
201*9daf10ffSOleksandr T. 
202*9daf10ffSOleksandr T. void test() {
203*9daf10ffSOleksandr T.   f1(S1<>{});
204*9daf10ffSOleksandr T.   f2(S1<>{});
205*9daf10ffSOleksandr T.   f3(S2<void>());
206*9daf10ffSOleksandr T. }
207*9daf10ffSOleksandr T. } // namespace GH113324
208