//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// "Meta" ASTConsumer for running different source analyses.
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/AnalysisConsumer.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ParentMap.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/Analyses/UninitializedValues.h"
#include "clang/Analysis/CFG.h"
#include "clang/Checker/Checkers/LocalCheckers.h"
#include "clang/Checker/ManagerRegistry.h"
#include "clang/Checker/BugReporter/PathDiagnostic.h"
#include "clang/Checker/PathSensitive/AnalysisManager.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "clang/Checker/PathSensitive/GRExprEngine.h"
#include "clang/Checker/PathSensitive/GRTransferFuncs.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/PathDiagnosticClients.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/System/Program.h"
#include "llvm/ADT/OwningPtr.h"

using namespace clang;

static ExplodedNode::Auditor* CreateUbiViz();

//===----------------------------------------------------------------------===//
// Basic type definitions.
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Special PathDiagnosticClients.
//===----------------------------------------------------------------------===//

static PathDiagnosticClient*
CreatePlistHTMLDiagnosticClient(const std::string& prefix,
                                const Preprocessor &PP) {
  llvm::sys::Path F(prefix);
  PathDiagnosticClient *PD = CreateHTMLDiagnosticClient(F.getDirname(), PP);
  return CreatePlistDiagnosticClient(prefix, PP, PD);
}

//===----------------------------------------------------------------------===//
// AnalysisConsumer declaration.
//===----------------------------------------------------------------------===//

namespace {

 class AnalysisConsumer : public ASTConsumer {
 public:
  typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);
  typedef void (*TUAction)(AnalysisConsumer &C, AnalysisManager &M,
                           TranslationUnitDecl &TU);

 private:
  typedef std::vector<CodeAction> Actions;
  typedef std::vector<TUAction> TUActions;

  Actions FunctionActions;
  Actions ObjCMethodActions;
  Actions ObjCImplementationActions;
  TUActions TranslationUnitActions;

public:
  ASTContext* Ctx;
  const Preprocessor &PP;
  const std::string OutDir;
  AnalyzerOptions Opts;
  bool declDisplayed;


  // PD is owned by AnalysisManager.
  PathDiagnosticClient *PD;

  StoreManagerCreator CreateStoreMgr;
  ConstraintManagerCreator CreateConstraintMgr;

  llvm::OwningPtr<AnalysisManager> Mgr;

  AnalysisConsumer(const Preprocessor& pp,
                   const std::string& outdir,
                   const AnalyzerOptions& opts)
    : Ctx(0), PP(pp), OutDir(outdir),
      Opts(opts), declDisplayed(false), PD(0) {
    DigestAnalyzerOptions();
  }

  void DigestAnalyzerOptions() {
    // Create the PathDiagnosticClient.
    if (!OutDir.empty()) {
      switch (Opts.AnalysisDiagOpt) {
      default:
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
        case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
#include "clang/Frontend/Analyses.def"
      }
    }

    // Create the analyzer component creators.
    if (ManagerRegistry::StoreMgrCreator != 0) {
      CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
    }
    else {
      switch (Opts.AnalysisStoreOpt) {
      default:
        assert(0 && "Unknown store manager.");
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN)           \
        case NAME##Model: CreateStoreMgr = CREATEFN; break;
#include "clang/Frontend/Analyses.def"
      }
    }

    if (ManagerRegistry::ConstraintMgrCreator != 0)
      CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
    else {
      switch (Opts.AnalysisConstraintsOpt) {
      default:
        assert(0 && "Unknown store manager.");
#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
        case NAME##Model: CreateConstraintMgr = CREATEFN; break;
#include "clang/Frontend/Analyses.def"
      }
    }
  }

  void DisplayFunction(const Decl *D) {
    if (!Opts.AnalyzerDisplayProgress || declDisplayed)
      return;

    declDisplayed = true;
    SourceManager &SM = Mgr->getASTContext().getSourceManager();
    PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
    llvm::errs() << "ANALYZE: " << Loc.getFilename();

    if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
      const NamedDecl *ND = cast<NamedDecl>(D);
      llvm::errs() << ' ' << ND->getNameAsString() << '\n';
    }
    else if (isa<BlockDecl>(D)) {
      llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
                   << Loc.getColumn() << '\n';
    }
  }

  void addCodeAction(CodeAction action) {
    FunctionActions.push_back(action);
    ObjCMethodActions.push_back(action);
  }

  void addObjCImplementationAction(CodeAction action) {
    ObjCImplementationActions.push_back(action);
  }

  void addTranslationUnitAction(TUAction action) {
    TranslationUnitActions.push_back(action);
  }

  virtual void Initialize(ASTContext &Context) {
    Ctx = &Context;
    Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
                                  PP.getLangOptions(), PD,
                                  CreateStoreMgr, CreateConstraintMgr,
                                  Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
                                  Opts.PurgeDead, Opts.EagerlyAssume,
                                  Opts.TrimGraph));
  }

  virtual void HandleTopLevelDecl(DeclGroupRef D) {
    declDisplayed = false;
    for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
      HandleTopLevelSingleDecl(*I);
  }

  void HandleTopLevelSingleDecl(Decl *D);
  virtual void HandleTranslationUnit(ASTContext &C);

  void HandleCode(Decl* D, Stmt* Body, Actions& actions);
};
} // end anonymous namespace

namespace llvm {
  template <> struct FoldingSetTrait<AnalysisConsumer::CodeAction> {
    static inline void Profile(AnalysisConsumer::CodeAction X,
                               FoldingSetNodeID& ID) {
      ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
    }
  };
}

//===----------------------------------------------------------------------===//
// AnalysisConsumer implementation.
//===----------------------------------------------------------------------===//

void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) {
  switch (D->getKind()) {
  case Decl::CXXConstructor:
  case Decl::CXXDestructor:
  case Decl::CXXConversion:
  case Decl::CXXMethod:
  case Decl::Function: {
    FunctionDecl* FD = cast<FunctionDecl>(D);
    if (!Opts.AnalyzeSpecificFunction.empty() &&
        FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
        break;

    if (Stmt *Body = FD->getBody())
      HandleCode(FD, Body, FunctionActions);
    break;
  }

  case Decl::ObjCMethod: {
    ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);

    if (!Opts.AnalyzeSpecificFunction.empty() &&
        Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString())
      return;

    if (Stmt* Body = MD->getBody())
      HandleCode(MD, Body, ObjCMethodActions);
    break;
  }

  default:
    break;
  }
}

void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {

  TranslationUnitDecl *TU = C.getTranslationUnitDecl();

  for (TUActions::iterator I = TranslationUnitActions.begin(),
                           E = TranslationUnitActions.end(); I != E; ++I) {
    (*I)(*this, *Mgr, *TU);
  }

  if (!ObjCImplementationActions.empty()) {
    for (DeclContext::decl_iterator I = TU->decls_begin(),
                                    E = TU->decls_end();
         I != E; ++I)
      if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
        HandleCode(ID, 0, ObjCImplementationActions);
  }

  // Explicitly destroy the PathDiagnosticClient.  This will flush its output.
  // FIXME: This should be replaced with something that doesn't rely on
  // side-effects in PathDiagnosticClient's destructor. This is required when
  // used with option -disable-free.
  Mgr.reset(NULL);
}

static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) {
  if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
    WL.push_back(BD);

  for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
       I!=E; ++I)
    if (DeclContext *DC = dyn_cast<DeclContext>(*I))
      FindBlocks(DC, WL);
}

void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {

  // Don't run the actions if an error has occured with parsing the file.
  if (PP.getDiagnostics().hasErrorOccurred())
    return;

  // Don't run the actions on declarations in header files unless
  // otherwise specified.
  if (!Opts.AnalyzeAll &&
      !Ctx->getSourceManager().isFromMainFile(D->getLocation()))
    return;

  // Clear the AnalysisManager of old AnalysisContexts.
  Mgr->ClearContexts();

  // Dispatch on the actions.
  llvm::SmallVector<Decl*, 10> WL;
  WL.push_back(D);

  if (Body && Opts.AnalyzeNestedBlocks)
    FindBlocks(cast<DeclContext>(D), WL);

  for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
    for (llvm::SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
         WI != WE; ++WI)
      (*I)(*this, *Mgr, *WI);
}

//===----------------------------------------------------------------------===//
// Analyses
//===----------------------------------------------------------------------===//

static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,
                                 Decl *D) {
  if (LiveVariables *L = mgr.getLiveVariables(D)) {
    C.DisplayFunction(D);
    BugReporter BR(mgr);
    CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);
  }
}

static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,
                                 Decl *D) {
  if (CFG* c = mgr.getCFG(D)) {
    C.DisplayFunction(D);
    CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
  }
}


