Gabor Horvath e350b0a196 Add Cross Translation Unit support library
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
2017-09-22 11:11:01 +00:00

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;
}