diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp | 79 |
1 files changed, 51 insertions, 28 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp index 59bc263..3e74dfc 100644 --- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp @@ -1,4 +1,4 @@ -//===--- JumpDiagnostics.cpp - Analyze Jump Targets for VLA issues --------===// +//===--- JumpDiagnostics.cpp - Protected scope jump analysis ------*- C++ -*-=// // // The LLVM Compiler Infrastructure // @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file implements the JumpScopeChecker class, which is used to diagnose -// jumps that enter a VLA scope in an invalid way. +// jumps that enter a protected scope in an invalid way. // //===----------------------------------------------------------------------===// @@ -58,12 +58,12 @@ class JumpScopeChecker { : ParentScope(parentScope), InDiag(InDiag), OutDiag(OutDiag), Loc(L) {} }; - llvm::SmallVector<GotoScope, 48> Scopes; + SmallVector<GotoScope, 48> Scopes; llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes; - llvm::SmallVector<Stmt*, 16> Jumps; + SmallVector<Stmt*, 16> Jumps; - llvm::SmallVector<IndirectGotoStmt*, 4> IndirectJumps; - llvm::SmallVector<LabelDecl*, 4> IndirectJumpTargets; + SmallVector<IndirectGotoStmt*, 4> IndirectJumps; + SmallVector<LabelDecl*, 4> IndirectJumpTargets; public: JumpScopeChecker(Stmt *Body, Sema &S); private: @@ -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,8 @@ 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, + diag::warn_goto_into_protected_scope); continue; } @@ -493,7 +495,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); } } } @@ -532,10 +534,10 @@ void JumpScopeChecker::VerifyIndirectJumps() { // indirect goto. For most code bases, this substantially cuts // down on the number of jump sites we'll have to consider later. typedef std::pair<unsigned, IndirectGotoStmt*> JumpScope; - llvm::SmallVector<JumpScope, 32> JumpScopes; + SmallVector<JumpScope, 32> JumpScopes; { llvm::DenseMap<unsigned, IndirectGotoStmt*> JumpScopesMap; - for (llvm::SmallVectorImpl<IndirectGotoStmt*>::iterator + for (SmallVectorImpl<IndirectGotoStmt*>::iterator I = IndirectJumps.begin(), E = IndirectJumps.end(); I != E; ++I) { IndirectGotoStmt *IG = *I; assert(LabelAndGotoScopes.count(IG) && @@ -554,7 +556,7 @@ void JumpScopeChecker::VerifyIndirectJumps() { // label whose address was taken somewhere in the function. // For most code bases, there will be only one such scope. llvm::DenseMap<unsigned, LabelDecl*> TargetScopes; - for (llvm::SmallVectorImpl<LabelDecl*>::iterator + for (SmallVectorImpl<LabelDecl*>::iterator I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end(); I != E; ++I) { LabelDecl *TheLabel = *I; @@ -599,7 +601,7 @@ void JumpScopeChecker::VerifyIndirectJumps() { // Walk through all the jump sites, checking that they can trivially // reach this label scope. - for (llvm::SmallVectorImpl<JumpScope>::iterator + for (SmallVectorImpl<JumpScope>::iterator I = JumpScopes.begin(), E = JumpScopes.end(); I != E; ++I) { unsigned Scope = I->first; @@ -660,10 +662,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 +691,30 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, if (CommonScope == ToScope) return; // Pull out (and reverse) any scopes we might need to diagnose skipping. - llvm::SmallVector<unsigned, 10> 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<unsigned, 10> ToScopesError; + SmallVector<unsigned, 10> ToScopesWarning; + for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) { + if (S.getLangOptions().MicrosoftMode && JumpDiagWarning != 0 && + 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) { |