forked from OSchip/llvm-project
In Microsoft mode, downgrade "goto into protected scope" from error to warning if we are jumping over a variable initialization via a goto.
This fixes a few errors when parsing MFC code with clang. llvm-svn: 139595
This commit is contained in:
parent
03faf78953
commit
051f5e5cba
|
@ -2657,6 +2657,8 @@ def warn_unused_label : Warning<"unused label %0">,
|
|||
InGroup<UnusedLabel>, DefaultIgnore;
|
||||
|
||||
def err_goto_into_protected_scope : Error<"goto into protected scope">;
|
||||
def warn_goto_into_protected_scope : ExtWarn<"goto into protected scope">,
|
||||
InGroup<Microsoft>;
|
||||
def err_switch_into_protected_scope : Error<
|
||||
"switch case is in protected scope">;
|
||||
def err_indirect_goto_without_addrlabel : Error<
|
||||
|
|
|
@ -76,8 +76,8 @@ private:
|
|||
void VerifyIndirectJumps();
|
||||
void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope,
|
||||
LabelDecl *Target, unsigned TargetScope);
|
||||
void CheckJump(Stmt *From, Stmt *To,
|
||||
SourceLocation DiagLoc, unsigned JumpDiag);
|
||||
void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
|
||||
unsigned JumpDiag, unsigned JumpDiagWarning);
|
||||
|
||||
unsigned GetDeepestCommonScope(unsigned A, unsigned B);
|
||||
};
|
||||
|
@ -476,7 +476,8 @@ void JumpScopeChecker::VerifyJumps() {
|
|||
// With a goto,
|
||||
if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
|
||||
CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
|
||||
diag::err_goto_into_protected_scope);
|
||||
diag::err_goto_into_protected_scope,
|
||||
diag::warn_goto_into_protected_scope);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -484,7 +485,7 @@ void JumpScopeChecker::VerifyJumps() {
|
|||
if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) {
|
||||
LabelDecl *Target = IGS->getConstantTarget();
|
||||
CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(),
|
||||
diag::err_goto_into_protected_scope);
|
||||
diag::err_goto_into_protected_scope, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -493,7 +494,7 @@ void JumpScopeChecker::VerifyJumps() {
|
|||
SC = SC->getNextSwitchCase()) {
|
||||
assert(LabelAndGotoScopes.count(SC) && "Case not visited?");
|
||||
CheckJump(SS, SC, SC->getLocStart(),
|
||||
diag::err_switch_into_protected_scope);
|
||||
diag::err_switch_into_protected_scope, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -660,10 +661,20 @@ void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump,
|
|||
S.Diag(Scopes[I].Loc, Scopes[I].InDiag);
|
||||
}
|
||||
|
||||
/// Return true if a particular error+note combination must be downgraded
|
||||
/// to a warning in Microsoft mode.
|
||||
static bool IsMicrosoftJumpWarning(unsigned JumpDiag, unsigned InDiagNote)
|
||||
{
|
||||
return (JumpDiag == diag::err_goto_into_protected_scope &&
|
||||
(InDiagNote == diag::note_protected_by_variable_init ||
|
||||
InDiagNote == diag::note_protected_by_variable_nontriv_destructor));
|
||||
}
|
||||
|
||||
|
||||
/// 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 *From, Stmt *To,
|
||||
SourceLocation DiagLoc, unsigned JumpDiag) {
|
||||
void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
|
||||
unsigned JumpDiagError, unsigned JumpDiagWarning) {
|
||||
assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?");
|
||||
unsigned FromScope = LabelAndGotoScopes[From];
|
||||
|
||||
|
@ -679,19 +690,30 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To,
|
|||
if (CommonScope == ToScope) return;
|
||||
|
||||
// Pull out (and reverse) any scopes we might need to diagnose skipping.
|
||||
SmallVector<unsigned, 10> ToScopes;
|
||||
for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope)
|
||||
if (Scopes[I].InDiag)
|
||||
ToScopes.push_back(I);
|
||||
SmallVector<unsigned, 10> ToScopesError;
|
||||
SmallVector<unsigned, 10> ToScopesWarning;
|
||||
for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) {
|
||||
if (S.getLangOptions().Microsoft &&
|
||||
IsMicrosoftJumpWarning(JumpDiagError, Scopes[I].InDiag))
|
||||
ToScopesWarning.push_back(I);
|
||||
else if (Scopes[I].InDiag)
|
||||
ToScopesError.push_back(I);
|
||||
}
|
||||
|
||||
// If the only scopes present are cleanup scopes, we're okay.
|
||||
if (ToScopes.empty()) return;
|
||||
// Handle warnings.
|
||||
if (!ToScopesWarning.empty()) {
|
||||
S.Diag(DiagLoc, JumpDiagWarning);
|
||||
for (unsigned i = 0, e = ToScopesWarning.size(); i != e; ++i)
|
||||
S.Diag(Scopes[ToScopesWarning[i]].Loc, Scopes[ToScopesWarning[i]].InDiag);
|
||||
}
|
||||
|
||||
S.Diag(DiagLoc, JumpDiag);
|
||||
|
||||
// Emit diagnostics for whatever is left in ToScopes.
|
||||
for (unsigned i = 0, e = ToScopes.size(); i != e; ++i)
|
||||
S.Diag(Scopes[ToScopes[i]].Loc, Scopes[ToScopes[i]].InDiag);
|
||||
// Handle errors.
|
||||
if (!ToScopesError.empty()) {
|
||||
S.Diag(DiagLoc, JumpDiagError);
|
||||
// Emit diagnostics note for whatever is left in ToScopesError.
|
||||
for (unsigned i = 0, e = ToScopesError.size(); i != e; ++i)
|
||||
S.Diag(Scopes[ToScopesError[i]].Loc, Scopes[ToScopesError[i]].InDiag);
|
||||
}
|
||||
}
|
||||
|
||||
void Sema::DiagnoseInvalidJumps(Stmt *Body) {
|
||||
|
|
|
@ -255,4 +255,58 @@ void f()
|
|||
Z* b;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ms_protected_scope {
|
||||
struct C { C(); };
|
||||
|
||||
int jump_over_variable_init(bool b) {
|
||||
if (b)
|
||||
goto foo; // expected-warning {{illegal goto into protected scope}}
|
||||
C c; // expected-note {{jump bypasses variable initialization}}
|
||||
foo:
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct Y {
|
||||
~Y();
|
||||
};
|
||||
|
||||
void jump_over_var_with_dtor() {
|
||||
goto end; // expected-warning{{goto into protected scope}}
|
||||
Y y; // expected-note {{jump bypasses variable initialization}}
|
||||
end:
|
||||
;
|
||||
}
|
||||
|
||||
void jump_over_variable_case(int c) {
|
||||
switch (c) {
|
||||
case 0:
|
||||
int x = 56; // expected-note {{jump bypasses variable initialization}}
|
||||
case 1: // expected-error {{switch case is in protected scope}}
|
||||
x = 10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void exception_jump() {
|
||||
goto l2; // expected-error {{illegal goto into protected scope}}
|
||||
try { // expected-note {{jump bypasses initialization of try block}}
|
||||
l2: ;
|
||||
} catch(int) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue