llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Sirraide
<details>
<summary>Changes</summary>
tl;dr: This makes e.g. `while (({ break; })) {}` ill-formed.
GCC used to allow this a long time ago (< GCC 9 I believe), but eventually
removed support for it; we originally allowed this both for GCC compatibility
and because there was actual code in the wild using it (see Richard’s comment
here for more background:
https://github.com/llvm/llvm-project/pull/152606#issuecomment-3166130973).
Note that this _is_ still allowed inside another loop, e.g. this
```c++
for (;;) {
while (({ break; true; })) {}
}
```
is well-formed; the `break` here will break out of the `for` loop.
Removing support for this gets rid of quite a bit of code and has a few more
benefits:
1. Currently, GCC and Clang _disagree_ on the meaning of this construct in
nested loops: in the code snippet above, Clang breaks out of the `while` loop,
whereas GCC breaks out of the `for` loop; this patch changes Clang to align
with GCC here. As a result, we can also remove code that emits a warning for
such cases.
2. It frees up a bit in `ScopeFlags::Flags`, which is a good thing because I
need one for expansion statements, and we’re out of bits. This is because we
currently use a bit as a hack to disallow `continue` inside the declaration of
the condition variable (because we’d `continue` to the condition before
initialising the variable); this bit becomes obsolete with this patch because
`continue` is now disallowed entirely within the condition (if there is no
outer loop).
Without this change, I’d have to refactor `Flags` to be a 64-bit integer,
which would also entail updating every place where we use an `unsigned` to
store score flags.
There is another change that I needed to make here: we currently suppress
`-Wcomma` (which warns about comma operators, because in most contexts, you
probably didn’t mean to use one) in some places, including the third part of a
C-style `for` loop. This is implemented by checking if we’re in a `BreakScope |
ContinueScope`, but those scope flags are now only set when parsing the loop
body. Instead, we now check for `ControlScope`. This requires us to also set
that flag in C90 mode, but that seems to be harmless as the only use of
`ControlScope` I was able to find is in C++ code paths, where that bit was
already set anyway.
When we introduced named loops for C2y, we purposefully didn’t support labeled
break/continue in the condition, so there’s nothing to be done there (we
already have tests for this too).
---
Patch is 37.23 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/198436.diff
16 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+31)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (-9)
- (modified) clang/include/clang/Parse/Parser.h (+1-5)
- (modified) clang/include/clang/Sema/Scope.h (+16-24)
- (modified) clang/include/clang/Sema/Sema.h (-4)
- (modified) clang/lib/Parse/ParseExprCXX.cpp (+5-25)
- (modified) clang/lib/Parse/ParseStmt.cpp (+14-32)
- (modified) clang/lib/Sema/Scope.cpp (+18-13)
- (modified) clang/lib/Sema/SemaExpr.cpp (+1-9)
- (modified) clang/lib/Sema/SemaStmt.cpp (-35)
- (modified) clang/test/Analysis/dead-stores.c (-14)
- (modified) clang/test/CoverageMapping/break.c (-11)
- (added) clang/test/Sema/break-continue-cond.c (+114)
- (modified) clang/test/Sema/loop-control.c (+25-25)
- (modified) clang/test/Sema/statements.c (+1-1)
- (modified) clang/test/SemaCXX/scope-check.cpp (+6-10)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f5660f9670eae..320a1926d7f02 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -40,6 +40,37 @@ Potentially Breaking Changes
C/C++ Language Potentially Breaking Changes
-------------------------------------------
+- Clang now makes it ill-formed to try to ``break`` out of or ``continue`` a
loop inside its own condition,
+ increment, or init-statement in all C and C++ language modes. This means
that code such as
+
+ .. code-block:: c++
+
+ while (({ break; })) {}
+
+ is now ill-formed. An outer loop can still be broken out of or continued so
long as the inner loop is
+ in the body of the outer loop:
+
+ .. code-block:: c++
+
+ // Ok, this breaks out of the 'for' loop.
+ for (;;) {
+ while (({ break; true; })) {}
+ }
+
+ // Error: can't break out of the 'for' loop from within its own increment.
+ for (;;({ while (({ break; true; })) {} })) {}
+
+ This also resolves a divergence from GCC: in a construct such as
+
+ .. code-block:: c++
+
+ for (;;) {
+ while (({ break; true; })) {}
+ }
+
+ Clang would previously ``break`` out of the ``while`` loop, whereas GCC
(since version 9) would
+ ``break`` out of the ``for`` loop here. Now, Clang and GCC both break out of
the ``for`` loop.
+
C++ Specific Potentially Breaking Changes
-----------------------------------------
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d7dd20d6a45e4..0be5d2ffa2f49 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6899,9 +6899,6 @@ def note_goto_ms_asm_label : Note<
def warn_unused_label : Warning<"unused label %0">,
InGroup<UnusedLabel>, DefaultIgnore;
-def err_continue_from_cond_var_init : Error<
- "cannot jump from this continue statement to the loop increment; "
- "jump bypasses initialization of loop condition variable">;
def err_goto_into_protected_scope : Error<
"cannot jump from this goto statement to its label">;
def ext_goto_into_protected_scope : ExtWarn<
@@ -11191,9 +11188,6 @@ def err_break_continue_label_not_found : Error<
"%select{loop or 'switch'|loop}0">;
def err_continue_switch : Error<
"label of 'continue' refers to a switch statement">;
-def warn_loop_ctrl_binds_to_inner : Warning<
- "'%0' is bound to current loop, GCC binds it to the enclosing loop">,
- InGroup<GccCompat>;
def err_omp_bind_required_on_loop : Error<
"expected 'bind' clause for 'loop' construct without an enclosing OpenMP "
"construct">;
@@ -11201,9 +11195,6 @@ def err_omp_loop_reduction_clause : Error<
"'reduction' clause not allowed with '#pragma omp loop bind(teams)'">;
def err_omp_split_counts_not_one_omp_fill : Error<
"exactly one 'omp_fill' must appear in the 'counts' clause">;
-def warn_break_binds_to_switch : Warning<
- "'break' is bound to loop, GCC binds it to switch">,
- InGroup<GccCompat>;
def err_default_not_in_switch : Error<
"'default' statement not in switch statement">;
def err_case_not_in_switch : Error<"'case' statement not in switch statement">;
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index dc3dc8a4ae0e9..c6c492b4980af 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -5035,16 +5035,12 @@ class Parser : public CodeCompletionHandler {
/// present will be parsed and stored here, and a null result will be
/// returned.
///
- /// \param EnterForConditionScope If true, enter a continue/break scope at
the
- /// appropriate moment for a 'for' loop.
- ///
/// \returns The parsed condition.
Sema::ConditionResult ParseCXXCondition(StmtResult *InitStmt,
SourceLocation Loc,
Sema::ConditionKind CK,
bool MissingOK,
- ForRangeInfo *FRI = nullptr,
- bool EnterForConditionScope = false);
+ ForRangeInfo *FRI = nullptr);
DeclGroupPtrTy ParseAliasDeclarationInInitStatement(DeclaratorContext
Context,
ParsedAttributes &Attrs);
diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h
index 0d1c0ff6a1e91..ab6471f907e59 100644
--- a/clang/include/clang/Sema/Scope.h
+++ b/clang/include/clang/Sema/Scope.h
@@ -140,10 +140,12 @@ class Scope {
/// This is the scope of a C++ catch statement.
CatchScope = 0x1000000,
- /// This is a scope in which a condition variable is currently being
- /// parsed. If such a scope is a ContinueScope, it's invalid to jump to the
- /// continue block from here.
- ConditionVarScope = 0x2000000,
+ /// This is the scope corresponding to a C++26 expansion statement.
+ ///
+ /// NOTE: While currently unused, this flag is reserved for the
+ /// implementation of expansion statements; do not remove it or
+ /// reuse it for anything else.
+ ExpansionStmtScope = 0x2000000,
/// This is a scope of some OpenMP directive with
/// order clause which specifies concurrent
@@ -274,11 +276,6 @@ class Scope {
/// Get the label that precedes this scope.
LabelDecl *getPrecedingLabel() const { return PrecedingLabel; }
- void setPrecedingLabel(LabelDecl *LD) {
- assert((Flags & BreakScope || Flags & ContinueScope) &&
- "not a loop or switch");
- PrecedingLabel = LD;
- }
/// isBlockScope - Return true if this scope correspond to a closure.
bool isBlockScope() const { return Flags & BlockScope; }
@@ -306,17 +303,6 @@ class Scope {
return const_cast<Scope*>(this)->getContinueParent();
}
- // Set whether we're in the scope of a condition variable, where 'continue'
- // is disallowed despite being a continue scope.
- void setIsConditionVarScope(bool InConditionVarScope) {
- Flags = (Flags & ~ConditionVarScope) |
- (InConditionVarScope ? ConditionVarScope : NoScope);
- }
-
- bool isConditionVarScope() const {
- return Flags & ConditionVarScope;
- }
-
/// getBreakParent - Return the closest scope that a break statement
/// would be affected by.
Scope *getBreakParent() {
@@ -636,6 +622,16 @@ class Scope {
/// is an ancestor of the other.
bool Contains(const Scope& rhs) const { return Depth < rhs.Depth; }
+ /// Mark that we're entering the body of a loop (for, while, do).
+ void EnterLoopBody(LabelDecl *PrecedingLabel);
+
+ /// Mark that we're entering the body of a switch statement.
+ void EnterSwitchBody(LabelDecl *PrecedingLabel);
+
+ /// Mark that we're leaving the body of a loop; this is only needed for do
+ /// loops where the condition follows the loop body.
+ void LeaveLoopBody();
+
/// containedInPrototypeScope - Return true if this or a parent scope
/// is a FunctionPrototypeScope.
bool containedInPrototypeScope() const;
@@ -659,10 +655,6 @@ class Scope {
/// Init - This is used by the parser to implement scope caching.
void Init(Scope *parent, unsigned flags);
- /// Sets up the specified scope flags and adjusts the scope state
- /// variables accordingly.
- void AddFlags(unsigned Flags);
-
void dumpImpl(raw_ostream &OS) const;
void dump() const;
};
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5202244cee2a7..e71794b2d92c9 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11338,10 +11338,6 @@ class Sema final : public SemaBase {
/// issuing a diagnostic and returning false if not.
bool checkMustTailAttr(const Stmt *St, const Attr &MTA);
- /// Check if the given expression contains 'break' or 'continue'
- /// statement that produces control flow different from GCC.
- void CheckBreakContinueBinding(Expr *E);
-
///@}
//
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 39c61f4b5bf5c..5646597622832 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1865,25 +1865,11 @@
Parser::ParseAliasDeclarationInInitStatement(DeclaratorContext Context,
return DG;
}
-Sema::ConditionResult
-Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc,
- Sema::ConditionKind CK, bool MissingOK,
- ForRangeInfo *FRI, bool EnterForConditionScope) {
- // Helper to ensure we always enter a continue/break scope if requested.
- struct ForConditionScopeRAII {
- Scope *S;
- void enter(bool IsConditionVariable) {
- if (S) {
- S->AddFlags(Scope::BreakScope | Scope::ContinueScope);
- S->setIsConditionVarScope(IsConditionVariable);
- }
- }
- ~ForConditionScopeRAII() {
- if (S)
- S->setIsConditionVarScope(false);
- }
- } ForConditionScope{EnterForConditionScope ? getCurScope() : nullptr};
-
+Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
+ SourceLocation Loc,
+ Sema::ConditionKind CK,
+ bool MissingOK,
+ ForRangeInfo *FRI) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
PreferredType.enterCondition(Actions, Tok.getLocation());
@@ -1907,9 +1893,6 @@ Parser::ParseCXXCondition(StmtResult *InitStmt,
SourceLocation Loc,
// Determine what kind of thing we have.
switch (isCXXConditionDeclarationOrInitStatement(InitStmt, FRI)) {
case ConditionOrInitStatement::Expression: {
- // If this is a for loop, we're entering its condition.
- ForConditionScope.enter(/*IsConditionVariable=*/false);
-
ProhibitAttributes(attrs);
// We can have an empty expression here.
@@ -1983,9 +1966,6 @@ Parser::ParseCXXCondition(StmtResult *InitStmt,
SourceLocation Loc,
break;
}
- // If this is a for loop, we're entering its condition.
- ForConditionScope.enter(/*IsConditionVariable=*/true);
-
// type-specifier-seq
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_condition);
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 1a45ed66950be..37f142e059930 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1697,8 +1697,7 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation
*TrailingElseLoc,
// See comments in ParseIfStatement for why we create a scope for the
// condition and a new scope for substatement in C++.
//
- getCurScope()->AddFlags(Scope::BreakScope);
- getCurScope()->setPrecedingLabel(PrecedingLabel);
+ getCurScope()->EnterSwitchBody(PrecedingLabel);
ParseScope InnerScope(this, Scope::DeclScope, C99orCXX,
Tok.is(tok::l_brace));
// We have incremented the mangling number for the SwitchScope and the
@@ -1742,12 +1741,7 @@ StmtResult Parser::ParseWhileStatement(SourceLocation
*TrailingElseLoc,
// while, for, and switch statements are local to the if, while, for, or
// switch statement (including the controlled statement).
//
- unsigned ScopeFlags;
- if (C99orCXX)
- ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
- Scope::DeclScope | Scope::ControlScope;
- else
- ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
+ unsigned ScopeFlags = Scope::ControlScope | (C99orCXX ? Scope::DeclScope :
0);
ParseScope WhileScope(this, ScopeFlags);
// Parse the condition.
@@ -1762,7 +1756,7 @@ StmtResult Parser::ParseWhileStatement(SourceLocation
*TrailingElseLoc,
// combinations, so diagnose that here in OpenACC mode.
SemaOpenACC::LoopInConstructRAII LCR{getActions().OpenACC()};
getActions().OpenACC().ActOnWhileStmt(WhileLoc);
- getCurScope()->setPrecedingLabel(PrecedingLabel);
+ getCurScope()->EnterLoopBody(PrecedingLabel);
// C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do
this
@@ -1800,19 +1794,14 @@ StmtResult Parser::ParseDoStatement(LabelDecl
*PrecedingLabel) {
// C99 6.8.5p5 - In C99, the do statement is a block. This is not
// the case for C90. Start the loop scope.
- unsigned ScopeFlags;
- if (getLangOpts().C99)
- ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope;
- else
- ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
-
+ unsigned ScopeFlags = getLangOpts().C99 ? Scope::DeclScope : 0;
ParseScope DoScope(this, ScopeFlags);
// OpenACC Restricts a do-while-loop inside of certain construct/clause
// combinations, so diagnose that here in OpenACC mode.
SemaOpenACC::LoopInConstructRAII LCR{getActions().OpenACC()};
getActions().OpenACC().ActOnDoStmt(DoLoc);
- getCurScope()->setPrecedingLabel(PrecedingLabel);
+ getCurScope()->EnterLoopBody(PrecedingLabel);
// C99 6.8.5p5 - In C99, the body of the do statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
@@ -1832,7 +1821,7 @@ StmtResult Parser::ParseDoStatement(LabelDecl
*PrecedingLabel) {
InnerScope.Exit();
// Reset this to disallow break/continue out of the condition.
- getCurScope()->setPrecedingLabel(nullptr);
+ getCurScope()->LeaveLoopBody();
if (Tok.isNot(tok::kw_while)) {
if (!Body.isInvalid()) {
@@ -1928,10 +1917,12 @@ StmtResult Parser::ParseForStatement(SourceLocation
*TrailingElseLoc,
// Names declared in the for-init-statement are in the same
declarative-region
// as those declared in the condition.
//
- unsigned ScopeFlags = 0;
- if (C99orCXXorObjC)
- ScopeFlags = Scope::DeclScope | Scope::ControlScope;
-
+ // Always enter a ControlScope, even in C90 mode; this is harmless as it
+ // doesn't cause declarations to bind to this scope. We use this to avoid
+ // diagnosing a comma operator in e.g. the third part of a for loop when
+ // '-Wcomma' is enabled.
+ unsigned ScopeFlags =
+ Scope::ControlScope | (C99orCXXorObjC ? Scope::DeclScope : 0);
ParseScope ForScope(this, ScopeFlags);
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -2112,8 +2103,7 @@ StmtResult Parser::ParseForStatement(SourceLocation
*TrailingElseLoc,
SecondPart = ParseCXXCondition(
/*InitStmt=*/nullptr, ForLoc, CK,
// FIXME: recovery if we don't see another semi!
- /*MissingOK=*/true, MightBeForRangeStmt ? &ForRangeInfo : nullptr,
- /*EnterForConditionScope=*/true);
+ /*MissingOK=*/true, MightBeForRangeStmt ? &ForRangeInfo : nullptr);
if (ForRangeInfo.ParsedForRangeDecl()) {
Diag(FirstPart.get() ? FirstPart.get()->getBeginLoc()
@@ -2143,9 +2133,6 @@ StmtResult Parser::ParseForStatement(SourceLocation
*TrailingElseLoc,
}
} else {
- // We permit 'continue' and 'break' in the condition of a for loop.
- getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
-
ExprResult SecondExpr = ParseExpression();
if (SecondExpr.isInvalid())
SecondPart = Sema::ConditionError();
@@ -2157,11 +2144,6 @@ StmtResult Parser::ParseForStatement(SourceLocation
*TrailingElseLoc,
}
}
- // Enter a break / continue scope, if we didn't already enter one while
- // parsing the second part.
- if (!getCurScope()->isContinueScope())
- getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
-
// Parse the third part of the for statement.
if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) {
if (Tok.isNot(tok::semi)) {
@@ -2230,7 +2212,7 @@ StmtResult Parser::ParseForStatement(SourceLocation
*TrailingElseLoc,
// Set this only right before parsing the body to disallow break/continue in
// the other parts.
- getCurScope()->setPrecedingLabel(PrecedingLabel);
+ getCurScope()->EnterLoopBody(PrecedingLabel);
// C99 6.8.5p5 - In C99, the body of the for statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do
this
diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp
index e66cce255230b..fc79b1a056ed9 100644
--- a/clang/lib/Sema/Scope.cpp
+++ b/clang/lib/Sema/Scope.cpp
@@ -113,18 +113,23 @@ bool Scope::containedInPrototypeScope() const {
return false;
}
-void Scope::AddFlags(unsigned FlagsToSet) {
- assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
- "Unsupported scope flags");
- if (FlagsToSet & BreakScope) {
- assert((Flags & BreakScope) == 0 && "Already set");
- BreakParent = this;
- }
- if (FlagsToSet & ContinueScope) {
- assert((Flags & ContinueScope) == 0 && "Already set");
- ContinueParent = this;
- }
- Flags |= FlagsToSet;
+void Scope::EnterLoopBody(LabelDecl *LD) {
+ Flags |= BreakScope | ContinueScope;
+ BreakParent = ContinueParent = this;
+ PrecedingLabel = LD;
+}
+
+void Scope::EnterSwitchBody(LabelDecl *LD) {
+ Flags |= BreakScope;
+ BreakParent = this;
+ PrecedingLabel = LD;
+}
+
+void Scope::LeaveLoopBody() {
+ Flags &= ~(BreakScope | ContinueScope);
+ BreakParent = getParent()->BreakParent;
+ ContinueParent = getParent()->ContinueParent;
+ PrecedingLabel = nullptr;
}
// The algorithm for updating NRVO candidate is as follows:
@@ -229,7 +234,7 @@ void Scope::dumpImpl(raw_ostream &OS) const {
{CompoundStmtScope, "CompoundStmtScope"},
{ClassInheritanceScope, "ClassInheritanceScope"},
{CatchScope, "CatchScope"},
- {ConditionVarScope, "ConditionVarScope"},
+ {ExpansionStmtScope, "ExpansionStmtScope"},
{OpenMPOrderClauseScope, "OpenMPOrderClauseScope"},
{LambdaScope, "LambdaScope"},
{OpenACCComputeConstructScope, "OpenACCComputeConstructScope"},
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 5b89236b11824..521a8516ac179 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -14636,15 +14636,7 @@ void Sema::DiagnoseCommaOperator(const Expr *LHS,
SourceLocation Loc) {
// The listed locations are the initialization and increment portions
// of a for loop. The additional checks are on the condition of
// if statements, do/while loops, and for loops.
- // Differences in scope flags for C89 mode requires the extra logic.
- const unsigned ForIncrementFlags =
- getLangOpts().C99 || getLangOpts().CPlusPlus
- ? Scope::ControlScope | Scope::ContinueScope | Scope::BreakScope
- : Scope::ContinueScope | Scope::BreakScope;
- const unsigned ForInitFlags = Scope::ControlScope | Scope::DeclScope;
- const unsigned ScopeFlags = getCurScope()->getFlags();
- if ((ScopeFlags & ForIncrementFlags) == ForIncrementFlags ||
- (ScopeFlags & ForInitFlags) == ForInitFlags)
+ if (getCurScope()->isControlScope())
return;
// If there are multiple comma operators used together, get the RHS of the
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 531147ef35b08..1d3c462833c7d 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -1794,7 +1794,6 @@ StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc,
return StmtError();
auto CondVal = Cond.get();
- CheckBreakContinueBinding(CondVal.second);
if (CondVal.second &&
!Diags.isIgnored(diag::warn_comma_operator,
CondVal.second->getExprLoc()))
@@ -1822,7 +1821,6 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
Expr *Cond, SourceLocation CondRParen) {
assert(Cond && "ActOnDoStmt(): missing expression");
- CheckBreakContinueBinding(Cond);
ExprResult CondResult = CheckBooleanCondition(DoLoc, Cond);
if (CondResult.isInvalid())
return StmtError();
@@ -1833,11 +1831,6 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
return StmtError();
Cond = CondResult.get();
- // Only call the CommaVisitor for C89 due to differences in scope flags.
- if (Cond && !getLangOpts().C99 && !getLangOpts().CPlusPlus &&
- !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc()))
- CommaVisitor(*this).Visit(Cond);
-
// OpenACC3.3 2.14.4:
// The update directive is executable. It must not appear in place of the
// statement following an 'if',...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/198436
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits