зеркало из https://github.com/microsoft/clang-1.git
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]; ^ git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69462 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
366920a45e
Коммит
a9768b72bb
|
@ -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<
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче