Rename ASTStreamers.* -> ASTConsumers.*


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42718 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp
new file mode 100644
index 0000000..ddacfa8
--- /dev/null
+++ b/Driver/ASTConsumers.cpp
@@ -0,0 +1,356 @@
+//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Chris Lattner and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// AST Consumer Implementations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTConsumers.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/CFG.h"
+#include "clang/Analysis/LiveVariables.h"
+#include "clang/Analysis/LocalCheckers.h"
+using namespace clang;
+
+
+static void PrintFunctionDeclStart(FunctionDecl *FD) {
+  bool HasBody = FD->getBody();
+  
+  fprintf(stderr, "\n");
+
+  switch (FD->getStorageClass()) {
+  default: assert(0 && "Unknown storage class");
+  case FunctionDecl::None: break;
+  case FunctionDecl::Extern: fprintf(stderr, "extern "); break;
+  case FunctionDecl::Static: fprintf(stderr, "static "); break;
+  }
+  
+  if (FD->isInline())
+    fprintf(stderr, "inline ");
+  
+  std::string Proto = FD->getName();
+  FunctionType *AFT = cast<FunctionType>(FD->getType());
+
+  if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
+    Proto += "(";
+    for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
+      if (i) Proto += ", ";
+      std::string ParamStr;
+      if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
+      
+      FT->getArgType(i).getAsStringInternal(ParamStr);
+      Proto += ParamStr;
+    }
+    
+    if (FT->isVariadic()) {
+      if (FD->getNumParams()) Proto += ", ";
+      Proto += "...";
+    }
+    Proto += ")";
+  } else {
+    assert(isa<FunctionTypeNoProto>(AFT));
+    Proto += "()";
+  }
+
+  AFT->getResultType().getAsStringInternal(Proto);
+  fprintf(stderr, "%s", Proto.c_str());
+  
+  if (!FD->getBody())
+    fprintf(stderr, ";\n");
+  // Doesn't print the body.
+}
+
+static void PrintTypeDefDecl(TypedefDecl *TD) {
+  std::string S = TD->getName();
+  TD->getUnderlyingType().getAsStringInternal(S);
+  fprintf(stderr, "typedef %s;\n", S.c_str());
+}
+
+static void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID) {
+  std::string S = OID->getName();
+  fprintf(stderr, "@interface %s;\n", S.c_str());
+  // FIXME: implement the rest...
+}
+
+namespace {
+  class ASTPrinter : public ASTConsumer {
+    virtual void HandleTopLevelDecl(Decl *D) {
+      if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+        PrintFunctionDeclStart(FD);
+        
+        if (FD->getBody()) {
+          fprintf(stderr, " ");
+          FD->getBody()->dumpPretty();
+          fprintf(stderr, "\n");
+        }
+      } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+        PrintTypeDefDecl(TD);
+      } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
+        fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
+      } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
+        PrintObjcInterfaceDecl(OID);
+      } else if (ObjcForwardProtocolDecl *OFPD = 
+                     dyn_cast<ObjcForwardProtocolDecl>(D)) {
+        fprintf(stderr, "@protocol ");
+        for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
+          const ObjcProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
+          if (i) fprintf(stderr, ", ");
+          fprintf(stderr, "%s", D->getName());
+        }
+        fprintf(stderr, ";\n");
+      } else if (ObjcImplementationDecl *OID = 
+                   dyn_cast<ObjcImplementationDecl>(D)) {
+        fprintf(stderr, "@implementation %s  [printing todo]\n",
+                OID->getName());
+      } else if (isa<ObjcClassDecl>(D)) {
+        fprintf(stderr, "@class [printing todo]\n");
+      } else {
+        assert(0 && "Unknown decl type!");
+      }
+    }
+  };
+}
+
+ASTConsumer *clang::CreateASTPrinter() { return new ASTPrinter(); }
+
+namespace {
+  class ASTDumper : 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()->dumpAll(*SM);
+          fprintf(stderr, "\n");
+        }
+      } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+        PrintTypeDefDecl(TD);
+      } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
+        fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
+      } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
+        fprintf(stderr, "Read objc interface '%s'\n", OID->getName());
+      } else if (isa<ObjcForwardProtocolDecl>(D)) {
+        fprintf(stderr, "Read objc fwd protocol decl\n");
+      } else {
+        assert(0 && "Unknown decl type!");
+      }
+    }
+  };
+}
+
+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.
+
+namespace {
+
+class CFGVisitor : public ASTConsumer {
+public:
+  // CFG Visitor interface to be implemented by subclass.
+  virtual void VisitCFG(CFG& C) = 0;
+  virtual bool printFuncDeclStart() { return true; }
+  
+  virtual void HandleTopLevelDecl(Decl *D);
+};
+
+} // end anonymous namespace
+
+void CFGVisitor::HandleTopLevelDecl(Decl *D) {
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+  if (!FD || !FD->getBody())
+    return;
+      
+  if (printFuncDeclStart()) {
+    PrintFunctionDeclStart(FD);          
+    fprintf(stderr,"\n");
+  }
+    
+  CFG *C = CFG::buildCFG(FD->getBody());
+  VisitCFG(*C);
+  delete C;
+}
+
+//===----------------------------------------------------------------------===//
+// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
+
+namespace {
+  class CFGDumper : public CFGVisitor {
+    const bool UseGraphviz;
+  public:
+    CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
+    
+    virtual void VisitCFG(CFG &C) {
+      if (UseGraphviz)
+        C.viewCFG();
+      else
+        C.dump();
+    }
+  }; 
+} // end anonymous namespace 
+  
+ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs) {
+  return new CFGDumper(ViewGraphs);
+}
+
+//===----------------------------------------------------------------------===//
+// AnalyzeLiveVariables - perform live variable analysis and dump results
+
+namespace {
+  class LivenessVisitor : public CFGVisitor {
+    SourceManager *SM;
+  public:
+    virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
+      SM = &Context.SourceMgr;
+    }
+
+    virtual void VisitCFG(CFG& C) {
+      LiveVariables L(C);
+      L.runOnCFG(C);
+      L.dumpBlockLiveness(*SM);
+    }
+  };
+} // end anonymous namespace
+  
+ASTConsumer *clang::CreateLiveVarAnalyzer() {
+  return new LivenessVisitor();
+}
+
+//===----------------------------------------------------------------------===//
+// DeadStores - run checker to locate dead stores in a function
+
+namespace {
+  class DeadStoreVisitor : public CFGVisitor {
+    Diagnostic &Diags;
+    ASTContext *Ctx;
+  public:
+    DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
+    virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
+      Ctx = &Context;
+    }
+    
+    virtual void VisitCFG(CFG& C) { CheckDeadStores(C, *Ctx, Diags); }
+    virtual bool printFuncDeclStart() { return false; }
+  }; 
+} // end anonymous namespace
+
+ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
+  return new DeadStoreVisitor(Diags);
+}
+
+//===----------------------------------------------------------------------===//
+// Unitialized Values - run checker to flag potential uses of uninitalized
+//  variables.
+
+namespace {
+  class UninitValsVisitor : public CFGVisitor {
+    Diagnostic &Diags;
+    ASTContext *Ctx;
+  public:
+    UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
+    virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
+      Ctx = &Context;
+    }
+    
+    virtual void VisitCFG(CFG& C) { CheckUninitializedValues(C, *Ctx, Diags); }
+    virtual bool printFuncDeclStart() { return false; }
+  }; 
+} // end anonymous namespace
+
+ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
+  return new UninitValsVisitor(Diags);
+}
+
+//===----------------------------------------------------------------------===//
+// LLVM Emitter
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "llvm/Module.h"
+#include <iostream>
+
+namespace {
+  class LLVMEmitter : public ASTConsumer {
+    Diagnostic &Diags;
+    llvm::Module *M;
+    ASTContext *Ctx;
+    CodeGen::BuilderTy *Builder;
+  public:
+    LLVMEmitter(Diagnostic &diags) : Diags(diags) {}
+    virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
+      Ctx = &Context;
+      M = new llvm::Module("foo");
+      Builder = CodeGen::Init(Context, *M);
+    }
+    
+    virtual void HandleTopLevelDecl(Decl *D) {
+      // If an error occurred, stop code generation, but continue parsing and
+      // semantic analysis (to ensure all warnings and errors are emitted).
+      if (Diags.hasErrorOccurred())
+        return;
+      
+      if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+        CodeGen::CodeGenFunction(Builder, FD);
+      } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
+        CodeGen::CodeGenGlobalVar(Builder, FVD);
+      } else {
+        assert(isa<TypedefDecl>(D) && "Only expected typedefs here");
+        // don't codegen for now, eventually pass down for debug info.
+        //std::cerr << "Read top-level typedef decl: '" << D->getName() << "'\n";
+      }
+    }
+    
+    ~LLVMEmitter() {
+      CodeGen::Terminate(Builder);
+      
+      // Print the generated code.
+      M->print(std::cout);
+      delete M;
+    }
+  }; 
+} // end anonymous namespace
+
+ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags) {
+  return new LLVMEmitter(Diags);
+}
+