190 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify %s2// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s3 4namespace N { 5 enum { C };6 template<class T> class B {7 void f(T);8 }; 9}10 11template<class C> void N::B<C>::f(C) {12 C b;13}14 15namespace N {16 enum { D };17 namespace M {18 enum { C , D };19 template<typename C> class X {20 template<typename U> void f(C, U);21 22 template<typename D> void g(C, D) {23 C c;24 D d;25 }26 };27 28 struct Y {29 template<typename U> void f(U); 30 };31 }32 33 struct Y {34 template<typename D> void f(D);35 };36}37 38template<typename C> 39template<typename D>40void N::M::X<C>::f(C, D) {41 C c;42 D d;43}44 45template<typename C>46void N::M::Y::f(C) {47 C c;48}49 50template<typename D> 51void N::Y::f(D) {52 D d;53}54 55// Ensure we properly interleave the searches within classes and template parameter lists.56namespace SearchClassBetweenTemplateParameterLists {57 int AA, BB; // none of the below lookups should ever consider these58 59 struct Base {60 using AA = void;61 using BB = void;62 };63 struct BaseT : Base {64 using T = void;65 };66 struct BaseU : Base {67 using U = void;68 };69 70 template<typename T> struct A {71 using AA = void;72 template<typename U> struct B { // #defined-here73 using BB = void;74 void f(U);75 void g(U);76 void h(T);77 void i(T);78 template<typename V> void j(V);79 template<typename V> void k(U);80 81 // OK: these find the template parameter not the member.82 template<typename AA> void l(AA x) { AA aa; }83 template<typename BB> void m(BB x) { BB bb; }84 85 struct C : Base {86 // All OK; these find the template parameters.87 template<typename> void f(T x) { T t; }88 template<typename> void g(U x) { U u; }89 template<typename AA> void h(AA x) { AA aa; }90 template<typename BB> void i(BB x) { BB bb; }91 };92 93 struct CT : BaseT {94 template<typename> void f(T x) { // expected-error {{void}}95 T t; // expected-error {{incomplete}}96 }97 template<typename> void g(U x) { U u; }98 template<typename AA> void h(AA x) { AA aa; }99 template<typename BB> void i(BB x) { BB bb; }100 };101 102 struct CU : BaseU {103 template<typename> void f(T x) { T t; }104 template<typename> void g(U x) { // expected-error {{void}}105 U u; // expected-error {{incomplete}}106 }107 template<typename AA> void h(AA x) { AA aa; }108 template<typename BB> void i(BB x) { BB bb; }109 };110 };111 };112 113 // Search order for the below is:114 // 1) template parameter scope of the function itself (if any)115 // 2) class of which function is a member116 // 3) template parameter scope of inner class117 // 4) class of which class is a member118 // 5) template parameter scope of outer class119 120 // OK, 'AA' found in (3)121 template<typename T> template<typename AA>122 void A<T>::B<AA>::f(AA) {123 AA aa;124 }125 126 // error, 'BB' found in (2)127 template<typename T> template<typename BB>128 void A<T>::B<BB>::g(BB) { // expected-error {{does not match}}129 BB bb; // expected-error {{incomplete type}}130 } // expected-note@#defined-here {{defined here}}131 132 // error, 'AA' found in (4)133 template<typename AA> template<typename U>134 void A<AA>::B<U>::h(AA) { // expected-error {{does not match}}135 AA aa; // expected-error {{incomplete type}}136 } // expected-note@#defined-here {{defined here}}137 138 // error, 'BB' found in (2)139 template<typename BB> template<typename U>140 void A<BB>::B<U>::i(BB) { // expected-error {{does not match}}141 BB bb; // expected-error {{incomplete type}}142 } // expected-note@#defined-here {{defined here}}143 144 // OK, 'BB' found in (1)145 template<typename T> template<typename U> template<typename BB>146 void A<T>::B<U>::j(BB) {147 BB bb;148 }149 150 // error, 'BB' found in (2)151 template<typename T> template<typename BB> template<typename V>152 void A<T>::B<BB>::k(V) { // expected-error {{does not match}}153 BB bb; // expected-error {{incomplete type}}154 } // expected-note@#defined-here {{defined here}}155 156 int CC;157 template <typename> struct C;158 template <template<typename> typename> struct D;159#if __cplusplus >= 202002L160 template <bool CC> requires (CC) struct E;161 template <typename> struct F;162 template <typename> concept True = true;163#endif164}165 166template <typename CC>167struct SearchClassBetweenTemplateParameterLists::C {168 void foo(CC); // This should find the template type parameter.169};170 171template <template<typename> typename CC>172struct SearchClassBetweenTemplateParameterLists::D {173 template <typename AA>174 CC<AA> foo(CC<AA>);175};176 177#if __cplusplus >= 202002L178 179template <bool CC> requires (CC)180struct SearchClassBetweenTemplateParameterLists::E {181 void foo() requires (CC);182};183 184template <SearchClassBetweenTemplateParameterLists::True CC>185struct SearchClassBetweenTemplateParameterLists::F<CC> {186 void foo(CC);187};188 189#endif190