
This patch introduces a class that can help to build tools that require cross translation unit facilities. This class allows function definitions to be loaded from external AST files based on an index. In order to use this functionality an index is required. The index format is a flat text file but it might be replaced with a different solution in the near future. USRs are used as names to look up the functions definitions. This class also does caching to avoid redundant loading of AST files. Right now only function defnitions can be loaded using this API because this is what the in progress cross translation unit feature of the Static Analyzer requires. In to future this might be extended to classes, types etc. Differential Revision: https://reviews.llvm.org/D34512 llvm-svn: 313975
125 lines
3.9 KiB
C++
125 lines
3.9 KiB
C++
//===- ClangFnMapGen.cpp -----------------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===--------------------------------------------------------------------===//
|
|
//
|
|
// Clang tool which creates a list of defined functions and the files in which
|
|
// they are defined.
|
|
//
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
#include "clang/AST/ASTConsumer.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/GlobalDecl.h"
|
|
#include "clang/AST/Mangle.h"
|
|
#include "clang/AST/StmtVisitor.h"
|
|
#include "clang/Basic/SourceManager.h"
|
|
#include "clang/Basic/TargetInfo.h"
|
|
#include "clang/CrossTU/CrossTranslationUnit.h"
|
|
#include "clang/Frontend/CompilerInstance.h"
|
|
#include "clang/Frontend/FrontendActions.h"
|
|
#include "clang/Index/USRGeneration.h"
|
|
#include "clang/Tooling/CommonOptionsParser.h"
|
|
#include "clang/Tooling/Tooling.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "llvm/Support/Signals.h"
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
using namespace llvm;
|
|
using namespace clang;
|
|
using namespace clang::cross_tu;
|
|
using namespace clang::tooling;
|
|
|
|
static cl::OptionCategory ClangFnMapGenCategory("clang-fnmapgen options");
|
|
|
|
class MapFunctionNamesConsumer : public ASTConsumer {
|
|
public:
|
|
MapFunctionNamesConsumer(ASTContext &Context) : Ctx(Context) {}
|
|
|
|
~MapFunctionNamesConsumer() {
|
|
// Flush results to standard output.
|
|
llvm::outs() << createCrossTUIndexString(Index);
|
|
}
|
|
|
|
virtual void HandleTranslationUnit(ASTContext &Ctx) {
|
|
handleDecl(Ctx.getTranslationUnitDecl());
|
|
}
|
|
|
|
private:
|
|
void handleDecl(const Decl *D);
|
|
|
|
ASTContext &Ctx;
|
|
llvm::StringMap<std::string> Index;
|
|
std::string CurrentFileName;
|
|
};
|
|
|
|
void MapFunctionNamesConsumer::handleDecl(const Decl *D) {
|
|
if (!D)
|
|
return;
|
|
|
|
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
|
|
if (FD->isThisDeclarationADefinition()) {
|
|
if (const Stmt *Body = FD->getBody()) {
|
|
std::string LookupName = CrossTranslationUnitContext::getLookupName(FD);
|
|
const SourceManager &SM = Ctx.getSourceManager();
|
|
if (CurrentFileName.empty()) {
|
|
CurrentFileName =
|
|
SM.getFileEntryForID(SM.getMainFileID())->tryGetRealPathName();
|
|
if (CurrentFileName.empty())
|
|
CurrentFileName = "invalid_file";
|
|
}
|
|
|
|
switch (FD->getLinkageInternal()) {
|
|
case ExternalLinkage:
|
|
case VisibleNoLinkage:
|
|
case UniqueExternalLinkage:
|
|
if (SM.isInMainFile(Body->getLocStart()))
|
|
Index[LookupName] = CurrentFileName;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (const auto *DC = dyn_cast<DeclContext>(D))
|
|
for (const Decl *D : DC->decls())
|
|
handleDecl(D);
|
|
}
|
|
|
|
class MapFunctionNamesAction : public ASTFrontendAction {
|
|
protected:
|
|
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
|
llvm::StringRef) {
|
|
std::unique_ptr<ASTConsumer> PFC(
|
|
new MapFunctionNamesConsumer(CI.getASTContext()));
|
|
return PFC;
|
|
}
|
|
};
|
|
|
|
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
|
|
|
|
int main(int argc, const char **argv) {
|
|
// Print a stack trace if we signal out.
|
|
sys::PrintStackTraceOnErrorSignal(argv[0], false);
|
|
PrettyStackTraceProgram X(argc, argv);
|
|
|
|
const char *Overview = "\nThis tool collects the USR name and location "
|
|
"of all functions definitions in the source files "
|
|
"(excluding headers).\n";
|
|
CommonOptionsParser OptionsParser(argc, argv, ClangFnMapGenCategory,
|
|
cl::ZeroOrMore, Overview);
|
|
|
|
ClangTool Tool(OptionsParser.getCompilations(),
|
|
OptionsParser.getSourcePathList());
|
|
Tool.run(newFrontendActionFactory<MapFunctionNamesAction>().get());
|
|
return 0;
|
|
}
|