@@ -4419,61 +4419,57 @@ void swift::performAbstractFuncDeclDiagnostics(AbstractFunctionDecl *AFD) {
44194419 }
44204420}
44214421
4422- // Perform MiscDiagnostics on Switch Statements.
4423- static void checkSwitch (ASTContext &ctx, const SwitchStmt *stmt,
4424- DeclContext *DC) {
4425- // We want to warn about "case .Foo, .Bar where 1 != 100:" since the where
4426- // clause only applies to the second case, and this is surprising.
4427- for (auto cs : stmt->getCases ()) {
4428- TypeChecker::checkExistentialTypes (ctx, cs, DC);
4429-
4430- // The case statement can have multiple case items, each can have a where.
4431- // If we find a "where", and there is a preceding item without a where, and
4432- // if they are on the same source line, then warn.
4433- auto items = cs->getCaseLabelItems ();
4434-
4435- // Don't do any work for the vastly most common case.
4436- if (items.size () == 1 ) continue ;
4437-
4438- // Ignore the first item, since it can't have preceding ones.
4439- for (unsigned i = 1 , e = items.size (); i != e; ++i) {
4440- // Must have a where clause.
4441- auto where = items[i].getGuardExpr ();
4442- if (!where)
4443- continue ;
4444-
4445- // Preceding item must not.
4446- if (items[i-1 ].getGuardExpr ())
4447- continue ;
4448-
4449- // Must be on the same source line.
4450- auto prevLoc = items[i-1 ].getStartLoc ();
4451- auto thisLoc = items[i].getStartLoc ();
4452- if (prevLoc.isInvalid () || thisLoc.isInvalid ())
4453- continue ;
4454-
4455- auto &SM = ctx.SourceMgr ;
4456- auto prevLineCol = SM.getLineAndColumnInBuffer (prevLoc);
4457- if (SM.getLineAndColumnInBuffer (thisLoc).first != prevLineCol.first )
4458- continue ;
4422+ static void diagnoseCaseStmtAmbiguousWhereClause (const CaseStmt *CS,
4423+ ASTContext &ctx) {
4424+ // The case statement can have multiple case items, each can have a where.
4425+ // If we find a "where", and there is a preceding item without a where, and
4426+ // if they are on the same source line, e.g
4427+ // "case .Foo, .Bar where 1 != 100:" then warn since it may be unexpected.
4428+ auto items = CS->getCaseLabelItems ();
4429+
4430+ // Don't do any work for the vastly most common case.
4431+ if (items.size () == 1 )
4432+ return ;
44594433
4460- ctx.Diags .diagnose (items[i].getWhereLoc (), diag::where_on_one_item)
4434+ // Ignore the first item, since it can't have preceding ones.
4435+ for (unsigned i = 1 , e = items.size (); i != e; ++i) {
4436+ // Must have a where clause.
4437+ auto where = items[i].getGuardExpr ();
4438+ if (!where)
4439+ continue ;
4440+
4441+ // Preceding item must not.
4442+ if (items[i - 1 ].getGuardExpr ())
4443+ continue ;
4444+
4445+ // Must be on the same source line.
4446+ auto prevLoc = items[i - 1 ].getStartLoc ();
4447+ auto thisLoc = items[i].getStartLoc ();
4448+ if (prevLoc.isInvalid () || thisLoc.isInvalid ())
4449+ continue ;
4450+
4451+ auto &SM = ctx.SourceMgr ;
4452+ auto prevLineCol = SM.getLineAndColumnInBuffer (prevLoc);
4453+ if (SM.getLineAndColumnInBuffer (thisLoc).first != prevLineCol.first )
4454+ continue ;
4455+
4456+ ctx.Diags
4457+ .diagnose (items[i].getWhereLoc (), diag::where_on_one_item,
4458+ CS->getParentKind () == CaseParentKind::DoCatch)
44614459 .highlight (items[i].getPattern ()->getSourceRange ())
44624460 .highlight (where->getSourceRange ());
4463-
4464- // Whitespace it out to the same column as the previous item.
4465- std::string whitespace (prevLineCol.second -1 , ' ' );
4466- ctx.Diags .diagnose (thisLoc, diag::add_where_newline)
4467- .fixItInsert (thisLoc, " \n " +whitespace);
4468-
4469- auto whereRange = SourceRange (items[i].getWhereLoc (),
4470- where->getEndLoc ());
4471- auto charRange = Lexer::getCharSourceRangeFromSourceRange (SM, whereRange);
4472- auto whereText = SM.extractText (charRange);
4473- ctx.Diags .diagnose (prevLoc, diag::duplicate_where)
4474- .fixItInsertAfter (items[i-1 ].getEndLoc (), " " + whereText.str ())
4475- .highlight (items[i-1 ].getSourceRange ());
4476- }
4461+
4462+ // Whitespace it out to the same column as the previous item.
4463+ std::string whitespace (prevLineCol.second - 1 , ' ' );
4464+ ctx.Diags .diagnose (thisLoc, diag::add_where_newline)
4465+ .fixItInsert (thisLoc, " \n " + whitespace);
4466+
4467+ auto whereRange = SourceRange (items[i].getWhereLoc (), where->getEndLoc ());
4468+ auto charRange = Lexer::getCharSourceRangeFromSourceRange (SM, whereRange);
4469+ auto whereText = SM.extractText (charRange);
4470+ ctx.Diags .diagnose (prevLoc, diag::duplicate_where)
4471+ .fixItInsertAfter (items[i - 1 ].getEndLoc (), " " + whereText.str ())
4472+ .highlight (items[i - 1 ].getSourceRange ());
44774473 }
44784474}
44794475
@@ -6194,8 +6190,8 @@ void swift::performStmtDiagnostics(const Stmt *S, DeclContext *DC) {
61946190
61956191 TypeChecker::checkExistentialTypes (ctx, const_cast <Stmt *>(S), DC);
61966192
6197- if (auto switchStmt = dyn_cast<SwitchStmt >(S))
6198- checkSwitch (ctx, switchStmt, DC );
6193+ if (auto *CS = dyn_cast<CaseStmt >(S))
6194+ diagnoseCaseStmtAmbiguousWhereClause (CS, ctx );
61996195
62006196 checkStmtConditionTrailingClosure (ctx, S);
62016197
0 commit comments