Improve switch diagnostic to emit the "jump" message on the

specific bad case instead of on the switch.  Putting it on the
switch means you don't know what case is the problem. For 
example:

scope-check.c:54:3: error: illegal switch case into protected scope
  case 2:
  ^
scope-check.c:53:9: note: jump bypasses initialization of variable length array
    int a[x];
        ^

llvm-svn: 69462
This commit is contained in:
Chris Lattner 2009-04-18 19:50:02 +00:00
parent 7535f41c66
commit 36dec99d12
3 changed files with 24 additions and 21 deletions

View File

@ -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<

View File

@ -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;

View File

@ -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;
}