forked from OSchip/llvm-project
[Parser][FixIt] Better diagnostics for "typedef" instead of "typename" typo
rdar://problem/10214588 Differential Revision: https://reviews.llvm.org/D42170 llvm-svn: 324607
This commit is contained in:
parent
133b6085e8
commit
3a98e51823
|
@ -1162,6 +1162,9 @@ def err_objc_parameterized_implementation : Error<
|
|||
|
||||
def err_objc_type_args_after_protocols : Error<
|
||||
"protocol qualifiers must precede type arguments">;
|
||||
|
||||
def note_meant_to_use_typename : Note<
|
||||
"did you mean to use 'typename'?">;
|
||||
}
|
||||
|
||||
let CategoryName = "Coroutines Issue" in {
|
||||
|
|
|
@ -488,6 +488,20 @@ NamedDecl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
|
|||
if (Tok.is(tok::kw_template))
|
||||
return ParseTemplateTemplateParameter(Depth, Position);
|
||||
|
||||
// Is there just a typo in the input code? ('typedef' instead of 'typename')
|
||||
if (Tok.is(tok::kw_typedef)) {
|
||||
Diag(Tok.getLocation(), diag::err_expected_template_parameter);
|
||||
|
||||
Diag(Tok.getLocation(), diag::note_meant_to_use_typename)
|
||||
<< FixItHint::CreateReplacement(CharSourceRange::getCharRange(
|
||||
Tok.getLocation(), Tok.getEndLoc()),
|
||||
"typename");
|
||||
|
||||
Tok.setKind(tok::kw_typename);
|
||||
|
||||
return ParseTypeParameter(Depth, Position);
|
||||
}
|
||||
|
||||
// If it's none of the above, then it must be a parameter declaration.
|
||||
// NOTE: This will pick up errors in the closure of the template parameter
|
||||
// list (e.g., template < ; Check here to implement >> style closures.
|
||||
|
|
|
@ -15,29 +15,29 @@ template<typename T, typename X<T>::type Value> struct Y1;
|
|||
|
||||
// A storage class shall not be specified in a template-parameter declaration.
|
||||
template<static int Value> struct Z; //expected-error{{invalid declaration specifier}}
|
||||
template<typedef int Value> struct Z0; //expected-error{{invalid declaration specifier}}
|
||||
template<extern inline int Value> struct Z0; //expected-error2{{invalid declaration specifier}}
|
||||
template<virtual int Value> struct Z0; //expected-error{{invalid declaration specifier}}
|
||||
template<explicit int Value> struct Z0; //expected-error{{invalid declaration specifier}}
|
||||
template<inline int Value> struct Z0; //expected-error{{invalid declaration specifier}}
|
||||
template<extern int> struct Z0; //expected-error{{invalid declaration specifier}}
|
||||
template<static int> struct Z0; //expected-error{{invalid declaration specifier}}
|
||||
template<explicit int Value> struct Z0; //expected-error{{invalid declaration specifier}}
|
||||
template<mutable int> struct Z0; //expected-error{{invalid declaration specifier}}
|
||||
template<typedef int Value> struct Z0; //expected-error{{expected template parameter}} expected-error{{expected identifier}} expected-error{{extraneous 'template<>' in declaration of struct 'Z0'}} expected-note{{did you mean to use 'typename'?}}
|
||||
template<extern inline int Value> struct Z1; //expected-error2{{invalid declaration specifier}}
|
||||
template<virtual int Value> struct Z2; //expected-error{{invalid declaration specifier}}
|
||||
template<explicit int Value> struct Z3; //expected-error{{invalid declaration specifier}}
|
||||
template<inline int Value> struct Z4; //expected-error{{invalid declaration specifier}}
|
||||
template<extern int> struct Z5; //expected-error{{invalid declaration specifier}}
|
||||
template<static int> struct Z6; //expected-error{{invalid declaration specifier}}
|
||||
template<explicit int Value> struct Z7; //expected-error{{invalid declaration specifier}}
|
||||
template<mutable int> struct Z8; //expected-error{{invalid declaration specifier}}
|
||||
|
||||
template<const int> struct Z0; // OK
|
||||
template<volatile int> struct Z0; // OK
|
||||
template<const int> struct Z9; // OK
|
||||
template<volatile int> struct Z10; // OK
|
||||
|
||||
|
||||
|
||||
#ifdef CPP11
|
||||
template<thread_local int> struct Z0; //expected-error{{invalid declaration specifier}}
|
||||
template<constexpr int> struct Z0; //expected-error{{invalid declaration specifier}}
|
||||
template<thread_local int> struct Z11; //expected-error{{invalid declaration specifier}}
|
||||
template<constexpr int> struct Z12; //expected-error{{invalid declaration specifier}}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CPP17
|
||||
template<auto> struct Z1; // OK
|
||||
template<auto> struct Z13; // OK
|
||||
#endif
|
||||
|
||||
// Make sure that we properly disambiguate non-type template parameters that
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
template <typename A, typedef B> struct Foo {
|
||||
// expected-error@-1 {{expected template parameter}} expected-note@-1 {{did you mean to use 'typename'?}}
|
||||
|
||||
// Check that we are speculatively (with fixit applied) trying to parse the rest.
|
||||
|
||||
// Should not produce error about type since parsing speculatively with fixit applied.
|
||||
B member;
|
||||
|
||||
a // expected-error {{unknown type name 'a'}} // expected-error@+1 {{expected member name or ';' after declaration specifiers}}
|
||||
};
|
||||
|
||||
|
||||
// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// CHECK: fix-it:{{.*}}:{3:23-3:30}:"typename"
|
Loading…
Reference in New Issue