diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-09 03:31:27 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-09 03:31:27 +0000 |
commit | fb98e7c13da639f34f34830a4e675367e0816cb6 (patch) | |
tree | 70e025e9b4a31559d1f061e72439b5414537ad3b /test | |
parent | 70cd574857c6023b8c60e325c4029a23f716c2dd (diff) | |
download | clang-fb98e7c13da639f34f34830a4e675367e0816cb6.tar.gz |
[c++20] Implement P0846R0: allow (ADL-only) calls to template-ids whose
template name is not visible to unqualified lookup.
In order to support this without a severe degradation in our ability to
diagnose typos in template names, this change significantly restructures
the way we handle template-id-shaped syntax for which lookup of the
template name finds nothing.
Instead of eagerly diagnosing an undeclared template name, we now form a
placeholder template-name representing a name that is known to not find
any templates. When the parser sees such a name, it attempts to
disambiguate whether we have a less-than comparison or a template-id.
Any diagnostics or typo-correction for the name are delayed until its
point of use.
The upshot should be a small improvement of our diagostic quality
overall: we now take more syntactic context into account when trying to
resolve an undeclared identifier on the left hand side of a '<'. In
fact, this works well enough that the backwards-compatible portion (for
an undeclared identifier rather than a lookup that finds functions but
no function templates) is enabled in all language modes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@360308 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r-- | test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp | 60 | ||||
-rw-r--r-- | test/CXX/drs/dr2xx.cpp | 7 | ||||
-rw-r--r-- | test/CXX/drs/dr6xx.cpp | 9 | ||||
-rw-r--r-- | test/CXX/temp/temp.spec/temp.explicit/p5.cpp | 5 | ||||
-rw-r--r-- | test/FixIt/typo-crash.cpp | 10 | ||||
-rw-r--r-- | test/Misc/diag-template-diffing.cpp | 2 | ||||
-rw-r--r-- | test/Modules/module-private.cpp | 4 | ||||
-rw-r--r-- | test/Modules/submodules-merge-defs.cpp | 4 | ||||
-rw-r--r-- | test/Parser/cxx-ambig-init-templ.cpp | 2 | ||||
-rw-r--r-- | test/Parser/cxx-template-argument.cpp | 23 | ||||
-rw-r--r-- | test/Parser/cxx-template-decl.cpp | 13 | ||||
-rw-r--r-- | test/SemaCXX/alias-template.cpp | 7 | ||||
-rw-r--r-- | test/SemaCXX/class.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/cxx2a-adl-only-template-id.cpp | 67 | ||||
-rw-r--r-- | test/SemaCXX/destructor.cpp | 5 | ||||
-rw-r--r-- | test/SemaCXX/invalid-member-expr.cpp | 5 | ||||
-rw-r--r-- | test/SemaCXX/typo-correction.cpp | 2 | ||||
-rw-r--r-- | test/SemaTemplate/dependent-base-classes.cpp | 2 | ||||
-rw-r--r-- | test/SemaTemplate/dependent-template-recover.cpp | 10 | ||||
-rw-r--r-- | test/SemaTemplate/rdar9173693.cpp | 7 | ||||
-rw-r--r-- | test/SemaTemplate/recovery-crash.cpp | 4 |
21 files changed, 182 insertions, 68 deletions
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp index abcc6eee94..0138b88578 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp @@ -1,25 +1,67 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s -typedef int f; +typedef int fn; namespace N0 { - struct A { - friend void f(); + struct A { + friend void fn(); void g() { - int i = f(1); + int i = fn(1); } }; } namespace N1 { - struct A { - friend void f(A &); + struct A { + friend void fn(A &); operator int(); void g(A a) { - // ADL should not apply to the lookup of 'f', it refers to the typedef + // ADL should not apply to the lookup of 'fn', it refers to the typedef // above. - int i = f(a); + int i = fn(a); } }; } + +namespace std_example { + int h; // expected-note {{non-template declaration}} + void g(); +#if __cplusplus <= 201703L + // expected-note@-2 {{non-template declaration}} +#endif + namespace N { + struct A {}; + template<class T> int f(T); + template<class T> int g(T); +#if __cplusplus <= 201703L + // expected-note@-2 {{here}} +#endif + template<class T> int h(T); // expected-note {{here}} + } + + int x = f<N::A>(N::A()); +#if __cplusplus <= 201703L + // expected-warning@-2 {{C++2a extension}} +#endif + int y = g<N::A>(N::A()); +#if __cplusplus <= 201703L + // expected-error@-2 {{'g' does not name a template but is followed by template arguments; did you mean 'N::g'?}} +#endif + int z = h<N::A>(N::A()); // expected-error {{'h' does not name a template but is followed by template arguments; did you mean 'N::h'?}} +} + +namespace AnnexD_example { + struct A {}; + void operator<(void (*fp)(), A); + void f() {} + int main() { + A a; + f < a; +#if __cplusplus > 201703L + // expected-error@-2 {{expected '>'}} +#endif + (f) < a; + } +} diff --git a/test/CXX/drs/dr2xx.cpp b/test/CXX/drs/dr2xx.cpp index b69c014b58..c7ffa77d30 100644 --- a/test/CXX/drs/dr2xx.cpp +++ b/test/CXX/drs/dr2xx.cpp @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // PR13819 -- __SIZE_TYPE__ is incompatible. typedef __SIZE_TYPE__ size_t; // expected-error 0-1 {{extension}} @@ -434,7 +435,7 @@ namespace dr239 { // dr239: yes namespace dr241 { // dr241: yes namespace A { struct B {}; - template <int X> void f(); // expected-note 2{{candidate}} + template <int X> void f(); // expected-note 3{{candidate}} template <int X> void g(B); } namespace C { @@ -442,8 +443,8 @@ namespace dr241 { // dr241: yes template <class T> void g(T t); // expected-note {{candidate}} } void h(A::B b) { - f<3>(b); // expected-error {{undeclared identifier}} - g<3>(b); // expected-error {{undeclared identifier}} + f<3>(b); // expected-error 0-1{{C++2a extension}} expected-error {{no matching}} + g<3>(b); // expected-error 0-1{{C++2a extension}} A::f<3>(b); // expected-error {{no matching}} A::g<3>(b); C::f<3>(b); // expected-error {{no matching}} diff --git a/test/CXX/drs/dr6xx.cpp b/test/CXX/drs/dr6xx.cpp index b4247b2260..318096c299 100644 --- a/test/CXX/drs/dr6xx.cpp +++ b/test/CXX/drs/dr6xx.cpp @@ -1048,10 +1048,13 @@ namespace dr686 { // dr686: yes template<struct R {} *> struct Y; // expected-error {{cannot be defined in a type specifier}} } -namespace dr687 { // dr687 still open +namespace dr687 { // dr687 (9 c++20, but the issue is still considered open) template<typename T> void f(T a) { - // FIXME: This is valid in C++20. - g<int>(a); // expected-error {{undeclared}} expected-error {{'('}} + // This is valid in C++20. + g<int>(a); +#if __cplusplus <= 201703L + // expected-error@-2 {{C++2a extension}} +#endif // This is not. template g<int>(a); // expected-error {{expected expression}} diff --git a/test/CXX/temp/temp.spec/temp.explicit/p5.cpp b/test/CXX/temp/temp.spec/temp.explicit/p5.cpp index ca1f9a391e..5f0c4547cf 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p5.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p5.cpp @@ -8,7 +8,10 @@ namespace N { }; } -template class Z<int>; // expected-error{{explicit instantiation of non-template class 'Z'}} +template class Z<int>; // expected-error{{explicit instantiation of undeclared template class 'Z'}} + +struct Q; +template class Q<int>; // expected-error{{explicit instantiation of non-template class 'Q'}} // FIXME: This example from the standard is wrong; note posted to CWG reflector // on 10/27/2009 diff --git a/test/FixIt/typo-crash.cpp b/test/FixIt/typo-crash.cpp index 4ea63c542a..5130e3e0e6 100644 --- a/test/FixIt/typo-crash.cpp +++ b/test/FixIt/typo-crash.cpp @@ -1,14 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// FIXME: The diagnostics and recovery here are very, very poor. - // PR10355 -template<typename T> void template_id1() { // expected-note {{'template_id1' declared here}} \ - // expected-note {{possible target for call}} - template_id2<> t; // expected-error {{no template named 'template_id2'; did you mean 'template_id1'?}} \ - // expected-error {{expected ';' after expression}} \ - // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} \ - // expected-error {{use of undeclared identifier 't'}} +template<typename T> void template_id1() { + template_id2<> t; // expected-error-re {{no template named 'template_id2'{{$}}}} } // FIXME: It would be nice if we could get this correction right. diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp index 5c85df434d..7d3e21533f 100644 --- a/test/Misc/diag-template-diffing.cpp +++ b/test/Misc/diag-template-diffing.cpp @@ -394,7 +394,7 @@ template<double* ...A> class class_ptrs {}; void set13(class_ptrs<&a13, &b13>) {} void test13() { set13(class_ptrs<&c13>()); - set13(class_ptrss<&a13, &b13, &d13>()); + set13(class_ptrs<&a13, &b13, &d13>()); } // CHECK-ELIDE-NOTREE: no matching function for call to 'set13' // CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class_ptrs<&c13, (no argument)>' to 'class_ptrs<&a13, &b13>' for 1st argument diff --git a/test/Modules/module-private.cpp b/test/Modules/module-private.cpp index 42ab185760..30957865d1 100644 --- a/test/Modules/module-private.cpp +++ b/test/Modules/module-private.cpp @@ -18,9 +18,7 @@ int test_broken() { int *ip = 0; f1(ip); // expected-error{{use of undeclared identifier 'f1'}} - vector<int> vec; // expected-error{{use of undeclared identifier 'vector'}} \ - // expected-error{{expected '(' for function-style cast or type construction}} \ - // expected-error{{use of undeclared identifier 'vec'}} + vector<int> vec; // expected-error{{no template named 'vector'}} VisibleStruct vs; vs.field = 0; // expected-error{{no member named 'field' in 'VisibleStruct'}} diff --git a/test/Modules/submodules-merge-defs.cpp b/test/Modules/submodules-merge-defs.cpp index 795150208c..0f7637de57 100644 --- a/test/Modules/submodules-merge-defs.cpp +++ b/test/Modules/submodules-merge-defs.cpp @@ -29,7 +29,7 @@ B::Inner2 pre_bi; // expected-error +{{must be imported}} // expected-note@defs.h:4 +{{here}} // expected-note@defs.h:17 +{{here}} void pre_bfi(B b) { // expected-error +{{must be imported}} - b.f<int>(); // expected-error +{{}} + b.f<int>(); } C_Base<1> pre_cb1; // expected-error +{{must be imported}} @@ -48,7 +48,7 @@ int pre_e = E(0); // expected-error {{must be imported}} // expected-note@defs.h:32 +{{here}} int pre_ff = F<int>().f(); // expected-error +{{must be imported}} -int pre_fg = F<int>().g<int>(); // expected-error +{{must be imported}} expected-error 2{{expected}} +int pre_fg = F<int>().g<int>(); // expected-error +{{must be imported}} // expected-note@defs.h:34 +{{here}} G::A pre_ga // expected-error +{{must be imported}} diff --git a/test/Parser/cxx-ambig-init-templ.cpp b/test/Parser/cxx-ambig-init-templ.cpp index 89ed5e570b..a64760f3f4 100644 --- a/test/Parser/cxx-ambig-init-templ.cpp +++ b/test/Parser/cxx-ambig-init-templ.cpp @@ -31,7 +31,7 @@ struct S { void f2a( // T3<int> here is a parameter type, so must be declared before it is used. - int k1 = c < b, T3 < int > x = 0 // expected-error {{unexpected end of default argument expression}} + int k1 = c < b, T3 < int > x = 0 // expected-error {{no template named 'T3'}} ); template<typename, int=0> struct T3 { T3(int); operator int(); }; diff --git a/test/Parser/cxx-template-argument.cpp b/test/Parser/cxx-template-argument.cpp index 963356eaab..b3a9071785 100644 --- a/test/Parser/cxx-template-argument.cpp +++ b/test/Parser/cxx-template-argument.cpp @@ -60,33 +60,32 @@ namespace pr16225add { template<int N1, int N2> struct ABC2 {}; template<class T1, typename T2> struct foo : - UnknownBase<T1,T2> // expected-error {{unknown template name 'UnknownBase'}} + UnknownBase<T1,T2> // expected-error {{no template named 'UnknownBase'}} { }; template<class T1, typename T2> struct foo2 : - UnknownBase<T1,T2>, // expected-error {{unknown template name 'UnknownBase'}} + UnknownBase<T1,T2>, // expected-error {{no template named 'UnknownBase'}} Known<T1> // expected-error {{too few template arguments for class template 'Known'}} { }; template<class T1, typename T2> struct foo3 : - UnknownBase<T1,T2,ABC<T2,T1> > // expected-error {{unknown template name 'UnknownBase'}} + UnknownBase<T1,T2,ABC<T2,T1> > // expected-error {{no template named 'UnknownBase'}} { }; template<class T1, typename T2> struct foo4 : - UnknownBase<T1,ABC<T2> >, // expected-error {{unknown template name 'UnknownBase'}} \ - // expected-error {{too few template arguments for class template 'ABC'}} + UnknownBase<T1,ABC<T2> >, // expected-error {{too few template arguments for class template 'ABC'}} Known<T1> // expected-error {{too few template arguments for class template 'Known'}} { }; template<class T1, typename T2> struct foo5 : - UnknownBase<T1,T2,ABC<T2,T1>> // expected-error {{unknown template name 'UnknownBase'}} + UnknownBase<T1,T2,ABC<T2,T1>> // expected-error {{no template named 'UnknownBase'}} #if __cplusplus <= 199711L // expected-error@-2 {{use '> >'}} #endif { }; template<class T1, typename T2> struct foo6 : - UnknownBase<T1,ABC<T2,T1>>, // expected-error {{unknown template name 'UnknownBase'}} + UnknownBase<T1,ABC<T2,T1>>, // expected-error {{no template named 'UnknownBase'}} #if __cplusplus <= 199711L // expected-error@-2 {{use '> >'}} #endif @@ -94,32 +93,32 @@ namespace pr16225add { { }; template<class T1, typename T2, int N> struct foo7 : - UnknownBase<T1,T2,(N>1)> // expected-error {{unknown template name 'UnknownBase'}} + UnknownBase<T1,T2,(N>1)> // expected-error {{no template named 'UnknownBase'}} { }; template<class T1, typename T2> struct foo8 : - UnknownBase<X<int,int>,X<int,int>> // expected-error {{unknown template name 'UnknownBase'}} + UnknownBase<X<int,int>,X<int,int>> // expected-error {{no template named 'UnknownBase'}} #if __cplusplus <= 199711L // expected-error@-2 {{use '> >'}} #endif { }; template<class T1, typename T2> struct foo9 : - UnknownBase<Known<int,int>,X<int,int>> // expected-error {{unknown template name 'UnknownBase'}} + UnknownBase<Known<int,int>,X<int,int>> // expected-error {{no template named 'UnknownBase'}} #if __cplusplus <= 199711L // expected-error@-2 {{use '> >'}} #endif { }; template<class T1, typename T2> struct foo10 : - UnknownBase<Known<int,int>,X<int,X<int,int>>> // expected-error {{unknown template name 'UnknownBase'}} + UnknownBase<Known<int,int>,X<int,X<int,int>>> // expected-error {{no template named 'UnknownBase'}} #if __cplusplus <= 199711L // expected-error@-2 {{use '> >'}} #endif { }; template<int N1, int N2> struct foo11 : - UnknownBase<2<N1,N2<4> // expected-error {{unknown template name 'UnknownBase'}} + UnknownBase<2<N1,N2<4> // expected-error {{no template named 'UnknownBase'}} { }; } diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp index 9ad422e7ab..64c485fc0e 100644 --- a/test/Parser/cxx-template-decl.cpp +++ b/test/Parser/cxx-template-decl.cpp @@ -128,8 +128,13 @@ void f2() { // PR3844 -template <> struct S<int> { }; // expected-error{{explicit specialization of non-template struct 'S'}} -template <> union U<int> { }; // expected-error{{explicit specialization of non-template union 'U'}} +template <> struct S<int> { }; // expected-error{{explicit specialization of undeclared template struct 'S'}} +template <> union U<int> { }; // expected-error{{explicit specialization of undeclared template union 'U'}} + +struct SS; +union UU; +template <> struct SS<int> { }; // expected-error{{explicit specialization of non-template struct 'SS'}} +template <> union UU<int> { }; // expected-error{{explicit specialization of non-template union 'UU'}} namespace PR6184 { namespace N { @@ -230,11 +235,11 @@ struct base { }; struct t1 : base<int, public: // expected-error {{expected expression}} -}; // expected-error {{expected class name}} +}; // expected-error@-1 {{expected '{' after base class list}} struct t2 : base<int, public // expected-error {{expected expression}} -}; // expected-error {{expected class name}} +}; // expected-error@-1 {{expected '{' after base class list}} } diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp index 0a92b9dd96..f41c3aa8bc 100644 --- a/test/SemaCXX/alias-template.cpp +++ b/test/SemaCXX/alias-template.cpp @@ -112,11 +112,8 @@ namespace StdExample { template<typename T> using handler_t = void (*)(T); extern handler_t<int> ignore; extern void (*ignore)(int); - // FIXME: we recover as if cell is an undeclared variable. the diagnostics are terrible! - template<typename T> using cell = pair<T*, cell<T>*>; // expected-error {{use of undeclared identifier 'cell'}} \ - expected-error {{'T' does not refer to a value}} \ - expected-note {{declared here}} \ - expected-error {{expected ';' after alias declaration}} + // FIXME: we recover as if cell is an undeclared variable template + template<typename T> using cell = pair<T*, cell<T>*>; // expected-error {{use of undeclared identifier 'cell'}} expected-error {{expected expression}} } namespace Access { diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp index a3593689b5..b571370911 100644 --- a/test/SemaCXX/class.cpp +++ b/test/SemaCXX/class.cpp @@ -138,7 +138,7 @@ struct S // Don't crash on this bogus code. namespace pr6629 { template<class T1, class T2> struct foo : - bogus<foo<T1,T2> > // expected-error {{unknown template name 'bogus'}} + bogus<foo<T1,T2> > // expected-error {{no template named 'bogus'}} { }; template<> struct foo<unknown,unknown> { // expected-error {{undeclared identifier 'unknown'}} diff --git a/test/SemaCXX/cxx2a-adl-only-template-id.cpp b/test/SemaCXX/cxx2a-adl-only-template-id.cpp new file mode 100644 index 0000000000..4bd9a22f5f --- /dev/null +++ b/test/SemaCXX/cxx2a-adl-only-template-id.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +namespace N { + struct Q {}; + template<typename> int f(Q); + template<int> int f(Q); + template<typename> int g(Q); + template<int> int g(Q); + + template<int> int some_long_name(Q); // expected-note {{here}} +} +N::Q q; +int g(); + +int h(); +template<int> int h(...); +int h(int); + +// OK, these find the above functions by ADL. +int a = f<int>(q); +int b(f<int>(q)); +int c(f<0>(q)); +int d = g<int>(q); + +int e = h<0>(q); // ok, found by unqualified lookup + +void fn() { + f<0>(q); + int f; + f<0>(q); // expected-error {{invalid operands to binary expression}} +} + +void disambig() { + // FIXME: It's unclear whether ending the template argument at the > inside the ?: is correct here (see DR579). + f<true ? 1 > 2 : 3>(q); // expected-error {{expected ':'}} expected-note {{to match}} expected-error {{expected expression}} + + f < 1 + 3 > (q); // ok, function call +} + +bool typo(int something) { // expected-note 4{{declared here}} + // FIXME: We shouldn't suggest the N:: for an ADL call if the candidate can be found by ADL. + some_logn_name<3>(q); // expected-error {{did you mean 'N::some_long_name'?}} + somethign < 3 ? h() > 4 : h(0); // expected-error {{did you mean 'something'}} + // This is parsed as a comparison on the left of a ?: expression. + somethign < 3 ? h() + 4 : h(0); // expected-error {{did you mean 'something'}} + // This is parsed as an ADL-only template-id call. + somethign < 3 ? h() + 4 : h(0) >(0); // expected-error {{undeclared identifier 'somethign'}} + bool k(somethign < 3); // expected-error {{did you mean 'something'}} + return somethign < 3; // expected-error {{did you mean 'something'}} +} + +// Ensure that treating undeclared identifiers as template names doesn't cause +// problems. +struct W<int> {}; // expected-error {{undeclared template struct 'W'}} +X<int>::Y xy; // expected-error {{no template named 'X'}} +void xf(X<int> x); // expected-error {{no template named 'X'}} +struct A : X<int> { // expected-error {{no template named 'X'}} + A() : X<int>() {} // expected-error {{no template named 'X'}} +}; + +// Similarly for treating overload sets of functions as template names. +struct g<int> {}; // expected-error {{'g' refers to a function template}} +g<int>::Y xy; // expected-error {{no template named 'g'}} FIXME lies +void xf(g<int> x); // expected-error {{variable has incomplete type 'void'}} expected-error 1+{{}} expected-note {{}} +struct B : g<int> { // expected-error {{expected class name}} + B() : g<int>() {} // expected-error {{expected class member or base class name}} +}; diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp index 00d2fc5529..2859953a02 100644 --- a/test/SemaCXX/destructor.cpp +++ b/test/SemaCXX/destructor.cpp @@ -99,7 +99,7 @@ struct Y { namespace PR6421 { class T; // expected-note{{forward declaration}} - class QGenericArgument // expected-note{{declared here}} + class QGenericArgument { template<typename U> void foo(T t) // expected-error{{variable has incomplete type}} @@ -108,8 +108,7 @@ namespace PR6421 { void disconnect() { T* t; - bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}} \ - // expected-error{{does not refer to a value}} + bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}} } }; } diff --git a/test/SemaCXX/invalid-member-expr.cpp b/test/SemaCXX/invalid-member-expr.cpp index fd50d328da..920d92380e 100644 --- a/test/SemaCXX/invalid-member-expr.cpp +++ b/test/SemaCXX/invalid-member-expr.cpp @@ -53,7 +53,10 @@ namespace test3 { namespace rdar11293995 { struct Length { - explicit Length(PassRefPtr<CalculationValue>); // expected-error {{no template named 'PassRefPtr}} expected-error {{undeclared identifier 'CalculationValue'}} + // FIXME: We try to annotate the template-id here during tentative parsing, + // and fail, then try again during the actual parse. This results in the same + // diagnostic being produced twice. :( + explicit Length(PassRefPtr<CalculationValue>); // expected-error 2{{undeclared identifier 'CalculationValue'}} }; struct LengthSize { diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp index ddd43c0809..33dea4d36b 100644 --- a/test/SemaCXX/typo-correction.cpp +++ b/test/SemaCXX/typo-correction.cpp @@ -438,7 +438,7 @@ namespace PR17394 { long zzzzzzzzzz; }; class B : private A {}; - B zzzzzzzzzy<>; // expected-error {{expected ';' after top level declarator}}{} + B zzzzzzzzzy<>; // expected-error {{template specialization requires 'template<>'}} expected-error {{no variable template matches specialization}} } namespace correct_fields_in_member_funcs { diff --git a/test/SemaTemplate/dependent-base-classes.cpp b/test/SemaTemplate/dependent-base-classes.cpp index 6d342f984d..bb4f3ca1f1 100644 --- a/test/SemaTemplate/dependent-base-classes.cpp +++ b/test/SemaTemplate/dependent-base-classes.cpp @@ -9,7 +9,7 @@ template<typename T, typename U> struct X1 : T::apply<U> { }; // expected-error{{use 'template' keyword to treat 'apply' as a dependent template name}} template<typename T> -struct X2 : vector<T> { }; // expected-error{{unknown template name 'vector'}} +struct X2 : vector<T> { }; // expected-error{{no template named 'vector'}} namespace PR6031 { template<typename T> diff --git a/test/SemaTemplate/dependent-template-recover.cpp b/test/SemaTemplate/dependent-template-recover.cpp index 37a8faa705..90ba3cd899 100644 --- a/test/SemaTemplate/dependent-template-recover.cpp +++ b/test/SemaTemplate/dependent-template-recover.cpp @@ -7,7 +7,7 @@ struct X { t->operator+<U const, 1>(1); // expected-error{{use 'template' keyword to treat 'operator +' as a dependent template name}} t->f1<int const, 2>(1); // expected-error{{use 'template' keyword to treat 'f1' as a dependent template name}} - t->f1<3, int const>(1); // expected-error{{missing 'template' keyword prior to dependent template name 'f1'}} + t->f1<3, int const>(1); // expected-error{{use 'template' keyword to treat 'f1' as a dependent template name}} T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}} t->T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}} @@ -15,7 +15,7 @@ struct X { (*t).f2<N>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}} (*t).f2<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}} T::f2<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}} - T::f2<0, int>(0); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}} + T::f2<0, int>(0); // expected-error{{use 'template' keyword to treat 'f2' as a dependent template name}} T::foo<N < 2 || N >= 4>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} @@ -24,7 +24,7 @@ struct X { T::foo<T::bar < 1>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} T::foo < T::bar<1>(); // expected-error{{missing 'template' keyword prior to dependent template name 'bar'}} - // Prefer to diagonse a missing 'template' keyword rather than finding a non-template name. + // Prefer to diagnose a missing 'template' keyword rather than finding a non-template name. xyz < T::foo < 1 > (); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} T::foo < xyz < 1 > (); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} @@ -83,12 +83,12 @@ template<int N, typename T> void f(T t) { T::g<mb>(0); // ... but this one must be a template-id. - T::g<mb, int>(0); // expected-error {{missing 'template' keyword prior to dependent template name 'g'}} + T::g<mb, int>(0); // expected-error {{use 'template' keyword to treat 'g' as a dependent template name}} expected-error {{no matching function}} } struct Y { template <int> void f(int); - template <int = 0> static void g(int); // expected-warning 0-1{{extension}} + template <int = 0> static void g(int); // expected-warning 0-1{{extension}} expected-note {{candidate}} }; void q() { void (*p)(int) = Y::g; } template void f<0>(Y); // expected-note {{in instantiation of}} diff --git a/test/SemaTemplate/rdar9173693.cpp b/test/SemaTemplate/rdar9173693.cpp index 86b49545a3..ed09a64a0d 100644 --- a/test/SemaTemplate/rdar9173693.cpp +++ b/test/SemaTemplate/rdar9173693.cpp @@ -2,5 +2,8 @@ // <rdar://problem/9173693> template< bool C > struct assert { }; -template< bool > struct assert_arg_pred_impl { }; // expected-note 3 {{declared here}} -template< typename Pred > assert<false> assert_not_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type ); // expected-error 5 {{}} +// FIXME: We diagnose the same problem multiple times here because we have no +// way to indicate in the token stream that we already tried to annotate a +// template-id and we failed. +template< bool > struct assert_arg_pred_impl { }; // expected-note 4 {{declared here}} +template< typename Pred > assert<false> assert_not_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type ); // expected-error 6 {{}} diff --git a/test/SemaTemplate/recovery-crash.cpp b/test/SemaTemplate/recovery-crash.cpp index c8e783f47b..ec44747ce5 100644 --- a/test/SemaTemplate/recovery-crash.cpp +++ b/test/SemaTemplate/recovery-crash.cpp @@ -28,12 +28,12 @@ namespace PR16134 { namespace PR16225 { template <typename T> void f(); template <typename C> void g(C*) { - struct LocalStruct : UnknownBase<Mumble, C> { }; // expected-error {{unknown template name 'UnknownBase'}} \ - // expected-error {{use of undeclared identifier 'Mumble'}} + struct LocalStruct : UnknownBase<Mumble, C> { }; // expected-error {{use of undeclared identifier 'Mumble'}} f<LocalStruct>(); #if __cplusplus <= 199711L // expected-warning@-2 {{template argument uses local type 'LocalStruct'}} #endif + struct LocalStruct2 : UnknownBase<C> { }; // expected-error {{no template named 'UnknownBase'}} } struct S; void h() { |