xref: /openbsd-src/gnu/llvm/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1a9ac8606Spatrick //===- ClangSrcLocDump.cpp ------------------------------------*- C++ -*---===//
2a9ac8606Spatrick //
3a9ac8606Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a9ac8606Spatrick // See https://llvm.org/LICENSE.txt for license information.
5a9ac8606Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a9ac8606Spatrick //
7a9ac8606Spatrick //===----------------------------------------------------------------------===//
8a9ac8606Spatrick 
9a9ac8606Spatrick #include "clang/Basic/Diagnostic.h"
10a9ac8606Spatrick #include "clang/Driver/Compilation.h"
11a9ac8606Spatrick #include "clang/Driver/Driver.h"
12a9ac8606Spatrick #include "clang/Driver/Job.h"
13a9ac8606Spatrick #include "clang/Driver/Options.h"
14a9ac8606Spatrick #include "clang/Driver/Tool.h"
15a9ac8606Spatrick #include "clang/Frontend/CompilerInstance.h"
16a9ac8606Spatrick #include "clang/Frontend/TextDiagnosticPrinter.h"
17a9ac8606Spatrick #include "clang/Lex/PreprocessorOptions.h"
18a9ac8606Spatrick #include "clang/Tooling/Tooling.h"
19a9ac8606Spatrick #include "llvm/Option/ArgList.h"
20a9ac8606Spatrick #include "llvm/Support/CommandLine.h"
21a9ac8606Spatrick #include "llvm/Support/Host.h"
22a9ac8606Spatrick #include "llvm/Support/JSON.h"
23a9ac8606Spatrick 
24a9ac8606Spatrick #include "ASTSrcLocProcessor.h"
25a9ac8606Spatrick 
26a9ac8606Spatrick using namespace clang::tooling;
27a9ac8606Spatrick using namespace clang;
28a9ac8606Spatrick using namespace llvm;
29a9ac8606Spatrick 
30a9ac8606Spatrick static cl::list<std::string> IncludeDirectories(
31a9ac8606Spatrick     "I", cl::desc("Include directories to use while compiling"),
32a9ac8606Spatrick     cl::value_desc("directory"), cl::Required, cl::OneOrMore, cl::Prefix);
33a9ac8606Spatrick 
34a9ac8606Spatrick static cl::opt<bool>
35a9ac8606Spatrick     SkipProcessing("skip-processing",
36a9ac8606Spatrick                    cl::desc("Avoid processing the AST header file"),
37a9ac8606Spatrick                    cl::Required, cl::value_desc("bool"));
38a9ac8606Spatrick 
39a9ac8606Spatrick static cl::opt<std::string> JsonOutputPath("json-output-path",
40a9ac8606Spatrick                                            cl::desc("json output path"),
41a9ac8606Spatrick                                            cl::Required,
42a9ac8606Spatrick                                            cl::value_desc("path"));
43a9ac8606Spatrick 
44a9ac8606Spatrick class ASTSrcLocGenerationAction : public clang::ASTFrontendAction {
45a9ac8606Spatrick public:
ASTSrcLocGenerationAction()46a9ac8606Spatrick   ASTSrcLocGenerationAction() : Processor(JsonOutputPath) {}
47a9ac8606Spatrick 
ExecuteAction()48a9ac8606Spatrick   void ExecuteAction() override {
49a9ac8606Spatrick     clang::ASTFrontendAction::ExecuteAction();
50a9ac8606Spatrick     if (getCompilerInstance().getDiagnostics().getNumErrors() > 0)
51a9ac8606Spatrick       Processor.generateEmpty();
52a9ac8606Spatrick     else
53a9ac8606Spatrick       Processor.generate();
54a9ac8606Spatrick   }
55a9ac8606Spatrick 
56a9ac8606Spatrick   std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance & Compiler,llvm::StringRef File)57a9ac8606Spatrick   CreateASTConsumer(clang::CompilerInstance &Compiler,
58a9ac8606Spatrick                     llvm::StringRef File) override {
59a9ac8606Spatrick     return Processor.createASTConsumer(Compiler, File);
60a9ac8606Spatrick   }
61a9ac8606Spatrick 
62a9ac8606Spatrick private:
63a9ac8606Spatrick   ASTSrcLocProcessor Processor;
64a9ac8606Spatrick };
65a9ac8606Spatrick 
66a9ac8606Spatrick static const char Filename[] = "ASTTU.cpp";
67a9ac8606Spatrick 
main(int argc,const char ** argv)68a9ac8606Spatrick int main(int argc, const char **argv) {
69a9ac8606Spatrick 
70a9ac8606Spatrick   cl::ParseCommandLineOptions(argc, argv);
71a9ac8606Spatrick 
72a9ac8606Spatrick   if (SkipProcessing) {
73a9ac8606Spatrick     std::error_code EC;
74a9ac8606Spatrick     llvm::raw_fd_ostream JsonOut(JsonOutputPath, EC, llvm::sys::fs::OF_Text);
75a9ac8606Spatrick     if (EC)
76a9ac8606Spatrick       return 1;
77a9ac8606Spatrick     JsonOut << formatv("{0:2}", llvm::json::Value(llvm::json::Object()));
78a9ac8606Spatrick     return 0;
79a9ac8606Spatrick   }
80a9ac8606Spatrick 
81a9ac8606Spatrick   std::vector<std::string> Args;
82a9ac8606Spatrick   Args.push_back("-cc1");
83a9ac8606Spatrick 
84a9ac8606Spatrick   llvm::transform(IncludeDirectories, std::back_inserter(Args),
85a9ac8606Spatrick                   [](const std::string &IncDir) { return "-I" + IncDir; });
86a9ac8606Spatrick 
87a9ac8606Spatrick   Args.push_back("-fsyntax-only");
88a9ac8606Spatrick   Args.push_back(Filename);
89a9ac8606Spatrick 
90a9ac8606Spatrick   std::vector<const char *> Argv(Args.size(), nullptr);
91a9ac8606Spatrick   llvm::transform(Args, Argv.begin(),
92a9ac8606Spatrick                   [](const std::string &Arg) { return Arg.c_str(); });
93a9ac8606Spatrick 
94*12c85518Srobert   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts =
95*12c85518Srobert       CreateAndPopulateDiagOpts(Argv);
96a9ac8606Spatrick 
97a9ac8606Spatrick   // Don't output diagnostics, because common scenarios such as
98a9ac8606Spatrick   // cross-compiling fail with diagnostics.  This is not fatal, but
99a9ac8606Spatrick   // just causes attempts to use the introspection API to return no data.
100a9ac8606Spatrick   TextDiagnosticPrinter DiagnosticPrinter(llvm::nulls(), &*DiagOpts);
101a9ac8606Spatrick   DiagnosticsEngine Diagnostics(
102a9ac8606Spatrick       IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
103a9ac8606Spatrick       &DiagnosticPrinter, false);
104a9ac8606Spatrick 
105a9ac8606Spatrick   auto *OFS = new llvm::vfs::OverlayFileSystem(vfs::getRealFileSystem());
106a9ac8606Spatrick 
107a9ac8606Spatrick   auto *MemFS = new llvm::vfs::InMemoryFileSystem();
108a9ac8606Spatrick   OFS->pushOverlay(MemFS);
109a9ac8606Spatrick   MemFS->addFile(Filename, 0,
110a9ac8606Spatrick                  MemoryBuffer::getMemBuffer("#include \"clang/AST/AST.h\"\n"));
111a9ac8606Spatrick 
112a9ac8606Spatrick   auto Files = llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions(), OFS);
113a9ac8606Spatrick 
114a9ac8606Spatrick   auto Driver = std::make_unique<driver::Driver>(
115a9ac8606Spatrick       "clang", llvm::sys::getDefaultTargetTriple(), Diagnostics,
116a9ac8606Spatrick       "ast-api-dump-tool", OFS);
117a9ac8606Spatrick 
118a9ac8606Spatrick   std::unique_ptr<clang::driver::Compilation> Comp(
119*12c85518Srobert       Driver->BuildCompilation(llvm::ArrayRef(Argv)));
120a9ac8606Spatrick   if (!Comp)
121a9ac8606Spatrick     return 1;
122a9ac8606Spatrick 
123a9ac8606Spatrick   const auto &Jobs = Comp->getJobs();
124a9ac8606Spatrick   if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
125a9ac8606Spatrick     SmallString<256> error_msg;
126a9ac8606Spatrick     llvm::raw_svector_ostream error_stream(error_msg);
127a9ac8606Spatrick     Jobs.Print(error_stream, "; ", true);
128a9ac8606Spatrick     return 1;
129a9ac8606Spatrick   }
130a9ac8606Spatrick 
131a9ac8606Spatrick   const auto &Cmd = cast<driver::Command>(*Jobs.begin());
132a9ac8606Spatrick   const llvm::opt::ArgStringList &CC1Args = Cmd.getArguments();
133a9ac8606Spatrick 
134a9ac8606Spatrick   auto Invocation = std::make_unique<CompilerInvocation>();
135a9ac8606Spatrick   CompilerInvocation::CreateFromArgs(*Invocation, CC1Args, Diagnostics);
136a9ac8606Spatrick 
137a9ac8606Spatrick   CompilerInstance Compiler(std::make_shared<clang::PCHContainerOperations>());
138a9ac8606Spatrick   Compiler.setInvocation(std::move(Invocation));
139a9ac8606Spatrick 
140a9ac8606Spatrick   Compiler.createDiagnostics(&DiagnosticPrinter, false);
141a9ac8606Spatrick   if (!Compiler.hasDiagnostics())
142a9ac8606Spatrick     return 1;
143a9ac8606Spatrick 
144a9ac8606Spatrick   // Suppress "2 errors generated" or similar messages
145a9ac8606Spatrick   Compiler.getDiagnosticOpts().ShowCarets = false;
146a9ac8606Spatrick   Compiler.createSourceManager(*Files);
147a9ac8606Spatrick   Compiler.setFileManager(Files.get());
148a9ac8606Spatrick 
149a9ac8606Spatrick   ASTSrcLocGenerationAction ScopedToolAction;
150a9ac8606Spatrick   Compiler.ExecuteAction(ScopedToolAction);
151a9ac8606Spatrick 
152a9ac8606Spatrick   Files->clearStatCache();
153a9ac8606Spatrick 
154a9ac8606Spatrick   return 0;
155a9ac8606Spatrick }
156