blob: b3517dfaef39d651295a1ff0fe2ca73be7fb8f88 [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
Chris Lattner95578782007-08-08 22:51:59 +000023
24static void PrintFunctionDeclStart(FunctionDecl *FD) {
Chris Lattner4b009652007-07-25 00:24:17 +000025 bool HasBody = FD->getBody();
26
Chris Lattner987058a2007-08-26 04:02:13 +000027 fprintf(stderr, "\n");
28
29 switch (FD->getStorageClass()) {
30 default: assert(0 && "Unknown storage class");
31 case FunctionDecl::None: break;
32 case FunctionDecl::Extern: fprintf(stderr, "extern "); break;
33 case FunctionDecl::Static: fprintf(stderr, "static "); break;
34 }
35
36 if (FD->isInline())
37 fprintf(stderr, "inline ");
38
Chris Lattner4b009652007-07-25 00:24:17 +000039 std::string Proto = FD->getName();
40 FunctionType *AFT = cast<FunctionType>(FD->getType());
41
42 if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
43 Proto += "(";
44 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
45 if (i) Proto += ", ";
46 std::string ParamStr;
47 if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
48
49 FT->getArgType(i).getAsStringInternal(ParamStr);
50 Proto += ParamStr;
51 }
52
53 if (FT->isVariadic()) {
54 if (FD->getNumParams()) Proto += ", ";
55 Proto += "...";
56 }
57 Proto += ")";
58 } else {
59 assert(isa<FunctionTypeNoProto>(AFT));
60 Proto += "()";
61 }
62
63 AFT->getResultType().getAsStringInternal(Proto);
Chris Lattner987058a2007-08-26 04:02:13 +000064 fprintf(stderr, "%s", Proto.c_str());
Chris Lattner4b009652007-07-25 00:24:17 +000065
Chris Lattner95578782007-08-08 22:51:59 +000066 if (!FD->getBody())
Chris Lattner4b009652007-07-25 00:24:17 +000067 fprintf(stderr, ";\n");
Chris Lattner95578782007-08-08 22:51:59 +000068 // Doesn't print the body.
Chris Lattner4b009652007-07-25 00:24:17 +000069}
70
Chris Lattner95578782007-08-08 22:51:59 +000071static void PrintTypeDefDecl(TypedefDecl *TD) {
Chris Lattner4b009652007-07-25 00:24:17 +000072 std::string S = TD->getName();
73 TD->getUnderlyingType().getAsStringInternal(S);
74 fprintf(stderr, "typedef %s;\n", S.c_str());
75}
76
Steve Narofffaed3bf2007-09-10 20:51:04 +000077static void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID) {
78 std::string S = OID->getName();
79 fprintf(stderr, "@interface %s;\n", S.c_str());
80 // FIXME: implement the rest...
81}
82
Chris Lattner4b009652007-07-25 00:24:17 +000083void clang::PrintASTs(Preprocessor &PP, unsigned MainFileID, bool Stats) {
Chris Lattner409dfd12007-09-13 01:14:03 +000084 ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(),
85 PP.getIdentifierTable());
Chris Lattner4b009652007-07-25 00:24:17 +000086 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
87
88 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
89 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Chris Lattner95578782007-08-08 22:51:59 +000090 PrintFunctionDeclStart(FD);
91
92 if (FD->getBody()) {
93 fprintf(stderr, " ");
94 FD->getBody()->dumpPretty();
95 fprintf(stderr, "\n");
96 }
Chris Lattner4b009652007-07-25 00:24:17 +000097 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
98 PrintTypeDefDecl(TD);
Steve Narofffaed3bf2007-09-10 20:51:04 +000099 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
100 PrintObjcInterfaceDecl(OID);
Steve Naroffcb597472007-09-13 21:41:19 +0000101 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
102 fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
Chris Lattner4b009652007-07-25 00:24:17 +0000103 }
104 }
105
106 if (Stats) {
107 fprintf(stderr, "\nSTATISTICS:\n");
108 ASTStreamer_PrintStats(Streamer);
109 Context.PrintStats();
110 }
111
112 ASTStreamer_Terminate(Streamer);
113}
Chris Lattner95578782007-08-08 22:51:59 +0000114
115void clang::DumpASTs(Preprocessor &PP, unsigned MainFileID, bool Stats) {
Chris Lattner409dfd12007-09-13 01:14:03 +0000116 ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(),
117 PP.getIdentifierTable());
Chris Lattner95578782007-08-08 22:51:59 +0000118 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
119
120 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
121 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
122 PrintFunctionDeclStart(FD);
123
124 if (FD->getBody()) {
125 fprintf(stderr, "\n");
Chris Lattnerbbc51ad2007-08-30 00:40:08 +0000126 FD->getBody()->dumpAll(PP.getSourceManager());
Chris Lattner95578782007-08-08 22:51:59 +0000127 fprintf(stderr, "\n");
128 }
129 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
130 PrintTypeDefDecl(TD);
Steve Naroffcb597472007-09-13 21:41:19 +0000131 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
132 fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
Chris Lattner95578782007-08-08 22:51:59 +0000133 }
134 }
135
136 if (Stats) {
137 fprintf(stderr, "\nSTATISTICS:\n");
138 ASTStreamer_PrintStats(Streamer);
139 Context.PrintStats();
140 }
141
142 ASTStreamer_Terminate(Streamer);
143}
144
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000145//===----------------------------------------------------------------------===//
146// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
147// the CFGs for all function definitions.
148
149namespace {
150
151class CFGVisitor {
152public:
153 virtual ~CFGVisitor() {}
154 virtual void VisitCFG(CFG& C) = 0;
155 virtual bool printFuncDeclStart() { return true; }
156};
157
158} // end anonymous namespace
159
160static void VisitCFGs(CFGVisitor& Visitor, Preprocessor& PP,
161 unsigned MainFileID, bool Stats) {
162
163 bool printFDecl = Visitor.printFuncDeclStart();
Chris Lattner409dfd12007-09-13 01:14:03 +0000164 ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(),
165 PP.getIdentifierTable());
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000166 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
167
168 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
169 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
170 if (FD->getBody()) {
171
172 if (printFDecl) {
173 PrintFunctionDeclStart(FD);
174 fprintf(stderr,"\n");
175 }
176
177 if (CFG* C = CFG::buildCFG(FD->getBody())) {
178 Visitor.VisitCFG(*C);
179 delete C;
180 }
181 else
182 fprintf(stderr," Error processing CFG.\n");
183 }
184 }
185
186 if (Stats) {
187 fprintf(stderr, "\nSTATISTICS:\n");
188 ASTStreamer_PrintStats(Streamer);
189 Context.PrintStats();
190 }
191
192 ASTStreamer_Terminate(Streamer);
193}
194
195//===----------------------------------------------------------------------===//
196// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
197
198namespace {
199 class CFGDumper : public CFGVisitor {
200 const bool UseGraphviz;
201 public:
202 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
203
204 virtual void VisitCFG(CFG& C) {
205 if (UseGraphviz) C.viewCFG();
206 else C.dump();
207 }
208 };
209} // end anonymous namespace
210
Ted Kremenekb3bb91b2007-08-29 21:56:09 +0000211void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID,
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000212 bool Stats, bool use_graphviz) {
213 CFGDumper Visitor(use_graphviz);
214 VisitCFGs(Visitor,PP,MainFileID,Stats);
Ted Kremenek97f75312007-08-21 21:42:03 +0000215}
216
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000217//===----------------------------------------------------------------------===//
218// AnalyzeLiveVariables - perform live variable analysis and dump results
219
220namespace {
221 class LivenessVisitor : public CFGVisitor {
222 Preprocessor& PP;
223 public:
224 LivenessVisitor(Preprocessor& pp) : PP(pp) {}
225
226 virtual void VisitCFG(CFG& C) {
227 LiveVariables L;
228 L.runOnCFG(C);
Ted Kremenek6b2b4e32007-09-10 17:36:42 +0000229 L.dumpBlockLiveness(PP.getSourceManager());
230 L.dumpVarLiveness(PP.getSourceManager());
Ted Kremenekaa04c512007-09-06 00:17:54 +0000231 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000232 };
233} // end anonymous namespace
234
235void clang::AnalyzeLiveVariables(Preprocessor &PP, unsigned MainFileID) {
236 LivenessVisitor Visitor(PP);
237 VisitCFGs(Visitor,PP,MainFileID,false);
Ted Kremenekaa04c512007-09-06 00:17:54 +0000238}
239
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000240//===----------------------------------------------------------------------===//
241// RunDeadStores - run checker to locate dead stores in a function
242
243namespace {
244 class DeadStoreVisitor : public CFGVisitor {
245 Preprocessor& PP;
246 public:
247 DeadStoreVisitor(Preprocessor& pp) : PP(pp) {}
248 virtual void VisitCFG(CFG& C) { CheckDeadStores(C,PP); }
Ted Kremenek39b8c4b2007-09-07 23:54:15 +0000249 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000250 };
251} // end anonymous namespace
252
253void clang::RunDeadStoresCheck(Preprocessor &PP,unsigned MainFileID,bool Stats){
254 DeadStoreVisitor Visitor(PP);
255 VisitCFGs(Visitor,PP,MainFileID,Stats);
Ted Kremeneke805c4a2007-09-06 23:00:42 +0000256}