]> granicus.if.org Git - clang/commitdiff
Enter an expression evaluation context when parsing
authorJohn McCall <rjmccall@apple.com>
Wed, 4 Apr 2012 01:27:53 +0000 (01:27 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 4 Apr 2012 01:27:53 +0000 (01:27 +0000)
statement-expressions.  Prevents cleanups and such from being
claimed by the first full-expression in the block.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153989 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Parse/ParseExpr.cpp
lib/Sema/SemaExpr.cpp
test/CodeGenObjC/arc-blocks.m

index 747feaab30c0fd1d8ae7263ea180f382989580ca..d45a14b5facc72d4faf729a43af5037c3df225f5 100644 (file)
@@ -2802,8 +2802,10 @@ public:
   ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
                             LabelDecl *TheDecl);
 
+  void ActOnStartStmtExpr();
   ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
                            SourceLocation RPLoc); // "({..})"
+  void ActOnStmtExprError();
 
   // __builtin_offsetof(type, identifier(.identifier|[expr])*)
   struct OffsetOfComponent {
index 888e84f2532754fcf6db4d45590c51909520c0f9..752e5c502d4b6b47e05f61930527605adec8c2b8 100644 (file)
@@ -1917,13 +1917,19 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
   // unless they've already reported an error.
   if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
     Diag(Tok, diag::ext_gnu_statement_expr);
+
+    Actions.ActOnStartStmtExpr();
+
     ParsedAttributes attrs(AttrFactory);
     StmtResult Stmt(ParseCompoundStatement(attrs, true));
     ExprType = CompoundStmt;
 
     // If the substmt parsed correctly, build the AST node.
-    if (!Stmt.isInvalid())
+    if (!Stmt.isInvalid()) {
       Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.take(), Tok.getLocation());
+    } else {
+      Actions.ActOnStmtExprError();
+    }
   } else if (ExprType >= CompoundLiteral && BridgeCast) {
     tok::TokenKind tokenKind = Tok.getKind();
     SourceLocation BridgeKeywordLoc = ConsumeToken();
index d424f388f6355f7d3145d3dec9fa9bbb419a93e9..9339c04c51390a90951644c620d7d29243a03783 100644 (file)
@@ -8546,12 +8546,26 @@ static Expr *maybeRebuildARCConsumingStmt(Stmt *Statement) {
   return cleanups;
 }
 
+void Sema::ActOnStartStmtExpr() {
+  PushExpressionEvaluationContext(ExprEvalContexts.back().Context);
+}
+
+void Sema::ActOnStmtExprError() {
+  DiscardCleanupsInEvaluationContext();
+  PopExpressionEvaluationContext();
+}
+
 ExprResult
 Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
                     SourceLocation RPLoc) { // "({..})"
   assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
   CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
 
+  if (hasAnyUnrecoverableErrorsInThisFunction())
+    DiscardCleanupsInEvaluationContext();
+  assert(!ExprNeedsCleanups && "cleanups within StmtExpr not correctly bound!");
+  PopExpressionEvaluationContext();
+
   bool isFileScope
     = (getCurFunctionOrMethodDecl() == 0) && (getCurBlock() == 0);
   if (isFileScope)
index bde5ec3747696712fee7caa2bc4bbc9e5e69f49b..06acf01ce0f739e001af88bc6cdd11a5ceefa786 100644 (file)
@@ -514,3 +514,10 @@ void test13(id x) {
 void test14() {
   void (^const x[1])(void) = { ^{} };
 }
+
+// rdar://11149025
+// Don't make invalid ASTs and crash.
+void test15_helper(void (^block)(void), int x);
+void test15(int a) {
+  test15_helper(^{ (void) a; }, ({ a; }));
+}