//=======- VirtualCallChecker.cpp --------------------------------*- 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 a checker that checks virtual function calls during 
//  construction or destruction of C++ objects.
//
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Support/SaveAndRestore.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"

using namespace clang;
using namespace ento;

namespace {

class WalkAST : public StmtVisitor<WalkAST> {
  BugReporter &BR;
  AnalysisDeclContext *AC;

  typedef const CallExpr * WorkListUnit;
  typedef SmallVector<WorkListUnit, 20> DFSWorkList;

  /// A vector representing the worklist which has a chain of CallExprs.
  DFSWorkList WList;
  
  // PreVisited : A CallExpr to this FunctionDecl is in the worklist, but the
  // body has not been visited yet.
  // PostVisited : A CallExpr to this FunctionDecl is in the worklist, and the
  // body has been visited.
  enum Kind { NotVisited,
              PreVisited,  /**< A CallExpr to this FunctionDecl is in the 
                                worklist, but the body has not yet been
                                visited. */
              PostVisited  /**< A CallExpr to this FunctionDecl is in the
                                worklist, and the body has been visited. */
  } K;

  /// A DenseMap that records visited states of FunctionDecls.
  llvm::DenseMap<const FunctionDecl *, Kind> VisitedFunctions;

  /// The CallExpr whose body is currently being visited.  This is used for
  /// generating bug reports.  This is null while visiting the body of a
  /// constructor or destructor.
  const CallExpr *visitingCallExpr;
  
public:
  WalkAST(BugReporter &br, AnalysisDeclContext *ac)
    : BR(br),
      AC(ac),
      visitingCallExpr(0) {}
  
  bool hasWork() const { return !WList.empty(); }

  /// This method adds a CallExpr to the worklist and marks the callee as
  /// being PreVisited.
  void Enqueue(WorkListUnit WLUnit) {
    const FunctionDecl *FD = WLUnit->getDirectCallee();
    if (!FD || !FD->getBody())
      return;    
    Kind &K = VisitedFunctions[FD];
    if (K != NotVisited)
      return;
    K = PreVisited;
    WList.push_back(WLUnit);
  }

  /// This method returns an item from the worklist without removing it.
  WorkListUnit Dequeue() {
    assert(!WList.empty());
    return WList.back();    
  }
  
  void Execute() {
    while (hasWork()) {
      WorkListUnit WLUnit = Dequeue();
      const FunctionDecl *FD = WLUnit->getDirectCallee();
      assert(FD && FD->getBody());

      if (VisitedFunctions[FD] == PreVisited) {
        // If the callee is PreVisited, walk its body.
        // Visit the body.
        SaveAndRestore<const CallExpr *> SaveCall(visitingCallExpr, WLUnit);
        Visit(FD->getBody());
        
        // Mark the function as being PostVisited to indicate we have
        // scanned the body.
        VisitedFunctions[FD] = PostVisited;
        continue;
      }

      // Otherwise, the callee is PostVisited.
      // Remove it from the worklist.
      assert(VisitedFunctions[FD] == PostVisited);
      WList.pop_back();
    }
  }

  // Stmt visitor methods.
  void VisitCallExpr(CallExpr *CE);
  void VisitCXXMemberCallExpr(CallExpr *CE);
  void VisitStmt(Stmt *S) { VisitChildren(S); }
  void VisitChildren(Stmt *S);
  
  void ReportVirtualCall(const CallExpr *CE, bool isPure);

};
} // end anonymous namespace

//===----------------------------------------------------------------------===//
// AST walking.
//===----------------------------------------------------------------------===//

void WalkAST::VisitChildren(Stmt *S) {
  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
    if (Stmt *child = *I)
      Visit(child);
}

void WalkAST::VisitCallExpr(CallExpr *CE) {
  VisitChildren(CE);
  Enqueue(CE);
}

void WalkAST::VisitCXXMemberCallExpr(CallExpr *CE) {
  VisitChildren(CE);
  bool callIsNonVirtual = false;
  
  // Several situations to elide for checking.
  if (MemberExpr *CME = dyn_cast<MemberExpr>(CE->getCallee())) {
    // If the member access is fully qualified (i.e., X::F), then treat
    // this as a non-virtual call and do not warn.
    if (CME->getQualifier())
      callIsNonVirtual = true;

    // Elide analyzing the call entirely if the base pointer is not 'this'.
    if (Expr *base = CME->getBase()->IgnoreImpCasts())
      if (!isa<CXXThisExpr>(base))
        return;
  }

  // Get the callee.
  const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CE->getDirectCallee());
  if (MD && MD->isVirtual() && !callIsNonVirtual)
    ReportVirtualCall(CE, MD->isPure());

  Enqueue(CE);
}

void WalkAST::ReportVirtualCall(const CallExpr *CE, bool isPure) {
  llvm::SmallString<100> buf;
  llvm::raw_svector_ostream os(buf);
  
  os << "Call Path : ";
  // Name of current visiting CallExpr.
  os << CE->getDirectCallee()->getNameAsString();

  // Name of the CallExpr whose body is current walking.
  if (visitingCallExpr)
    os << " <-- " << visitingCallExpr->getDirectCallee()->getNameAsString();
  // Names of FunctionDecls in worklist with state PostVisited.
  for (SmallVectorImpl<const CallExpr *>::iterator I = WList.end(),
         E = WList.begin(); I != E; --I) {
    const FunctionDecl *FD = (*(I-1))->getDirectCallee();
    assert(FD);
    if (VisitedFunctions[FD] == PostVisited)
      os << " <-- " << FD->getNameAsString();
  }

  PathDiagnosticLocation CELoc =
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
  SourceRange R = CE->getCallee()->getSourceRange();
  
  if (isPure) {
    os << "\n" <<  "Call pure virtual functions during construction or "
       << "destruction may leads undefined behaviour";
    BR.EmitBasicReport("Call pure virtual function during construction or "
                       "Destruction",
                       "Cplusplus",
                       os.str(), CELoc, &R, 1);
    return;
  }
  else {
    os << "\n" << "Call virtual functions during construction or "
       << "destruction will never go to a more derived class";
    BR.EmitBasicReport("Call virtual function during construction or "
                       "Destruction",
                       "Cplusplus",
                       os.str(), CELoc, &R, 1);
    return;
  }
}

//===----------------------------------------------------------------------===//
// VirtualCallChecker
//===----------------------------------------------------------------------===//

namespace {
class VirtualCallChecker : public Checker<check::ASTDecl<CXXRecordDecl> > {
public:
  void checkASTDecl(const CXXRecordDecl *RD, AnalysisManager& mgr,
                    BugReporter &BR) const {
    WalkAST walker(BR, mgr.getAnalysisDeclContext(RD));

    // Check the constructors.
    for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(), E = RD->ctor_end();
         I != E; ++I) {
      if (!I->isCopyOrMoveConstructor())
        if (Stmt *Body = I->getBody()) {
          walker.Visit(Body);
          walker.Execute();
        }
    }

    // Check the destructor.
    if (CXXDestructorDecl *DD = RD->getDestructor())
      if (Stmt *Body = DD->getBody()) {
        walker.Visit(Body);
        walker.Execute();
      }
  }
};
}

void ento::registerVirtualCallChecker(CheckerManager &mgr) {
  mgr.registerChecker<VirtualCallChecker>();
}
