]> granicus.if.org Git - clang/commitdiff
Fix tentative parsing so it knows how to handle an ambiguous for-range-declaration...
authorEli Friedman <eli.friedman@gmail.com>
Tue, 20 Dec 2011 01:50:37 +0000 (01:50 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 20 Dec 2011 01:50:37 +0000 (01:50 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146953 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseStmt.cpp
lib/Parse/ParseTentative.cpp
test/SemaCXX/for-range-no-std.cpp

index 07d21bfeed0890fa07133ea274532a9516740d4d..e4318375af0861e7296a912c1a28dcc49af309ea 100644 (file)
@@ -1683,13 +1683,13 @@ private:
     return isDeclarationSpecifier(true);
   }
 
-  /// isSimpleDeclaration - Disambiguates between a declaration or an
-  /// expression, mainly used for the C 'clause-1' or the C++
+  /// isForInitDeclaration - Disambiguates between a declaration or an
+  /// expression in the context of the C 'clause-1' or the C++
   // 'for-init-statement' part of a 'for' statement.
   /// Returns true for declaration, false for expression.
-  bool isSimpleDeclaration() {
+  bool isForInitDeclaration() {
     if (getLang().CPlusPlus)
-      return isCXXSimpleDeclaration();
+      return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/true);
     return isDeclarationSpecifier(true);
   }
 
@@ -1734,7 +1734,7 @@ private:
   /// If during the disambiguation process a parsing error is encountered,
   /// the function returns true to let the declaration parsing code handle it.
   /// Returns false if the statement is disambiguated as expression.
-  bool isCXXSimpleDeclaration();
+  bool isCXXSimpleDeclaration(bool AllowForRangeDecl);
 
   /// isCXXFunctionDeclarator - Disambiguates between a function declarator or
   /// a constructor-style initializer, when parsing declaration statements.
@@ -1808,7 +1808,7 @@ private:
   // They all consume tokens, so backtracking should be used after calling them.
 
   TPResult TryParseDeclarationSpecifier();
-  TPResult TryParseSimpleDeclaration();
+  TPResult TryParseSimpleDeclaration(bool AllowForRangeDecl);
   TPResult TryParseTypeofSpecifier();
   TPResult TryParseProtocolQualifiers();
   TPResult TryParseInitDeclaratorList();
index da0e865862cc4de9b6e886f078f245d5ef5835b8..435bde33753c424cc66419c7097ae3d7efaaa158 100644 (file)
@@ -1306,7 +1306,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) {
   if (Tok.is(tok::semi)) {  // for (;
     // no first part, eat the ';'.
     ConsumeToken();
-  } else if (isSimpleDeclaration()) {  // for (int X = 4;
+  } else if (isForInitDeclaration()) {  // for (int X = 4;
     // Parse declaration, which eats the ';'.
     if (!C99orCXXorObjC)   // Use of C99-style for loops in C90 mode?
       Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
index 7c280ff50be9e1937648c48c9b1edab05eab18c3..2c9018316a6eb5c3b3d3d0a73851117bafbd2b84 100644 (file)
@@ -62,7 +62,7 @@ bool Parser::isCXXDeclarationStatement() {
     return true;
     // simple-declaration
   default:
-    return isCXXSimpleDeclaration();
+    return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);
   }
 }
 
@@ -75,7 +75,11 @@ bool Parser::isCXXDeclarationStatement() {
 /// simple-declaration:
 ///   decl-specifier-seq init-declarator-list[opt] ';'
 ///
-bool Parser::isCXXSimpleDeclaration() {
+/// (if AllowForRangeDecl specified)
+/// for ( for-range-declaration : for-range-initializer ) statement
+/// for-range-declaration: 
+///    attribute-specifier-seqopt type-specifier-seq declarator
+bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
   // C++ 6.8p1:
   // There is an ambiguity in the grammar involving expression-statements and
   // declarations: An expression-statement with a function-style explicit type
@@ -112,7 +116,7 @@ bool Parser::isCXXSimpleDeclaration() {
   // We need tentative parsing...
 
   TentativeParsingAction PA(*this);
-  TPR = TryParseSimpleDeclaration();
+  TPR = TryParseSimpleDeclaration(AllowForRangeDecl);
   PA.Revert();
 
   // In case of an error, let the declaration parsing code handle it.
@@ -130,7 +134,12 @@ bool Parser::isCXXSimpleDeclaration() {
 /// simple-declaration:
 ///   decl-specifier-seq init-declarator-list[opt] ';'
 ///
-Parser::TPResult Parser::TryParseSimpleDeclaration() {
+/// (if AllowForRangeDecl specified)
+/// for ( for-range-declaration : for-range-initializer ) statement
+/// for-range-declaration: 
+///    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());
@@ -150,7 +159,7 @@ Parser::TPResult Parser::TryParseSimpleDeclaration() {
   if (TPR != TPResult::Ambiguous())
     return TPR;
 
-  if (Tok.isNot(tok::semi))
+  if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))
     return TPResult::False();
 
   return TPResult::Ambiguous();
index b4b34ee54e3c2f2706c48ad95ca6077a05e23bfd..fa42ca45a58fb423f81c55531b02a2162046c938 100644 (file)
@@ -36,3 +36,8 @@ void f() {
   for (int b : NS::ADL()) {} // ok
   for (int b : NS::NoADL()) {} // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}}
 }
+
+void PR11601() {
+  void (*vv[])() = {PR11601, PR11601, PR11601};
+  for (void (*i)() : vv) i();
+}