Added GraphTraits to source-level CFGs (CFG and CFGBlock) to allow
(LLVM-provided) graph algorithms such as DFS and graph visualization
to work effortless on source-level CFGs.

Further cleanup on pretty printing of CFGs.  CFGBlock::dump and
CFGBlock::print now take the parent CFG as an argument.  This allows
CFGBlocks to print their own appropriate label indicating whether or
not they are the Entry/Exit/IndirectGotoBlock without the CFG::print
routine doing it instead.

Added Graphviz visualization for CFGs: CFG::viewCFG.  This employs the
GraphTraits just implemented.

Added "-view-cfg" mode the to clang driver.  This is identical to
"-dump-cfg" except that it calls Graphviz to visualize the CFGs
instead of dumping them to the terminal.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41580 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Driver/ASTStreamers.cpp b/Driver/ASTStreamers.cpp
index c819623..5e78e03 100644
--- a/Driver/ASTStreamers.cpp
+++ b/Driver/ASTStreamers.cpp
@@ -155,7 +155,9 @@
   ASTStreamer_Terminate(Streamer);
 }
 
-void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID, bool Stats) {
+void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID,
+                     bool Stats, bool use_graphviz) 
+{
   ASTContext Context(PP.getTargetInfo(), PP.getIdentifierTable());
   ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
   
@@ -164,8 +166,9 @@
       if (FD->getBody()) {
         PrintFunctionDeclStart(FD);
         fprintf(stderr,"\n");
-        if (CFG* C = CFG::buildCFG(FD->getBody()))
-          C->dump();
+        if (CFG* C = CFG::buildCFG(FD->getBody())) {
+          if (use_graphviz) C->viewCFG(); else C->dump();
+        }
         else
           fprintf(stderr," Error processing CFG.\n");
       }
diff --git a/Driver/ASTStreamers.h b/Driver/ASTStreamers.h
index 6e90e2f..dfd9d54 100644
--- a/Driver/ASTStreamers.h
+++ b/Driver/ASTStreamers.h
@@ -23,7 +23,9 @@
 void BuildASTs(Preprocessor &PP, unsigned MainFileID, bool Stats);
 void PrintASTs(Preprocessor &PP, unsigned MainFileID, bool Stats);
 void DumpASTs(Preprocessor &PP, unsigned MainFileID, bool Stats);
-void DumpCFGs(Preprocessor &PP, unsigned MainFileID, bool Stats);  
+
+void DumpCFGs(Preprocessor &PP, unsigned MainFileID,
+              bool Stats, bool use_graphviz = false);  
 
 } // end clang namespace
 
diff --git a/Driver/clang.cpp b/Driver/clang.cpp
index 14f4887..2bb4422 100644
--- a/Driver/clang.cpp
+++ b/Driver/clang.cpp
@@ -53,6 +53,7 @@
   ParseASTCheck,                // Parse ASTs and check diagnostics.
   ParseAST,                     // Parse ASTs.
   ParseCFGDump,                 // Parse ASTS. Build CFGs. Print CFGs.
+  ParseCFGView,                 // Parse ASTS. Build CFGs. View CFGs (Graphviz).
   ParsePrintCallbacks,          // Parse and print each callback.
   ParseSyntaxOnly,              // Parse and perform semantic analysis.
   ParseNoop,                    // Parse with noop callbacks.
@@ -86,7 +87,9 @@
              clEnumValN(ParseASTCheck, "parse-ast-check",
                         "Run parser, build ASTs, then check diagnostics"),
              clEnumValN(ParseCFGDump, "dump-cfg",
-                        "Run parser, build ASTs, then build and print CFGs."),
+                        "Run parser, then build and print CFGs."),
+             clEnumValN(ParseCFGView, "view-cfg",
+                        "Run parser, then build and view CFGs with Graphviz."),  
              clEnumValN(EmitLLVM, "emit-llvm",
                         "Build ASTs then convert to LLVM, emit .ll file"),
              clEnumValEnd));
@@ -840,6 +843,9 @@
   case ParseCFGDump:
     DumpCFGs(PP, MainFileID, Stats);
     break;
+  case ParseCFGView:
+    DumpCFGs(PP, MainFileID, Stats, true);
+    break;
   case EmitLLVM:
     EmitLLVMFromASTs(PP, MainFileID, Stats);
     break;