r183699 - Make sure we don't emit invalid IR for StmtExprs with complex cleanups.

Eli Friedman eli.friedman at gmail.com
Mon Jun 10 15:04:49 PDT 2013


Author: efriedma
Date: Mon Jun 10 17:04:49 2013
New Revision: 183699

URL: http://llvm.org/viewvc/llvm-project?rev=183699&view=rev
Log:
Make sure we don't emit invalid IR for StmtExprs with complex cleanups.

Fixes <rdar://problem/14074868>.


Modified:
    cfe/trunk/lib/CodeGen/CGExprComplex.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGenCXX/stmtexpr.cpp
    cfe/trunk/test/CodeGenObjC/arc.m

Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=183699&r1=183698&r2=183699&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Mon Jun 10 17:04:49 2013
@@ -358,7 +358,9 @@ ComplexPairTy ComplexExprEmitter::VisitC
 
 ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) {
   CodeGenFunction::StmtExprEvaluation eval(CGF);
-  return CGF.EmitCompoundStmt(*E->getSubStmt(), true).getComplexVal();
+  llvm::Value *RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(), true);
+  assert(RetAlloca && "Expected complex return value");
+  return EmitLoadOfLValue(CGF.MakeAddrLValue(RetAlloca, E->getType()));
 }
 
 /// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=183699&r1=183698&r2=183699&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Jun 10 17:04:49 2013
@@ -1442,8 +1442,12 @@ Value *ScalarExprEmitter::VisitCastExpr(
 
 Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) {
   CodeGenFunction::StmtExprEvaluation eval(CGF);
-  return CGF.EmitCompoundStmt(*E->getSubStmt(), !E->getType()->isVoidType())
-    .getScalarVal();
+  llvm::Value *RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(),
+                                                !E->getType()->isVoidType());
+  if (!RetAlloca)
+    return 0;
+  return CGF.EmitLoadOfScalar(CGF.MakeAddrLValue(RetAlloca, E->getType()));
+
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=183699&r1=183698&r2=183699&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Mon Jun 10 17:04:49 2013
@@ -196,8 +196,8 @@ bool CodeGenFunction::EmitSimpleStmt(con
 /// EmitCompoundStmt - Emit a compound statement {..} node.  If GetLast is true,
 /// this captures the expression result of the last sub-statement and returns it
 /// (for use by the statement expression extension).
-RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
-                                         AggValueSlot AggSlot) {
+llvm::Value* CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
+                                               AggValueSlot AggSlot) {
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),S.getLBracLoc(),
                              "LLVM IR generation of compound statement ('{}')");
 
@@ -207,17 +207,17 @@ RValue CodeGenFunction::EmitCompoundStmt
   return EmitCompoundStmtWithoutScope(S, GetLast, AggSlot);
 }
 
-RValue CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast,
-                                         AggValueSlot AggSlot) {
+llvm::Value*
+CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S,
+                                              bool GetLast,
+                                              AggValueSlot AggSlot) {
 
   for (CompoundStmt::const_body_iterator I = S.body_begin(),
        E = S.body_end()-GetLast; I != E; ++I)
     EmitStmt(*I);
 
-  RValue RV;
-  if (!GetLast)
-    RV = RValue::get(0);
-  else {
+  llvm::Value *RetAlloca = 0;
+  if (GetLast) {
     // We have to special case labels here.  They are statements, but when put
     // at the end of a statement expression, they yield the value of their
     // subexpression.  Handle this by walking through all labels we encounter,
@@ -230,10 +230,21 @@ RValue CodeGenFunction::EmitCompoundStmt
 
     EnsureInsertPoint();
 
-    RV = EmitAnyExpr(cast<Expr>(LastStmt), AggSlot);
+    QualType ExprTy = cast<Expr>(LastStmt)->getType();
+    if (hasAggregateEvaluationKind(ExprTy)) {
+      EmitAggExpr(cast<Expr>(LastStmt), AggSlot);
+    } else {
+      // We can't return an RValue here because there might be cleanups at
+      // the end of the StmtExpr.  Because of that, we have to emit the result
+      // here into a temporary alloca.
+      RetAlloca = CreateMemTemp(ExprTy);
+      EmitAnyExprToMem(cast<Expr>(LastStmt), RetAlloca, Qualifiers(),
+                       /*IsInit*/false);
+    }
+      
   }
 
-  return RV;
+  return RetAlloca;
 }
 
 void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) {

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=183699&r1=183698&r2=183699&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Jun 10 17:04:49 2013
@@ -1767,11 +1767,12 @@ public:
   /// \return True if the statement was handled.
   bool EmitSimpleStmt(const Stmt *S);
 
-  RValue EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
-                          AggValueSlot AVS = AggValueSlot::ignored());
-  RValue EmitCompoundStmtWithoutScope(const CompoundStmt &S,
-                                      bool GetLast = false, AggValueSlot AVS =
-                                          AggValueSlot::ignored());
+  llvm::Value *EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
+                                AggValueSlot AVS = AggValueSlot::ignored());
+  llvm::Value *EmitCompoundStmtWithoutScope(const CompoundStmt &S,
+                                            bool GetLast = false,
+                                            AggValueSlot AVS =
+                                                AggValueSlot::ignored());
 
   /// EmitLabel - Emit the block for the given label. It is legal to call this
   /// function even if there is no current insertion point.

Modified: cfe/trunk/test/CodeGenCXX/stmtexpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/stmtexpr.cpp?rev=183699&r1=183698&r2=183699&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/stmtexpr.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/stmtexpr.cpp Mon Jun 10 17:04:49 2013
@@ -73,3 +73,10 @@ int* foo5() {
   return (({ a; }));
 }
 
+// <rdar://problem/14074868>
+// Make sure this doesn't crash.
+int foo5(bool b) {
+  int y = 0;
+  y = ({ A a(1); if (b) goto G; a.i; });
+  G: return y;
+}

Modified: cfe/trunk/test/CodeGenObjC/arc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=183699&r1=183698&r2=183699&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/arc.m (original)
+++ cfe/trunk/test/CodeGenObjC/arc.m Mon Jun 10 17:04:49 2013
@@ -1115,11 +1115,14 @@ id test52(void) {
 
 // CHECK:    define i8* @test52()
 // CHECK:      [[X:%.*]] = alloca i32
+// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca i8*
 // CHECK-NEXT: store i32 5, i32* [[X]],
 // CHECK-NEXT: [[T0:%.*]] = load i32* [[X]],
 // CHECK-NEXT: [[T1:%.*]] = call i8* @test52_helper(i32 [[T0]])
-// CHECK-NEXT: [[T2:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T1]])
-// CHECK-NEXT: ret i8* [[T2]]
+// CHECK-NEXT: store i8* [[T1]], i8** [[TMPALLOCA]]
+// CHECK-NEXT: [[T2:%.*]] = load i8** [[TMPALLOCA]]
+// CHECK-NEXT: [[T3:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T2]])
+// CHECK-NEXT: ret i8* [[T3]]
 }
 
 // rdar://problem/9400644
@@ -1130,14 +1133,17 @@ void test53(void) {
 // CHECK:    define void @test53()
 // CHECK:      [[X:%.*]] = alloca i8*,
 // CHECK-NEXT: [[Y:%.*]] = alloca i8*,
+// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca i8*,
 // CHECK-NEXT: [[T0:%.*]] = call i8* @test53_helper()
 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
 // CHECK-NEXT: store i8* [[T1]], i8** [[Y]],
 // CHECK-NEXT: [[T0:%.*]] = load i8** [[Y]],
 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+// CHECK-NEXT: store i8* [[T1]], i8** [[TMPALLOCA]]
 // CHECK-NEXT: [[T2:%.*]] = load i8** [[Y]]
 // CHECK-NEXT: call void @objc_release(i8* [[T2]])
-// CHECK-NEXT: store i8* [[T1]], i8** [[X]],
+// CHECK-NEXT: [[T3:%.*]] = load i8** [[TMPALLOCA]]
+// CHECK-NEXT: store i8* [[T3]], i8** [[X]],
 // CHECK-NEXT: load i8** [[X]],
 // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]]
 // CHECK-NEXT: call void @objc_release(i8* [[T0]])





More information about the cfe-commits mailing list