//===--- JumpDiagnostics.cpp - Analyze Jump Targets for VLA issues --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the JumpScopeChecker class, which is used to diagnose
// jumps that enter a VLA scope in an invalid way.
//
//===----------------------------------------------------------------------===//

#include "Sema.h"
#include "clang/AST/Expr.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtCXX.h"
using namespace clang;

namespace {

/// JumpScopeChecker - This object is used by Sema to diagnose invalid jumps
/// into VLA and other protected scopes.  For example, this rejects:
///    goto L;
///    int a[n];
///  L:
///
class JumpScopeChecker {
  Sema &S;

  /// GotoScope - This is a record that we use to keep track of all of the
  /// scopes that are introduced by VLAs and other things that scope jumps like
  /// gotos.  This scope tree has nothing to do with the source scope tree,
  /// because you can have multiple VLA scopes per compound statement, and most
  /// compound statements don't introduce any scopes.
  struct GotoScope {
    /// ParentScope - The index in ScopeMap of the parent scope.  This is 0 for
    /// the parent scope is the function body.
    unsigned ParentScope;

    /// Diag - The diagnostic to emit if there is a jump into this scope.
    unsigned Diag;

    /// Loc - Location to emit the diagnostic.
    SourceLocation Loc;

    GotoScope(unsigned parentScope, unsigned diag, SourceLocation L)
    : ParentScope(parentScope), Diag(diag), Loc(L) {}
  };

  llvm::SmallVector<GotoScope, 48> Scopes;
  llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes;
  llvm::SmallVector<Stmt*, 16> Jumps;
public:
  JumpScopeChecker(Stmt *Body, Sema &S);
private:
  void BuildScopeInformation(Stmt *S, unsigned ParentScope);
  void VerifyJumps();
  void CheckJump(Stmt *From, Stmt *To,
                 SourceLocation DiagLoc, unsigned JumpDiag);
};
} // end anonymous namespace


JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) {
  // Add a scope entry for function scope.
  Scopes.push_back(GotoScope(~0U, ~0U, SourceLocation()));

  // Build information for the top level compound statement, so that we have a
  // defined scope record for every "goto" and label.
  BuildScopeInformation(Body, 0);

  // Check that all jumps we saw are kosher.
  VerifyJumps();
}

/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
/// diagnostic that should be emitted if control goes over it. If not, return 0.
static unsigned GetDiagForGotoScopeDecl(const Decl *D, bool isCPlusPlus) {
  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
    if (VD->getType()->isVariablyModifiedType())
      return diag::note_protected_by_vla;
    if (VD->hasAttr<CleanupAttr>())
      return diag::note_protected_by_cleanup;
    if (VD->hasAttr<BlocksAttr>())
      return diag::note_protected_by___block;
    // FIXME: In C++0x, we have to check more conditions than "did we
    // just give it an initializer?". See 6.7p3.
    if (isCPlusPlus && VD->hasLocalStorage() && VD->hasInit())
      return diag::note_protected_by_variable_init;
    
  } else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
    if (TD->getUnderlyingType()->isVariablyModifiedType())
      return diag::note_protected_by_vla_typedef;
  }

  return 0;
}


/// BuildScopeInformation - The statements from CI to CE are known to form a
/// coherent VLA scope with a specified parent node.  Walk through the
/// statements, adding any labels or gotos to LabelAndGotoScopes and recursively
/// walking the AST as needed.
void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {

  // If we found a label, remember that it is in ParentScope scope.
  if (isa<LabelStmt>(S) || isa<DefaultStmt>(S) || isa<CaseStmt>(S)) {
    LabelAndGotoScopes[S] = ParentScope;
  } else if (isa<GotoStmt>(S) || isa<SwitchStmt>(S) ||
             isa<IndirectGotoStmt>(S) || isa<AddrLabelExpr>(S)) {
    // Remember both what scope a goto is in as well as the fact that we have
    // it.  This makes the second scan not have to walk the AST again.
    LabelAndGotoScopes[S] = ParentScope;
    Jumps.push_back(S);
  }

  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E;
       ++CI) {
    Stmt *SubStmt = *CI;
    if (SubStmt == 0) continue;

    bool isCPlusPlus = this->S.getLangOptions().CPlusPlus;

    // If this is a declstmt with a VLA definition, it defines a scope from here
    // to the end of the containing context.
    if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) {
      // The decl statement creates a scope if any of the decls in it are VLAs
      // or have the cleanup attribute.
      for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
           I != E; ++I) {
        // If this decl causes a new scope, push and switch to it.
        if (unsigned Diag = GetDiagForGotoScopeDecl(*I, isCPlusPlus)) {
          Scopes.push_back(GotoScope(ParentScope, Diag, (*I)->getLocation()));
          ParentScope = Scopes.size()-1;
        }

        // If the decl has an initializer, walk it with the potentially new
        // scope we just installed.
        if (VarDecl *VD = dyn_cast<VarDecl>(*I))
          if (Expr *Init = VD->getInit())
            BuildScopeInformation(Init, ParentScope);
      }
      continue;
    }

    // Disallow jumps into any part of an @try statement by pushing a scope and
    // walking all sub-stmts in that scope.
    if (ObjCAtTryStmt *AT = dyn_cast<ObjCAtTryStmt>(SubStmt)) {
      // Recursively walk the AST for the @try part.
      Scopes.push_back(GotoScope(ParentScope,diag::note_protected_by_objc_try,
                                 AT->getAtTryLoc()));
      if (Stmt *TryPart = AT->getTryBody())
        BuildScopeInformation(TryPart, Scopes.size()-1);

      // Jump from the catch to the finally or try is not valid.
      for (ObjCAtCatchStmt *AC = AT->getCatchStmts(); AC;
           AC = AC->getNextCatchStmt()) {
        Scopes.push_back(GotoScope(ParentScope,
                                   diag::note_protected_by_objc_catch,
                                   AC->getAtCatchLoc()));
        // @catches are nested and it isn't
        BuildScopeInformation(AC->getCatchBody(), Scopes.size()-1);
      }

      // Jump from the finally to the try or catch is not valid.
      if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) {
        Scopes.push_back(GotoScope(ParentScope,
                                   diag::note_protected_by_objc_finally,
                                   AF->getAtFinallyLoc()));
        BuildScopeInformation(AF, Scopes.size()-1);
      }

      continue;
    }

    // Disallow jumps into the protected statement of an @synchronized, but
    // allow jumps into the object expression it protects.
    if (ObjCAtSynchronizedStmt *AS = dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)){
      // Recursively walk the AST for the @synchronized object expr, it is
      // evaluated in the normal scope.
      BuildScopeInformation(AS->getSynchExpr(), ParentScope);

      // Recursively walk the AST for the @synchronized part, protected by a new
      // scope.
      Scopes.push_back(GotoScope(ParentScope,
                                 diag::note_protected_by_objc_synchronized,
                                 AS->getAtSynchronizedLoc()));
      BuildScopeInformation(AS->getSynchBody(), Scopes.size()-1);
      continue;
    }

    // Disallow jumps into any part of a C++ try statement. This is pretty
    // much the same as for Obj-C.
    if (CXXTryStmt *TS = dyn_cast<CXXTryStmt>(SubStmt)) {
      Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_cxx_try,
                                 TS->getSourceRange().getBegin()));
      if (Stmt *TryBlock = TS->getTryBlock())
        BuildScopeInformation(TryBlock, Scopes.size()-1);

      // Jump from the catch into the try is not allowed either.
      for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) {
        CXXCatchStmt *CS = TS->getHandler(I);
        Scopes.push_back(GotoScope(ParentScope,
                                   diag::note_protected_by_cxx_catch,
                                   CS->getSourceRange().getBegin()));
        BuildScopeInformation(CS->getHandlerBlock(), Scopes.size()-1);
      }

      continue;
    }

    // Recursively walk the AST.
    BuildScopeInformation(SubStmt, ParentScope);
  }
}

