1 //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // AST Consumer Implementations.
12 //===----------------------------------------------------------------------===//
14 #include "ASTConsumers.h"
15 #include "clang/AST/TranslationUnit.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "clang/Basic/FileManager.h"
18 #include "clang/AST/AST.h"
19 #include "clang/AST/ASTConsumer.h"
20 #include "clang/AST/CFG.h"
21 #include "clang/Analysis/Analyses/LiveVariables.h"
22 #include "clang/Analysis/Analyses/GRConstants.h"
23 #include "clang/Analysis/LocalCheckers.h"
24 #include "llvm/Support/Streams.h"
25 using namespace clang;
27 //===----------------------------------------------------------------------===//
28 /// DeclPrinter - Utility class for printing top-level decls.
35 DeclPrinter(std::ostream* out) : Out(out ? *out : *llvm::cerr.stream()) {}
36 DeclPrinter() : Out(*llvm::cerr.stream()) {}
38 void PrintDecl(Decl *D);
39 void PrintFunctionDeclStart(FunctionDecl *FD);
40 void PrintTypeDefDecl(TypedefDecl *TD);
41 void PrintLinkageSpec(LinkageSpecDecl *LS);
42 void PrintObjCMethodDecl(ObjCMethodDecl *OMD);
43 void PrintObjCImplementationDecl(ObjCImplementationDecl *OID);
44 void PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID);
45 void PrintObjCProtocolDecl(ObjCProtocolDecl *PID);
46 void PrintObjCCategoryImplDecl(ObjCCategoryImplDecl *PID);
47 void PrintObjCCategoryDecl(ObjCCategoryDecl *PID);
48 void PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID);
50 } // end anonymous namespace
52 void DeclPrinter:: PrintDecl(Decl *D) {
53 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
54 PrintFunctionDeclStart(FD);
58 FD->getBody()->printPretty(Out);
61 } else if (isa<ObjCMethodDecl>(D)) {
62 // Do nothing, methods definitions are printed in
63 // PrintObjCImplementationDecl.
64 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
66 } else if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(D)) {
67 PrintObjCInterfaceDecl(OID);
68 } else if (ObjCProtocolDecl *PID = dyn_cast<ObjCProtocolDecl>(D)) {
69 PrintObjCProtocolDecl(PID);
70 } else if (ObjCForwardProtocolDecl *OFPD =
71 dyn_cast<ObjCForwardProtocolDecl>(D)) {
73 for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
74 const ObjCProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
79 } else if (ObjCImplementationDecl *OID =
80 dyn_cast<ObjCImplementationDecl>(D)) {
81 PrintObjCImplementationDecl(OID);
82 } else if (ObjCCategoryImplDecl *OID =
83 dyn_cast<ObjCCategoryImplDecl>(D)) {
84 PrintObjCCategoryImplDecl(OID);
85 } else if (ObjCCategoryDecl *OID =
86 dyn_cast<ObjCCategoryDecl>(D)) {
87 PrintObjCCategoryDecl(OID);
88 } else if (ObjCCompatibleAliasDecl *OID =
89 dyn_cast<ObjCCompatibleAliasDecl>(D)) {
90 PrintObjCCompatibleAliasDecl(OID);
91 } else if (isa<ObjCClassDecl>(D)) {
92 Out << "@class [printing todo]\n";
93 } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
94 Out << "Read top-level tag decl: '" << TD->getName() << "'\n";
95 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
96 Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
97 } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
98 PrintLinkageSpec(LSD);
100 assert(0 && "Unknown decl type!");
104 void DeclPrinter::PrintFunctionDeclStart(FunctionDecl *FD) {
105 bool HasBody = FD->getBody();
109 switch (FD->getStorageClass()) {
110 default: assert(0 && "Unknown storage class");
111 case FunctionDecl::None: break;
112 case FunctionDecl::Extern: Out << "extern "; break;
113 case FunctionDecl::Static: Out << "static "; break;
119 std::string Proto = FD->getName();
120 const FunctionType *AFT = FD->getType()->getAsFunctionType();
122 if (const FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
124 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
125 if (i) Proto += ", ";
126 std::string ParamStr;
127 if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
129 FT->getArgType(i).getAsStringInternal(ParamStr);
133 if (FT->isVariadic()) {
134 if (FD->getNumParams()) Proto += ", ";
139 assert(isa<FunctionTypeNoProto>(AFT));
143 AFT->getResultType().getAsStringInternal(Proto);
148 // Doesn't print the body.
151 void DeclPrinter::PrintTypeDefDecl(TypedefDecl *TD) {
152 std::string S = TD->getName();
153 TD->getUnderlyingType().getAsStringInternal(S);
154 Out << "typedef " << S << ";\n";
157 void DeclPrinter::PrintLinkageSpec(LinkageSpecDecl *LS) {
159 if (LS->getLanguage() == LinkageSpecDecl::lang_c)
161 else if (LS->getLanguage() == LinkageSpecDecl::lang_cxx)
163 else assert(0 && "unknown language in linkage specification");
164 Out << "extern \"" << l << "\" { ";
165 PrintDecl(LS->getDecl());
169 void DeclPrinter::PrintObjCMethodDecl(ObjCMethodDecl *OMD) {
170 if (OMD->isInstance())
174 if (!OMD->getResultType().isNull())
175 Out << '(' << OMD->getResultType().getAsString() << ") ";
176 // FIXME: just print original selector name!
177 Out << OMD->getSelector().getName();
179 for (int i = 0; i < OMD->getNumParams(); i++) {
180 ParmVarDecl *PDecl = OMD->getParamDecl(i);
181 // FIXME: selector is missing here!
182 Out << " :(" << PDecl->getType().getAsString() << ") " << PDecl->getName();
186 void DeclPrinter::PrintObjCImplementationDecl(ObjCImplementationDecl *OID) {
187 std::string I = OID->getName();
188 ObjCInterfaceDecl *SID = OID->getSuperClass();
191 Out << "@implementation " << I << " : " << SID->getName();
193 Out << "@implementation " << I;
195 for (ObjCImplementationDecl::instmeth_iterator I = OID->instmeth_begin(),
196 E = OID->instmeth_end(); I != E; ++I) {
197 ObjCMethodDecl *OMD = *I;
198 PrintObjCMethodDecl(OMD);
199 if (OMD->getBody()) {
201 OMD->getBody()->printPretty(Out);
206 for (ObjCImplementationDecl::classmeth_iterator I = OID->classmeth_begin(),
207 E = OID->classmeth_end(); I != E; ++I) {
208 ObjCMethodDecl *OMD = *I;
209 PrintObjCMethodDecl(OMD);
210 if (OMD->getBody()) {
212 OMD->getBody()->printPretty(Out);
221 void DeclPrinter::PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
222 std::string I = OID->getName();
223 ObjCInterfaceDecl *SID = OID->getSuperClass();
226 Out << "@interface " << I << " : " << SID->getName();
228 Out << "@interface " << I;
231 int count = OID->getNumIntfRefProtocols();
234 ObjCProtocolDecl **refProtocols = OID->getReferencedProtocols();
235 for (int i = 0; i < count; i++)
236 Out << (i == 0 ? '<' : ',') << refProtocols[i]->getName();
244 if (OID->getNumInstanceVariables() > 0) {
246 for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(),
247 E = OID->ivar_end(); I != E; ++I) {
248 Out << '\t' << (*I)->getType().getAsString()
249 << ' ' << (*I)->getName() << ";\n";
254 int NumProperties = OID->getNumPropertyDecl();
255 if (NumProperties > 0) {
256 for (int i = 0; i < NumProperties; i++) {
257 ObjCPropertyDecl *PDecl = OID->getPropertyDecl()[i];
259 if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
262 if (PDecl->getPropertyAttributes() &
263 ObjCPropertyDecl::OBJC_PR_readonly) {
264 Out << (first ? ' ' : ',') << "readonly";
268 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
269 Out << (first ? ' ' : ',') << "getter = "
270 << PDecl->getGetterName()->getName();
273 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
274 Out << (first ? ' ' : ',') << "setter = "
275 << PDecl->getSetterName()->getName();
279 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
280 Out << (first ? ' ' : ',') << "assign";
284 if (PDecl->getPropertyAttributes() &
285 ObjCPropertyDecl::OBJC_PR_readwrite) {
286 Out << (first ? ' ' : ',') << "readwrite";
290 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
291 Out << (first ? ' ' : ',') << "retain";
295 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
296 Out << (first ? ' ' : ',') << "copy";
300 if (PDecl->getPropertyAttributes() &
301 ObjCPropertyDecl::OBJC_PR_nonatomic) {
302 Out << (first ? ' ' : ',') << "nonatomic";
308 ObjCIvarDecl **IDecl = PDecl->getPropertyDecls();
310 Out << ' ' << IDecl[0]->getType().getAsString()
311 << ' ' << IDecl[0]->getName();
313 for (int j = 1; j < PDecl->getNumPropertyDecls(); j++)
314 Out << ", " << IDecl[j]->getName();
321 // FIXME: implement the rest...
324 void DeclPrinter::PrintObjCProtocolDecl(ObjCProtocolDecl *PID) {
325 Out << "@protocol " << PID->getName() << '\n';
326 // FIXME: implement the rest...
329 void DeclPrinter::PrintObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
330 Out << "@implementation "
331 << PID->getClassInterface()->getName()
332 << '(' << PID->getName() << ");\n";
334 // FIXME: implement the rest...
337 void DeclPrinter::PrintObjCCategoryDecl(ObjCCategoryDecl *PID) {
339 << PID->getClassInterface()->getName()
340 << '(' << PID->getName() << ");\n";
341 // FIXME: implement the rest...
344 void DeclPrinter::PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
345 Out << "@compatibility_alias " << AID->getName()
346 << ' ' << AID->getClassInterface()->getName() << ";\n";
349 //===----------------------------------------------------------------------===//
350 /// ASTPrinter - Pretty-printer of ASTs
353 class ASTPrinter : public ASTConsumer, public DeclPrinter {
355 ASTPrinter(std::ostream* o = NULL) : DeclPrinter(o) {}
357 virtual void HandleTopLevelDecl(Decl *D) {
363 ASTConsumer *clang::CreateASTPrinter(std::ostream* out) {
364 return new ASTPrinter(out);
367 //===----------------------------------------------------------------------===//
368 /// ASTDumper - Low-level dumper of ASTs
371 class ASTDumper : public ASTConsumer, public DeclPrinter {
374 ASTDumper() : DeclPrinter() {}
376 void Initialize(ASTContext &Context) {
377 SM = &Context.getSourceManager();
380 virtual void HandleTopLevelDecl(Decl *D) {
381 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
382 PrintFunctionDeclStart(FD);
386 // FIXME: convert dumper to use std::ostream?
387 FD->getBody()->dumpAll(*SM);
390 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
391 PrintTypeDefDecl(TD);
392 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
393 Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
394 } else if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(D)) {
395 Out << "Read objc interface '" << OID->getName() << "'\n";
396 } else if (ObjCProtocolDecl *OPD = dyn_cast<ObjCProtocolDecl>(D)) {
397 Out << "Read objc protocol '" << OPD->getName() << "'\n";
398 } else if (ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(D)) {
399 Out << "Read objc category '" << OCD->getName() << "'\n";
400 } else if (isa<ObjCForwardProtocolDecl>(D)) {
401 Out << "Read objc fwd protocol decl\n";
402 } else if (isa<ObjCClassDecl>(D)) {
403 Out << "Read objc fwd class decl\n";
405 assert(0 && "Unknown decl type!");
411 ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
413 //===----------------------------------------------------------------------===//
414 /// ASTViewer - AST Visualization
417 class ASTViewer : public ASTConsumer {
420 void Initialize(ASTContext &Context) {
421 SM = &Context.getSourceManager();
424 virtual void HandleTopLevelDecl(Decl *D) {
425 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
426 DeclPrinter().PrintFunctionDeclStart(FD);
430 FD->getBody()->viewAST();
438 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
441 //===----------------------------------------------------------------------===//
442 // CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
443 // the CFGs for all function definitions.
447 class CFGVisitor : public ASTConsumer {
449 // CFG Visitor interface to be implemented by subclass.
450 virtual void VisitCFG(CFG& C, FunctionDecl& FD) = 0;
451 virtual bool printFuncDeclStart() { return true; }
453 virtual void HandleTopLevelDecl(Decl *D);
456 } // end anonymous namespace
458 void CFGVisitor::HandleTopLevelDecl(Decl *D) {
459 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
460 if (!FD || !FD->getBody())
463 if (printFuncDeclStart()) {
464 DeclPrinter().PrintFunctionDeclStart(FD);
468 CFG *C = CFG::buildCFG(FD->getBody());
473 //===----------------------------------------------------------------------===//
474 // DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
477 class CFGDumper : public CFGVisitor {
478 const bool UseGraphviz;
480 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
482 virtual void VisitCFG(CFG& C, FunctionDecl&) {
489 } // end anonymous namespace
491 ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs) {
492 return new CFGDumper(ViewGraphs);
495 //===----------------------------------------------------------------------===//
496 // AnalyzeLiveVariables - perform live variable analysis and dump results
499 class LivenessVisitor : public CFGVisitor {
502 virtual void Initialize(ASTContext &Context) {
503 SM = &Context.getSourceManager();
506 virtual void VisitCFG(CFG& C, FunctionDecl& FD) {
507 LiveVariables L(C, FD);
509 L.dumpBlockLiveness(*SM);
512 } // end anonymous namespace
514 ASTConsumer *clang::CreateLiveVarAnalyzer() {
515 return new LivenessVisitor();
518 //===----------------------------------------------------------------------===//
519 // DeadStores - run checker to locate dead stores in a function
522 class DeadStoreVisitor : public CFGVisitor {
526 DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
527 virtual void Initialize(ASTContext &Context) {
531 virtual void VisitCFG(CFG& C, FunctionDecl& FD) {
532 CheckDeadStores(C, FD, *Ctx, Diags);
535 virtual bool printFuncDeclStart() { return false; }
537 } // end anonymous namespace
539 ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
540 return new DeadStoreVisitor(Diags);
543 //===----------------------------------------------------------------------===//
544 // Unitialized Values - run checker to flag potential uses of uninitalized
548 class UninitValsVisitor : public CFGVisitor {
552 UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
553 virtual void Initialize(ASTContext &Context) {
557 virtual void VisitCFG(CFG& C, FunctionDecl&) {
558 CheckUninitializedValues(C, *Ctx, Diags);
561 virtual bool printFuncDeclStart() { return false; }
563 } // end anonymous namespace
565 ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
566 return new UninitValsVisitor(Diags);
569 //===----------------------------------------------------------------------===//
570 // GRConstants - Perform intra-procedural, path-sensitive constant propagation.
573 class GRConstantsVisitor : public CFGVisitor {
577 virtual void Initialize(ASTContext &Context) { Ctx = &Context; }
578 virtual void VisitCFG(CFG& C, FunctionDecl&);
580 } // end anonymous namespace
582 ASTConsumer* clang::CreateGRConstants() {
583 return new GRConstantsVisitor();
586 void GRConstantsVisitor::VisitCFG(CFG& C, FunctionDecl& FD) {
587 RunGRConstants(C, FD, *Ctx);
590 //===----------------------------------------------------------------------===//
593 #include "clang/Basic/Diagnostic.h"
594 #include "clang/Basic/TargetInfo.h"
595 #include "clang/CodeGen/ModuleBuilder.h"
596 #include "llvm/Module.h"
597 #include "llvm/Target/TargetData.h"
598 #include "llvm/Target/TargetMachine.h"
599 #include "llvm/Bitcode/ReaderWriter.h"
602 class CodeGenerator : public ASTConsumer {
604 const llvm::TargetData *TD;
606 const LangOptions &Features;
609 CodeGen::CodeGenModule *Builder;
611 CodeGenerator(Diagnostic &diags, const LangOptions &LO,
612 llvm::Module *&DestModule)
613 : Diags(diags), Features(LO), M(DestModule) {}
616 CodeGen::Terminate(Builder);
619 virtual void Initialize(ASTContext &Context) {
622 M->setTargetTriple(Ctx->Target.getTargetTriple());
623 M->setDataLayout(Ctx->Target.getTargetDescription());
624 TD = new llvm::TargetData(Ctx->Target.getTargetDescription());
625 Builder = CodeGen::Init(Context, Features, *M, *TD, Diags);
628 virtual void HandleTopLevelDecl(Decl *D) {
629 // If an error occurred, stop code generation, but continue parsing and
630 // semantic analysis (to ensure all warnings and errors are emitted).
631 if (Diags.hasErrorOccurred())
634 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
635 CodeGen::CodeGenFunction(Builder, FD);
636 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
637 CodeGen::CodeGenGlobalVar(Builder, FVD);
638 } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
639 CodeGen::CodeGenLinkageSpec(Builder, LSD);
641 CodeGen::CodeGenTypeDecl(Builder, cast<TypeDecl>(D));
647 ASTConsumer *clang::CreateLLVMCodeGen(Diagnostic &Diags,
648 const LangOptions &Features,
649 llvm::Module *&DestModule) {
650 return new CodeGenerator(Diags, Features, DestModule);
653 //===----------------------------------------------------------------------===//
658 class ASTSerializer : public ASTConsumer {
663 ASTSerializer(Diagnostic& diags, const LangOptions& LO)
664 : Diags(diags), TU(LO) {}
666 virtual void Initialize(ASTContext &Context) {
667 TU.setContext(&Context);
670 virtual void HandleTopLevelDecl(Decl *D) {
671 if (Diags.hasErrorOccurred())
674 TU.AddTopLevelDecl(D);
678 class SingleFileSerializer : public ASTSerializer {
679 const llvm::sys::Path FName;
681 SingleFileSerializer(const llvm::sys::Path& F, Diagnostic &diags,
682 const LangOptions &LO)
683 : ASTSerializer(diags,LO), FName(F) {}
685 ~SingleFileSerializer() {
686 EmitASTBitcodeFile(TU,FName);
690 class BuildSerializer : public ASTSerializer {
691 llvm::sys::Path EmitDir;
693 BuildSerializer(const llvm::sys::Path& dir, Diagnostic &diags,
694 const LangOptions &LO)
695 : ASTSerializer(diags,LO), EmitDir(dir) {}
698 SourceManager& SourceMgr = TU.getASTContext()->getSourceManager();
699 unsigned ID = SourceMgr.getMainFileID();
700 assert (ID && "MainFileID not set!");
701 const FileEntry* FE = SourceMgr.getFileEntryForID(ID);
702 assert (FE && "No FileEntry for main file.");
704 // FIXME: This is not portable to Windows.
705 // FIXME: This logic should probably be moved elsewhere later.
707 llvm::sys::Path FName(EmitDir);
709 std::vector<char> buf;
710 buf.reserve(strlen(FE->getName())+100);
712 sprintf(&buf[0], "dev_%llx", (uint64_t) FE->getDevice());
713 FName.appendComponent(&buf[0]);
714 FName.createDirectoryOnDisk(true);
715 if (!FName.canWrite() || !FName.isDirectory()) {
716 assert (false && "Could not create 'device' serialization directory.");
720 sprintf(&buf[0], "%s-%llX.ast", FE->getName(), (uint64_t) FE->getInode());
721 FName.appendComponent(&buf[0]);
722 EmitASTBitcodeFile(TU,FName);
724 // Now emit the sources.
730 } // end anonymous namespace
733 ASTConsumer* clang::CreateASTSerializer(const std::string& InFile,
734 const std::string& OutputFile,
736 const LangOptions &Features) {
738 if (OutputFile.size()) {
741 "error: Cannot use --serialize with -o for source read from STDIN.\n";
745 // The user specified an AST-emission directory. Determine if the path
747 llvm::sys::Path EmitDir(OutputFile);
749 if (!EmitDir.isAbsolute()) {
751 "error: Output directory for --serialize must be an absolute path.\n";
756 // Create the directory if it does not exist.
757 EmitDir.createDirectoryOnDisk(true);
758 if (!EmitDir.canWrite() || !EmitDir.isDirectory()) {
760 "error: Could not create output directory for --serialize.\n";
765 // FIXME: We should probably only allow using BuildSerializer when
766 // the ASTs come from parsed source files, and not from .ast files.
767 return new BuildSerializer(EmitDir, Diags, Features);
770 // The user did not specify an output directory for serialized ASTs.
771 // Serialize the translation to a single file whose name is the same
772 // as the input file with the ".ast" extension appended.
774 llvm::sys::Path FName(InFile.c_str());
775 FName.appendSuffix("ast");
776 return new SingleFileSerializer(FName, Diags, Features);