From: Argyrios Kyrtzidis Date: Sun, 5 Oct 2008 15:03:47 +0000 (+0000) Subject: Disambiguate between a declaration or expression for the 'condition' part of a if... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a8a4598b6f2a07339ab8a1248295a07d771a2b2a;p=clang Disambiguate between a declaration or expression for the 'condition' part of a if/switch/while/for statement. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57109 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index aa49530b0e..df5e59fda9 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -610,6 +610,12 @@ private: /// the function returns true to let the declaration parsing code handle it. bool isCXXFunctionDeclarator(); + /// isCXXConditionDeclaration - Disambiguates between a declaration or an + /// expression for a condition of a if/switch/while/for statement. + /// If during the disambiguation process a parsing error is encountered, + /// the function returns true to let the declaration parsing code handle it. + bool isCXXConditionDeclaration(); + /// isCXXDeclarationSpecifier - Returns TPR_true if it is a declaration /// specifier, TPR_false if it is not, TPR_ambiguous if it could be either /// a decl-specifier or a function-style cast, and TPR_error if a parsing diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 28071b6e29..8b4db30950 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -162,7 +162,7 @@ Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { /// '=' assignment-expression /// Parser::ExprResult Parser::ParseCXXCondition() { - if (!isDeclarationSpecifier()) + if (!isCXXConditionDeclaration()) return ParseExpression(); // expression SourceLocation StartLoc = Tok.getLocation(); diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 5e4888f699..95512a6269 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -225,6 +225,60 @@ Parser::TentativeParsingResult Parser::TryParseInitDeclaratorList() { return TPR_ambiguous; } +/// isCXXConditionDeclaration - Disambiguates between a declaration or an +/// expression for a condition of a if/switch/while/for statement. +/// If during the disambiguation process a parsing error is encountered, +/// the function returns true to let the declaration parsing code handle it. +/// +/// condition: +/// expression +/// type-specifier-seq declarator '=' assignment-expression +/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] +/// '=' assignment-expression +/// +bool Parser::isCXXConditionDeclaration() { + TentativeParsingResult TPR = isCXXDeclarationSpecifier(); + if (TPR != TPR_ambiguous) + return TPR != TPR_false; // Returns true for TPR_true or TPR_error. + + // 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... + + TentativeParsingAction PA(*this); + + // type-specifier-seq + if (Tok.is(tok::kw_typeof)) + TryParseTypeofSpecifier(); + else + ConsumeToken(); + assert(Tok.is(tok::l_paren) && "Expected '('"); + + // declarator + TPR = TryParseDeclarator(false/*mayBeAbstract*/); + + PA.Revert(); + + // In case of an error, let the declaration parsing code handle it. + if (TPR == TPR_error) + return true; + + if (TPR == TPR_ambiguous) { + // '=' + // [GNU] simple-asm-expr[opt] attributes[opt] + if (Tok.is(tok::equal) || + Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) + TPR = TPR_true; + else + TPR = TPR_false; + } + + assert(TPR == TPR_true || TPR == TPR_false); + return TPR == TPR_true; +} + /// declarator: /// direct-declarator /// ptr-operator declarator diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp index 48e132097e..5b4ddbea0b 100644 --- a/test/SemaCXX/decl-expr-ambiguity.cpp +++ b/test/SemaCXX/decl-expr-ambiguity.cpp @@ -11,6 +11,7 @@ void f() { __extension__ int(a)++; // expected-error {{invalid lvalue in increment/decrement expression}} typeof(int)(a,5)<