//=-- GRExprEngineInternalChecks.cpp - Builtin GRExprEngine Checks---*- C++ -*-=
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the BugType classes used by GRExprEngine to report
//  bugs derived from builtin checks in the path-sensitive engine.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "llvm/Support/Compiler.h"
#include <sstream>

using namespace clang;

//===----------------------------------------------------------------------===//
// Utility functions.
//===----------------------------------------------------------------------===//

template <typename ITERATOR> inline
ExplodedNode<ValueState>* GetNode(ITERATOR I) {
  return *I;
}

template <> inline
ExplodedNode<ValueState>* GetNode(GRExprEngine::undef_arg_iterator I) {
  return I->first;
}

//===----------------------------------------------------------------------===//
// Bug Descriptions.
//===----------------------------------------------------------------------===//

namespace {
class VISIBILITY_HIDDEN BuiltinBug : public BugTypeCacheLocation {
  const char* name;
  const char* desc;
public:
  BuiltinBug(const char* n, const char* d = 0) : name(n), desc(d) {}  
  virtual const char* getName() const { return name; }
  virtual const char* getDescription() const {
    return desc ? desc : name;
  }
  
  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) = 0;
  virtual void EmitWarnings(BugReporter& BR) {
    EmitBuiltinWarnings(BR, cast<GRBugReporter>(BR).getEngine());
  }
  
  template <typename ITER>
  void Emit(BugReporter& BR, ITER I, ITER E) {
    for (; I != E; ++I) {
      BugReport R(*this, GetNode(I));
      BR.EmitWarning(R);
    }
  }
};
  
class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
public:
  NullDeref() : BuiltinBug("null dereference",
                           "Dereference of null pointer.") {}

  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
    Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
  }
};
  
class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
public:
  UndefinedDeref() : BuiltinBug("bad dereference",
                                "Dereference of undefined value.") {}
  
  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
    Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
  }
};

class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
public:
  DivZero() : BuiltinBug("divide-by-zero",
                         "Division by zero/undefined value.") {}
  
  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
    Emit(BR, Eng.explicit_bad_divides_begin(), Eng.explicit_bad_divides_end());
  }
};
  
class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
public:
  UndefResult() : BuiltinBug("undefined result",
                             "Result of operation is undefined.") {}
  
  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
    Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end());
  }
};
  
class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
public:
  BadCall()
  : BuiltinBug("invalid function call",
        "Called function is a NULL or undefined function pointer value.") {}
  
  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
    Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
  }
};

class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
public:
  BadArg() : BuiltinBug("bad argument",  
    "Pass-by-value argument in function is undefined.") {}

  BadArg(const char* d) : BuiltinBug("bad argument", d) {}
  
  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
    for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
         E = Eng.undef_arg_end(); I!=E; ++I) {

      // Generate a report for this bug.
      RangedBugReport report(*this, I->first);
      report.addRange(I->second->getSourceRange());

      // Emit the warning.
      BR.EmitWarning(report);
    }
  }
};
  
class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
public:
  BadMsgExprArg() 
    : BadArg("Pass-by-value argument in message expression is undefined.") {}
  
  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
    for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
         E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
      
      // Generate a report for this bug.
      RangedBugReport report(*this, I->first);
      report.addRange(I->second->getSourceRange());
      
      // Emit the warning.
      BR.EmitWarning(report);
    }    
  }
};
  
class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
public:  
  BadReceiver()
  : BuiltinBug("bad receiver",
               "Receiver in message expression is an uninitialized value.") {}
  
  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
    for (GRExprEngine::UndefReceiversTy::iterator I=Eng.undef_receivers_begin(),
         End = Eng.undef_receivers_end(); I!=End; ++I) {
      
      // Generate a report for this bug.
      RangedBugReport report(*this, *I);
      
      ExplodedNode<ValueState>* N = *I;
      Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
      Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
      assert (E && "Receiver cannot be NULL");
      report.addRange(E->getSourceRange());
      
      // Emit the warning.
      BR.EmitWarning(report);
    }    
  }
};
  
class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
public:
  RetStack() : BuiltinBug("return of stack address") {}
  
  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
    for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
         End = Eng.ret_stackaddr_end(); I!=End; ++I) {

      ExplodedNode<ValueState>* N = *I;
      Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
      Expr* E = cast<ReturnStmt>(S)->getRetValue();
      assert (E && "Return expression cannot be NULL");
      
      // Get the value associated with E.
      lval::DeclVal V =
        cast<lval::DeclVal>(Eng.getStateManager().GetRVal(N->getState(), E));
      
      // Generate a report for this bug.
      std::ostringstream os;
      os << "Address of stack memory associated with local variable '"
         << V.getDecl()->getName() << "' returned.";
      
      std::string s = os.str();
      
      RangedBugReport report(*this, N, s.c_str());
      report.addRange(E->getSourceRange());
      
      // Emit the warning.
      BR.EmitWarning(report);
    }
  }
};


