[cfe-commits] r69086 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp test/SemaCXX/namespace.cpp test/SemaCXX/nested-name-spec.cpp test/SemaTemplate/instantiate-typedef.cpp test/SemaTemplate/nested-name-spec-template.cpp test/SemaTemplate/typename-specifier.cpp

Chris Lattner sabre at nondot.org
Tue Apr 14 15:17:06 PDT 2009


Author: lattner
Date: Tue Apr 14 17:17:06 2009
New Revision: 69086

URL: http://llvm.org/viewvc/llvm-project?rev=69086&view=rev
Log:
Make the implicit-int handling error recovery stuff handle C++
nested name specifiers.  Now we emit stuff like:

t.cpp:8:13: error: unknown type name 'X'
static foo::X  P;
       ~~~~ ^

instead of:

t.cpp:8:16: error: invalid token after top level declarator
static foo::X  P;
               ^

This is inspired by a really awful error message I got from 
g++ when I misspelt diag::kind as diag::Kind.


Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/test/SemaCXX/namespace.cpp
    cfe/trunk/test/SemaCXX/nested-name-spec.cpp
    cfe/trunk/test/SemaTemplate/instantiate-typedef.cpp
    cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp
    cfe/trunk/test/SemaTemplate/typename-specifier.cpp

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=69086&r1=69085&r2=69086&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Apr 14 17:17:06 2009
@@ -816,7 +816,8 @@
   DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
   DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
   
