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