class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
  struct VISIBILITY_HIDDEN FindUndefExpr {
    ValueStateManager& VM;
    const ValueState* St;
    
    FindUndefExpr(ValueStateManager& V, const ValueState* S) : VM(V), St(S) {}
    
    Expr* FindExpr(Expr* Ex) {      
      if (!MatchesCriteria(Ex))
        return 0;
      
      for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
        if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
          Expr* E2 = FindExpr(ExI);
          if (E2) return E2;
        }
      
      return Ex;
    }
    
    bool MatchesCriteria(Expr* Ex) { return VM.GetRVal(St, Ex).isUndef(); }
  };
  
public:
  UndefBranch()
    : BuiltinBug("uninitialized value",
                 "Branch condition evaluates to an uninitialized value.") {}
  
  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
    for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
         E=Eng.undef_branches_end(); I!=E; ++I) {

      // What's going on here: we want to highlight the subexpression of the
      // condition that is the most likely source of the "uninitialized
      // branch condition."  We do a recursive walk of the condition's
      // subexpressions and roughly look for the most nested subexpression
      // that binds to Undefined.  We then highlight that expression's range.

      BlockEdge B = cast<BlockEdge>((*I)->getLocation());
      Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
      assert (Ex && "Block must have a terminator.");

      // Get the predecessor node and check if is a PostStmt with the Stmt
      // being the terminator condition.  We want to inspect the state
      // of that node instead because it will contain main information about
      // the subexpressions.

      assert (!(*I)->pred_empty());

      // Note: any predecessor will do.  They should have identical state,
      // since all the BlockEdge did was act as an error sink since the value
      // had to already be undefined.
      ExplodedNode<ValueState> *N = *(*I)->pred_begin();
      ProgramPoint P = N->getLocation();

      const ValueState* St = (*I)->getState();

      if (PostStmt* PS = dyn_cast<PostStmt>(&P))
        if (PS->getStmt() == Ex)
          St = N->getState();

      FindUndefExpr FindIt(Eng.getStateManager(), St);
      Ex = FindIt.FindExpr(Ex);

      RangedBugReport R(*this, *I);
      R.addRange(Ex->getSourceRange());

      BR.EmitWarning(R);
    }
  }
};

//===----------------------------------------------------------------------===//
// __attribute__(nonnull) checking

class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
  SimpleBugType BT;
  std::list<RangedBugReport> Reports;
  
public:
  CheckAttrNonNull() :
  BT("'nonnull' argument passed null",
     "Null pointer passed as an argument to a 'nonnull' parameter") {}

  virtual bool Audit(ExplodedNode<ValueState>* N, ValueStateManager& VMgr) {
    CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
    const ValueState* state = N->getState();
    
    RVal X = VMgr.GetRVal(state, CE->getCallee());
    
    if (!isa<lval::FuncVal>(X))
      return false;
    
    FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<lval::FuncVal>(X).getDecl());
    const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
    
    if (!Att)
      return false;
    
    // Iterate through the arguments of CE and check them for null.
    
    unsigned idx = 0;
    bool hasError = false;
    
    for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
         ++I, ++idx) {
      
      if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
        continue;
      
      RangedBugReport R(BT, N);
      R.addRange((*I)->getSourceRange());
      Reports.push_back(R);
      hasError = true;
    }
    
    return hasError;
  }
  
  virtual void EmitWarnings(BugReporter& BR) {
    for (std::list<RangedBugReport>::iterator I=Reports.begin(),
         E=Reports.end(); I!=E; ++I)
      BR.EmitWarning(*I);
  }
};
} // end anonymous namespace

//===----------------------------------------------------------------------===//
// Check registration.

void GRExprEngine::RegisterInternalChecks() {
  Register(new NullDeref());
  Register(new UndefinedDeref());
  Register(new UndefBranch());
  Register(new DivZero());
  Register(new UndefResult());
  Register(new BadCall());
  Register(new RetStack());
  Register(new BadArg());
  Register(new BadMsgExprArg());
  Register(new BadReceiver());
  AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass); 
}
