This revision was automatically updated to reflect the committed changes. Closed by commit rC324607: [Parser][FixIt] Better diagnostics for "typedef" instead of "typename" typo (authored by jkorous, committed by ).
Changed prior to commit: https://reviews.llvm.org/D42170?vs=132135&id=133412#toc Repository: rC Clang https://reviews.llvm.org/D42170 Files: include/clang/Basic/DiagnosticParseKinds.td lib/Parse/ParseTemplate.cpp test/CXX/temp/temp.param/p2.cpp test/FixIt/fixit-typedef-instead-of-typename-typo.cpp
Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -1162,6 +1162,9 @@ 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 { Index: test/CXX/temp/temp.param/p2.cpp =================================================================== --- test/CXX/temp/temp.param/p2.cpp +++ test/CXX/temp/temp.param/p2.cpp @@ -15,29 +15,29 @@ // 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 Index: test/FixIt/fixit-typedef-instead-of-typename-typo.cpp =================================================================== --- test/FixIt/fixit-typedef-instead-of-typename-typo.cpp +++ test/FixIt/fixit-typedef-instead-of-typename-typo.cpp @@ -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" Index: lib/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -488,6 +488,20 @@ 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.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits