blob: 029f2769e99d95cf18bef765d7ab8b552aa4b13c [file] [log] [blame]
Chris Lattner4b009652007-07-25 00:24:17 +00001//===--- ASTStreamers.cpp - ASTStreamer Drivers ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Bill Wendling and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// ASTStreamer drivers.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ASTStreamers.h"
15#include "clang/AST/AST.h"
Chris Lattnerb73abd52007-09-15 23:02:28 +000016#include "clang/AST/ASTConsumer.h"
Ted Kremenek97f75312007-08-21 21:42:03 +000017#include "clang/AST/CFG.h"
Ted Kremenekaa04c512007-09-06 00:17:54 +000018#include "clang/Analysis/LiveVariables.h"
Ted Kremeneke805c4a2007-09-06 23:00:42 +000019#include "clang/Analysis/LocalCheckers.h"
Chris Lattner95578782007-08-08 22:51:59 +000020using namespace clang;
Chris Lattner4b009652007-07-25 00:24:17 +000021
Chris Lattner95578782007-08-08 22:51:59 +000022
23static void PrintFunctionDeclStart(FunctionDecl *FD) {
Chris Lattner4b009652007-07-25 00:24:17 +000024 bool HasBody = FD->getBody();
25
Chris Lattner987058a2007-08-26 04:02:13 +000026 fprintf(stderr, "\n");
27
28 switch (FD->getStorageClass()) {
29 default: assert(0 && "Unknown storage class");
30 case FunctionDecl::None: break;
31 case FunctionDecl::Extern: fprintf(stderr, "extern "); break;
32 case FunctionDecl::Static: fprintf(stderr, "static "); break;
33 }
34
35 if (FD->isInline())
36 fprintf(stderr, "inline ");
37
Chris Lattner4b009652007-07-25 00:24:17 +000038 std::string Proto = FD->getName();
39 FunctionType *AFT = cast<FunctionType>(FD->getType());
40
41 if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
42 Proto += "(";
43 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
44 if (i) Proto += ", ";
45 std::string ParamStr;
46 if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
47
48 FT->getArgType(i).getAsStringInternal(ParamStr);
49 Proto += ParamStr;
50 }
51
52 if (FT->isVariadic()) {
53 if (FD->getNumParams()) Proto += ", ";
54 Proto += "...";
55 }
56 Proto += ")";
57 } else {
58 assert(isa<FunctionTypeNoProto>(AFT));
59 Proto += "()";
60 }
61
62 AFT->getResultType().getAsStringInternal(Proto);
Chris Lattner987058a2007-08-26 04:02:13 +000063 fprintf(stderr, "%s", Proto.c_str());
Chris Lattner4b009652007-07-25 00:24:17 +000064
Chris Lattner95578782007-08-08 22:51:59 +000065 if (!FD->getBody())
Chris Lattner4b009652007-07-25 00:24:17 +000066 fprintf(stderr, ";\n");
Chris Lattner95578782007-08-08 22:51:59 +000067 // Doesn't print the body.
Chris Lattner4b009652007-07-25 00:24:17 +000068}
69
Chris Lattner95578782007-08-08 22:51:59 +000070static void PrintTypeDefDecl(TypedefDecl *TD) {
Chris Lattner4b009652007-07-25 00:24:17 +000071 std::string S = TD->getName();
72 TD->getUnderlyingType().getAsStringInternal(S);
73 fprintf(stderr, "typedef %s;\n", S.c_str());
74}
75
Steve Narofffaed3bf2007-09-10 20:51:04 +000076static void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID) {
77 std::string S = OID->getName();
78 fprintf(stderr, "@interface %s;\n", S.c_str());
79 // FIXME: implement the rest...
80}
81
Chris Lattnerb73abd52007-09-15 23:02:28 +000082namespace {
83 class ASTPrinter : public ASTConsumer {
84 virtual void HandleTopLevelDecl(Decl *D) {
85 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
86 PrintFunctionDeclStart(FD);
87
88 if (FD->getBody()) {
89 fprintf(stderr, " ");
90 FD->getBody()->dumpPretty();
91 fprintf(stderr, "\n");
92 }
93 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
94 PrintTypeDefDecl(TD);
95 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
96 PrintObjcInterfaceDecl(OID);
97 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
98 fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
Chris Lattner95578782007-08-08 22:51:59 +000099 }
Chris Lattner4b009652007-07-25 00:24:17 +0000100 }
Chris Lattnerb73abd52007-09-15 23:02:28 +0000101 };
Chris Lattner4b009652007-07-25 00:24:17 +0000102}
Chris Lattner95578782007-08-08 22:51:59 +0000103
Chris Lattnerb73abd52007-09-15 23:02:28 +0000104ASTConsumer *clang::CreateASTPrinter() { return new ASTPrinter(); }
105
106namespace {
107 class ASTDumper : public ASTConsumer {
108 SourceManager *SM;
109 public:
110 void Initialize(ASTContext &Context, unsigned MainFileID) {
111 SM = &Context.SourceMgr;
Chris Lattner95578782007-08-08 22:51:59 +0000112 }
Chris Lattnerb73abd52007-09-15 23:02:28 +0000113
114 virtual void HandleTopLevelDecl(Decl *D) {
115 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
116 PrintFunctionDeclStart(FD);
117
118 if (FD->getBody()) {
119 fprintf(stderr, "\n");
120 FD->getBody()->dumpAll(*SM);
121 fprintf(stderr, "\n");
122 }
123 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
124 PrintTypeDefDecl(TD);
125 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
126 fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
127 }
128 }
129 };
Chris Lattner95578782007-08-08 22:51:59 +0000130}
131
Chris Lattnerb73abd52007-09-15 23:02:28 +0000132ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
133
Ted Kremenekb6976a22007-09-19 21:29:43 +0000134namespace {
135 class ASTViewer : public ASTConsumer {
136 SourceManager *SM;
137 public:
138 void Initialize(ASTContext &Context, unsigned MainFileID) {
139 SM = &Context.SourceMgr;
140 }
141
142 virtual void HandleTopLevelDecl(Decl *D) {
143 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
144 PrintFunctionDeclStart(FD);
145
146 if (FD->getBody()) {
147 fprintf(stderr, "\n");
148 FD->getBody()->viewAST();
149 fprintf(stderr, "\n");
150 }
151 }
152 }
153 };
154}
155
156ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
157
158
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000159//===----------------------------------------------------------------------===//
160// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
161// the CFGs for all function definitions.
162
163namespace {
164
Chris Lattner52332d02007-09-15 23:21:08 +0000165class CFGVisitor : public ASTConsumer {
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000166public:
Chris Lattner52332d02007-09-15 23:21:08 +0000167 // CFG Visitor interface to be implemented by subclass.
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000168 virtual void VisitCFG(CFG& C) = 0;
169 virtual bool printFuncDeclStart() { return true; }
Chris Lattner52332d02007-09-15 23:21:08 +0000170
171 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000172};
173
174} // end anonymous namespace
175
Chris Lattner52332d02007-09-15 23:21:08 +0000176void CFGVisitor::HandleTopLevelDecl(Decl *D) {
177 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
178 if (!FD || !FD->getBody())
179 return;
180
181 if (printFuncDeclStart()) {
182 PrintFunctionDeclStart(FD);
183 fprintf(stderr,"\n");
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000184 }
Chris Lattner52332d02007-09-15 23:21:08 +0000185
Ted Kremenek3e88d752007-09-17 17:10:02 +0000186 CFG *C = CFG::buildCFG(FD->getBody());
187 VisitCFG(*C);
188 delete C;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000189}
190
191//===----------------------------------------------------------------------===//
192// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
193
194namespace {
195 class CFGDumper : public CFGVisitor {
196 const bool UseGraphviz;
197 public:
198 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
199
Chris Lattner52332d02007-09-15 23:21:08 +0000200 virtual void VisitCFG(CFG &C) {
201 if (UseGraphviz)
202 C.viewCFG();
203 else
204 C.dump();
205 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000206 };
207} // end anonymous namespace
208
Chris Lattner52332d02007-09-15 23:21:08 +0000209ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs) {
210 return new CFGDumper(ViewGraphs);
Ted Kremenek97f75312007-08-21 21:42:03 +0000211}
212
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000213//===----------------------------------------------------------------------===//
214// AnalyzeLiveVariables - perform live variable analysis and dump results
215
216namespace {
217 class LivenessVisitor : public CFGVisitor {
Chris Lattner52332d02007-09-15 23:21:08 +0000218 SourceManager *SM;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000219 public:
Chris Lattner52332d02007-09-15 23:21:08 +0000220 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
221 SM = &Context.SourceMgr;
222 }
223
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000224 virtual void VisitCFG(CFG& C) {
225 LiveVariables L;
226 L.runOnCFG(C);
Chris Lattner52332d02007-09-15 23:21:08 +0000227 L.dumpBlockLiveness(*SM);
228 L.dumpVarLiveness(*SM);
Ted Kremenekaa04c512007-09-06 00:17:54 +0000229 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000230 };
231} // end anonymous namespace
232
Chris Lattner52332d02007-09-15 23:21:08 +0000233ASTConsumer *clang::CreateLiveVarAnalyzer() {
234 return new LivenessVisitor();
Ted Kremenekaa04c512007-09-06 00:17:54 +0000235}
236
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000237//===----------------------------------------------------------------------===//
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000238// DeadStores - run checker to locate dead stores in a function
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000239
240namespace {
241 class DeadStoreVisitor : public CFGVisitor {
Chris Lattner52332d02007-09-15 23:21:08 +0000242 Diagnostic &Diags;
243 ASTContext *Ctx;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000244 public:
Chris Lattner52332d02007-09-15 23:21:08 +0000245 DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
246 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
247 Ctx = &Context;
248 }
249
250 virtual void VisitCFG(CFG& C) { CheckDeadStores(C, *Ctx, Diags); }
Ted Kremenek39b8c4b2007-09-07 23:54:15 +0000251 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000252 };
253} // end anonymous namespace
254
Chris Lattner52332d02007-09-15 23:21:08 +0000255ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
256 return new DeadStoreVisitor(Diags);
Ted Kremeneke805c4a2007-09-06 23:00:42 +0000257}
Chris Lattner129758d2007-09-16 19:46:59 +0000258
259//===----------------------------------------------------------------------===//
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000260// Unitialized Values - run checker to flag potential uses of uninitalized
261// variables.
262
263namespace {
264 class UninitValsVisitor : public CFGVisitor {
265 Diagnostic &Diags;
266 ASTContext *Ctx;
267 public:
268 UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
269 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
270 Ctx = &Context;
271 }
272
273 virtual void VisitCFG(CFG& C) { CheckUninitializedValues(C, *Ctx, Diags); }
274 virtual bool printFuncDeclStart() { return false; }
275 };
276} // end anonymous namespace
277
278ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
279 return new UninitValsVisitor(Diags);
280}
281
282//===----------------------------------------------------------------------===//
Chris Lattner129758d2007-09-16 19:46:59 +0000283// LLVM Emitter
284
285#include "clang/Basic/Diagnostic.h"
286#include "clang/CodeGen/ModuleBuilder.h"
287#include "llvm/Module.h"
288#include <iostream>
289
290namespace {
291 class LLVMEmitter : public ASTConsumer {
292 Diagnostic &Diags;
293 llvm::Module *M;
294 ASTContext *Ctx;
295 CodeGen::BuilderTy *Builder;
296 public:
297 LLVMEmitter(Diagnostic &diags) : Diags(diags) {}
298 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
299 Ctx = &Context;
300 M = new llvm::Module("foo");
301 Builder = CodeGen::Init(Context, *M);
302 }
303
304 virtual void HandleTopLevelDecl(Decl *D) {
305 // If an error occurred, stop code generation, but continue parsing and
306 // semantic analysis (to ensure all warnings and errors are emitted).
307 if (Diags.hasErrorOccurred())
308 return;
309
310 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
311 CodeGen::CodeGenFunction(Builder, FD);
312 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
313 CodeGen::CodeGenGlobalVar(Builder, FVD);
314 } else {
315 assert(isa<TypedefDecl>(D) && "Only expected typedefs here");
316 // don't codegen for now, eventually pass down for debug info.
317 //std::cerr << "Read top-level typedef decl: '" << D->getName() << "'\n";
318 }
319 }
320
321 ~LLVMEmitter() {
322 CodeGen::Terminate(Builder);
323
324 // Print the generated code.
325 M->print(std::cout);
326 delete M;
327 }
328 };
329} // end anonymous namespace
330
331ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags) {
332 return new LLVMEmitter(Diags);
333}
334