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 | 07524039dce5c820f111a1b3f772b4261f004b4a (patch) | |
tree | a796032fe9a98b7216910a08f50a405fa2ec9847 /lib/Parse/ParseObjc.cpp | |
parent | a2ee20aa9660851080135219cac5b31fbac08b78 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136271 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseObjc.cpp')
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index ff9e20504b..c8b2a09d5e 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/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: |