[cfe-commits] r146953 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseStmt.cpp lib/Parse/ParseTentative.cpp test/SemaCXX/for-range-no-std.cpp
Eli Friedman
eli.friedman at gmail.com
Mon Dec 19 17:50:37 PST 2011
Author: efriedma
Date: Mon Dec 19 19:50:37 2011
New Revision: 146953
URL: http://llvm.org/viewvc/llvm-project?rev=146953&view=rev
Log:
Fix tentative parsing so it knows how to handle an ambiguous for-range-declaration. PR11601.
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Parse/ParseTentative.cpp
cfe/trunk/test/SemaCXX/for-range-no-std.cpp
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=146953&r1=146952&r2=146953&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Dec 19 19:50:37 2011
@@ -1683,13 +1683,13 @@
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 @@
/// 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 @@
// 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();
Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=146953&r1=146952&r2=146953&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Mon Dec 19 19:50:37 2011
@@ -1306,7 +1306,7 @@
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);
Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=146953&r1=146952&r2=146953&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Mon Dec 19 19:50:37 2011
@@ -62,7 +62,7 @@
return true;
// simple-declaration
default:
- return isCXXSimpleDeclaration();
+ return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);
}
}
@@ -75,7 +75,11 @@
/// 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 @@
// 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 @@
/// 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 @@
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();
Modified: cfe/trunk/test/SemaCXX/for-range-no-std.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/for-range-no-std.cpp?rev=146953&r1=146952&r2=146953&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/for-range-no-std.cpp (original)
+++ cfe/trunk/test/SemaCXX/for-range-no-std.cpp Mon Dec 19 19:50:37 2011
@@ -36,3 +36,8 @@
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();
+}
More information about the cfe-commits
mailing list