summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGExprScalar.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2017-03-06 22:18:34 +0000
committerReid Kleckner <rnk@google.com>2017-03-06 22:18:34 +0000
commit092d065265999ddedcfb07735c56ac2dca7e90b5 (patch)
treedc1a325806abd50d131bf62089f58f40c797e5dd /clang/lib/CodeGen/CGExprScalar.cpp
parente844a54a855bdcb9b84f309d728b14d91cc003cb (diff)
downloadbcm5719-llvm-092d065265999ddedcfb07735c56ac2dca7e90b5.tar.gz
bcm5719-llvm-092d065265999ddedcfb07735c56ac2dca7e90b5.zip
Don't assume cleanup emission preserves dominance in expr evaluation
Summary: Because of the existence branches out of GNU statement expressions, it is possible that emitting cleanups for a full expression may cause the new insertion point to not be dominated by the result of the inner expression. Consider this example: struct Foo { Foo(); ~Foo(); int x; }; int g(Foo, int); int f(bool cond) { int n = g(Foo(), ({ if (cond) return 0; 42; })); return n; } Before this change, result of the call to 'g' did not dominate its use in the store to 'n'. The early return exit from the statement expression branches to a shared cleanup block, which ends in a switch between the fallthrough destination (the assignment to 'n') or the function exit block. This change solves the problem by spilling and reloading expression evaluation results when any of the active cleanups have branches. I audited the other call sites of enterFullExpression, and they don't appear to keep and Values live across the site of the cleanup, except in ARC code. I wasn't able to create a test case for ARC that exhibits this problem, though. Reviewers: rjmccall, rsmith Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D30590 llvm-svn: 297084
Diffstat (limited to 'clang/lib/CodeGen/CGExprScalar.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp17
1 files changed, 12 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 145248c04aa..2896e3556e5 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGCleanup.h"
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
@@ -477,11 +478,7 @@ public:
return CGF.LoadCXXThis();
}
- Value *VisitExprWithCleanups(ExprWithCleanups *E) {
- CGF.enterFullExpression(E);
- CodeGenFunction::RunCleanupsScope Scope(CGF);
- return Visit(E->getSubExpr());
- }
+ Value *VisitExprWithCleanups(ExprWithCleanups *E);
Value *VisitCXXNewExpr(const CXXNewExpr *E) {
return CGF.EmitCXXNewExpr(E);
}
@@ -1691,6 +1688,16 @@ Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) {
E->getExprLoc());
}
+Value *ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
+ CGF.enterFullExpression(E);
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ Value *V = Visit(E->getSubExpr());
+ // Defend against dominance problems caused by jumps out of expression
+ // evaluation through the shared cleanup block.
+ Scope.ForceCleanup({&V});
+ return V;
+}
+
//===----------------------------------------------------------------------===//
// Unary Operators
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud