diff options
author | Daniel Dunbar <daniel@zuster.org> | 2010-06-15 17:48:49 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2010-06-15 17:48:49 +0000 |
commit | 9b414d3e2d0cb84512b55a3275a98490b090162a (patch) | |
tree | a9e89bf09e843286a73c99a9e18520c48ad725b0 /lib/Frontend/AnalysisConsumer.cpp | |
parent | c722ea4fbf886d6460b256b5e819a4ee751d5fff (diff) |
Break Frontend's dependency on Rewrite, Checker and CodeGen in shared library configuration
Currently, all AST consumers are located in the Frontend library,
meaning that in a shared library configuration, Frontend has a
dependency on Rewrite, Checker and CodeGen. This is suboptimal for
clients which only wish to make use of the frontend. CodeGen in
particular introduces a large number of unwanted dependencies.
This patch breaks the dependency by moving all AST consumers with
dependencies on Rewrite, Checker and/or CodeGen to their respective
libraries. The patch therefore introduces dependencies in the other
direction (i.e. from Rewrite, Checker and CodeGen to Frontend).
After applying this patch, Clang builds correctly using CMake and
shared libraries ("cmake -DBUILD_SHARED_LIBS=ON").
N.B. This patch includes file renames which are indicated in the
patch body.
Changes in this revision of the patch:
- Fixed some copy-paste mistakes in the header files
- Modified certain aspects of the coding to comply with the LLVM
Coding Standards
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106010 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/AnalysisConsumer.cpp')
-rw-r--r-- | lib/Frontend/AnalysisConsumer.cpp | 588 |
1 files changed, 0 insertions, 588 deletions
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp deleted file mode 100644 index 0589008033..0000000000 --- a/lib/Frontend/AnalysisConsumer.cpp +++ /dev/null @@ -1,588 +0,0 @@ -//===--- 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(); - -//===----------------------------------------------------------------------===// -// 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; - Actions CXXMethodActions; - TUActions TranslationUnitActions; // Remove this. - -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 << '\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); - CXXMethodActions.push_back(action); - } - - void addTranslationUnitAction(TUAction action) { - TranslationUnitActions.push_back(action); - } - - void addObjCImplementationAction(CodeAction action) { - ObjCImplementationActions.push_back(action); - } - - virtual void Initialize(ASTContext &Context) { - Ctx = &Context; - Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(), - PP.getLangOptions(), PD, - CreateStoreMgr, CreateConstraintMgr, - Opts.MaxNodes, Opts.MaxLoop, - Opts.VisualizeEGDot, Opts.VisualizeEGUbi, - Opts.PurgeDead, Opts.EagerlyAssume, - Opts.TrimGraph, Opts.InlineCall)); - } - - virtual void HandleTranslationUnit(ASTContext &C); - void HandleCode(Decl *D, Stmt* Body, Actions& actions); -}; -} // end anonymous namespace - -//===----------------------------------------------------------------------===// -// AnalysisConsumer implementation. -//===----------------------------------------------------------------------===// - -void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { - - TranslationUnitDecl *TU = C.getTranslationUnitDecl(); - - for (DeclContext::decl_iterator I = TU->decls_begin(), E = TU->decls_end(); - I != E; ++I) { - Decl *D = *I; - - switch (D->getKind()) { - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - case Decl::CXXMethod: - case Decl::Function: { - FunctionDecl* FD = cast<FunctionDecl>(D); - - if (FD->isThisDeclarationADefinition()) { - if (!Opts.AnalyzeSpecificFunction.empty() && - FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction) - break; - HandleCode(FD, FD->getBody(), FunctionActions); - } - break; - } - - case Decl::ObjCMethod: { - ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D); - - if (MD->isThisDeclarationADefinition()) { - if (!Opts.AnalyzeSpecificFunction.empty() && - Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString()) - break; - HandleCode(MD, MD->getBody(), ObjCMethodActions); - } - break; - } - - case Decl::ObjCImplementation: { - ObjCImplementationDecl* ID = cast<ObjCImplementationDecl>(*I); - HandleCode(ID, 0, ObjCImplementationActions); - - for (ObjCImplementationDecl::method_iterator MI = ID->meth_begin(), - ME = ID->meth_end(); MI != ME; ++MI) { - if ((*MI)->isThisDeclarationADefinition()) { - if (!Opts.AnalyzeSpecificFunction.empty() && - Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString()) - break; - HandleCode(*MI, (*MI)->getBody(), ObjCMethodActions); - } - } - break; - } - - default: - break; - } - } - - for (TUActions::iterator I = TranslationUnitActions.begin(), - E = TranslationUnitActions.end(); I != E; ++I) { - (*I)(*this, *Mgr, *TU); - } - - // 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. - Diagnostic &Diags = PP.getDiagnostics(); - if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) - return; - - // Don't run the actions on declarations in header files unless - // otherwise specified. - SourceManager &SM = Ctx->getSourceManager(); - SourceLocation SL = SM.getInstantiationLoc(D->getLocation()); - if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL)) - 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)) { - 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)) { - CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic()); - } -} - - -static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D, - GRTransferFuncs* tf) { - - llvm::OwningPtr<GRTransferFuncs> TF(tf); - - // 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), mgr.getMaxNodes()); - - // 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)) { - L->dumpBlockLiveness(mgr.getSourceManager()); - } -} - -static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { - if (CFG *cfg = mgr.getCFG(D)) { - cfg->dump(mgr.getLangOptions()); - } -} - -static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { - if (CFG *cfg = mgr.getCFG(D)) { - cfg->viewCFG(mgr.getLangOptions()); - } -} - -static void ActionSecuritySyntacticChecks(AnalysisConsumer &C, - AnalysisManager &mgr, Decl *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; - BugReporter BR(mgr); - CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR); -} - -static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D) { - BugReporter BR(mgr); - CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR); -} - -static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D) { - BugReporter BR(mgr); - CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR); -} - -static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr, - Decl *D) { - BugReporter BR(mgr); - CheckSizeofPointer(D, BR); -} - -//===----------------------------------------------------------------------===// -// 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); -} |