summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2008-10-05 15:03:47 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2008-10-05 15:03:47 +0000
commit71f3e19df07e179f41e891abbd8c100df486aace (patch)
treef3039524d15a3bad270b6330861ef262298a8e79
parent7b87f2743880efa3ab5887f403b3f391140841a6 (diff)
downloadbcm5719-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.h6
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp2
-rw-r--r--clang/lib/Parse/ParseTentative.cpp54
-rw-r--r--clang/test/SemaCXX/decl-expr-ambiguity.cpp1
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}}
OpenPOWER on IntegriCloud