diff --git a/clang/lib/Tooling/CMakeLists.txt b/clang/lib/Tooling/CMakeLists.txt --- a/clang/lib/Tooling/CMakeLists.txt +++ b/clang/lib/Tooling/CMakeLists.txt @@ -85,7 +85,7 @@ set(implicitDirs) foreach(implicitDir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) - list(APPEND implicitDirs -I ${implicitDir}) + list(APPEND implicitDirs -implicit-include ${implicitDir}) endforeach() add_custom_command( diff --git a/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp b/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp --- a/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp +++ b/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp @@ -31,6 +31,10 @@ "I", cl::desc("Include directories to use while compiling"), cl::value_desc("directory"), cl::Required, cl::OneOrMore, cl::Prefix); +static cl::list ImplicitIncludeDirectories( + "implicit-include", cl::desc("Include directories to use while compiling"), + cl::value_desc("directory"), cl::OneOrMore, cl::Prefix); + static cl::opt SkipProcessing("skip-processing", cl::desc("Avoid processing the AST header file"), @@ -47,10 +51,10 @@ void ExecuteAction() override { clang::ASTFrontendAction::ExecuteAction(); - if (getCompilerInstance().getDiagnostics().getNumErrors() > 0) - Processor.generateEmpty(); - else + if (getCompilerInstance().getDiagnostics().getNumErrors() == 0) { Processor.generate(); + HasWritten = true; + } } std::unique_ptr @@ -59,8 +63,11 @@ return Processor.createASTConsumer(Compiler, File); } + bool hasWritten() const { return HasWritten; } + private: ASTSrcLocProcessor Processor; + bool HasWritten = false; }; static const char Filename[] = "ASTTU.cpp"; @@ -78,24 +85,31 @@ return 0; } - std::vector Args; - Args.push_back("-cc1"); - - llvm::transform(IncludeDirectories, std::back_inserter(Args), - [](const std::string &IncDir) { return "-I" + IncDir; }); - - Args.push_back("-fsyntax-only"); - Args.push_back(Filename); - - std::vector Argv(Args.size(), nullptr); - llvm::transform(Args, Argv.begin(), - [](const std::string &Arg) { return Arg.c_str(); }); + llvm::BumpPtrAllocator Alloc; + unsigned long Argc = + IncludeDirectories.size() + ImplicitIncludeDirectories.size() + 3; + MutableArrayRef Argv(Alloc.Allocate(Argc), Argc); + Argv[0] = "-cc1"; + Argv[1] = "-fsyntax-only"; + Argv[2] = Filename; + const char **Iter = Argv.drop_front(3).begin(); + auto AddArg = [&Iter, &Alloc](StringRef Prefix, StringRef Item) { + char *Ptr = Alloc.Allocate(Prefix.size() + Item.size() + 1); + std::memcpy(Ptr, Prefix.data(), Prefix.size()); + std::memcpy(Ptr + Prefix.size(), Item.data(), Item.size()); + Ptr[Prefix.size() + Item.size()] = '\0'; + *Iter++ = Ptr; + }; + for (auto &IncludeDir : IncludeDirectories) + AddArg("-I", IncludeDir); + for (auto &IncludeDir : ImplicitIncludeDirectories) + AddArg("-isystem", IncludeDir); IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); unsigned MissingArgIndex, MissingArgCount; auto Opts = driver::getDriverOptTable(); - auto ParsedArgs = Opts.ParseArgs(llvm::makeArrayRef(Argv).slice(1), - MissingArgIndex, MissingArgCount); + auto ParsedArgs = + Opts.ParseArgs(Argv.drop_front(), MissingArgIndex, MissingArgCount); ParseDiagnosticArgs(*DiagOpts, ParsedArgs); // Don't output diagnostics, because common scenarios such as @@ -119,41 +133,48 @@ "clang", llvm::sys::getDefaultTargetTriple(), Diagnostics, "ast-api-dump-tool", OFS); - std::unique_ptr Comp( - Driver->BuildCompilation(llvm::makeArrayRef(Argv))); - if (!Comp) - return 1; - - const auto &Jobs = Comp->getJobs(); - if (Jobs.size() != 1 || !isa(*Jobs.begin())) { - SmallString<256> error_msg; - llvm::raw_svector_ostream error_stream(error_msg); - Jobs.Print(error_stream, "; ", true); - return 1; - } - - const auto &Cmd = cast(*Jobs.begin()); - const llvm::opt::ArgStringList &CC1Args = Cmd.getArguments(); - - auto Invocation = std::make_unique(); - CompilerInvocation::CreateFromArgs(*Invocation, CC1Args, Diagnostics); - - CompilerInstance Compiler(std::make_shared()); - Compiler.setInvocation(std::move(Invocation)); - - Compiler.createDiagnostics(&DiagnosticPrinter, false); - if (!Compiler.hasDiagnostics()) - return 1; + SmallVector, 2> Commands; + Commands.push_back(Argv); + if (!ImplicitIncludeDirectories.empty()) + Commands.push_back(Argv.drop_back(ImplicitIncludeDirectories.size())); + bool BadCommand = true; + + for (auto &Command : Commands) { + std::unique_ptr Comp( + Driver->BuildCompilation(Command)); + if (!Comp) + continue; + const auto &Jobs = Comp->getJobs(); + if (Jobs.size() != 1 || !isa(*Jobs.begin())) + continue; + + BadCommand = false; + const auto &Cmd = cast(*Jobs.begin()); + const llvm::opt::ArgStringList &CC1Args = Cmd.getArguments(); + CompilerInstance Compiler( + std::make_shared()); + + Compiler.createDiagnostics(&DiagnosticPrinter, false); + if (!Compiler.hasDiagnostics()) + return 1; - // Suppress "2 errors generated" or similar messages - Compiler.getDiagnosticOpts().ShowCarets = false; - Compiler.createSourceManager(*Files); - Compiler.setFileManager(Files.get()); + Compiler.setFileManager(Files.get()); + Compiler.createSourceManager(*Files); - ASTSrcLocGenerationAction ScopedToolAction; - Compiler.ExecuteAction(ScopedToolAction); + auto Invocation = std::make_unique(); + CompilerInvocation::CreateFromArgs(*Invocation, CC1Args, Diagnostics); + Compiler.setInvocation(std::move(Invocation)); + // Suppress "2 errors generated" or similar messages + Compiler.getDiagnosticOpts().ShowCarets = false; - Files->clearStatCache(); + ASTSrcLocGenerationAction ScopedToolAction; + Compiler.ExecuteAction(ScopedToolAction); - return 0; + if (ScopedToolAction.hasWritten()) + return 0; + Compiler.getDiagnostics().Reset(); + Compiler.getDiagnostics().getClient()->clear(); + } + ASTSrcLocProcessor(JsonOutputPath).generateEmpty(); + return BadCommand; }