static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
                               Decl *D,
                               GRTransferFuncs* tf) {

  llvm::OwningPtr<GRTransferFuncs> TF(tf);

  // Display progress.
  C.DisplayFunction(D);

  // Construct the analysis engine.  We first query for the LiveVariables
  // information to see if the CFG is valid.
  // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
  if (!mgr.getLiveVariables(D))
    return;

  GRExprEngine Eng(mgr, TF.take());

  if (C.Opts.EnableExperimentalInternalChecks)
    RegisterExperimentalInternalChecks(Eng);

  RegisterAppleChecks(Eng, *D);

  if (C.Opts.EnableExperimentalChecks)
    RegisterExperimentalChecks(Eng);

  // Set the graph auditor.
  llvm::OwningPtr<ExplodedNode::Auditor> Auditor;
  if (mgr.shouldVisualizeUbigraph()) {
    Auditor.reset(CreateUbiViz());
    ExplodedNode::SetAuditor(Auditor.get());
  }

  // Execute the worklist algorithm.
  Eng.ExecuteWorkList(mgr.getStackFrame(D));

  // Release the auditor (if any) so that it doesn't monitor the graph
  // created BugReporter.
  ExplodedNode::SetAuditor(0);

  // Visualize the exploded graph.
  if (mgr.shouldVisualizeGraphviz())
    Eng.ViewGraph(mgr.shouldTrimGraph());

  // Display warnings.
  Eng.getBugReporter().FlushReports();
}

static void ActionObjCMemCheckerAux(AnalysisConsumer &C, AnalysisManager& mgr,
                                  Decl *D, bool GCEnabled) {

  GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
                                         GCEnabled,
                                         mgr.getLangOptions());

  ActionGRExprEngine(C, mgr, D, TF);
}

static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr,
                               Decl *D) {

 switch (mgr.getLangOptions().getGCMode()) {
 default:
   assert (false && "Invalid GC mode.");
 case LangOptions::NonGC:
   ActionObjCMemCheckerAux(C, mgr, D, false);
   break;

 case LangOptions::GCOnly:
   ActionObjCMemCheckerAux(C, mgr, D, true);
   break;

 case LangOptions::HybridGC:
   ActionObjCMemCheckerAux(C, mgr, D, false);
   ActionObjCMemCheckerAux(C, mgr, D, true);
   break;
 }
}

static void ActionDisplayLiveVariables(AnalysisConsumer &C,
                                       AnalysisManager& mgr, Decl *D) {
  if (LiveVariables* L = mgr.getLiveVariables(D)) {
    C.DisplayFunction(D);
    L->dumpBlockLiveness(mgr.getSourceManager());
  }
}

static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
  if (CFG *cfg = mgr.getCFG(D)) {
    C.DisplayFunction(D);
    cfg->dump(mgr.getLangOptions());
  }
}

static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
  if (CFG *cfg = mgr.getCFG(D)) {
    C.DisplayFunction(D);
    cfg->viewCFG(mgr.getLangOptions());
  }
}

static void ActionSecuritySyntacticChecks(AnalysisConsumer &C,
                                          AnalysisManager &mgr, Decl *D) {
  C.DisplayFunction(D);
  BugReporter BR(mgr);
  CheckSecuritySyntaxOnly(D, BR);
}

static void ActionLLVMConventionChecker(AnalysisConsumer &C,
                                        AnalysisManager &mgr,
                                        TranslationUnitDecl &TU) {
  BugReporter BR(mgr);
  CheckLLVMConventions(TU, BR);
}

static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr,
                                  Decl *D) {
  if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
    return;

  C.DisplayFunction(D);
  BugReporter BR(mgr);
  CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
}

static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr,
                                      Decl *D) {
  C.DisplayFunction(D);
  BugReporter BR(mgr);
  CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
}

static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr,
                                   Decl *D) {
  C.DisplayFunction(D);
  BugReporter BR(mgr);
  CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR);
}

static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr,
                                    Decl *D) {
  C.DisplayFunction(D);
  BugReporter BR(mgr);
  CheckSizeofPointer(D, BR);
}

