mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-11 04:06:20 +00:00
![Richard Smith](/assets/img/avatar_default.png)
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. llvm-svn: 360308
68 lines
2.3 KiB
C++
68 lines
2.3 KiB
C++
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
|
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
|
|
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
|
|
|
|
// Clang used to crash trying to recover while adding 'this->' before Work(x);
|
|
|
|
template <typename> struct A {
|
|
static void Work(int); // expected-note{{must qualify identifier}}
|
|
};
|
|
|
|
template <typename T> struct B : public A<T> {
|
|
template <typename T2> B(T2 x) {
|
|
Work(x); // expected-error{{use of undeclared identifier}}
|
|
}
|
|
};
|
|
|
|
void Test() {
|
|
B<int> b(0); // expected-note{{in instantiation of function template}}
|
|
}
|
|
|
|
|
|
// Don't crash here.
|
|
namespace PR16134 {
|
|
template <class P> struct S // expected-error {{expected ';'}}
|
|
template <> static S<Q>::f() // expected-error +{{}}
|
|
}
|
|
|
|
namespace PR16225 {
|
|
template <typename T> void f();
|
|
template <typename C> void g(C*) {
|
|
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() {
|
|
g<S>(0);
|
|
#if __cplusplus <= 199711L
|
|
// expected-note@-2 {{in instantiation of function template specialization}}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
namespace test1 {
|
|
template <typename> class ArraySlice {};
|
|
class Foo;
|
|
class NonTemplateClass {
|
|
void MemberFunction(ArraySlice<Foo>, int);
|
|
template <class T> void MemberFuncTemplate(ArraySlice<T>, int);
|
|
};
|
|
void NonTemplateClass::MemberFunction(ArraySlice<Foo> resource_data,
|
|
int now) {
|
|
// expected-note@+1 {{in instantiation of function template specialization 'test1::NonTemplateClass::MemberFuncTemplate<test1::Foo>'}}
|
|
MemberFuncTemplate(resource_data, now);
|
|
}
|
|
template <class T>
|
|
void NonTemplateClass::MemberFuncTemplate(ArraySlice<T> resource_data, int) {
|
|
// expected-error@+1 {{use of undeclared identifier 'UndeclaredMethod'}}
|
|
UndeclaredMethod(resource_data);
|
|
}
|
|
// expected-error@+2 {{out-of-line definition of 'UndeclaredMethod' does not match any declaration}}
|
|
// expected-note@+1 {{must qualify identifier to find this declaration in dependent base class}}
|
|
void NonTemplateClass::UndeclaredMethod() {}
|
|
}
|