aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Sema/SemaDecl.cpp37
-rw-r--r--test/Sema/scope-check.c6
3 files changed, 24 insertions, 21 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 9560614058..f0a7e848db 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -833,7 +833,7 @@ def err_undeclared_label_use : Error<"use of undeclared label '%0'">;
def err_goto_into_protected_scope : Error<"illegal goto into protected scope">;
def err_switch_into_protected_scope : Error<
- "illegal switch into protected scope">;
+ "illegal switch case into protected scope">;
def note_protected_by_vla_typedef : Note<
"jump bypasses initialization of VLA typedef">;
def note_protected_by_vla : Note<
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 48351407d9..814b730575 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2953,7 +2953,8 @@ private:
bool StatementCreatesScope(DeclStmt *S, unsigned ParentScope);
void BuildScopeInformation(Stmt *S, unsigned ParentScope);
void VerifyJumps();
- void CheckJump(Stmt *S, unsigned JumpTargetScope, unsigned JumpDiag);
+ void CheckJump(Stmt *From, Stmt *To,
+ SourceLocation DiagLoc, unsigned JumpDiag);
};
} // end anonymous namespace
@@ -3067,14 +3068,13 @@ void JumpScopeChecker::VerifyJumps() {
Stmt *Jump = Jumps.pop_back_val();
if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
- assert(LabelAndGotoScopes.count(GS->getLabel()) && "Label not visited?");
- CheckJump(GS, LabelAndGotoScopes[GS->getLabel()],
+ CheckJump(GS, GS->getLabel(), GS->getGotoLoc(),
diag::err_goto_into_protected_scope);
} else if (SwitchStmt *SS = dyn_cast<SwitchStmt>(Jump)) {
for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase()) {
assert(LabelAndGotoScopes.count(SC) && "Case not visited?");
- CheckJump(SS, LabelAndGotoScopes[SC],
+ CheckJump(SS, SC, SC->getLocStart(),
diag::err_switch_into_protected_scope);
}
continue;
@@ -3088,22 +3088,25 @@ void JumpScopeChecker::VerifyJumps() {
/// CheckJump - Validate that the specified jump statement is valid: that it is
/// jumping within or out of its current scope, not into a deeper one.
-void JumpScopeChecker::CheckJump(Stmt *Jump, unsigned JumpTargetScope,
- unsigned JumpDiag) {
- assert(LabelAndGotoScopes.count(Jump) && "Jump didn't get added to scopes?");
- unsigned JumpScope = LabelAndGotoScopes[Jump];
+void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To,
+ SourceLocation DiagLoc, unsigned JumpDiag) {
+ assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?");
+ unsigned FromScope = LabelAndGotoScopes[From];
+ assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?");
+ unsigned ToScope = LabelAndGotoScopes[To];
+
// Common case: exactly the same scope, which is fine.
- if (JumpScope == JumpTargetScope) return;
+ if (FromScope == ToScope) return;
// The only valid mismatch jump case happens when the jump is more deeply
// nested inside the jump target. Do a quick scan to see if the jump is valid
// because valid code is more common than invalid code.
- unsigned TestScope = Scopes[JumpScope].ParentScope;
+ unsigned TestScope = Scopes[FromScope].ParentScope;
while (TestScope != ~0U) {
// If we found the jump target, then we're jumping out of our current scope,
// which is perfectly fine.
- if (TestScope == JumpTargetScope) return;
+ if (TestScope == ToScope) return;
// Otherwise, scan up the hierarchy.
TestScope = Scopes[TestScope].ParentScope;
@@ -3111,23 +3114,23 @@ void JumpScopeChecker::CheckJump(Stmt *Jump, unsigned JumpTargetScope,
// If we get here, then we know we have invalid code. Diagnose the bad jump,
// and then emit a note at each VLA being jumped out of.
- S.Diag(Jump->getLocStart(), JumpDiag);
+ S.Diag(DiagLoc, JumpDiag);
// FIXME: This is N^2 and silly.
while (1) {
// Diagnose that the jump jumps over this declaration.
- const GotoScope &TargetScope = Scopes[JumpTargetScope];
+ const GotoScope &TargetScope = Scopes[ToScope];
S.Diag(TargetScope.Loc, TargetScope.Diag);
// Walk out one level.
- JumpTargetScope = Scopes[JumpTargetScope].ParentScope;
- assert(JumpTargetScope != ~0U && "Didn't find top-level function scope?");
+ ToScope = Scopes[ToScope].ParentScope;
+ assert(ToScope != ~0U && "Didn't find top-level function scope?");
// Check to see if the jump is valid now.
- unsigned TestScope = JumpScope;
+ unsigned TestScope = FromScope;
while (TestScope != ~0U) {
// If we found the jump target, the the jump became valid.
- if (TestScope == JumpTargetScope) return;
+ if (TestScope == ToScope) return;
// Otherwise, scan up the hierarchy.
TestScope = Scopes[TestScope].ParentScope;
diff --git a/test/Sema/scope-check.c b/test/Sema/scope-check.c
index 59d4d134a8..93120cdf94 100644
--- a/test/Sema/scope-check.c
+++ b/test/Sema/scope-check.c
@@ -47,11 +47,11 @@ int test6() {
}
void test7(int x) {
-foo:
- switch (x) { // expected-error {{illegal switch into protected scope}}
+foo: // FIXME: remove
+ switch (x) {
case 1: ;
int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
- case 2:
+ case 2: // expected-error {{illegal switch case into protected scope}}
a[1] = 2;
break;
}