blob: 72524f16bc76af12e8286114701616661047f550 [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"
Reid Spencer5f016e22007-07-11 17:01:13 +000020#include "clang/Lex/Preprocessor.h"
21#include "clang/Sema/ASTStreamer.h"
Chris Lattner6000dac2007-08-08 22:51:59 +000022using namespace clang;
Reid Spencer5f016e22007-07-11 17:01:13 +000023
Chris Lattner6000dac2007-08-08 22:51:59 +000024
25static void PrintFunctionDeclStart(FunctionDecl *FD) {
Reid Spencer5f016e22007-07-11 17:01:13 +000026 bool HasBody = FD->getBody();
27
Chris Lattner70c8b2e2007-08-26 04:02:13 +000028 fprintf(stderr, "\n");
29
30 switch (FD->getStorageClass()) {
31 default: assert(0 && "Unknown storage class");
32 case FunctionDecl::None: break;
33 case FunctionDecl::Extern: fprintf(stderr, "extern "); break;
34 case FunctionDecl::Static: fprintf(stderr, "static "); break;
35 }
36
37 if (FD->isInline())
38 fprintf(stderr, "inline ");
39
Reid Spencer5f016e22007-07-11 17:01:13 +000040 std::string Proto = FD->getName();
41 FunctionType *AFT = cast<FunctionType>(FD->getType());
42
43 if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
44 Proto += "(";
45 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
46 if (i) Proto += ", ";
47 std::string ParamStr;
48 if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
49
50 FT->getArgType(i).getAsStringInternal(ParamStr);
51 Proto += ParamStr;
52 }
53
54 if (FT->isVariadic()) {
55 if (FD->getNumParams()) Proto += ", ";
56 Proto += "...";
57 }
58 Proto += ")";
59 } else {
60 assert(isa<FunctionTypeNoProto>(AFT));
61 Proto += "()";
62 }
63
64 AFT->getResultType().getAsStringInternal(Proto);
Chris Lattner70c8b2e2007-08-26 04:02:13 +000065 fprintf(stderr, "%s", Proto.c_str());
Reid Spencer5f016e22007-07-11 17:01:13 +000066
Chris Lattner6000dac2007-08-08 22:51:59 +000067 if (!FD->getBody())
Reid Spencer5f016e22007-07-11 17:01:13 +000068 fprintf(stderr, ";\n");
Chris Lattner6000dac2007-08-08 22:51:59 +000069 // Doesn't print the body.
Reid Spencer5f016e22007-07-11 17:01:13 +000070}
71
Chris Lattner6000dac2007-08-08 22:51:59 +000072static void PrintTypeDefDecl(TypedefDecl *TD) {
Reid Spencer5f016e22007-07-11 17:01:13 +000073 std::string S = TD->getName();
74 TD->getUnderlyingType().getAsStringInternal(S);
75 fprintf(stderr, "typedef %s;\n", S.c_str());
76}
77
Steve Naroff2bd42fa2007-09-10 20:51:04 +000078static void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID) {
79 std::string S = OID->getName();
80 fprintf(stderr, "@interface %s;\n", S.c_str());
81 // FIXME: implement the rest...
82}
83
Chris Lattner3d4997d2007-09-15 23:02:28 +000084namespace {
85 class ASTPrinter : public ASTConsumer {
86 virtual void HandleTopLevelDecl(Decl *D) {
87 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
88 PrintFunctionDeclStart(FD);
89
90 if (FD->getBody()) {
91 fprintf(stderr, " ");
92 FD->getBody()->dumpPretty();
93 fprintf(stderr, "\n");
94 }
95 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
96 PrintTypeDefDecl(TD);
97 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
98 PrintObjcInterfaceDecl(OID);
99 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
100 fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
Chris Lattner6000dac2007-08-08 22:51:59 +0000101 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000102 }
Chris Lattner3d4997d2007-09-15 23:02:28 +0000103 };
Reid Spencer5f016e22007-07-11 17:01:13 +0000104}
Chris Lattner6000dac2007-08-08 22:51:59 +0000105
Chris Lattner3d4997d2007-09-15 23:02:28 +0000106ASTConsumer *clang::CreateASTPrinter() { return new ASTPrinter(); }
107
108namespace {
109 class ASTDumper : public ASTConsumer {
110 SourceManager *SM;
111 public:
112 void Initialize(ASTContext &Context, unsigned MainFileID) {
113 SM = &Context.SourceMgr;
Chris Lattner6000dac2007-08-08 22:51:59 +0000114 }
Chris Lattner3d4997d2007-09-15 23:02:28 +0000115
116 virtual void HandleTopLevelDecl(Decl *D) {
117 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
118 PrintFunctionDeclStart(FD);
119
120 if (FD->getBody()) {
121 fprintf(stderr, "\n");
122 FD->getBody()->dumpAll(*SM);
123 fprintf(stderr, "\n");
124 }
125 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
126 PrintTypeDefDecl(TD);
127 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
128 fprintf(stderr, "Read top-level variable decl: '%s'\n", SD->getName());
129 }
130 }
131 };
Chris Lattner6000dac2007-08-08 22:51:59 +0000132}
133
Chris Lattner3d4997d2007-09-15 23:02:28 +0000134ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
135
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000136//===----------------------------------------------------------------------===//
137// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
138// the CFGs for all function definitions.
139
140namespace {
141
142class CFGVisitor {
143public:
144 virtual ~CFGVisitor() {}
145 virtual void VisitCFG(CFG& C) = 0;
146 virtual bool printFuncDeclStart() { return true; }
147};
148
149} // end anonymous namespace
150
151static void VisitCFGs(CFGVisitor& Visitor, Preprocessor& PP,
152 unsigned MainFileID, bool Stats) {
153
154 bool printFDecl = Visitor.printFuncDeclStart();
Chris Lattnerb800dc22007-09-13 01:14:03 +0000155 ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(),
156 PP.getIdentifierTable());
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000157 ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
158
159 while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
160 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
161 if (FD->getBody()) {
162
163 if (printFDecl) {
164 PrintFunctionDeclStart(FD);
165 fprintf(stderr,"\n");
166 }
167
168 if (CFG* C = CFG::buildCFG(FD->getBody())) {
169 Visitor.VisitCFG(*C);
170 delete C;
171 }
172 else
173 fprintf(stderr," Error processing CFG.\n");
174 }
175 }
176
177 if (Stats) {
178 fprintf(stderr, "\nSTATISTICS:\n");
179 ASTStreamer_PrintStats(Streamer);
180 Context.PrintStats();
181 }
182
183 ASTStreamer_Terminate(Streamer);
184}
185
186//===----------------------------------------------------------------------===//
187// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
188
189namespace {
190 class CFGDumper : public CFGVisitor {
191 const bool UseGraphviz;
192 public:
193 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
194
195 virtual void VisitCFG(CFG& C) {
196 if (UseGraphviz) C.viewCFG();
197 else C.dump();
198 }
199 };
200} // end anonymous namespace
201
Ted Kremenek7dba8602007-08-29 21:56:09 +0000202void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID,
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000203 bool Stats, bool use_graphviz) {
204 CFGDumper Visitor(use_graphviz);
205 VisitCFGs(Visitor,PP,MainFileID,Stats);
Ted Kremenekfddd5182007-08-21 21:42:03 +0000206}
207
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000208//===----------------------------------------------------------------------===//
209// AnalyzeLiveVariables - perform live variable analysis and dump results
210
211namespace {
212 class LivenessVisitor : public CFGVisitor {
213 Preprocessor& PP;
214 public:
215 LivenessVisitor(Preprocessor& pp) : PP(pp) {}
216
217 virtual void VisitCFG(CFG& C) {
218 LiveVariables L;
219 L.runOnCFG(C);
Ted Kremenekc0576ca2007-09-10 17:36:42 +0000220 L.dumpBlockLiveness(PP.getSourceManager());
221 L.dumpVarLiveness(PP.getSourceManager());
Ted Kremeneke4e63342007-09-06 00:17:54 +0000222 }
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000223 };
224} // end anonymous namespace
225
226void clang::AnalyzeLiveVariables(Preprocessor &PP, unsigned MainFileID) {
227 LivenessVisitor Visitor(PP);
228 VisitCFGs(Visitor,PP,MainFileID,false);
Ted Kremeneke4e63342007-09-06 00:17:54 +0000229}
230
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000231//===----------------------------------------------------------------------===//
232// RunDeadStores - run checker to locate dead stores in a function
233
234namespace {
235 class DeadStoreVisitor : public CFGVisitor {
236 Preprocessor& PP;
237 public:
238 DeadStoreVisitor(Preprocessor& pp) : PP(pp) {}
239 virtual void VisitCFG(CFG& C) { CheckDeadStores(C,PP); }
Ted Kremenek567a7e62007-09-07 23:54:15 +0000240 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000241 };
242} // end anonymous namespace
243
244void clang::RunDeadStoresCheck(Preprocessor &PP,unsigned MainFileID,bool Stats){
245 DeadStoreVisitor Visitor(PP);
246 VisitCFGs(Visitor,PP,MainFileID,Stats);
Ted Kremenek055c2752007-09-06 23:00:42 +0000247}