Author: jkorous Date: Thu Feb 8 06:37:58 2018 New Revision: 324607 URL: http://llvm.org/viewvc/llvm-project?rev=324607&view=rev Log: [Parser][FixIt] Better diagnostics for "typedef" instead of "typename" typo
rdar://problem/10214588 Differential Revision: https://reviews.llvm.org/D42170 Added: cfe/trunk/test/FixIt/fixit-typedef-instead-of-typename-typo.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/lib/Parse/ParseTemplate.cpp cfe/trunk/test/CXX/temp/temp.param/p2.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=324607&r1=324606&r2=324607&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Feb 8 06:37:58 2018 @@ -1162,6 +1162,9 @@ def err_objc_parameterized_implementatio 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 { Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=324607&r1=324606&r2=324607&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseTemplate.cpp (original) +++ cfe/trunk/lib/Parse/ParseTemplate.cpp Thu Feb 8 06:37:58 2018 @@ -488,6 +488,20 @@ NamedDecl *Parser::ParseTemplateParamete 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. Modified: cfe/trunk/test/CXX/temp/temp.param/p2.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.param/p2.cpp?rev=324607&r1=324606&r2=324607&view=diff ============================================================================== --- cfe/trunk/test/CXX/temp/temp.param/p2.cpp (original) +++ cfe/trunk/test/CXX/temp/temp.param/p2.cpp Thu Feb 8 06:37:58 2018 @@ -15,29 +15,29 @@ template<typename T, typename X<T>::type // 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 Added: cfe/trunk/test/FixIt/fixit-typedef-instead-of-typename-typo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-typedef-instead-of-typename-typo.cpp?rev=324607&view=auto ============================================================================== --- cfe/trunk/test/FixIt/fixit-typedef-instead-of-typename-typo.cpp (added) +++ cfe/trunk/test/FixIt/fixit-typedef-instead-of-typename-typo.cpp Thu Feb 8 06:37:58 2018 @@ -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" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits