[cfe-commits] r162464 - in /cfe/trunk: lib/Parse/ParseTentative.cpp test/CXX/class.access/class.friend/p1.cpp test/Modules/module-private.cpp test/Parser/cxx-ambig-decl-expr.cpp test/SemaObjCXX/category-lookup.mm

Richard Smith richard-llvm at metafoo.co.uk
Thu Aug 23 13:19:14 PDT 2012


Author: rsmith
Date: Thu Aug 23 15:19:14 2012
New Revision: 162464

URL: http://llvm.org/viewvc/llvm-project?rev=162464&view=rev
Log:
When disambiguating an expression-statement from a declaraton-statement, if the
statement starts with an identifier for which name lookup will fail either way,
look at later tokens to disambiguate in order to improve error recovery.

Modified:
    cfe/trunk/lib/Parse/ParseTentative.cpp
    cfe/trunk/test/CXX/class.access/class.friend/p1.cpp
    cfe/trunk/test/Modules/module-private.cpp
    cfe/trunk/test/Parser/cxx-ambig-decl-expr.cpp
    cfe/trunk/test/SemaObjCXX/category-lookup.mm

Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=162464&r1=162463&r2=162464&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Thu Aug 23 15:19:14 2012
@@ -104,16 +104,27 @@
   // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
   // a case.
 
-  TPResult TPR = isCXXDeclarationSpecifier();
+  bool InvalidAsDeclaration = false;
+  TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),
+                                           &InvalidAsDeclaration);
   if (TPR != TPResult::Ambiguous())
     return TPR != TPResult::False(); // Returns true for TPResult::True() or
                                      // TPResult::Error().
 
+  // FIXME: TryParseSimpleDeclaration doesn't look past the first initializer,
+  // and so gets some cases wrong. We can't carry on if we've already seen
+  // something which makes this statement invalid as a declaration in this case,
+  // since it can cause us to misparse valid code. Revisit this once
+  // TryParseInitDeclaratorList is fixed.
+  if (InvalidAsDeclaration)
+    return false;
+
   // FIXME: Add statistics about the number of ambiguous statements encountered
   // and how they were resolved (number of declarations+number of expressions).
 
-  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
-  // We need tentative parsing...
+  // Ok, we have a simple-type-specifier/typename-specifier followed by a '(',
+  // or an identifier which doesn't resolve as anything. We need tentative
+  // parsing...
 
   TentativeParsingAction PA(*this);
   TPR = TryParseSimpleDeclaration(AllowForRangeDecl);
@@ -140,20 +151,28 @@
 ///    attribute-specifier-seqopt type-specifier-seq declarator
 ///
 Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
-  // We know that we have a simple-type-specifier/typename-specifier followed
-  // by a '('.
-  assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous());
-
   if (Tok.is(tok::kw_typeof))
     TryParseTypeofSpecifier();
   else {
+    if (Tok.is(tok::annot_cxxscope))
+      ConsumeToken();
     ConsumeToken();
-    
+
     if (getLangOpts().ObjC1 && Tok.is(tok::less))
       TryParseProtocolQualifiers();
   }
-  
-  assert(Tok.is(tok::l_paren) && "Expected '('");
+
+  // Two decl-specifiers in a row conclusively disambiguate this as being a
+  // simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the
+  // overwhelmingly common case that the next token is a '('.
+  if (Tok.isNot(tok::l_paren)) {
+    TPResult TPR = isCXXDeclarationSpecifier();
+    if (TPR == TPResult::Ambiguous())
+      return TPResult::True();
+    if (TPR == TPResult::True() || TPR == TPResult::Error())
+      return TPR;
+    assert(TPR == TPResult::False());
+  }
 
   TPResult TPR = TryParseInitDeclaratorList();
   if (TPR != TPResult::Ambiguous())

Modified: cfe/trunk/test/CXX/class.access/class.friend/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/class.friend/p1.cpp?rev=162464&r1=162463&r2=162464&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/class.friend/p1.cpp (original)
+++ cfe/trunk/test/CXX/class.access/class.friend/p1.cpp Thu Aug 23 15:19:14 2012
@@ -20,7 +20,7 @@
   g()->f();
   S::f();
   X::g(); // expected-error{{no member named 'g' in 'X'}}
-  X::S x_s; // expected-error{{no member named 'S' in 'X'}}
+  X::S x_s; // expected-error{{no type named 'S' in 'X'}}
   X x;
   x.g(); // expected-error{{no member named 'g' in 'X'}}
 }
@@ -44,16 +44,16 @@
     S s;
     S::f();
     X::g(); // expected-error{{no member named 'g' in 'N::X'}}
-    X::S x_s; // expected-error{{no member named 'S' in 'N::X'}}
+    X::S x_s; // expected-error{{no type named 'S' in 'N::X'}}
     X x;
     x.g(); // expected-error{{no member named 'g' in 'N::X'}}
 
     g2();
     S2 s2;
     ::g2(); // expected-error{{no member named 'g2' in the global namespace}}
-    ::S2 g_s2; // expected-error{{no member named 'S2' in the global namespace}}
+    ::S2 g_s2; // expected-error{{no type named 'S2' in the global namespace}}
     X::g2(); // expected-error{{no member named 'g2' in 'N::X'}}
-    X::S2 x_s2; // expected-error{{no member named 'S2' in 'N::X'}}
+    X::S2 x_s2; // expected-error{{no type named 'S2' in 'N::X'}}
     x.g2(); // expected-error{{no member named 'g2' in 'N::X'}}
   }
 }

Modified: cfe/trunk/test/Modules/module-private.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/module-private.cpp?rev=162464&r1=162463&r2=162464&view=diff
==============================================================================
--- cfe/trunk/test/Modules/module-private.cpp (original)
+++ cfe/trunk/test/Modules/module-private.cpp Thu Aug 23 15:19:14 2012
@@ -12,9 +12,12 @@
 }
 
 int test_broken() {
-  HiddenStruct hidden; // expected-error{{use of undeclared identifier 'HiddenStruct'}}
+  HiddenStruct hidden; // \
+  // expected-error{{must use 'struct' tag to refer to type 'HiddenStruct' in this scope}} \
+  // expected-error{{definition of 'struct HiddenStruct' must be imported}}
+  // expected-note at 3 {{previous definition is here}}
 
-  Integer i; // expected-error{{use of undeclared identifier 'Integer'}}
+  Integer i; // expected-error{{unknown type name 'Integer'}}
 
   int *ip = 0;
   f1(ip); // expected-error{{use of undeclared identifier 'f1'}}

Modified: cfe/trunk/test/Parser/cxx-ambig-decl-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-ambig-decl-expr.cpp?rev=162464&r1=162463&r2=162464&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-ambig-decl-expr.cpp (original)
+++ cfe/trunk/test/Parser/cxx-ambig-decl-expr.cpp Thu Aug 23 15:19:14 2012
@@ -7,4 +7,7 @@
 
 void f() {
   void (*ptr)(int, int) = &X::f<int, int>;
+
+  unknown *p = 0; // expected-error {{unknown type name 'unknown'}}
+  unknown * p + 0; // expected-error {{undeclared identifier 'unknown'}}
 }

Modified: cfe/trunk/test/SemaObjCXX/category-lookup.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/category-lookup.mm?rev=162464&r1=162463&r2=162464&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/category-lookup.mm (original)
+++ cfe/trunk/test/SemaObjCXX/category-lookup.mm Thu Aug 23 15:19:14 2012
@@ -6,5 +6,5 @@
 @end
 
 void f() {
-  NSScriptClassDescription *f; // expected-error {{use of undeclared identifier 'NSScriptClassDescription'}}
+  NSScriptClassDescription *f; // expected-error {{unknown type name 'NSScriptClassDescription'}}
 }





More information about the cfe-commits mailing list