blob: 7f3b7155705b6c4c72ff504777a87dd8f0ba59a2 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +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 Lattner3d4997d2007-09-15 23:02:28 +000016#include "clang/AST/ASTConsumer.h"
Ted Kremenekfddd5182007-08-21 21:42:03 +000017#include "clang/AST/CFG.h"
Ted Kremeneke4e63342007-09-06 00:17:54 +000018#include "clang/Analysis/LiveVariables.h"
Ted Kremenek055c2752007-09-06 23:00:42 +000019#include "clang/Analysis/LocalCheckers.h"
Chris Lattner6000dac2007-08-08 22:51:59 +000020using namespace clang;
Reid Spencer5f016e22007-07-11 17:01:13 +000021
Chris Lattner6000dac2007-08-08 22:51:59 +000022
23static void PrintFunctionDeclStart(FunctionDecl *FD) {
Reid Spencer5f016e22007-07-11 17:01:13 +000024 bool HasBody = FD->getBody();
25
Chris Lattner70c8b2e2007-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
Reid Spencer5f016e22007-07-11 17:01:13 +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 Lattner70c8b2e2007-08-26 04:02:13 +000063 fprintf(stderr, "%s", Proto.c_str());
Reid Spencer5f016e22007-07-11 17:01:13 +000064
Chris Lattner6000dac2007-08-08 22:51:59 +000065 if (!FD->getBody())
Reid Spencer5f016e22007-07-11 17:01:13 +000066 fprintf(stderr, ";\n");
Chris Lattner6000dac2007-08-08 22:51:59 +000067 // Doesn't print the body.
Reid Spencer5f016e22007-07-11 17:01:13 +000068}
69
Chris Lattner6000dac2007-08-08 22:51:59 +000070static void PrintTypeDefDecl(TypedefDecl *TD) {
Reid Spencer5f016e22007-07-11 17:01:13 +000071 std::string S = TD->getName();
72 TD->getUnderlyingType().getAsStringInternal(S);
73 fprintf(stderr, "typedef %s;\n", S.c_str());
74}
75
Steve Naroff2bd42fa2007-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 Lattner3d4997d2007-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);
Chris Lattner3d4997d2007-09-15 23:02:28 +000095 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
96 fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
Chris Lattner9fa5e652007-10-06 18:52:10 +000097 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
98 PrintObjcInterfaceDecl(OID);
99 } else if (ObjcForwardProtocolDecl *OFPD =
100 dyn_cast<ObjcForwardProtocolDecl>(D)) {
101 fprintf(stderr, "@protocol ");
102 for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
103 const ObjcProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
104 if (i) fprintf(stderr, ", ");
105 fprintf(stderr, "%s", D->getName());
106 }
107 fprintf(stderr, "\n");
108 } else if (ObjcImplementationDecl *OID =
109 dyn_cast<ObjcImplementationDecl>(D)) {
110 fprintf(stderr, "@implementation %s [printing todo]\n",
111 OID->getName());
112 } else if (isa<ObjcClassDecl>(D)) {
113 fprintf(stderr, "@class [printing todo]\n");
114 } else {
115 assert(0 && "Unknown decl type!");
Chris Lattner6000dac2007-08-08 22:51:59 +0000116 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000117 }
Chris Lattner3d4997d2007-09-15 23:02:28 +0000118 };
Reid Spencer5f016e22007-07-11 17:01:13 +0000119}
Chris Lattner6000dac2007-08-08 22:51:59 +0000120
Chris Lattner3d4997d2007-09-15 23:02:28 +0000121ASTConsumer *clang::CreateASTPrinter() { return new ASTPrinter(); }
122
123namespace {
124 class ASTDumper : public ASTConsumer {
125 SourceManager *SM;
126 public:
127 void Initialize(ASTContext &Context, unsigned MainFileID) {
128 SM = &Context.SourceMgr;
Chris Lattner6000dac2007-08-08 22:51:59 +0000129 }
Chris Lattner3d4997d2007-09-15 23:02:28 +0000130
131 virtual void HandleTopLevelDecl(Decl *D) {
132 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
133 PrintFunctionDeclStart(FD);
134
135 if (FD->getBody()) {
136 fprintf(stderr, "\n");
137 FD->getBody()->dumpAll(*SM);
138 fprintf(stderr, "\n");
139 }
140 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
141 PrintTypeDefDecl(TD);
142 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
143 fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
Chris Lattner9fa5e652007-10-06 18:52:10 +0000144 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
145 fprintf(stderr, "Read objc interface '%s'\n", OID->getName());
146 } else if (isa<ObjcForwardProtocolDecl>(D)) {
147 fprintf(stderr, "Read objc fwd protocol decl\n");
148 } else {
149 assert(0 && "Unknown decl type!");
Chris Lattner3d4997d2007-09-15 23:02:28 +0000150 }
151 }
152 };
Chris Lattner6000dac2007-08-08 22:51:59 +0000153}
154
Chris Lattner3d4997d2007-09-15 23:02:28 +0000155ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
156
Ted Kremenek80de08f2007-09-19 21:29:43 +0000157namespace {
158 class ASTViewer : public ASTConsumer {
159 SourceManager *SM;
160 public:
161 void Initialize(ASTContext &Context, unsigned MainFileID) {
162 SM = &Context.SourceMgr;
163 }
164
165 virtual void HandleTopLevelDecl(Decl *D) {
166 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
167 PrintFunctionDeclStart(FD);
168
169 if (FD->getBody()) {
170 fprintf(stderr, "\n");
171 FD->getBody()->viewAST();
172 fprintf(stderr, "\n");
173 }
174 }
175 }
176 };
177}
178
179ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
180
181
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000182//===----------------------------------------------------------------------===//
183// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
184// the CFGs for all function definitions.
185
186namespace {
187
Chris Lattnerc0508f92007-09-15 23:21:08 +0000188class CFGVisitor : public ASTConsumer {
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000189public:
Chris Lattnerc0508f92007-09-15 23:21:08 +0000190 // CFG Visitor interface to be implemented by subclass.
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000191 virtual void VisitCFG(CFG& C) = 0;
192 virtual bool printFuncDeclStart() { return true; }
Chris Lattnerc0508f92007-09-15 23:21:08 +0000193
194 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000195};
196
197} // end anonymous namespace
198
Chris Lattnerc0508f92007-09-15 23:21:08 +0000199void CFGVisitor::HandleTopLevelDecl(Decl *D) {
200 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
201 if (!FD || !FD->getBody())
202 return;
203
204 if (printFuncDeclStart()) {
205 PrintFunctionDeclStart(FD);
206 fprintf(stderr,"\n");
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000207 }
Chris Lattnerc0508f92007-09-15 23:21:08 +0000208
Ted Kremenek12259662007-09-17 17:10:02 +0000209 CFG *C = CFG::buildCFG(FD->getBody());
210 VisitCFG(*C);
211 delete C;
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000212}
213
214//===----------------------------------------------------------------------===//
215// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
216
217namespace {
218 class CFGDumper : public CFGVisitor {
219 const bool UseGraphviz;
220 public:
221 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
222
Chris Lattnerc0508f92007-09-15 23:21:08 +0000223 virtual void VisitCFG(CFG &C) {
224 if (UseGraphviz)
225 C.viewCFG();
226 else
227 C.dump();
228 }
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000229 };
230} // end anonymous namespace
231
Chris Lattnerc0508f92007-09-15 23:21:08 +0000232ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs) {
233 return new CFGDumper(ViewGraphs);
Ted Kremenekfddd5182007-08-21 21:42:03 +0000234}
235
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000236//===----------------------------------------------------------------------===//
237// AnalyzeLiveVariables - perform live variable analysis and dump results
238
239namespace {
240 class LivenessVisitor : public CFGVisitor {
Chris Lattnerc0508f92007-09-15 23:21:08 +0000241 SourceManager *SM;
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000242 public:
Chris Lattnerc0508f92007-09-15 23:21:08 +0000243 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
244 SM = &Context.SourceMgr;
245 }
246
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000247 virtual void VisitCFG(CFG& C) {
Ted Kremenek11e72182007-10-01 20:33:52 +0000248 LiveVariables L(C);
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000249 L.runOnCFG(C);
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000250 L.dumpBlockLiveness(*SM);
Ted Kremeneke4e63342007-09-06 00:17:54 +0000251 }
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000252 };
253} // end anonymous namespace
254
Chris Lattnerc0508f92007-09-15 23:21:08 +0000255ASTConsumer *clang::CreateLiveVarAnalyzer() {
256 return new LivenessVisitor();
Ted Kremeneke4e63342007-09-06 00:17:54 +0000257}
258
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000259//===----------------------------------------------------------------------===//
Ted Kremenek2bf55142007-09-17 20:49:30 +0000260// DeadStores - run checker to locate dead stores in a function
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000261
262namespace {
263 class DeadStoreVisitor : public CFGVisitor {
Chris Lattnerc0508f92007-09-15 23:21:08 +0000264 Diagnostic &Diags;
265 ASTContext *Ctx;
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000266 public:
Chris Lattnerc0508f92007-09-15 23:21:08 +0000267 DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
268 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
269 Ctx = &Context;
270 }
271
272 virtual void VisitCFG(CFG& C) { CheckDeadStores(C, *Ctx, Diags); }
Ted Kremenek567a7e62007-09-07 23:54:15 +0000273 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000274 };
275} // end anonymous namespace
276
Chris Lattnerc0508f92007-09-15 23:21:08 +0000277ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
278 return new DeadStoreVisitor(Diags);
Ted Kremenek055c2752007-09-06 23:00:42 +0000279}
Chris Lattner580980b2007-09-16 19:46:59 +0000280
281//===----------------------------------------------------------------------===//
Ted Kremenek2bf55142007-09-17 20:49:30 +0000282// Unitialized Values - run checker to flag potential uses of uninitalized
283// variables.
284
285namespace {
286 class UninitValsVisitor : public CFGVisitor {
287 Diagnostic &Diags;
288 ASTContext *Ctx;
289 public:
290 UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
291 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
292 Ctx = &Context;
293 }
294
295 virtual void VisitCFG(CFG& C) { CheckUninitializedValues(C, *Ctx, Diags); }
296 virtual bool printFuncDeclStart() { return false; }
297 };
298} // end anonymous namespace
299
300ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
301 return new UninitValsVisitor(Diags);
302}
303
304//===----------------------------------------------------------------------===//
Chris Lattner580980b2007-09-16 19:46:59 +0000305// LLVM Emitter
306
307#include "clang/Basic/Diagnostic.h"
308#include "clang/CodeGen/ModuleBuilder.h"
309#include "llvm/Module.h"
310#include <iostream>
311
312namespace {
313 class LLVMEmitter : public ASTConsumer {
314 Diagnostic &Diags;
315 llvm::Module *M;
316 ASTContext *Ctx;
317 CodeGen::BuilderTy *Builder;
318 public:
319 LLVMEmitter(Diagnostic &diags) : Diags(diags) {}
320 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
321 Ctx = &Context;
322 M = new llvm::Module("foo");
323 Builder = CodeGen::Init(Context, *M);
324 }
325
326 virtual void HandleTopLevelDecl(Decl *D) {
327 // If an error occurred, stop code generation, but continue parsing and
328 // semantic analysis (to ensure all warnings and errors are emitted).
329 if (Diags.hasErrorOccurred())
330 return;
331
332 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
333 CodeGen::CodeGenFunction(Builder, FD);
334 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
335 CodeGen::CodeGenGlobalVar(Builder, FVD);
336 } else {
337 assert(isa<TypedefDecl>(D) && "Only expected typedefs here");
338 // don't codegen for now, eventually pass down for debug info.
339 //std::cerr << "Read top-level typedef decl: '" << D->getName() << "'\n";
340 }
341 }
342
343 ~LLVMEmitter() {
344 CodeGen::Terminate(Builder);
345
346 // Print the generated code.
347 M->print(std::cout);
348 delete M;
349 }
350 };
351} // end anonymous namespace
352
353ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags) {
354 return new LLVMEmitter(Diags);
355}
356