diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-10-05 15:03:47 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-10-05 15:03:47 +0000 |
commit | 71f3e19df07e179f41e891abbd8c100df486aace (patch) | |
tree | f3039524d15a3bad270b6330861ef262298a8e79 | |
parent | 7b87f2743880efa3ab5887f403b3f391140841a6 (diff) | |
download | bcm5719-llvm-71f3e19df07e179f41e891abbd8c100df486aace.tar.gz bcm5719-llvm-71f3e19df07e179f41e891abbd8c100df486aace.zip |
Disambiguate between a declaration or expression for the 'condition' part of a if/switch/while/for statement.
llvm-svn: 57109
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 6 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 54 | ||||
-rw-r--r-- | clang/test/SemaCXX/decl-expr-ambiguity.cpp | 1 |
4 files changed, 62 insertions, 1 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index aa49530b0e1..df5e59fda93 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/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/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 28071b6e29d..8b4db309508 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/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/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 5e4888f6990..95512a62693 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/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/clang/test/SemaCXX/decl-expr-ambiguity.cpp b/clang/test/SemaCXX/decl-expr-ambiguity.cpp index 48e132097e4..5b4ddbea0b8 100644 --- a/clang/test/SemaCXX/decl-expr-ambiguity.cpp +++ b/clang/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)<<a; // expected-error {{function-style cast to a builtin type can only take one argument}} void(a), ++a; // expected-warning {{statement was disambiguated as expression}} expected-warning {{expression result unused}} + if (int(a)+1) {} // Declarations. T(*d)(int(p)); // expected-warning {{statement was disambiguated as declaration}} expected-error {{previous definition is here}} |