https://github.com/Decodetalkers updated https://github.com/llvm/llvm-project/pull/200001
>From 2e37c3823a082be2822ae1130136836b36ae2357 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons <[email protected]> Date: Sun, 24 May 2026 22:43:33 +0900 Subject: [PATCH] feat: add gcc scan rules But it still does not work, I need some help --- clang-tools-extra/clangd/ClangdLSPServer.cpp | 1 + clang-tools-extra/clangd/ClangdServer.cpp | 1 + .../clangd/GlobalCompilationDatabase.cpp | 15 +- .../clangd/GlobalCompilationDatabase.h | 2 +- clang-tools-extra/clangd/ModulesBuilder.cpp | 24 ++ clang-tools-extra/clangd/Preamble.cpp | 4 + clang-tools-extra/clangd/ProjectModules.cpp | 210 +++++++++++++++++- clang-tools-extra/clangd/TUScheduler.cpp | 8 + clang/lib/Tooling/JSONCompilationDatabase.cpp | 57 +++-- 9 files changed, 294 insertions(+), 28 deletions(-) diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index 04f58ab6446d1..f52d46248c4cf 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -567,6 +567,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, std::move(Mangler)); if (Opts.EnableExperimentalModulesSupport) { + // Here build a ModulesManager ModulesManager.emplace(*CDB); Opts.ModulesManager = &*ModulesManager; } diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index 9c9290b8b6b1b..e01e8f5752f8a 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -230,6 +230,7 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB, Transient(Opts.ImplicitCancellation ? TUScheduler::InvalidateOnUpdate : TUScheduler::NoInvalidation), DirtyFS(std::make_unique<DraftStoreFS>(TFS, DraftMgr)) { + // NOTE: main logic here if (Opts.AsyncThreadsCount != 0) IndexTasks.emplace(); // Pass a callback into `WorkScheduler` to extract symbols from a newly diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index adb771ecbbaad..92564f0816919 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -269,6 +269,7 @@ parseFixed(PathRef Path, llvm::StringRef Data, std::string &Error) { llvm::sys::path::parent_path(Path), Data, Error); } +// NOTE: Core bool DirectoryBasedGlobalCompilationDatabase::DirectoryCache::load( llvm::vfs::FileSystem &FS) { dlog("Probing directory {0}", Path); @@ -309,11 +310,19 @@ bool DirectoryBasedGlobalCompilationDatabase::DirectoryCache::load( return true; case CachedFile::LoadResult::FoundNewData: // We have a new CDB! + // NOTE: this time the --driver is still not be added CDB = Entry.Parser(Entry.File->Path, Loaded.Buffer->getBuffer(), Error); - if (CDB) + if (CDB) { log("{0} compilation database from {1}", Active ? "Reloaded" : "Loaded", Entry.File->Path); - else + elog(" =========== the command len ==============, {0}", CDB->getAllCompileCommands().size()); + auto commmand_0 = CDB->getAllCompileCommands()[0]; + std::string a_command; + for(auto &command : commmand_0.CommandLine) { + a_command += " " + command; + } + elog(" =========== the command {0} ==============", a_command); + } else elog("Failed to load compilation database from {0}: {1}", Entry.File->Path, Error); ActiveCachedFile = Entry.File; @@ -771,6 +780,7 @@ DirectoryBasedGlobalCompilationDatabase::getProjectModules(PathRef File) const { if (!Res) return {}; + // NOTE: 3 return clang::clangd::getProjectModules(Res->CDB, Opts.TFS); } @@ -811,6 +821,7 @@ OverlayCDB::getCompileCommand(PathRef File) const { if (!Cmd) return std::nullopt; if (Mangler) + // NOTE: from here, the command line changed forever Mangler(*Cmd, File); return Cmd; } diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h b/clang-tools-extra/clangd/GlobalCompilationDatabase.h index 415c7f50f8606..9cff6a310d4ff 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h @@ -201,7 +201,7 @@ getSystemIncludeExtractor(llvm::ArrayRef<std::string> QueryDriverGlobs); class OverlayCDB : public DelegatingCDB { public: // Makes adjustments to a tooling::CompileCommand which will be used to - // process a file (possibly different from the one in the command). + // ---driver-mode-driver-modeprocess a file (possibly different from the one in the command). using CommandMangler = llvm::unique_function<void(tooling::CompileCommand &, StringRef File) const>; diff --git a/clang-tools-extra/clangd/ModulesBuilder.cpp b/clang-tools-extra/clangd/ModulesBuilder.cpp index 706fd459e15ec..14fc987296e6a 100644 --- a/clang-tools-extra/clangd/ModulesBuilder.cpp +++ b/clang-tools-extra/clangd/ModulesBuilder.cpp @@ -862,6 +862,7 @@ class CachingProjectModules : public ProjectModules { } std::vector<std::string> getRequiredModules(PathRef File) override { + elog("========= get module here ======"); return MDB->getRequiredModules(File); } @@ -873,10 +874,12 @@ class CachingProjectModules : public ProjectModules { return MDB->getModuleNameState(ModuleName); } + // NOTE: then it enter here std::string getSourceForModuleName(llvm::StringRef ModuleName, PathRef RequiredSrcFile) override { auto ModuleState = MDB->getModuleNameState(ModuleName); + elog("Scan start"); if (ModuleState == ModuleNameState::Multiple) { std::string CachedResult = Cache.getMultipleSourceForModuleName(ModuleName, RequiredSrcFile); @@ -884,6 +887,8 @@ class CachingProjectModules : public ProjectModules { // Verify Cached Result by seeing if the source declaring the same module // as we query. if (!CachedResult.empty()) { + // NOTE: MDB is ScanningAllProjectModules + std::string ModuleNameOfCachedSource = MDB->getModuleNameForSource(CachedResult); if (ModuleNameOfCachedSource == ModuleName) @@ -1059,6 +1064,7 @@ void ModulesBuilder::ModulesBuilderImpl:: CacheRoot); } +// I need to add the data here instead go to the next logic void ModulesBuilder::ModulesBuilderImpl::getPrebuiltModuleFile( StringRef ModuleName, PathRef ModuleUnitFileName, const ThreadsafeFS &TFS, ReusablePrerequisiteModules &BuiltModuleFiles) { @@ -1103,14 +1109,20 @@ void ModulesBuilder::ModulesBuilderImpl::getPrebuiltModuleFile( } } +// NOTE Problem is the BuiltModuleFiles +// NOTE: so it is the first place it start scanning +// FIXME: cannot use gcc.gcm llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile( PathRef RequiredSource, StringRef ModuleName, const ThreadsafeFS &TFS, CachingProjectModules &MDB, ReusablePrerequisiteModules &BuiltModuleFiles) { if (BuiltModuleFiles.isModuleUnitBuilt(ModuleName)) return llvm::Error::success(); + elog("============== scanning starts from here? ============="); std::string ModuleUnitFileName = MDB.getSourceForModuleName(ModuleName, RequiredSource); + + elog("====== so we got gcc module source {0}, file is : {1}", ModuleName, ModuleUnitFileName); /// It is possible that we're meeting third party modules (modules whose /// source are not in the project. e.g, the std module may be a third-party /// module for most project) or something wrong with the implementation of @@ -1129,7 +1141,11 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile( // Get Required modules in topological order. auto ReqModuleNames = getAllRequiredModules(RequiredSource, MDB, ModuleName); + // NOTE: Ok, seems we can get the right module name, also , we can get its source. + // Then let's do it + // We should not reuse the logic of clangd, This time we can get the Cmd, so we can also know if it is gcc for (llvm::StringRef ReqModuleName : ReqModuleNames) { + elog("ReqModuleName: {0}", ReqModuleName.str()); if (BuiltModuleFiles.isModuleUnitBuilt(ReqModuleName)) continue; @@ -1144,6 +1160,7 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile( garbageCollectModuleCacheForProjectRoot(PI->SourceRoot); const std::string CommandHash = getCompileCommandStringHash(*Cmd); + // NOTE: this logic is for clang++, so We should never use it const std::string PublishedModuleFilePath = getPublishedModuleFilePath( ReqModuleName, getModuleFilesDirectory(ReqFileName, *Cmd, getCDB())); @@ -1219,6 +1236,8 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile( } bool ModulesBuilder::hasRequiredModules(PathRef File) { + // NOTE: the right logic is in DirectoryBasedGlobalCompilationDatabase + // Now it is CompoundProjectModules std::unique_ptr<ProjectModules> MDB = Impl->getCDB().getProjectModules(File); if (!MDB) return false; @@ -1228,10 +1247,14 @@ bool ModulesBuilder::hasRequiredModules(PathRef File) { return !CachedMDB.getRequiredModules(File).empty(); } +// NOTE: so we finally got to the position +// Maybe we can just create a gcc version std::unique_ptr<PrerequisiteModules> ModulesBuilder::buildPrerequisiteModulesFor(PathRef File, const ThreadsafeFS &TFS) { + // NOTE: them MDB always is the DirectoryBasedGlobalCompilationDatabase std::unique_ptr<ProjectModules> MDB = Impl->getCDB().getProjectModules(File); + elog("Enter here? ====================="); if (!MDB) { elog("Failed to get Project Modules information for {0}", File); return std::make_unique<FailedPrerequisiteModules>(); @@ -1244,6 +1267,7 @@ ModulesBuilder::buildPrerequisiteModulesFor(PathRef File, if (RequiredModuleNames.empty()) return std::make_unique<ReusablePrerequisiteModules>(); + // NOTE: Seems we need to change here auto RequiredModules = std::make_unique<ReusablePrerequisiteModules>(); for (llvm::StringRef RequiredModuleName : RequiredModuleNames) { // Return early if there is any error. diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp index 58da7edcf3b93..aa555938ffb9a 100644 --- a/clang-tools-extra/clangd/Preamble.cpp +++ b/clang-tools-extra/clangd/Preamble.cpp @@ -569,6 +569,7 @@ class DiagPatcher { }; } // namespace +// NOTE: here did we enter here? std::shared_ptr<const PreambleData> buildPreamble(PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs, bool StoreInMemory, @@ -584,6 +585,7 @@ buildPreamble(PathRef FileName, CompilerInvocation CI, trace::Span Tracer("BuildPreamble"); SPAN_ATTACH(Tracer, "File", FileName); std::vector<std::unique_ptr<FeatureModule::ASTListener>> ASTListeners; + // NOTE: ok seems we got it? if (Inputs.FeatureModules) { for (auto &M : *Inputs.FeatureModules) { if (auto Listener = M.astListeners()) @@ -676,6 +678,8 @@ buildPreamble(PathRef FileName, CompilerInvocation CI, if (Inputs.ModulesManager) { WallTimer PrerequisiteModuleTimer; PrerequisiteModuleTimer.startTimer(); + // NOTE: It is the real enter point 2 =========== + // NOTE: it failed to get the RequiredModules Result->RequiredModules = Inputs.ModulesManager->buildPrerequisiteModulesFor(FileName, *Inputs.TFS); diff --git a/clang-tools-extra/clangd/ProjectModules.cpp b/clang-tools-extra/clangd/ProjectModules.cpp index d3727171bff12..4e856999a982a 100644 --- a/clang-tools-extra/clangd/ProjectModules.cpp +++ b/clang-tools-extra/clangd/ProjectModules.cpp @@ -12,11 +12,16 @@ #include "clang/DependencyScanning/DependencyScanningService.h" #include "clang/Tooling/DependencyScanningTool.h" #include "clang/Tooling/Tooling.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Regex.h" #include "llvm/TargetParser/Host.h" namespace clang::clangd { @@ -171,6 +176,8 @@ class ModuleDependencyScanner { /// Scanning the single file specified by \param FilePath. std::optional<ModuleDependencyInfo> scan(PathRef FilePath, const ProjectModules::CommandMangler &Mangler); + std::optional<ModuleDependencyInfo> scanGcc(tooling::CompileCommand Cmd, + PathRef MapFile); /// Scanning every source file in the current project to get the /// <module-name> to <module-unit-source> map. @@ -209,15 +216,214 @@ class ModuleDependencyScanner { llvm::StringMap<std::string> ModuleNameToSource; }; +namespace gcc { +static const llvm::Regex ImportRegex = + llvm::Regex("import: ([^ ]*) ([^ ]*.gcm)"); +static const llvm::Regex ModuleRegex = llvm::Regex("module: ([^ ]*)"); +static const llvm::Regex SourceRegex = llvm::Regex("source: ([^ ]*)"); +static const llvm::Regex CwdRegex = llvm::Regex("cwd: ([^ ]*)"); + +static const llvm::Regex ModmapRegex = llvm::Regex("([^ ^$^\n]*) ([^ ]*.gcm)"); + +struct RoadMapInfo { + std::string Name; + std::string Path; +}; + +struct ReadElfInfo { + std::string Source; + std::string ModuleName; + std::vector<std::string> Imports; + + static std::optional<ReadElfInfo> get(llvm::StringRef Source); +}; + +std::optional<ReadElfInfo> ReadElfInfo::get(llvm::StringRef Content) { + std::vector<std::string> Imports = {}; + std::string Source; + std::string ModuleName; + std::string Cwd; + { + llvm::StringRef CwdText = Content; + llvm::SmallVector<llvm::StringRef, 1> Matches; + std::string Error; + if (!CwdRegex.match(CwdText, &Matches, &Error)) { + return std::nullopt; + } + Cwd = Matches[1].trim().str(); + } + { + llvm::StringRef ImportText = Content; + while (!ImportText.empty()) { + llvm::SmallVector<llvm::StringRef, 2> Matches; + std::string Error; + if (!ImportRegex.match(ImportText, &Matches, &Error)) { + break; + } + + auto ImportModule = Matches[1].trim().str(); + Imports.push_back(ImportModule); + size_t Pos = ImportText.find(Matches[0]); + ImportText = ImportText.drop_front(Pos + Matches[0].size()); + } + } + + { + llvm::StringRef SourceText = Content; + llvm::SmallVector<llvm::StringRef, 1> Matches; + std::string Error; + if (!SourceRegex.match(SourceText, &Matches, &Error)) { + return std::nullopt; + } + + llvm::StringRef SourcePa = Matches[1].trim(); + if (llvm::sys::path::is_absolute(SourcePa)) { + Source = SourcePa.str(); + + } else { + llvm::StringRef PathRef = Cwd; + llvm::SmallString<128> CurrentPath = PathRef; + llvm::sys::path::append(CurrentPath, SourcePa); + Source = CurrentPath.str(); + } + } + { + llvm::StringRef ModuleText = Content; + llvm::SmallVector<llvm::StringRef, 1> Matches; + std::string Error; + if (!ModuleRegex.match(ModuleText, &Matches, &Error)) { + return std::nullopt; + } + ModuleName = Matches[1].trim().str(); + } + return ReadElfInfo{Source, ModuleName, Imports}; +} + +static bool fitGccModulePath(std::string Cmd) { + llvm::StringRef Arg = Cmd; + return Arg.starts_with("-fmodule-mapper=") && Arg.ends_with("modmap"); +} + +std::optional<ReadElfInfo> scanGcm(llvm::StringRef GCMPath) { + llvm::SmallString<64> OutputFile; + llvm::sys::fs::createTemporaryFile("readref", "", OutputFile); + llvm::FileRemover OutRemover(OutputFile); + std::optional<llvm::StringRef> Redirects[3] = { + /*Stdin*/ {""}, {OutputFile.str()}, {}}; + std::string ErrorMessage; + auto Readelf = llvm::sys::findProgramByName("readelf"); + if (!Readelf) { + return std::nullopt; + } + int Ret = llvm::sys::ExecuteAndWait( + *Readelf, {"readelf", "-p.gnu.c++.README", GCMPath}, std::nullopt, + Redirects, 10, 0, &ErrorMessage); + if (Ret != 0) { + return std::nullopt; + } + auto Buf = llvm::MemoryBuffer::getFile(OutputFile); + + if (!Buf) { + return std::nullopt; + } + llvm::StringRef Path = Buf->get()->getBuffer().trim(); + if (Path.empty()) { + return std::nullopt; + } + llvm::StringRef Text = Path; + return ReadElfInfo::get(Text); +} + +struct ModuleResult { + std::optional<std::string> ModuleName; + std::vector<std::string> RequiredModules; +}; + +} // namespace gcc +std::optional<ModuleDependencyScanner::ModuleDependencyInfo> +ModuleDependencyScanner::scanGcc(tooling::CompileCommand Cmd, PathRef MapFile) { + using namespace gcc; + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File = + llvm::MemoryBuffer::getFile(MapFile); + if (std::error_code Result = File.getError()) { + elog("File Not Found, {0}", MapFile); + return std::nullopt; + } + auto Content = (*File)->getBuffer(); + llvm::StringRef CurrentDir = Cmd.Directory; + std::vector<gcc::RoadMapInfo> RoadMapInfos = {}; + llvm::StringRef Text = Content; + while (!Text.empty()) { + llvm::SmallVector<llvm::StringRef, 2> Matches; + std::string Error; + if (!gcc::ModmapRegex.match(Text, &Matches, &Error)) { + break; + } + + auto Name = Matches[1].trim().str(); + + auto ReadPath = Matches[2].trim(); + std::string Path; + if (llvm::sys::path::is_absolute(ReadPath)) { + Path = ReadPath.str(); + } else { + llvm::SmallString<128> CurrentPath = CurrentDir; + llvm::sys::path::append(CurrentPath, ReadPath); + Path = CurrentPath.str(); + } + RoadMapInfos.push_back(RoadMapInfo{Name, Path}); + + size_t Pos = Text.find(Matches[0]); + Text = Text.drop_front(Pos + Matches[0].size()); + } + elog("fileName: {0} ", Cmd.Filename); + ModuleDependencyScanner::ModuleDependencyInfo Result; + for (const RoadMapInfo &Info : RoadMapInfos) { + auto GCMInfo = scanGcm(Info.Path); + if (!GCMInfo) { + continue; + } + + ModuleNameToSource.try_emplace(GCMInfo->ModuleName, GCMInfo->Source); + elog("Info {0}, CurrentPath: {1}, source: {2}", Info.Name, Cmd.Filename, + GCMInfo->Source); + if (GCMInfo->Source == Cmd.Filename) { + elog("Hello? {0}, {1}", GCMInfo->Source, GCMInfo->ModuleName); + Result.ModuleName = GCMInfo->ModuleName; + } + Result.RequiredModules.push_back(Info.Name); + } + return Result; +} + +// I need to read deeper here +// problem is here +// We can read the data from modmap +// But we cannot get the the required module +// it can be itself std::optional<ModuleDependencyScanner::ModuleDependencyInfo> ModuleDependencyScanner::scan(PathRef FilePath, const ProjectModules::CommandMangler &Mangler) { + // FIXME: why it always become clang++? or it it the problem here? auto Cmd = getCompileCommandForFile(*CDB, FilePath, Mangler); - if (!Cmd) - return std::nullopt; + + elog("filepath: {0}, dir: {1}", FilePath, Cmd->Directory); using namespace clang::tooling; + auto CmdLine = Cmd->CommandLine; + auto It = llvm::find_if(CmdLine, gcc::fitGccModulePath); + if (It != CmdLine.end()) { + llvm::StringRef Module = *It; + // NOTE: we can use it to check the module Name, and its name + if (Module.consume_front("-fmodule-mapper=")) { + elog("Enter: filepath: {0}, dir: {1}", FilePath, Cmd->Directory); + llvm::StringRef Cwd = Cmd->Directory; + llvm::SmallString<128> MapFile = Cwd; + llvm::sys::path::append(MapFile, Module); + return scanGcc(*Cmd, MapFile); + } + } DependencyScanningTool ScanningTool(Service); std::string S; diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp index 0661ecb58008e..69cfaebdf3a4d 100644 --- a/clang-tools-extra/clangd/TUScheduler.cpp +++ b/clang-tools-extra/clangd/TUScheduler.cpp @@ -442,9 +442,11 @@ class PreambleThread { /// will be built. void update(std::unique_ptr<CompilerInvocation> CI, ParseInputs PI, std::vector<Diag> CIDiags, WantDiagnostics WantDiags) { + // NOTE: then it entered Req Request Req = {std::move(CI), std::move(PI), std::move(CIDiags), WantDiags, Context::current().clone()}; if (RunSync) { + // NOTE: and go to build build(std::move(Req)); Status.update([](TUStatus &Status) { Status.PreambleActivity = PreambleAction::Idle; @@ -944,6 +946,7 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags, return; } + // NOTE: happened here // Inform preamble peer, before attempting to build diagnostics so that they // can be built concurrently. PreamblePeer.update(std::make_unique<CompilerInvocation>(*Invocation), @@ -1048,6 +1051,7 @@ static void crashDumpParseInputs(llvm::raw_ostream &OS, crashDumpFileContents(OS, FileInputs.Contents); } +// NOTE: then why it comes here? I do not know void PreambleThread::build(Request Req) { assert(Req.CI && "Got preamble request with null compiler invocation"); const ParseInputs &Inputs = Req.Inputs; @@ -1057,6 +1061,8 @@ void PreambleThread::build(Request Req) { Status.PreambleActivity = PreambleAction::Building; }); llvm::scope_exit _([this, &Req, &ReusedPreamble] { + // NOTE: enter point 1? + // But seems it is ASTPeer ASTPeer.updatePreamble(std::move(Req.CI), std::move(Req.Inputs), LatestBuild, std::move(Req.CIDiags), std::move(Req.WantDiags)); @@ -1670,8 +1676,10 @@ bool TUScheduler::blockUntilIdle(Deadline D) const { return true; } +// NOTE: There are information about modules and etc in ParseInputs bool TUScheduler::update(PathRef File, ParseInputs Inputs, WantDiagnostics WantDiags) { + // NOTE: then it comes here std::unique_ptr<FileData> &FD = Files[File]; bool NewFile = FD == nullptr; bool ContentChanged = false; diff --git a/clang/lib/Tooling/JSONCompilationDatabase.cpp b/clang/lib/Tooling/JSONCompilationDatabase.cpp index 0efa75970d986..361f107328f3b 100644 --- a/clang/lib/Tooling/JSONCompilationDatabase.cpp +++ b/clang/lib/Tooling/JSONCompilationDatabase.cpp @@ -45,9 +45,9 @@ namespace { /// Assumes \-escaping for quoted arguments (see the documentation of /// unescapeCommandLine(...)). class CommandLineArgumentParser { - public: +public: CommandLineArgumentParser(StringRef CommandLine) - : Input(CommandLine), Position(Input.begin()-1) {} + : Input(CommandLine), Position(Input.begin() - 1) {} std::vector<std::string> parse() { bool HasMoreInput = true; @@ -59,46 +59,56 @@ class CommandLineArgumentParser { return CommandLine; } - private: +private: // All private methods return true if there is more input available. bool parseStringInto(std::string &String) { do { if (*Position == '"') { - if (!parseDoubleQuotedStringInto(String)) return false; + if (!parseDoubleQuotedStringInto(String)) + return false; } else if (*Position == '\'') { - if (!parseSingleQuotedStringInto(String)) return false; + if (!parseSingleQuotedStringInto(String)) + return false; } else { - if (!parseFreeStringInto(String)) return false; + if (!parseFreeStringInto(String)) + return false; } } while (*Position != ' '); return true; } bool parseDoubleQuotedStringInto(std::string &String) { - if (!next()) return false; + if (!next()) + return false; while (*Position != '"') { - if (!skipEscapeCharacter()) return false; + if (!skipEscapeCharacter()) + return false; String.push_back(*Position); - if (!next()) return false; + if (!next()) + return false; } return next(); } bool parseSingleQuotedStringInto(std::string &String) { - if (!next()) return false; + if (!next()) + return false; while (*Position != '\'') { String.push_back(*Position); - if (!next()) return false; + if (!next()) + return false; } return next(); } bool parseFreeStringInto(std::string &String) { do { - if (!skipEscapeCharacter()) return false; + if (!skipEscapeCharacter()) + return false; String.push_back(*Position); - if (!next()) return false; + if (!next()) + return false; } while (*Position != ' ' && *Position != '"' && *Position != '\''); return true; } @@ -112,7 +122,8 @@ class CommandLineArgumentParser { bool nextNonWhitespace() { do { - if (!next()) return false; + if (!next()) + return false; } while (*Position == ' '); return true; } @@ -160,6 +171,7 @@ class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin { llvm::sys::path::append(JSONDatabasePath, "compile_commands.json"); auto Base = JSONCompilationDatabase::loadFromFile( JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect); + return Base ? inferTargetAndDriverMode( inferMissingCompileCommands(expandResponseFiles( std::move(Base), llvm::vfs::getRealFileSystem()))) @@ -172,7 +184,8 @@ class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin { // Register the JSONCompilationDatabasePlugin with the // CompilationDatabasePluginRegistry using this statically initialized variable. static CompilationDatabasePluginRegistry::Add<JSONCompilationDatabasePlugin> -X("json-compilation-database", "Reads JSON formatted compilation databases"); + X("json-compilation-database", + "Reads JSON formatted compilation databases"); namespace clang { namespace tooling { @@ -235,8 +248,7 @@ JSONCompilationDatabase::getCompileCommands(StringRef FilePath) const { return Commands; } -std::vector<std::string> -JSONCompilationDatabase::getAllFiles() const { +std::vector<std::string> JSONCompilationDatabase::getAllFiles() const { std::vector<std::string> Result; for (const auto &CommandRef : IndexByFile) Result.push_back(CommandRef.first().str()); @@ -312,11 +324,10 @@ void JSONCompilationDatabase::getCommands( SmallString<32> FilenameStorage; SmallString<32> OutputStorage; auto Output = std::get<3>(CommandRef); - Commands.emplace_back( - std::get<0>(CommandRef)->getValue(DirectoryStorage), - std::get<1>(CommandRef)->getValue(FilenameStorage), - nodeToCommandLine(Syntax, std::get<2>(CommandRef)), - Output ? Output->getValue(OutputStorage) : ""); + Commands.emplace_back(std::get<0>(CommandRef)->getValue(DirectoryStorage), + std::get<1>(CommandRef)->getValue(FilenameStorage), + nodeToCommandLine(Syntax, std::get<2>(CommandRef)), + Output ? Output->getValue(OutputStorage) : ""); } } @@ -346,7 +357,7 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) { std::optional<std::vector<llvm::yaml::ScalarNode *>> Command; llvm::yaml::ScalarNode *File = nullptr; llvm::yaml::ScalarNode *Output = nullptr; - for (auto& NextKeyValue : *Object) { + for (auto &NextKeyValue : *Object) { auto *KeyString = dyn_cast_if_present<llvm::yaml::ScalarNode>(NextKeyValue.getKey()); if (!KeyString) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
