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 59bc2637c8f3..3e74dfccbdb1 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) {  | 
