r324607 - [Parser][FixIt] Better diagnostics for "typedef" instead of "typename" typo

Jan Korous via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 8 06:37:58 PST 2018


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 at -1 {{expected template parameter}} expected-note at -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 at +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"




More information about the cfe-commits mailing list