Skip to content

Commit 2e03726

Browse files
committed
Reimplement labeled statement shadowing using ASTScope.
Switch the "shadowing" check for labeled statements over to using the ASTScope-based lookup of visible labeled statements.
1 parent 0d90adf commit 2e03726

File tree

1 file changed

+46
-36
lines changed

1 file changed

+46
-36
lines changed

lib/Sema/TypeCheckStmt.cpp

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,27 @@ static void tryDiagnoseUnnecessaryCastOverOptionSet(ASTContext &Ctx,
290290
.fixItRemove(SourceRange(ME->getDotLoc(), E->getEndLoc()));
291291
}
292292

293+
/// Check that a labeled statement doesn't shadow another statement with the
294+
/// same label.
295+
static void checkLabeledStmtShadowing(
296+
ASTContext &ctx, SourceFile *sourceFile, LabeledStmt *ls) {
297+
auto name = ls->getLabelInfo().Name;
298+
if (name.empty() || !sourceFile || ls->getStartLoc().isInvalid())
299+
return;
300+
301+
auto activeLabeledStmtsVec = ASTScope::lookupLabeledStmts(
302+
sourceFile, ls->getStartLoc());
303+
auto activeLabeledStmts = llvm::makeArrayRef(activeLabeledStmtsVec);
304+
for (auto prevLS : activeLabeledStmts.slice(1)) {
305+
if (prevLS->getLabelInfo().Name == name) {
306+
ctx.Diags.diagnose(
307+
ls->getLabelInfo().Loc, diag::label_shadowed, name);
308+
ctx.Diags.diagnose(
309+
prevLS->getLabelInfo().Loc, diag::invalid_redecl_prev, name);
310+
}
311+
}
312+
}
313+
293314
namespace {
294315
class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
295316
public:
@@ -332,50 +353,39 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
332353
StmtChecker &SC;
333354
AddLabeledStmt(StmtChecker &SC, LabeledStmt *LS) : SC(SC) {
334355
// Verify that we don't have label shadowing.
335-
if (!LS->getLabelInfo().Name.empty())
336-
for (auto PrevLS : SC.ActiveLabeledStmts) {
337-
if (PrevLS->getLabelInfo().Name == LS->getLabelInfo().Name) {
338-
auto &DE = SC.getASTContext().Diags;
339-
DE.diagnose(LS->getLabelInfo().Loc,
340-
diag::label_shadowed, LS->getLabelInfo().Name);
341-
DE.diagnose(PrevLS->getLabelInfo().Loc,
342-
diag::invalid_redecl_prev,
343-
PrevLS->getLabelInfo().Name);
344-
}
345-
}
356+
auto sourceFile = SC.DC->getParentSourceFile();
357+
checkLabeledStmtShadowing(SC.getASTContext(), sourceFile, LS);
346358

347359
// In any case, remember that we're in this labeled statement so that
348360
// break and continue are aware of it.
349361
SC.ActiveLabeledStmts.push_back(LS);
350362

351363
// Verify that the ASTScope-based query for active labeled statements
352364
// is equivalent to what we have here.
353-
if (LS->getStartLoc().isValid()) {
354-
if (auto sourceFile = SC.DC->getParentSourceFile()) {
355-
// The labeled statements from ASTScope lookup have the
356-
// innermost labeled statement first, so reverse it to
357-
// match the data structure maintained here.
358-
auto activeFromASTScope = ASTScope::lookupLabeledStmts(
359-
sourceFile, LS->getStartLoc());
360-
assert(activeFromASTScope.front() == LS);
361-
std::reverse(activeFromASTScope.begin(), activeFromASTScope.end());
362-
if (activeFromASTScope != SC.ActiveLabeledStmts) {
363-
llvm::errs() << "Old: ";
364-
llvm::interleave(SC.ActiveLabeledStmts, [&](LabeledStmt *LS) {
365-
llvm::errs() << LS;
366-
}, [&] {
367-
llvm::errs() << ' ';
368-
});
369-
llvm::errs() << "\nNew: ";
370-
llvm::interleave(activeFromASTScope, [&](LabeledStmt *LS) {
371-
llvm::errs() << LS;
372-
}, [&] {
373-
llvm::errs() << ' ';
374-
});
375-
llvm::errs() << "\n";
376-
}
377-
assert(activeFromASTScope == SC.ActiveLabeledStmts);
365+
if (LS->getStartLoc().isValid() && sourceFile) {
366+
// The labeled statements from ASTScope lookup have the
367+
// innermost labeled statement first, so reverse it to
368+
// match the data structure maintained here.
369+
auto activeFromASTScope = ASTScope::lookupLabeledStmts(
370+
sourceFile, LS->getStartLoc());
371+
assert(activeFromASTScope.front() == LS);
372+
std::reverse(activeFromASTScope.begin(), activeFromASTScope.end());
373+
if (activeFromASTScope != SC.ActiveLabeledStmts) {
374+
llvm::errs() << "Old: ";
375+
llvm::interleave(SC.ActiveLabeledStmts, [&](LabeledStmt *LS) {
376+
llvm::errs() << LS;
377+
}, [&] {
378+
llvm::errs() << ' ';
379+
});
380+
llvm::errs() << "\nNew: ";
381+
llvm::interleave(activeFromASTScope, [&](LabeledStmt *LS) {
382+
llvm::errs() << LS;
383+
}, [&] {
384+
llvm::errs() << ' ';
385+
});
386+
llvm::errs() << "\n";
378387
}
388+
assert(activeFromASTScope == SC.ActiveLabeledStmts);
379389
}
380390
}
381391
~AddLabeledStmt() {

0 commit comments

Comments
 (0)