forked from OSchip/llvm-project
Fix tentative parsing so it knows how to handle an ambiguous for-range-declaration. PR11601.
llvm-svn: 146953
This commit is contained in:
parent
bc40eef82b
commit
0ffc31c55b
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue