//== AnalysisManager.h - Path sensitive analysis data manager ------*- 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 AnalysisManager class that manages the data and policy
// for path sensitive analysis.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_GR_ANALYSISMANAGER_H
#define LLVM_CLANG_GR_ANALYSISMANAGER_H

#include "clang/Analysis/AnalysisContext.h"
#include "clang/Frontend/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"

namespace clang {

namespace ento {
  class CheckerManager;

class AnalysisManager : public BugReporterData {
  virtual void anchor();
  AnalysisDeclContextManager AnaCtxMgr;

  ASTContext &Ctx;
  DiagnosticsEngine &Diags;
  const LangOptions &LangOpts;
  PathDiagnosticConsumers PathConsumers;

  // Configurable components creators.
  StoreManagerCreator CreateStoreMgr;
  ConstraintManagerCreator CreateConstraintMgr;

  CheckerManager *CheckerMgr;

  /// \brief The maximum number of exploded nodes the analyzer will generate.
  unsigned MaxNodes;

  /// \brief The maximum number of times the analyzer visits a block.
  unsigned MaxVisit;

  bool VisualizeEGDot;
  bool VisualizeEGUbi;
  AnalysisPurgeMode PurgeDead;

  /// \brief The flag regulates if we should eagerly assume evaluations of
  /// conditionals, thus, bifurcating the path.
  ///
  /// EagerlyAssume - A flag indicating how the engine should handle
  ///   expressions such as: 'x = (y != 0)'.  When this flag is true then
  ///   the subexpression 'y != 0' will be eagerly assumed to be true or false,
  ///   thus evaluating it to the integers 0 or 1 respectively.  The upside
  ///   is that this can increase analysis precision until we have a better way
  ///   to lazily evaluate such logic.  The downside is that it eagerly
  ///   bifurcates paths.
  bool EagerlyAssume;
  bool TrimGraph;
  bool EagerlyTrimEGraph;

public:
  // \brief inter-procedural analysis mode.
  AnalysisIPAMode IPAMode;

  // Settings for inlining tuning.
  /// \brief The inlining stack depth limit.
  unsigned InlineMaxStackDepth;
  /// \brief The max number of basic blocks in a function being inlined.
  unsigned InlineMaxFunctionSize;
  /// \brief The mode of function selection used during inlining.
  AnalysisInliningMode InliningMode;

  /// \brief Do not re-analyze paths leading to exhausted nodes with a different
  /// strategy. We get better code coverage when retry is enabled.
  bool NoRetryExhausted;

public:
  AnalysisManager(ASTContext &ctx,DiagnosticsEngine &diags,
                  const LangOptions &lang,
                  const PathDiagnosticConsumers &Consumers,
                  StoreManagerCreator storemgr,
                  ConstraintManagerCreator constraintmgr, 
                  CheckerManager *checkerMgr,
                  unsigned maxnodes, unsigned maxvisit,
                  bool vizdot, bool vizubi, AnalysisPurgeMode purge,
                  bool eager, bool trim,
                  bool useUnoptimizedCFG,
                  bool addImplicitDtors,
                  bool eagerlyTrimEGraph,
                  AnalysisIPAMode ipa,
                  unsigned inlineMaxStack,
                  unsigned inlineMaxFunctionSize,
                  AnalysisInliningMode inliningMode,
                  bool NoRetry);

  ~AnalysisManager();
  
  void ClearContexts() {
    AnaCtxMgr.clear();
  }
  
  AnalysisDeclContextManager& getAnalysisDeclContextManager() {
    return AnaCtxMgr;
  }

  StoreManagerCreator getStoreManagerCreator() {
    return CreateStoreMgr;
  }

  ConstraintManagerCreator getConstraintManagerCreator() {
    return CreateConstraintMgr;
  }

  CheckerManager *getCheckerManager() const { return CheckerMgr; }

  virtual ASTContext &getASTContext() {
    return Ctx;
  }

  virtual SourceManager &getSourceManager() {
    return getASTContext().getSourceManager();
  }

  virtual DiagnosticsEngine &getDiagnostic() {
    return Diags;
  }

  const LangOptions &getLangOpts() const {
    return LangOpts;
  }

  ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers()  {
    return PathConsumers;
  }

  void FlushDiagnostics();

  unsigned getMaxNodes() const { return MaxNodes; }

  unsigned getMaxVisit() const { return MaxVisit; }

  bool shouldVisualizeGraphviz() const { return VisualizeEGDot; }

  bool shouldVisualizeUbigraph() const { return VisualizeEGUbi; }

  bool shouldVisualize() const {
    return VisualizeEGDot || VisualizeEGUbi;
  }

  bool shouldEagerlyTrimExplodedGraph() const { return EagerlyTrimEGraph; }

  bool shouldTrimGraph() const { return TrimGraph; }

  AnalysisPurgeMode getPurgeMode() const { return PurgeDead; }

  bool shouldEagerlyAssume() const { return EagerlyAssume; }

  bool shouldInlineCall() const { return (IPAMode != None); }

  CFG *getCFG(Decl const *D) {
    return AnaCtxMgr.getContext(D)->getCFG();
  }

  template <typename T>
  T *getAnalysis(Decl const *D) {
    return AnaCtxMgr.getContext(D)->getAnalysis<T>();
  }

  ParentMap &getParentMap(Decl const *D) {
    return AnaCtxMgr.getContext(D)->getParentMap();
  }

  AnalysisDeclContext *getAnalysisDeclContext(const Decl *D) {
    return AnaCtxMgr.getContext(D);
  }

};

} // enAnaCtxMgrspace

} // end clang namespace

#endif
