// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s // expected-note@temp_arg_template_p0522.cpp:* 1+{{template is declared here}} // expected-note@temp_arg_template_p0522.cpp:* 1+{{template parameter is declared here}} // expected-note@temp_arg_template_p0522.cpp:* 1+{{previous template template parameter is here}} template typename> struct Ti; // #Ti template typename> struct TPi; // #TPi template typename> struct TiPi; template typename> struct TPiPi; // FIXME: Why is this not ill-formed? template typename> struct tT0; // #tT0 template typename> struct Tt0; // #Tt0 template typename> struct Tt; template typename> struct TtPt; template struct i; template struct iDi; template struct ii; template struct Pi; template struct iiPi; template struct iDt; // #iDt template struct it; // #it template struct t0; template struct Pt; namespace IntParam { using ok = Pt, Ti, Ti, Ti>; using err1 = Ti; // expected-error {{too few template arguments for class template 'ii'}} // expected-note@-1 {{different template parameters}} using err2 = Ti; // expected-error {{too few template arguments for class template 'iiPi'}} // expected-note@-1 {{different template parameters}} using err3 = Ti; // expected-error@#Ti {{template argument for template type parameter must be a type}} // expected-note@-1 {{different template parameters}} using err4 = Ti; // expected-error {{too few template arguments for class template 'it'}} // expected-note@-1 {{different template parameters}} } // These are accepted by the backwards-compatibility "parameter pack in // parameter matches any number of parameters in arguments" rule. namespace IntPackParam { using ok = TPi; using ok_compat = Pt, TPi, TPi, TPi>; using err1 = TPi; // expected-error@#TPi {{template argument for template type parameter must be a type}} // expected-note@-1 {{different template parameters}} using err2 = TPi; // expected-error@#TPi {{template argument for template type parameter must be a type}} // expected-note@-1 {{different template parameters}} using err3 = TPi; // expected-error@#TPi {{template argument for template type parameter must be a type}} // expected-note@-1 {{different template parameters}} } namespace IntAndPackParam { using ok = TiPi; using ok_compat = Pt, TiPi, TiPi>; using err = TiPi; } namespace DependentType { using ok = Pt, tT0>; using err1 = tT0; // expected-error {{too few template arguments for class template 'ii'}} // expected-note@-1 {{different template parameters}} using err2 = tT0; using err2a = tT0; // expected-error@#tT0 {{cannot be narrowed from type 'long long' to 'int'}} // expected-note@-1 {{different template parameters}} using err2b = tT0; // expected-error@#tT0 {{value of type 'void *' is not implicitly convertible to 'int'}} // expected-note@-1 {{different template parameters}} using err3 = tT0; // expected-error@#tT0 {{template argument for template type parameter must be a type}} // expected-note@-1 {{different template parameters}} using ok2 = Tt0; using err4 = Tt0; // expected-error@#Tt0 {{template argument for non-type template parameter must be an expression}} // expected-note@-1 {{different template parameters}} } namespace Auto { template typename T> struct TInt {}; // #TInt template typename T> struct TIntPtr {}; // #TIntPtr template typename T> struct TAuto {}; template typename T> struct TAutoPtr {}; template typename T> struct TDecltypeAuto {}; template struct Auto; template struct AutoPtr; // #AutoPtr template struct DecltypeAuto; template struct Int; template struct IntPtr; TInt ia; TInt iap; // expected-error@#TInt {{non-type template parameter '' with type 'auto *' has incompatible initializer of type 'int'}} // expected-note@-1 {{different template parameters}} TInt ida; TInt ii; TInt iip; // expected-error@#TInt {{conversion from 'int' to 'int *' is not allowed in a converted constant expression}} // expected-note@-1 {{different template parameters}} TIntPtr ipa; TIntPtr ipap; TIntPtr ipda; TIntPtr ipi; // expected-error@#TIntPtr {{value of type 'int *' is not implicitly convertible to 'int'}} // expected-note@-1 {{different template parameters}} TIntPtr ipip; TAuto aa; TAuto aap; // expected-error@#AutoPtr {{could not match 'auto *' against 'auto'}} // expected-note@-1 {{different template parameters}} TAuto ai; // FIXME: ill-formed (?) TAuto aip; // FIXME: ill-formed (?) TAutoPtr apa; TAutoPtr apap; TAutoPtr api; // FIXME: ill-formed (?) TAutoPtr apip; // FIXME: ill-formed (?) TDecltypeAuto dada; TDecltypeAuto dai; // FIXME: ill-formed (?) TDecltypeAuto daip; // FIXME: ill-formed (?) // FIXME: It's completely unclear what should happen here, but these results // seem at least plausible: TAuto ada; TAutoPtr apda; // Perhaps this case should be invalid, as there are valid 'decltype(auto)' // parameters (such as 'user-defined-type &') that are not valid 'auto' // parameters. TDecltypeAuto daa; TDecltypeAuto daap; // expected-error@#AutoPtr {{could not match 'auto *' against 'decltype(auto)'}} // expected-note@-1 {{different template parameters}} int n; template struct SubstFailure; TInt isf; // FIXME: this should be ill-formed TIntPtr ipsf; } namespace GH62529 { // Note: the constraint here is just for bypassing a fast-path. template requires(true) using A = int; template class TT1, class T3> struct B {}; template B f(); auto t = f(); } // namespace GH62529 namespace GH101394 { struct X {}; // #X struct Y { constexpr Y(const X &) {} }; namespace t1 { template class> struct A {}; template struct B; template struct A; } // namespace t1 namespace t2 { template class> struct A {}; // #A template struct B; // #B template struct A; // expected-error@#A {{no viable conversion from 'const Y' to 'X'}} // expected-note@-2 {{different template parameters}} // expected-note@#X 2{{not viable}} // expected-note@#B {{passing argument to parameter here}} } // namespace t2 } // namespace GH101394