Index: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td +++ cfe/trunk/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: cfe/trunk/lib/Parse/ParseTemplate.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseTemplate.cpp +++ cfe/trunk/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. Index: cfe/trunk/test/CXX/temp/temp.param/p2.cpp =================================================================== --- cfe/trunk/test/CXX/temp/temp.param/p2.cpp +++ cfe/trunk/test/CXX/temp/temp.param/p2.cpp @@ -15,29 +15,29 @@ // A storage class shall not be specified in a template-parameter declaration. template struct Z; //expected-error{{invalid declaration specifier}} -template struct Z0; //expected-error{{invalid declaration specifier}} -template struct Z0; //expected-error2{{invalid declaration specifier}} -template struct Z0; //expected-error{{invalid declaration specifier}} -template struct Z0; //expected-error{{invalid declaration specifier}} -template struct Z0; //expected-error{{invalid declaration specifier}} -template struct Z0; //expected-error{{invalid declaration specifier}} -template struct Z0; //expected-error{{invalid declaration specifier}} -template struct Z0; //expected-error{{invalid declaration specifier}} -template struct Z0; //expected-error{{invalid declaration specifier}} +template 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 struct Z1; //expected-error2{{invalid declaration specifier}} +template struct Z2; //expected-error{{invalid declaration specifier}} +template struct Z3; //expected-error{{invalid declaration specifier}} +template struct Z4; //expected-error{{invalid declaration specifier}} +template struct Z5; //expected-error{{invalid declaration specifier}} +template struct Z6; //expected-error{{invalid declaration specifier}} +template struct Z7; //expected-error{{invalid declaration specifier}} +template struct Z8; //expected-error{{invalid declaration specifier}} -template struct Z0; // OK -template struct Z0; // OK +template struct Z9; // OK +template struct Z10; // OK #ifdef CPP11 -template struct Z0; //expected-error{{invalid declaration specifier}} -template struct Z0; //expected-error{{invalid declaration specifier}} +template struct Z11; //expected-error{{invalid declaration specifier}} +template struct Z12; //expected-error{{invalid declaration specifier}} #endif #ifdef CPP17 -template struct Z1; // OK +template struct Z13; // OK #endif // Make sure that we properly disambiguate non-type template parameters that Index: cfe/trunk/test/FixIt/fixit-typedef-instead-of-typename-typo.cpp =================================================================== --- cfe/trunk/test/FixIt/fixit-typedef-instead-of-typename-typo.cpp +++ cfe/trunk/test/FixIt/fixit-typedef-instead-of-typename-typo.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template 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"