From c985b88efc9188845952ab524fe6d4717705257b Mon Sep 17 00:00:00 2001 From: Francois Pichet Date: Tue, 13 Sep 2011 10:26:51 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139595 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 + lib/Sema/JumpDiagnostics.cpp | 58 +++++++++++++++------- test/SemaCXX/MicrosoftExtensions.cpp | 56 ++++++++++++++++++++- 3 files changed, 97 insertions(+), 19 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 651a642cc3..0a0fea3868 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2657,6 +2657,8 @@ def warn_unused_label : Warning<"unused label %0">, InGroup, DefaultIgnore; def err_goto_into_protected_scope : Error<"goto into protected scope">; +def warn_goto_into_protected_scope : ExtWarn<"goto into protected scope">, + InGroup; def err_switch_into_protected_scope : Error< "switch case is in protected scope">; def err_indirect_goto_without_addrlabel : Error< diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index 2b32518f64..565a610b8c 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -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(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(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 ToScopes; - for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) - if (Scopes[I].InDiag) - ToScopes.push_back(I); - - // If the only scopes present are cleanup scopes, we're okay. - if (ToScopes.empty()) return; + SmallVector ToScopesError; + SmallVector 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); + } - S.Diag(DiagLoc, JumpDiag); + // 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); + } - // 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) { diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index db6d30a9c6..d92eda711c 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -255,4 +255,58 @@ void f() Z* b; } - } \ No newline at end of file +} + + + + + + + + + + +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) { + } +} + +} + + + -- 2.40.0