blob: 342ee6b32763879df400ff2293e9d85dfac2516f [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
Chris Lattner409dfd12007-09-13 01:14:03 +000030 ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(),
31 PP.getIdentifierTable());
Chris Lattner4b009652007-07-25 00:24:17 +000032 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
33
34 while (ASTStreamer_ReadTopLevelDecl(Streamer))
35 /* keep reading */;
36
37 if (Stats) {
38 fprintf(stderr, "\nSTATISTICS:\n");
39 ASTStreamer_PrintStats(Streamer);
40 Context.PrintStats();
41 Decl::PrintStats();
42 Stmt::PrintStats();
43 }
44
45 ASTStreamer_Terminate(Streamer);
46}
47
Chris Lattner95578782007-08-08 22:51:59 +000048
49
50static void PrintFunctionDeclStart(FunctionDecl *FD) {
Chris Lattner4b009652007-07-25 00:24:17 +000051 bool HasBody = FD->getBody();
52
Chris Lattner987058a2007-08-26 04:02:13 +000053 fprintf(stderr, "\n");
54
55 switch (FD->getStorageClass()) {
56 default: assert(0 && "Unknown storage class");
57 case FunctionDecl::None: break;
58 case FunctionDecl::Extern: fprintf(stderr, "extern "); break;
59 case FunctionDecl::Static: fprintf(stderr, "static "); break;
60 }
61
62 if (FD->isInline())
63 fprintf(stderr, "inline ");
64
Chris Lattner4b009652007-07-25 00:24:17 +000065 std::string Proto = FD->getName();
66 FunctionType *AFT = cast<FunctionType>(FD->getType());
67
68 if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
69 Proto += "(";
70 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
71 if (i) Proto += ", ";
72 std::string ParamStr;
73 if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
74
75 FT->getArgType(i).getAsStringInternal(ParamStr);
76 Proto += ParamStr;
77 }
78
79 if (FT->isVariadic()) {
80 if (FD->getNumParams()) Proto += ", ";
81 Proto += "...";
82 }
83 Proto += ")";
84 } else {
85 assert(isa<FunctionTypeNoProto>(AFT));
86 Proto += "()";
87 }
88
89 AFT->getResultType().getAsStringInternal(Proto);
Chris Lattner987058a2007-08-26 04:02:13 +000090 fprintf(stderr, "%s", Proto.c_str());
Chris Lattner4b009652007-07-25 00:24:17 +000091
Chris Lattner95578782007-08-08 22:51:59 +000092 if (!FD->getBody())
Chris Lattner4b009652007-07-25 00:24:17 +000093 fprintf(stderr, ";\n");
Chris Lattner95578782007-08-08 22:51:59 +000094 // Doesn't print the body.
Chris Lattner4b009652007-07-25 00:24:17 +000095}
96
Chris Lattner95578782007-08-08 22:51:59 +000097static void PrintTypeDefDecl(TypedefDecl *TD) {
Chris Lattner4b009652007-07-25 00:24:17 +000098 std::string S = TD->getName();
99 TD->getUnderlyingType().getAsStringInternal(S);
100 fprintf(stderr, "typedef %s;\n", S.c_str());
101}
102
Steve Narofffaed3bf2007-09-10 20:51:04 +0000103static void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID) {
104 std::string S = OID->getName();
105 fprintf(stderr, "@interface %s;\n", S.c_str());
106 // FIXME: implement the rest...
107}
108
Chris Lattner4b009652007-07-25 00:24:17 +0000109void clang::PrintASTs(Preprocessor &PP, unsigned MainFileID, bool Stats) {
Chris Lattner409dfd12007-09-13 01:14:03 +0000110 ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(),
111 PP.getIdentifierTable());
Chris Lattner4b009652007-07-25 00:24:17 +0000112 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
113
114 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
115 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Chris Lattner95578782007-08-08 22:51:59 +0000116 PrintFunctionDeclStart(FD);
117
118 if (FD->getBody()) {
119 fprintf(stderr, " ");
120 FD->getBody()->dumpPretty();
121 fprintf(stderr, "\n");
122 }
Chris Lattner4b009652007-07-25 00:24:17 +0000123 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
124 PrintTypeDefDecl(TD);
Steve Narofffaed3bf2007-09-10 20:51:04 +0000125 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
126 PrintObjcInterfaceDecl(OID);
Chris Lattner4b009652007-07-25 00:24:17 +0000127 } else {
128 fprintf(stderr, "Read top-level variable decl: '%s'\n", D->getName());
129 }
130 }
131
132 if (Stats) {
133 fprintf(stderr, "\nSTATISTICS:\n");
134 ASTStreamer_PrintStats(Streamer);
135 Context.PrintStats();
136 }
137
138 ASTStreamer_Terminate(Streamer);
139}
Chris Lattner95578782007-08-08 22:51:59 +0000140
141void clang::DumpASTs(Preprocessor &PP, unsigned MainFileID, bool Stats) {
Chris Lattner409dfd12007-09-13 01:14:03 +0000142 ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(),
143 PP.getIdentifierTable());
Chris Lattner95578782007-08-08 22:51:59 +0000144 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
145
146 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
147 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
148 PrintFunctionDeclStart(FD);
149
150 if (FD->getBody()) {
151 fprintf(stderr, "\n");
Chris Lattnerbbc51ad2007-08-30 00:40:08 +0000152 FD->getBody()->dumpAll(PP.getSourceManager());
Chris Lattner95578782007-08-08 22:51:59 +0000153 fprintf(stderr, "\n");
154 }
155 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
156 PrintTypeDefDecl(TD);
157 } else {
158 fprintf(stderr, "Read top-level variable decl: '%s'\n", D->getName());
159 }
160 }
161
162 if (Stats) {
163 fprintf(stderr, "\nSTATISTICS:\n");
164 ASTStreamer_PrintStats(Streamer);
165 Context.PrintStats();
166 }
167
168 ASTStreamer_Terminate(Streamer);
169}
170
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000171//===----------------------------------------------------------------------===//
172// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
173// the CFGs for all function definitions.
174
175namespace {
176
177class CFGVisitor {
178public:
179 virtual ~CFGVisitor() {}
180 virtual void VisitCFG(CFG& C) = 0;
181 virtual bool printFuncDeclStart() { return true; }
182};
183
184} // end anonymous namespace
185
186static void VisitCFGs(CFGVisitor& Visitor, Preprocessor& PP,
187 unsigned MainFileID, bool Stats) {
188
189 bool printFDecl = Visitor.printFuncDeclStart();
Chris Lattner409dfd12007-09-13 01:14:03 +0000190 ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(),
191 PP.getIdentifierTable());
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000192 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
193
194 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
195 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
196 if (FD->getBody()) {
197
198 if (printFDecl) {
199 PrintFunctionDeclStart(FD);
200 fprintf(stderr,"\n");
201 }
202
203 if (CFG* C = CFG::buildCFG(FD->getBody())) {
204 Visitor.VisitCFG(*C);
205 delete C;
206 }
207 else
208 fprintf(stderr," Error processing CFG.\n");
209 }
210 }
211
212 if (Stats) {
213 fprintf(stderr, "\nSTATISTICS:\n");
214 ASTStreamer_PrintStats(Streamer);
215 Context.PrintStats();
216 }
217
218 ASTStreamer_Terminate(Streamer);
219}
220
221//===----------------------------------------------------------------------===//
222// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
223
224namespace {
225 class CFGDumper : public CFGVisitor {
226 const bool UseGraphviz;
227 public:
228 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
229
230 virtual void VisitCFG(CFG& C) {
231 if (UseGraphviz) C.viewCFG();
232 else C.dump();
233 }
234 };
235} // end anonymous namespace
236
Ted Kremenekb3bb91b2007-08-29 21:56:09 +0000237void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID,
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000238 bool Stats, bool use_graphviz) {
239 CFGDumper Visitor(use_graphviz);
240 VisitCFGs(Visitor,PP,MainFileID,Stats);
Ted Kremenek97f75312007-08-21 21:42:03 +0000241}
242
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000243//===----------------------------------------------------------------------===//
244// AnalyzeLiveVariables - perform live variable analysis and dump results
245
246namespace {
247 class LivenessVisitor : public CFGVisitor {
248 Preprocessor& PP;
249 public:
250 LivenessVisitor(Preprocessor& pp) : PP(pp) {}
251
252 virtual void VisitCFG(CFG& C) {
253 LiveVariables L;
254 L.runOnCFG(C);
Ted Kremenek6b2b4e32007-09-10 17:36:42 +0000255 L.dumpBlockLiveness(PP.getSourceManager());
256 L.dumpVarLiveness(PP.getSourceManager());
Ted Kremenekaa04c512007-09-06 00:17:54 +0000257 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000258 };
259} // end anonymous namespace
260
261void clang::AnalyzeLiveVariables(Preprocessor &PP, unsigned MainFileID) {
262 LivenessVisitor Visitor(PP);
263 VisitCFGs(Visitor,PP,MainFileID,false);
Ted Kremenekaa04c512007-09-06 00:17:54 +0000264}
265
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000266//===----------------------------------------------------------------------===//
267// RunDeadStores - run checker to locate dead stores in a function
268
269namespace {
270 class DeadStoreVisitor : public CFGVisitor {
271 Preprocessor& PP;
272 public:
273 DeadStoreVisitor(Preprocessor& pp) : PP(pp) {}
274 virtual void VisitCFG(CFG& C) { CheckDeadStores(C,PP); }
Ted Kremenek39b8c4b2007-09-07 23:54:15 +0000275 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000276 };
277} // end anonymous namespace
278
279void clang::RunDeadStoresCheck(Preprocessor &PP,unsigned MainFileID,bool Stats){
280 DeadStoreVisitor Visitor(PP);
281 VisitCFGs(Visitor,PP,MainFileID,Stats);
Ted Kremeneke805c4a2007-09-06 23:00:42 +0000282}