// RUN: %clang_cc1 -std=c++20 -pedantic -verify %s struct X { using type = int; static constexpr int value = 1; class tclass {}; }; template void f() { // it is a qualified name in a type-id-only context (see below), or // [its smallest enclosing [/new/defining/]-type-id is]: // - a new-type-id auto *Ptr = new T::type(); // - a defining-type-id class T::tclass Empty1; T::tclass Empty2; // expected-error{{missing 'typename'}} // - a trailing-return-type auto f()->T::type; // - default argument of a type-parameter of a template [see below] // - type-id of a // static_cast, auto StaticCast = static_cast(1.2); // const_cast, const auto *ConstCast = const_cast(Ptr); // reinterpret_cast, int ReinterpretCast = reinterpret_cast(4); // dynamic_cast struct B { virtual ~B() = default; }; struct D : T::tclass {}; auto *Base = dynamic_cast(new B); T::type Invalid; // expected-error{{missing 'typename'}} } template void f(); // As default argument. template struct DefaultArg {}; template struct DefaultArg; // it is a decl-specifier of the decl-specifier-seq of a // - simple-declaration or a function-definition in namespace scope template T::type VarTemp = 1; template int VarTemp; template T::type FuncDef() { return 1; } template int FuncDef(); template T::type funcDecl(); template void FuncParam(T::type); // ok, but variable template // expected-error@-1{{variable has incomplete type 'void'}} template void FuncParam2(const T::type, int); // expected-error{{missing 'typename'}} template struct MemberDecl { // member-declaration, T::type Member; // parameter-declaration in a member-declaration, unless that // parameter-declaration appears in a default argument void NoDefault(T::type); void Default(int A = T::value); }; template struct MemberDecl; // parameter-declaration in a declarator of a function or function template // declaration where the declarator-id is qualified, unless that // parameter-declaration appears in a default argument, struct QualifiedFunc { template void foo(typename T::type); template void bar(T::type); }; template void QualifiedFunc::foo(T::type) {} template void QualifiedFunc::bar(typename T::type) {} template void g() { // parameter-declaration in a lambda-declarator, unless that // parameter-declaration appears in a default argument, or auto Lambda1 = [](T::type) {}; auto Lambda2 = [](int A = T::value) {}; } template void g(); // parameter-declaration of a (non-type) template-parameter. template void NonTypeArg() {} template void NonTypeArg(); template void f(T::type) {} // expected-error {{missing 'typename'}} namespace N { template int f(typename T::type); template extern int Var; } template int N::f(T::type); // ok, function template int N::Var(T::value); // ok, variable int h() { return N::f(10) + N::Var; } namespace NN { inline namespace A { template int f(typename T::type); } // expected-note{{previous definition is here}} inline namespace B { template int f(T::type); } } template int NN::f(T::type); // expected-error{{redefinition of 'f' as different kind of symbol}} template struct videntity { static constexpr auto value = V; }; template ::value> void f(int = T::value) {} template int test() = delete; template int test(); template int Test = test(); template int Test; template struct A { enum E : T::type {}; // expected-error{{missing 'typename'}} operator T::type() {} // expected-error{{missing 'typename'}} void f() { this->operator T::type(); } // expected-error{{missing 'typename'}} }; template struct C { C(T::type); // implicit typename context friend C (T::fn)(); // not implicit typename context, declarator-id of friend declaration C(T::type::*x)[3]; // not implicit typename context, pointer-to-member type }; template C::C(T::type) {} namespace GH63119 { struct X { X(int); X(auto); void f(int); }; template struct S { friend X::X(T::type); friend X::X(T::type = (int)(void(*)(typename T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}} friend X::X(T::type = (int)(void(*)(T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}} \ // expected-error {{expected expression}} friend void X::f(T::type); }; }