blob: 6fe6fac41112344f1f2090740b18f1a1237667b8 [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"
Ted Kremenek97f75312007-08-21 21:42:03 +000016#include "clang/AST/CFG.h"
Ted Kremenekaa04c512007-09-06 00:17:54 +000017#include "clang/Analysis/LiveVariables.h"
Ted Kremeneke805c4a2007-09-06 23:00:42 +000018#include "clang/Analysis/LocalCheckers.h"
Chris Lattner4b009652007-07-25 00:24:17 +000019#include "clang/Lex/Preprocessor.h"
20#include "clang/Sema/ASTStreamer.h"
Chris Lattner95578782007-08-08 22:51:59 +000021using namespace clang;
Chris Lattner4b009652007-07-25 00:24:17 +000022
23void clang::BuildASTs(Preprocessor &PP, unsigned MainFileID, bool Stats) {
24 // collect global stats on Decls/Stmts (until we have a module streamer)
25 if (Stats) {
26 Decl::CollectingStats(true);
27 Stmt::CollectingStats(true);
28 }
29
30 ASTContext Context(PP.getTargetInfo(), PP.getIdentifierTable());
31 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
32
33 while (ASTStreamer_ReadTopLevelDecl(Streamer))
34 /* keep reading */;
35
36 if (Stats) {
37 fprintf(stderr, "\nSTATISTICS:\n");
38 ASTStreamer_PrintStats(Streamer);
39 Context.PrintStats();
40 Decl::PrintStats();
41 Stmt::PrintStats();
42 }
43
44 ASTStreamer_Terminate(Streamer);
45}
46
Chris Lattner95578782007-08-08 22:51:59 +000047
48
49static void PrintFunctionDeclStart(FunctionDecl *FD) {
Chris Lattner4b009652007-07-25 00:24:17 +000050 bool HasBody = FD->getBody();
51
Chris Lattner987058a2007-08-26 04:02:13 +000052 fprintf(stderr, "\n");
53
54 switch (FD->getStorageClass()) {
55 default: assert(0 && "Unknown storage class");
56 case FunctionDecl::None: break;
57 case FunctionDecl::Extern: fprintf(stderr, "extern "); break;
58 case FunctionDecl::Static: fprintf(stderr, "static "); break;
59 }
60
61 if (FD->isInline())
62 fprintf(stderr, "inline ");
63
Chris Lattner4b009652007-07-25 00:24:17 +000064 std::string Proto = FD->getName();
65 FunctionType *AFT = cast<FunctionType>(FD->getType());
66
67 if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
68 Proto += "(";
69 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
70 if (i) Proto += ", ";
71 std::string ParamStr;
72 if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
73
74 FT->getArgType(i).getAsStringInternal(ParamStr);
75 Proto += ParamStr;
76 }
77
78 if (FT->isVariadic()) {
79 if (FD->getNumParams()) Proto += ", ";
80 Proto += "...";
81 }
82 Proto += ")";
83 } else {
84 assert(isa<FunctionTypeNoProto>(AFT));
85 Proto += "()";
86 }
87
88 AFT->getResultType().getAsStringInternal(Proto);
Chris Lattner987058a2007-08-26 04:02:13 +000089 fprintf(stderr, "%s", Proto.c_str());
Chris Lattner4b009652007-07-25 00:24:17 +000090
Chris Lattner95578782007-08-08 22:51:59 +000091 if (!FD->getBody())
Chris Lattner4b009652007-07-25 00:24:17 +000092 fprintf(stderr, ";\n");
Chris Lattner95578782007-08-08 22:51:59 +000093 // Doesn't print the body.
Chris Lattner4b009652007-07-25 00:24:17 +000094}
95
Chris Lattner95578782007-08-08 22:51:59 +000096static void PrintTypeDefDecl(TypedefDecl *TD) {
Chris Lattner4b009652007-07-25 00:24:17 +000097 std::string S = TD->getName();
98 TD->getUnderlyingType().getAsStringInternal(S);
99 fprintf(stderr, "typedef %s;\n", S.c_str());
100}
101
Steve Narofffaed3bf2007-09-10 20:51:04 +0000102static void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID) {
103 std::string S = OID->getName();
104 fprintf(stderr, "@interface %s;\n", S.c_str());
105 // FIXME: implement the rest...
106}
107
Chris Lattner4b009652007-07-25 00:24:17 +0000108void clang::PrintASTs(Preprocessor &PP, unsigned MainFileID, bool Stats) {
109 ASTContext Context(PP.getTargetInfo(), PP.getIdentifierTable());
110 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
111
112 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
113 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Chris Lattner95578782007-08-08 22:51:59 +0000114 PrintFunctionDeclStart(FD);
115
116 if (FD->getBody()) {
117 fprintf(stderr, " ");
118 FD->getBody()->dumpPretty();
119 fprintf(stderr, "\n");
120 }
Chris Lattner4b009652007-07-25 00:24:17 +0000121 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
122 PrintTypeDefDecl(TD);
Steve Narofffaed3bf2007-09-10 20:51:04 +0000123 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
124 PrintObjcInterfaceDecl(OID);
Chris Lattner4b009652007-07-25 00:24:17 +0000125 } else {
126 fprintf(stderr, "Read top-level variable decl: '%s'\n", D->getName());
127 }
128 }
129
130 if (Stats) {
131 fprintf(stderr, "\nSTATISTICS:\n");
132 ASTStreamer_PrintStats(Streamer);
133 Context.PrintStats();
134 }
135
136 ASTStreamer_Terminate(Streamer);
137}
Chris Lattner95578782007-08-08 22:51:59 +0000138
139void clang::DumpASTs(Preprocessor &PP, unsigned MainFileID, bool Stats) {
140 ASTContext Context(PP.getTargetInfo(), PP.getIdentifierTable());
141 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
142
143 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
144 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
145 PrintFunctionDeclStart(FD);
146
147 if (FD->getBody()) {
148 fprintf(stderr, "\n");
Chris Lattnerbbc51ad2007-08-30 00:40:08 +0000149 FD->getBody()->dumpAll(PP.getSourceManager());
Chris Lattner95578782007-08-08 22:51:59 +0000150 fprintf(stderr, "\n");
151 }
152 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
153 PrintTypeDefDecl(TD);
154 } else {
155 fprintf(stderr, "Read top-level variable decl: '%s'\n", D->getName());
156 }
157 }
158
159 if (Stats) {
160 fprintf(stderr, "\nSTATISTICS:\n");
161 ASTStreamer_PrintStats(Streamer);
162 Context.PrintStats();
163 }
164
165 ASTStreamer_Terminate(Streamer);
166}
167
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000168//===----------------------------------------------------------------------===//
169// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
170// the CFGs for all function definitions.
171
172namespace {
173
174class CFGVisitor {
175public:
176 virtual ~CFGVisitor() {}
177 virtual void VisitCFG(CFG& C) = 0;
178 virtual bool printFuncDeclStart() { return true; }
179};
180
181} // end anonymous namespace
182
183static void VisitCFGs(CFGVisitor& Visitor, Preprocessor& PP,
184 unsigned MainFileID, bool Stats) {
185
186 bool printFDecl = Visitor.printFuncDeclStart();
187 ASTContext Context(PP.getTargetInfo(), PP.getIdentifierTable());
188 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
189
190 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
191 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
192 if (FD->getBody()) {
193
194 if (printFDecl) {
195 PrintFunctionDeclStart(FD);
196 fprintf(stderr,"\n");
197 }
198
199 if (CFG* C = CFG::buildCFG(FD->getBody())) {
200 Visitor.VisitCFG(*C);
201 delete C;
202 }
203 else
204 fprintf(stderr," Error processing CFG.\n");
205 }
206 }
207
208 if (Stats) {
209 fprintf(stderr, "\nSTATISTICS:\n");
210 ASTStreamer_PrintStats(Streamer);
211 Context.PrintStats();
212 }
213
214 ASTStreamer_Terminate(Streamer);
215}
216
217//===----------------------------------------------------------------------===//
218// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
219
220namespace {
221 class CFGDumper : public CFGVisitor {
222 const bool UseGraphviz;
223 public:
224 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
225
226 virtual void VisitCFG(CFG& C) {
227 if (UseGraphviz) C.viewCFG();
228 else C.dump();
229 }
230 };
231} // end anonymous namespace
232
Ted Kremenekb3bb91b2007-08-29 21:56:09 +0000233void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID,
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000234 bool Stats, bool use_graphviz) {
235 CFGDumper Visitor(use_graphviz);
236 VisitCFGs(Visitor,PP,MainFileID,Stats);
Ted Kremenek97f75312007-08-21 21:42:03 +0000237}
238
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000239//===----------------------------------------------------------------------===//
240// AnalyzeLiveVariables - perform live variable analysis and dump results
241
242namespace {
243 class LivenessVisitor : public CFGVisitor {
244 Preprocessor& PP;
245 public:
246 LivenessVisitor(Preprocessor& pp) : PP(pp) {}
247
248 virtual void VisitCFG(CFG& C) {
249 LiveVariables L;
250 L.runOnCFG(C);
Ted Kremenek6b2b4e32007-09-10 17:36:42 +0000251 L.dumpBlockLiveness(PP.getSourceManager());
252 L.dumpVarLiveness(PP.getSourceManager());
Ted Kremenekaa04c512007-09-06 00:17:54 +0000253 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000254 };
255} // end anonymous namespace
256
257void clang::AnalyzeLiveVariables(Preprocessor &PP, unsigned MainFileID) {
258 LivenessVisitor Visitor(PP);
259 VisitCFGs(Visitor,PP,MainFileID,false);
Ted Kremenekaa04c512007-09-06 00:17:54 +0000260}
261
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000262//===----------------------------------------------------------------------===//
263// RunDeadStores - run checker to locate dead stores in a function
264
265namespace {
266 class DeadStoreVisitor : public CFGVisitor {
267 Preprocessor& PP;
268 public:
269 DeadStoreVisitor(Preprocessor& pp) : PP(pp) {}
270 virtual void VisitCFG(CFG& C) { CheckDeadStores(C,PP); }
Ted Kremenek39b8c4b2007-09-07 23:54:15 +0000271 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000272 };
273} // end anonymous namespace
274
275void clang::RunDeadStoresCheck(Preprocessor &PP,unsigned MainFileID,bool Stats){
276 DeadStoreVisitor Visitor(PP);
277 VisitCFGs(Visitor,PP,MainFileID,Stats);
Ted Kremeneke805c4a2007-09-06 23:00:42 +0000278}