diff options
author | Ted Kremenek <kremenek@apple.com> | 2007-09-19 21:29:43 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2007-09-19 21:29:43 +0000 |
commit | 80de08fc6f7ebfee07b1b2c520c99e31c3243365 (patch) | |
tree | e8ca70240dc740a2b152e46f137cb6e54bc7989a | |
parent | d2a4a1af1088fca80e2dc76eb3369db0fbbfdefd (diff) |
Added support to clang driver to view ASTs using GraphViz. This
functionality is still preliminary.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42152 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | AST/StmtViz.cpp | 60 | ||||
-rw-r--r-- | Driver/ASTStreamers.cpp | 25 | ||||
-rw-r--r-- | Driver/ASTStreamers.h | 1 | ||||
-rw-r--r-- | Driver/clang.cpp | 10 | ||||
-rw-r--r-- | clang.xcodeproj/project.pbxproj | 7 |
5 files changed, 102 insertions, 1 deletions
diff --git a/AST/StmtViz.cpp b/AST/StmtViz.cpp new file mode 100644 index 0000000000..ee18bf050b --- /dev/null +++ b/AST/StmtViz.cpp @@ -0,0 +1,60 @@ +//===--- StmtViz.cpp - Graphviz visualization for Stmt ASTs -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Ted Kremenek and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements Stmt::viewAST, which generates a Graphviz DOT file +// that depicts the AST and then calls Graphviz/dot+gv on it. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/StmtGraphTraits.h" +#include "llvm/Support/GraphWriter.h" +#include <iostream> +#include <sstream> + +using namespace clang; + +void Stmt::viewAST() const { +#ifndef NDEBUG + llvm::ViewGraph(this,"AST"); +#else + std::cerr << "Stmt::viewAST is only available in debug builds on " + << "systems with Graphviz or gv!\n"; +#endif +} + +namespace llvm { +template<> +struct DOTGraphTraits<const Stmt*> : public DefaultDOTGraphTraits { + static std::string getNodeLabel(const Stmt* Node, const Stmt* Graph) { + +#ifndef NDEBUG + std::ostringstream Out; + + if (Node) + Out << Node->getStmtClassName(); + else + Out << "<NULL>"; + + std::string OutStr = Out.str(); + if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); + + // Process string output to make it nicer... + for (unsigned i = 0; i != OutStr.length(); ++i) + if (OutStr[i] == '\n') { // Left justify + OutStr[i] = '\\'; + OutStr.insert(OutStr.begin()+i+1, 'l'); + } + + return OutStr; +#else + return ""; +#endif + } +}; +} // end namespace llvm diff --git a/Driver/ASTStreamers.cpp b/Driver/ASTStreamers.cpp index cce19e795a..029f2769e9 100644 --- a/Driver/ASTStreamers.cpp +++ b/Driver/ASTStreamers.cpp @@ -131,6 +131,31 @@ namespace { ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); } +namespace { + class ASTViewer : public ASTConsumer { + SourceManager *SM; + public: + void Initialize(ASTContext &Context, unsigned MainFileID) { + SM = &Context.SourceMgr; + } + + virtual void HandleTopLevelDecl(Decl *D) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + PrintFunctionDeclStart(FD); + + if (FD->getBody()) { + fprintf(stderr, "\n"); + FD->getBody()->viewAST(); + fprintf(stderr, "\n"); + } + } + } + }; +} + +ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); } + + //===----------------------------------------------------------------------===// // CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit // the CFGs for all function definitions. diff --git a/Driver/ASTStreamers.h b/Driver/ASTStreamers.h index 2d4a18fdc2..129241e379 100644 --- a/Driver/ASTStreamers.h +++ b/Driver/ASTStreamers.h @@ -21,6 +21,7 @@ class Diagnostic; ASTConsumer *CreateASTPrinter(); ASTConsumer *CreateASTDumper(); +ASTConsumer *CreateASTViewer(); ASTConsumer *CreateCFGDumper(bool ViewGraphs = false); ASTConsumer *CreateLiveVarAnalyzer(); ASTConsumer *CreateDeadStoreChecker(Diagnostic &Diags); diff --git a/Driver/clang.cpp b/Driver/clang.cpp index aca94f711d..48e1c42dac 100644 --- a/Driver/clang.cpp +++ b/Driver/clang.cpp @@ -52,8 +52,9 @@ enum ProgActions { EmitLLVM, // Emit a .ll file. ParseASTPrint, // Parse ASTs and print them. ParseASTDump, // Parse ASTs and dump them. + ParseASTView, // Parse ASTs and view them in Graphviz. ParseASTCheck, // Parse ASTs and check diagnostics. - BuildAST, // Parse ASTs. + BuildAST, // Parse ASTs. ParseCFGDump, // Parse ASTS. Build CFGs. Print CFGs. ParseCFGView, // Parse ASTS. Build CFGs. View CFGs. AnalysisLiveVariables, // Print results of live-variable analysis. @@ -89,6 +90,8 @@ ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore, "Run parser, build ASTs, then print ASTs"), clEnumValN(ParseASTDump, "parse-ast-dump", "Run parser, build ASTs, then dump them"), + clEnumValN(ParseASTView, "parse-ast-view", + "Run parser, build ASTs, and view them with GraphViz."), clEnumValN(ParseASTCheck, "parse-ast-check", "Run parser, build ASTs, then check diagnostics"), clEnumValN(ParseCFGDump, "dump-cfg", @@ -857,6 +860,11 @@ static void ProcessInputFile(Preprocessor &PP, unsigned MainFileID, ParseAST(PP, MainFileID, *C.get(), Stats); break; } + case ParseASTView: { + std::auto_ptr<ASTConsumer> C(CreateASTViewer()); + ParseAST(PP, MainFileID, *C.get(), Stats); + break; + } case ParseCFGDump: case ParseCFGView: { std::auto_ptr<ASTConsumer> C(CreateCFGDumper(ProgAction == ParseCFGView)); diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index 0bf3c3b32e..91066d1fe8 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 35260CA50C7F75C000D66CE9 /* ExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35260CA40C7F75C000D66CE9 /* ExprCXX.cpp */; }; 355CF6840C90A8D400A08AA3 /* DeadStores.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 355CF6830C90A8D400A08AA3 /* DeadStores.cpp */; }; 356EF9B50C8F7DDF006650F5 /* LiveVariables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 356EF9B40C8F7DDF006650F5 /* LiveVariables.cpp */; }; + 35CFFE000CA1CBCB00E6F2BE /* StmtViz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35CFFDFF0CA1CBCB00E6F2BE /* StmtViz.cpp */; }; 84D9A8880C1A57E100AC7ABC /* AttributeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */; }; 84D9A88C0C1A581300AC7ABC /* AttributeList.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D9A88B0C1A581300AC7ABC /* AttributeList.h */; }; DE01DA490B12ADA300AC22CE /* PPCallbacks.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE01DA480B12ADA300AC22CE /* PPCallbacks.h */; }; @@ -226,6 +227,8 @@ 35AE0F660C9B4CA300CC1279 /* UninitializedValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UninitializedValues.h; path = clang/Analysis/UninitializedValues.h; sourceTree = "<group>"; }; 35AE0F670C9B4CC200CC1279 /* DataflowSolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataflowSolver.h; path = Analysis/DataflowSolver.h; sourceTree = "<group>"; }; 35BFBD2B0C9EDE1E006CB644 /* ASTConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTConsumer.h; path = clang/AST/ASTConsumer.h; sourceTree = "<group>"; }; + 35CFFDFF0CA1CBCB00E6F2BE /* StmtViz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StmtViz.cpp; path = AST/StmtViz.cpp; sourceTree = "<group>"; }; + 35CFFE010CA1CBDD00E6F2BE /* StmtGraphTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StmtGraphTraits.h; path = clang/AST/StmtGraphTraits.h; sourceTree = "<group>"; }; 84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = Parse/AttributeList.cpp; sourceTree = "<group>"; }; 84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = "<group>"; }; 8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -561,6 +564,7 @@ DE3452800AEF1B1800DBC861 /* Stmt.h */, DE345F210AFD347900DBC861 /* StmtNodes.def */, DE345C190AFC658B00DBC861 /* StmtVisitor.h */, + 35CFFE010CA1CBDD00E6F2BE /* StmtGraphTraits.h */, DE3464210B03040900DBC861 /* Type.h */, ); name = AST; @@ -579,6 +583,7 @@ DE75EDF00B06880E0020CF81 /* Type.cpp */, DEF2EDA60C6A4252000C4259 /* StmtDumper.cpp */, DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */, + 35CFFDFF0CA1CBCB00E6F2BE /* StmtViz.cpp */, ); name = AST; sourceTree = "<group>"; @@ -708,6 +713,7 @@ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */; + compatibilityVersion = "Xcode 2.4"; hasScannedForEncodings = 1; mainGroup = 08FB7794FE84155DC02AAC07 /* clang */; projectDirPath = ""; @@ -792,6 +798,7 @@ 355CF6840C90A8D400A08AA3 /* DeadStores.cpp in Sources */, DEF7D9F90C9C8B1D0001F598 /* Rewriter.cpp in Sources */, 3513BD550C9F207900FA56C6 /* UninitializedValues.cpp in Sources */, + 35CFFE000CA1CBCB00E6F2BE /* StmtViz.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; |