diff options
author | John McCall <rjmccall@apple.com> | 2011-07-27 21:50:02 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-07-27 21:50:02 +0000 |
commit | d9bb743e0d343b3a199e218368b33f52f4886a72 (patch) | |
tree | f5328f00546cc49004c1f10f5d5a71e97bd1b0d4 /clang/lib/Parse/ParseObjc.cpp | |
parent | a94a1544d8d0ae7b54b5a78300e46e81b267e2f9 (diff) | |
download | bcm5719-llvm-d9bb743e0d343b3a199e218368b33f52f4886a72.tar.gz bcm5719-llvm-d9bb743e0d343b3a199e218368b33f52f4886a72.zip |
The lock operand to an @synchronized statement is also
supposed to be a full-expression; make it so. In ARC, make sure
we retain the lock for the entire protected block.
llvm-svn: 136271
Diffstat (limited to 'clang/lib/Parse/ParseObjc.cpp')
-rw-r--r-- | clang/lib/Parse/ParseObjc.cpp | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index ff9e20504ba..c8b2a09d5ea 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -1560,31 +1560,46 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { Diag(Tok, diag::err_expected_lparen_after) << "@synchronized"; return StmtError(); } + + // The operand is surrounded with parentheses. ConsumeParen(); // '(' - ExprResult Res(ParseExpression()); - if (Res.isInvalid()) { - SkipUntil(tok::semi); - return StmtError(); - } - if (Tok.isNot(tok::r_paren)) { - Diag(Tok, diag::err_expected_lbrace); - return StmtError(); + ExprResult operand(ParseExpression()); + + if (Tok.is(tok::r_paren)) { + ConsumeParen(); // ')' + } else { + if (!operand.isInvalid()) + Diag(Tok, diag::err_expected_rparen); + + // Skip forward until we see a left brace, but don't consume it. + SkipUntil(tok::l_brace, true, true); } - ConsumeParen(); // ')' + + // Require a compound statement. if (Tok.isNot(tok::l_brace)) { - Diag(Tok, diag::err_expected_lbrace); + if (!operand.isInvalid()) + Diag(Tok, diag::err_expected_lbrace); return StmtError(); } - // Enter a scope to hold everything within the compound stmt. Compound - // statements can always hold declarations. - ParseScope BodyScope(this, Scope::DeclScope); - StmtResult SynchBody(ParseCompoundStatementBody()); + // Check the @synchronized operand now. + if (!operand.isInvalid()) + operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.take()); - BodyScope.Exit(); - if (SynchBody.isInvalid()) - SynchBody = Actions.ActOnNullStmt(Tok.getLocation()); - return Actions.ActOnObjCAtSynchronizedStmt(atLoc, Res.take(), SynchBody.take()); + // Parse the compound statement within a new scope. + ParseScope bodyScope(this, Scope::DeclScope); + StmtResult body(ParseCompoundStatementBody()); + bodyScope.Exit(); + + // If there was a semantic or parse error earlier with the + // operand, fail now. + if (operand.isInvalid()) + return StmtError(); + + if (body.isInvalid()) + body = Actions.ActOnNullStmt(Tok.getLocation()); + + return Actions.ActOnObjCAtSynchronizedStmt(atLoc, operand.get(), body.get()); } /// objc-try-catch-statement: |