static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr,
                             TranslationUnitDecl &TU) {

  // Find the entry function definition (if any).
  FunctionDecl *D = 0;

  // Must specify an entry function.
  if (!C.Opts.AnalyzeSpecificFunction.empty()) {
    for (DeclContext::decl_iterator I=TU.decls_begin(), E=TU.decls_end();
         I != E; ++I) {
      if (FunctionDecl *fd = dyn_cast<FunctionDecl>(*I))
        if (fd->isThisDeclarationADefinition() &&
            fd->getNameAsString() == C.Opts.AnalyzeSpecificFunction) {
          D = fd;
          break;
        }
    }
  }

  if (!D)
    return;


  // FIXME: This is largely copy of ActionGRExprEngine. Needs cleanup.
  // Display progress.
  C.DisplayFunction(D);

  // FIXME: Make a fake transfer function. The GRTransferFunc interface
  // eventually will be removed.
  GRExprEngine Eng(mgr, new GRTransferFuncs());

  if (C.Opts.EnableExperimentalInternalChecks)
    RegisterExperimentalInternalChecks(Eng);

  RegisterAppleChecks(Eng, *D);

  if (C.Opts.EnableExperimentalChecks)
    RegisterExperimentalChecks(Eng);

  // Register call inliner as the last checker.
  RegisterCallInliner(Eng);

  // Execute the worklist algorithm.
  Eng.ExecuteWorkList(mgr.getStackFrame(D));

  // Visualize the exploded graph.
  if (mgr.shouldVisualizeGraphviz())
    Eng.ViewGraph(mgr.shouldTrimGraph());

  // Display warnings.
  Eng.getBugReporter().FlushReports();
}

//===----------------------------------------------------------------------===//
// AnalysisConsumer creation.
//===----------------------------------------------------------------------===//

ASTConsumer* clang::CreateAnalysisConsumer(const Preprocessor& pp,
                                           const std::string& OutDir,
                                           const AnalyzerOptions& Opts) {
  llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(pp, OutDir, Opts));

  for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i)
    switch (Opts.AnalysisList[i]) {
#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
    case NAME:\
      C->add ## SCOPE ## Action(&Action ## NAME);\
      break;
#include "clang/Frontend/Analyses.def"
    default: break;
    }

  // Last, disable the effects of '-Werror' when using the AnalysisConsumer.
  pp.getDiagnostics().setWarningsAsErrors(false);

  return C.take();
}

//===----------------------------------------------------------------------===//
// Ubigraph Visualization.  FIXME: Move to separate file.
//===----------------------------------------------------------------------===//

namespace {

class UbigraphViz : public ExplodedNode::Auditor {
  llvm::OwningPtr<llvm::raw_ostream> Out;
  llvm::sys::Path Dir, Filename;
  unsigned Cntr;

  typedef llvm::DenseMap<void*,unsigned> VMap;
  VMap M;

public:
  UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
              llvm::sys::Path& filename);

  ~UbigraphViz();

  virtual void AddEdge(ExplodedNode* Src, ExplodedNode* Dst);
};

} // end anonymous namespace

static ExplodedNode::Auditor* CreateUbiViz() {
  std::string ErrMsg;

  llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
  if (!ErrMsg.empty())
    return 0;

  llvm::sys::Path Filename = Dir;
  Filename.appendComponent("llvm_ubi");
  Filename.makeUnique(true,&ErrMsg);

  if (!ErrMsg.empty())
    return 0;

  llvm::errs() << "Writing '" << Filename.str() << "'.\n";

  llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
  Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));

  if (!ErrMsg.empty())
    return 0;

  return new UbigraphViz(Stream.take(), Dir, Filename);
}

void UbigraphViz::AddEdge(ExplodedNode* Src, ExplodedNode* Dst) {

  assert (Src != Dst && "Self-edges are not allowed.");

  // Lookup the Src.  If it is a new node, it's a root.
  VMap::iterator SrcI= M.find(Src);
  unsigned SrcID;

  if (SrcI == M.end()) {
    M[Src] = SrcID = Cntr++;
    *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
  }
  else
    SrcID = SrcI->second;

  // Lookup the Dst.
  VMap::iterator DstI= M.find(Dst);
  unsigned DstID;

  if (DstI == M.end()) {
    M[Dst] = DstID = Cntr++;
    *Out << "('vertex', " << DstID << ")\n";
  }
  else {
    // We have hit DstID before.  Change its style to reflect a cache hit.
    DstID = DstI->second;
    *Out << "('change_vertex_style', " << DstID << ", 1)\n";
  }

  // Add the edge.
  *Out << "('edge', " << SrcID << ", " << DstID
       << ", ('arrow','true'), ('oriented', 'true'))\n";
}

UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
                         llvm::sys::Path& filename)
  : Out(out), Dir(dir), Filename(filename), Cntr(0) {

  *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
  *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
          " ('size', '1.5'))\n";
}

UbigraphViz::~UbigraphViz() {
  Out.reset(0);
  llvm::errs() << "Running 'ubiviz' program... ";
  std::string ErrMsg;
  llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
  std::vector<const char*> args;
  args.push_back(Ubiviz.c_str());
  args.push_back(Filename.c_str());
  args.push_back(0);

  if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
    llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
  }

  // Delete the directory.
  Dir.eraseFromDisk(true);
}