/// VerifyJumps - Verify each element of the Jumps array to see if they are
/// valid, emitting diagnostics if not.
void JumpScopeChecker::VerifyJumps() {
  while (!Jumps.empty()) {
    Stmt *Jump = Jumps.pop_back_val();

    // With a goto,
    if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
      CheckJump(GS, GS->getLabel(), GS->getGotoLoc(),
                diag::err_goto_into_protected_scope);
      continue;
    }

    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, SC, SC->getLocStart(),
                  diag::err_switch_into_protected_scope);
      }
      continue;
    }

    unsigned DiagnosticScope;

    // We don't know where an indirect goto goes, require that it be at the
    // top level of scoping.
    if (IndirectGotoStmt *IG = dyn_cast<IndirectGotoStmt>(Jump)) {
      assert(LabelAndGotoScopes.count(Jump) &&
             "Jump didn't get added to scopes?");
      unsigned GotoScope = LabelAndGotoScopes[IG];
      if (GotoScope == 0) continue;  // indirect jump is ok.
      S.Diag(IG->getGotoLoc(), diag::err_indirect_goto_in_protected_scope);
      DiagnosticScope = GotoScope;
    } else {
      // We model &&Label as a jump for purposes of scope tracking.  We actually
      // don't care *where* the address of label is, but we require the *label
      // itself* to be in scope 0.  If it is nested inside of a VLA scope, then
      // it is possible for an indirect goto to illegally enter the VLA scope by
      // indirectly jumping to the label.
      assert(isa<AddrLabelExpr>(Jump) && "Unknown jump type");
      LabelStmt *TheLabel = cast<AddrLabelExpr>(Jump)->getLabel();

      assert(LabelAndGotoScopes.count(TheLabel) &&
             "Referenced label didn't get added to scopes?");
      unsigned LabelScope = LabelAndGotoScopes[TheLabel];
      if (LabelScope == 0) continue; // Addr of label is ok.

      S.Diag(Jump->getLocStart(), diag::err_addr_of_label_in_protected_scope);
      DiagnosticScope = LabelScope;
    }

    // Report all the things that would be skipped over by this &&label or
    // indirect goto.
    while (DiagnosticScope != 0) {
      S.Diag(Scopes[DiagnosticScope].Loc, Scopes[DiagnosticScope].Diag);
      DiagnosticScope = Scopes[DiagnosticScope].ParentScope;
    }
  }
}

/// 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) {
  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 (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[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 == ToScope) return;

    // Otherwise, scan up the hierarchy.
    TestScope = Scopes[TestScope].ParentScope;
  }

  // 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(DiagLoc, JumpDiag);

  // Eliminate the common prefix of the jump and the target.  Start by
  // linearizing both scopes, reversing them as we go.
  std::vector<unsigned> FromScopes, ToScopes;
  for (TestScope = FromScope; TestScope != ~0U;
       TestScope = Scopes[TestScope].ParentScope)
    FromScopes.push_back(TestScope);
  for (TestScope = ToScope; TestScope != ~0U;
       TestScope = Scopes[TestScope].ParentScope)
    ToScopes.push_back(TestScope);

  // Remove any common entries (such as the top-level function scope).
  while (!FromScopes.empty() && FromScopes.back() == ToScopes.back()) {
    FromScopes.pop_back();
    ToScopes.pop_back();
  }

  // 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]].Diag);
}

void Sema::DiagnoseInvalidJumps(Stmt *Body) {
  (void)JumpScopeChecker(Body, *this);
}
