blob: d4c55ad681a5dcc4db9ec1985a18d7acf83ff244 [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
102void clang::PrintASTs(Preprocessor &PP, unsigned MainFileID, bool Stats) {
103 ASTContext Context(PP.getTargetInfo(), PP.getIdentifierTable());
104 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
105
106 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
107 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Chris Lattner95578782007-08-08 22:51:59 +0000108 PrintFunctionDeclStart(FD);
109
110 if (FD->getBody()) {
111 fprintf(stderr, " ");
112 FD->getBody()->dumpPretty();
113 fprintf(stderr, "\n");
114 }
Chris Lattner4b009652007-07-25 00:24:17 +0000115 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
116 PrintTypeDefDecl(TD);
117 } else {
118 fprintf(stderr, "Read top-level variable decl: '%s'\n", D->getName());
119 }
120 }
121
122 if (Stats) {
123 fprintf(stderr, "\nSTATISTICS:\n");
124 ASTStreamer_PrintStats(Streamer);
125 Context.PrintStats();
126 }
127
128 ASTStreamer_Terminate(Streamer);
129}
Chris Lattner95578782007-08-08 22:51:59 +0000130
131void clang::DumpASTs(Preprocessor &PP, unsigned MainFileID, bool Stats) {
132 ASTContext Context(PP.getTargetInfo(), PP.getIdentifierTable());
133 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
134
135 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
136 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
137 PrintFunctionDeclStart(FD);
138
139 if (FD->getBody()) {
140 fprintf(stderr, "\n");
Chris Lattnerbbc51ad2007-08-30 00:40:08 +0000141 FD->getBody()->dumpAll(PP.getSourceManager());
Chris Lattner95578782007-08-08 22:51:59 +0000142 fprintf(stderr, "\n");
143 }
144 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
145 PrintTypeDefDecl(TD);
146 } else {
147 fprintf(stderr, "Read top-level variable decl: '%s'\n", D->getName());
148 }
149 }
150
151 if (Stats) {
152 fprintf(stderr, "\nSTATISTICS:\n");
153 ASTStreamer_PrintStats(Streamer);
154 Context.PrintStats();
155 }
156
157 ASTStreamer_Terminate(Streamer);
158}
159
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000160//===----------------------------------------------------------------------===//
161// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
162// the CFGs for all function definitions.
163
164namespace {
165
166class CFGVisitor {
167public:
168 virtual ~CFGVisitor() {}
169 virtual void VisitCFG(CFG& C) = 0;
170 virtual bool printFuncDeclStart() { return true; }
171};
172
173} // end anonymous namespace
174
175static void VisitCFGs(CFGVisitor& Visitor, Preprocessor& PP,
176 unsigned MainFileID, bool Stats) {
177
178 bool printFDecl = Visitor.printFuncDeclStart();
179 ASTContext Context(PP.getTargetInfo(), PP.getIdentifierTable());
180 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
181
182 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
183 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
184 if (FD->getBody()) {
185
186 if (printFDecl) {
187 PrintFunctionDeclStart(FD);
188 fprintf(stderr,"\n");
189 }
190
191 if (CFG* C = CFG::buildCFG(FD->getBody())) {
192 Visitor.VisitCFG(*C);
193 delete C;
194 }
195 else
196 fprintf(stderr," Error processing CFG.\n");
197 }
198 }
199
200 if (Stats) {
201 fprintf(stderr, "\nSTATISTICS:\n");
202 ASTStreamer_PrintStats(Streamer);
203 Context.PrintStats();
204 }
205
206 ASTStreamer_Terminate(Streamer);
207}
208
209//===----------------------------------------------------------------------===//
210// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
211
212namespace {
213 class CFGDumper : public CFGVisitor {
214 const bool UseGraphviz;
215 public:
216 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
217
218 virtual void VisitCFG(CFG& C) {
219 if (UseGraphviz) C.viewCFG();
220 else C.dump();
221 }
222 };
223} // end anonymous namespace
224
Ted Kremenekb3bb91b2007-08-29 21:56:09 +0000225void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID,
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000226 bool Stats, bool use_graphviz) {
227 CFGDumper Visitor(use_graphviz);
228 VisitCFGs(Visitor,PP,MainFileID,Stats);
Ted Kremenek97f75312007-08-21 21:42:03 +0000229}
230
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000231//===----------------------------------------------------------------------===//
232// AnalyzeLiveVariables - perform live variable analysis and dump results
233
234namespace {
235 class LivenessVisitor : public CFGVisitor {
236 Preprocessor& PP;
237 public:
238 LivenessVisitor(Preprocessor& pp) : PP(pp) {}
239
240 virtual void VisitCFG(CFG& C) {
241 LiveVariables L;
242 L.runOnCFG(C);
Ted Kremenek6b2b4e32007-09-10 17:36:42 +0000243 L.dumpBlockLiveness(PP.getSourceManager());
244 L.dumpVarLiveness(PP.getSourceManager());
Ted Kremenekaa04c512007-09-06 00:17:54 +0000245 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000246 };
247} // end anonymous namespace
248
249void clang::AnalyzeLiveVariables(Preprocessor &PP, unsigned MainFileID) {
250 LivenessVisitor Visitor(PP);
251 VisitCFGs(Visitor,PP,MainFileID,false);
Ted Kremenekaa04c512007-09-06 00:17:54 +0000252}
253
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000254//===----------------------------------------------------------------------===//
255// RunDeadStores - run checker to locate dead stores in a function
256
257namespace {
258 class DeadStoreVisitor : public CFGVisitor {
259 Preprocessor& PP;
260 public:
261 DeadStoreVisitor(Preprocessor& pp) : PP(pp) {}
262 virtual void VisitCFG(CFG& C) { CheckDeadStores(C,PP); }
Ted Kremenek39b8c4b2007-09-07 23:54:15 +0000263 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000264 };
265} // end anonymous namespace
266
267void clang::RunDeadStoresCheck(Preprocessor &PP,unsigned MainFileID,bool Stats){
268 DeadStoreVisitor Visitor(PP);
269 VisitCFGs(Visitor,PP,MainFileID,Stats);
Ted Kremeneke805c4a2007-09-06 23:00:42 +0000270}