-  bool ParseImplicitInt(DeclSpec &DS, TemplateParameterLists *TemplateParams,
+  bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
+                        TemplateParameterLists *TemplateParams,
                         AccessSpecifier AS);
   void ParseDeclarationSpecifiers(DeclSpec &DS, 
                                   TemplateParameterLists *TemplateParams = 0,

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=69086&r1=69085&r2=69086&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Apr 14 17:17:06 2009
@@ -499,9 +499,11 @@
 /// declspec is done being processed.  If it recovers and thinks there may be
 /// other pieces of declspec after it, it returns true.
 ///
-bool Parser::ParseImplicitInt(DeclSpec &DS,
+bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
                               TemplateParameterLists *TemplateParams,
                               AccessSpecifier AS) {
+  assert(Tok.is(tok::identifier) && "should have identifier");
+  
   SourceLocation Loc = Tok.getLocation();
   // If we see an identifier that is not a type name, we normally would
   // parse it as the identifer being declared.  However, when a typename
@@ -530,10 +532,12 @@
   // error anyway.  Try to recover from various common problems.  Check
   // to see if this was a reference to a tag name without a tag specified.
   // This is a common problem in C (saying 'foo' instead of 'struct foo').
-  const char *TagName = 0;
-  tok::TokenKind TagKind = tok::unknown;
+  //
+  // C++ doesn't need this, and isTagName doesn't take SS.
+  if (SS == 0) {
+    const char *TagName = 0;
+    tok::TokenKind TagKind = tok::unknown;
   
-  if (Tok.is(tok::identifier)) {
     switch (Actions.isTagName(*Tok.getIdentifierInfo(), CurScope)) {
       default: break;
       case DeclSpec::TST_enum:  TagName="enum"  ;TagKind=tok::kw_enum  ;break;
@@ -541,25 +545,28 @@
       case DeclSpec::TST_struct:TagName="struct";TagKind=tok::kw_struct;break;
       case DeclSpec::TST_class: TagName="class" ;TagKind=tok::kw_class ;break;
     }
-  }
   
-  if (TagName) {
-    Diag(Loc, diag::err_use_of_tag_name_without_tag)
-      << Tok.getIdentifierInfo() << TagName
-      << CodeModificationHint::CreateInsertion(Tok.getLocation(),TagName);
-    
-    // Parse this as a tag as if the missing tag were present.
-    if (TagKind == tok::kw_enum)
-      ParseEnumSpecifier(Loc, DS, AS);
-    else
-      ParseClassSpecifier(TagKind, Loc, DS, TemplateParams, AS);
-    return true;
+    if (TagName) {
+      Diag(Loc, diag::err_use_of_tag_name_without_tag)
+        << Tok.getIdentifierInfo() << TagName
+        << CodeModificationHint::CreateInsertion(Tok.getLocation(),TagName);
+      
+      // Parse this as a tag as if the missing tag were present.
+      if (TagKind == tok::kw_enum)
+        ParseEnumSpecifier(Loc, DS, AS);
+      else
+        ParseClassSpecifier(TagKind, Loc, DS, TemplateParams, AS);
+      return true;
+    }
   }
   
   // Since this is almost certainly an invalid type name, emit a
   // diagnostic that says it, eat the token, and mark the declspec as
   // invalid.
-  Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo();
+  SourceRange R;
+  if (SS) R = SS->getRange();
+  
+  Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R;
   const char *PrevSpec;
   DS.SetTypeSpecType(DeclSpec::TST_error, Loc, PrevSpec);
   DS.SetRangeEnd(Tok.getLocation());
@@ -642,7 +649,7 @@
       // If the next token is the name of the class type that the C++ scope
       // denotes, followed by a '(', then this is a constructor declaration.
       // We're done with the decl-specifiers.
-      if (Actions.isCurrentClassName(*NextToken().getIdentifierInfo(),
+      if (Actions.isCurrentClassName(*Next.getIdentifierInfo(),
                                      CurScope, &SS) &&
           GetLookAheadToken(2).is(tok::l_paren))
         goto DoneWithDeclSpec;
@@ -650,8 +657,15 @@
       TypeTy *TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(),
                                             Next.getLocation(), CurScope, &SS);
 
-      if (TypeRep == 0)
+      // If the referenced identifier is not a type, then this declspec is
+      // erroneous: We already checked about that it has no type specifier, and
+      // C++ doesn't have implicit int.  Diagnose it as a typo w.r.t. to the
+      // typename.  
+      if (TypeRep == 0) {
+        ConsumeToken();   // Eat the scope spec so the identifier is current.
+        if (ParseImplicitInt(DS, &SS, TemplateParams, AS)) continue;
         goto DoneWithDeclSpec;
+      }
       
       ConsumeToken(); // The C++ scope.
 
@@ -711,7 +725,7 @@
       // If this is not a typedef name, don't parse it as part of the declspec,
       // it must be an implicit int or an error.
       if (TypeRep == 0) {
-        if (ParseImplicitInt(DS, TemplateParams, AS)) continue;
+        if (ParseImplicitInt(DS, 0, TemplateParams, AS)) continue;
         goto DoneWithDeclSpec;
       }
 

Modified: cfe/trunk/test/SemaCXX/namespace.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/namespace.cpp?rev=69086&r1=69085&r2=69086&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/namespace.cpp (original)
+++ cfe/trunk/test/SemaCXX/namespace.cpp Tue Apr 14 17:17:06 2009
@@ -56,3 +56,14 @@
 }
 
 namespace B {} // expected-error {{redefinition of 'B' as different kind of symbol}}
+
+
+namespace foo {
+  enum x {
+    Y
+  };
+}
+
+static foo::x  test1;  // ok
+
+static foo::X  test2;  // typo: expected-error {{unknown type name 'X'}}

Modified: cfe/trunk/test/SemaCXX/nested-name-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/nested-name-spec.cpp?rev=69086&r1=69085&r2=69086&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/nested-name-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/nested-name-spec.cpp Tue Apr 14 17:17:06 2009
@@ -13,8 +13,8 @@
 }
 
 A:: ; // expected-error {{expected unqualified-id}}
-::A::ax::undef ex3; // expected-error {{expected a class or namespace}} expected-error {{invalid token after top level declarator}}
-A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}} expected-error {{invalid token after top level declarator}}
+::A::ax::undef ex3; // expected-error {{expected a class or namespace}} expected-error {{unknown type name 'undef'}}
+A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}} expected-error {{unknown type name 'undef2'}}
 
 int A::C::Ag1() { return 0; }
 
@@ -166,7 +166,7 @@
 
 struct Y;  // expected-note{{forward declaration of 'struct Y'}}
 Y::foo y; // expected-error{{incomplete type 'struct Y' named in nested name specifier}} \
-         // FIXME: ugly: expected-error{{invalid token after top level declarator}}
+         // expected-error{{unknown type name 'foo'}}
 
 X::X() : a(5) { } // expected-error{{use of undeclared identifier 'X'}} \
       // expected-error{{C++ requires a type specifier for all declarations}} \

Modified: cfe/trunk/test/SemaTemplate/instantiate-typedef.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-typedef.cpp?rev=69086&r1=69085&r2=69086&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-typedef.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-typedef.cpp Tue Apr 14 17:17:06 2009
@@ -11,5 +11,5 @@
   return ptr; // expected-error{{incompatible type returning 'int *', expected 'add_pointer<float>::type' (aka 'float *')}}
 }
 
-add_pointer<int&>::type // expected-note{{in instantiation of template class 'struct add_pointer<int &>' requested here}}
-test3(); // FIXME: expected-error{{invalid token after top level declarator}}
+add_pointer<int&>::type // expected-note{{in instantiation of template class 'struct add_pointer<int &>' requested here}} expected-error {{unknown type name 'type'}}
+test3(); 

Modified: cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp?rev=69086&r1=69085&r2=69086&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp Tue Apr 14 17:17:06 2009
@@ -2,7 +2,7 @@
 
 namespace N { 
   namespace M {
-    template<typename T> struct Promote; // expected-note{{previous definition is here}}
+    template<typename T> struct Promote;
     
     template<> struct Promote<short> {
       typedef int type;
@@ -32,8 +32,7 @@
                // expected-error{{expected unqualified-id}}
 
 N::M::template Promote; // expected-error{{expected '<' after 'template Promote' in nested name specifier}} \
-// expected-error{{C++ requires a type specifier for all declarations}} \
-// expected-error{{redefinition of 'Promote' as different kind of symbol}}
+// expected-error{{C++ requires a type specifier for all declarations}}
 
 namespace N {
   template<typename T> struct A;

Modified: cfe/trunk/test/SemaTemplate/typename-specifier.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/typename-specifier.cpp?rev=69086&r1=69085&r2=69086&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/typename-specifier.cpp (original)
+++ cfe/trunk/test/SemaTemplate/typename-specifier.cpp Tue Apr 14 17:17:06 2009
@@ -42,12 +42,12 @@
 
 N::X<N::A>::type *ip4 = &i;
 N::X<N::B>::type *ip5 = &i; // expected-note{{in instantiation of template class 'struct N::X<struct N::B>' requested here}} \
-// FIXME: expected-error{{invalid token after top level declarator}}
+// expected-error{{unknown type name 'type'}}
 N::X<N::C>::type *ip6 = &i; // expected-note{{in instantiation of template class 'struct N::X<struct N::C>' requested here}} \
-// FIXME: expected-error{{invalid token after top level declarator}}
+// expected-error{{unknown type name 'type'}}
 
 N::X<int>::type fail1; // expected-note{{in instantiation of template class 'struct N::X<int>' requested here}} \
-// FIXME: expected-error{{invalid token after top level declarator}}
+// expected-error{{unknown type name 'type'}}
 
 template<typename T>
 struct Y {
@@ -69,6 +69,6 @@
 
 ::Y<A>::type ip7 = &i;
 ::Y<B>::type ip8 = &i; // expected-note{{in instantiation of template class 'struct Y<struct B>' requested here}} \
-// FIXME: expected-error{{invalid token after top level declarator}}
+// expected-error{{unknown type name 'type'}}
 ::Y<C>::type ip9 = &i; // expected-note{{in instantiation of template class 'struct Y<struct C>' requested here}} \
-// FIXME: expected-error{{invalid token after top level declarator}}
+// expected-error{{unknown type name 'type'}}





More information about the cfe-commits mailing list