blob: 4bf812fffe3419f11172eb3bb75fd68c5a1640d6 [file] [log] [blame]
Gabor Horvathe350b0a2017-09-22 11:11:01 +00001//===- ClangFnMapGen.cpp -----------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===--------------------------------------------------------------------===//
9//
10// Clang tool which creates a list of defined functions and the files in which
11// they are defined.
12//
13//===--------------------------------------------------------------------===//
14
15#include "clang/AST/ASTConsumer.h"
16#include "clang/AST/ASTContext.h"
17#include "clang/AST/GlobalDecl.h"
18#include "clang/AST/Mangle.h"
19#include "clang/AST/StmtVisitor.h"
20#include "clang/Basic/SourceManager.h"
21#include "clang/Basic/TargetInfo.h"
22#include "clang/CrossTU/CrossTranslationUnit.h"
23#include "clang/Frontend/CompilerInstance.h"
24#include "clang/Frontend/FrontendActions.h"
25#include "clang/Index/USRGeneration.h"
26#include "clang/Tooling/CommonOptionsParser.h"
27#include "clang/Tooling/Tooling.h"
28#include "llvm/Support/CommandLine.h"
29#include "llvm/Support/Path.h"
30#include "llvm/Support/Signals.h"
31#include <sstream>
32#include <string>
33#include <vector>
34
35using namespace llvm;
36using namespace clang;
37using namespace clang::cross_tu;
38using namespace clang::tooling;
39
40static cl::OptionCategory ClangFnMapGenCategory("clang-fnmapgen options");
41
42class MapFunctionNamesConsumer : public ASTConsumer {
43public:
44 MapFunctionNamesConsumer(ASTContext &Context) : Ctx(Context) {}
45
46 ~MapFunctionNamesConsumer() {
47 // Flush results to standard output.
48 llvm::outs() << createCrossTUIndexString(Index);
49 }
50
51 virtual void HandleTranslationUnit(ASTContext &Ctx) {
52 handleDecl(Ctx.getTranslationUnitDecl());
53 }
54
55private:
56 void handleDecl(const Decl *D);
57
58 ASTContext &Ctx;
59 llvm::StringMap<std::string> Index;
60 std::string CurrentFileName;
61};
62
63void MapFunctionNamesConsumer::handleDecl(const Decl *D) {
64 if (!D)
65 return;
66
67 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
68 if (FD->isThisDeclarationADefinition()) {
69 if (const Stmt *Body = FD->getBody()) {
70 std::string LookupName = CrossTranslationUnitContext::getLookupName(FD);
71 const SourceManager &SM = Ctx.getSourceManager();
72 if (CurrentFileName.empty()) {
73 CurrentFileName =
74 SM.getFileEntryForID(SM.getMainFileID())->tryGetRealPathName();
75 if (CurrentFileName.empty())
76 CurrentFileName = "invalid_file";
77 }
78
79 switch (FD->getLinkageInternal()) {
80 case ExternalLinkage:
81 case VisibleNoLinkage:
82 case UniqueExternalLinkage:
83 if (SM.isInMainFile(Body->getLocStart()))
84 Index[LookupName] = CurrentFileName;
85 default:
86 break;
87 }
88 }
89 }
90 }
91
92 if (const auto *DC = dyn_cast<DeclContext>(D))
93 for (const Decl *D : DC->decls())
94 handleDecl(D);
95}
96
97class MapFunctionNamesAction : public ASTFrontendAction {
98protected:
99 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
100 llvm::StringRef) {
101 std::unique_ptr<ASTConsumer> PFC(
102 new MapFunctionNamesConsumer(CI.getASTContext()));
103 return PFC;
104 }
105};
106
107static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
108
109int main(int argc, const char **argv) {
110 // Print a stack trace if we signal out.
111 sys::PrintStackTraceOnErrorSignal(argv[0], false);
112 PrettyStackTraceProgram X(argc, argv);
113
114 const char *Overview = "\nThis tool collects the USR name and location "
115 "of all functions definitions in the source files "
116 "(excluding headers).\n";
117 CommonOptionsParser OptionsParser(argc, argv, ClangFnMapGenCategory,
118 cl::ZeroOrMore, Overview);
119
120 ClangTool Tool(OptionsParser.getCompilations(),
121 OptionsParser.getSourcePathList());
122 Tool.run(newFrontendActionFactory<MapFunctionNamesAction>().get());
123 return 0;
124}