summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGStmt.cpp
diff options
context:
space:
mode:
authorSerge Pavlov <sepavloff@gmail.com>2014-01-23 15:05:00 +0000
committerSerge Pavlov <sepavloff@gmail.com>2014-01-23 15:05:00 +0000
commit09f9924acf1a8644e9458833d3c8ea40d7ddbc46 (patch)
treeab81b6c65a12f96059f2bed913314d8f138c7925 /clang/lib/CodeGen/CGStmt.cpp
parent5a68c4b28747fc5da182916b801de9a34e59a0dd (diff)
downloadbcm5719-llvm-09f9924acf1a8644e9458833d3c8ea40d7ddbc46.tar.gz
bcm5719-llvm-09f9924acf1a8644e9458833d3c8ea40d7ddbc46.zip
Fix to PR8880 (clang dies processing a for loop)
Due to statement expressions supported as GCC extension, it is possible to put 'break' or 'continue' into a loop/switch statement but outside its body, for example: for ( ; ({ if (first) { first = 0; continue; } 0; }); ) This code is rejected by GCC if compiled in C mode but is accepted in C++ code. GCC bug 44715 tracks this discrepancy. Clang used code generation that differs from GCC in both modes: only statement of the third expression of 'for' behaves as if it was inside loop body. This change makes code generation more close to GCC, considering 'break' or 'continue' statement in condition and increment expressions of a loop as it was inside the loop body. It also adds error for the cases when 'break'/'continue' appear outside loop due to this syntax. If code generation differ from GCC, warning is issued. Differential Revision: http://llvm-reviews.chandlerc.com/D2518 llvm-svn: 199897
Diffstat (limited to 'clang/lib/CodeGen/CGStmt.cpp')
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp24
1 files changed, 12 insertions, 12 deletions
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 880e801189a..eba0c2dcac7 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -614,8 +614,6 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
}
Cnt.adjustForControlFlow();
- BreakContinueStack.pop_back();
-
EmitBlock(LoopCond.getBlock());
// C99 6.8.5.2: "The evaluation of the controlling expression takes place
@@ -626,6 +624,8 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
// compares unequal to 0. The condition must be a scalar type.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+ BreakContinueStack.pop_back();
+
// "do {} while (0)" is common in macros, avoid extra blocks. Be sure
// to correctly handle break/continue though.
bool EmitBoolCondBranch = true;
@@ -673,6 +673,16 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
llvm::BasicBlock *CondBlock = Continue.getBlock();
EmitBlock(CondBlock);
+ // If the for loop doesn't have an increment we can just use the
+ // condition as the continue block. Otherwise we'll need to create
+ // a block for it (in the current scope, i.e. in the scope of the
+ // condition), and that we will become our continue block.
+ if (S.getInc())
+ Continue = getJumpDestInCurrentScope("for.inc");
+
+ // Store the blocks to use for break and continue.
+ BreakContinueStack.push_back(BreakContinue(LoopExit, Continue, &Cnt));
+
// Create a cleanup scope for the condition variable cleanups.
RunCleanupsScope ConditionScope(*this);
@@ -710,16 +720,6 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
}
Cnt.beginRegion(Builder);
- // If the for loop doesn't have an increment we can just use the
- // condition as the continue block. Otherwise we'll need to create
- // a block for it (in the current scope, i.e. in the scope of the
- // condition), and that we will become our continue block.
- if (S.getInc())
- Continue = getJumpDestInCurrentScope("for.inc");
-
- // Store the blocks to use for break and continue.
- BreakContinueStack.push_back(BreakContinue(LoopExit, Continue, &Cnt));
-
{
// Create a separate cleanup scope for the body, in case it is not
// a compound statement.
OpenPOWER on IntegriCloud