[clang] [clang][deps] Collect discovered module dependencies' Link Libraries (PR #93588)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/93588 >From f69fd6e79ca7232672b4b3759253e818e8b2cec7 Mon Sep 17 00:00:00 2001 From: artemcm Date: Fri, 24 May 2024 15:13:45 -0700 Subject: [PATCH] [clang][deps] Collect discovered module dependencies' Link Libraries This will allow scanner clients to be able to compute e.g. auto-linking dependencies of the scanned translation unit. --- .../DependencyScanning/ModuleDepCollector.h | 5 + .../DependencyScanning/ModuleDepCollector.cpp | 4 + clang/test/ClangScanDeps/diagnostics.c| 1 + .../header-search-pruning-transitive.c| 4 + .../ClangScanDeps/header-search-pruning.cpp | 3 + clang/test/ClangScanDeps/link-libraries.c | 121 ++ .../modules-canononical-module-map-case.c | 6 + .../test/ClangScanDeps/modules-context-hash.c | 2 + clang/test/ClangScanDeps/modules-dep-args.c | 2 + .../ClangScanDeps/modules-excluded-header.m | 1 + .../ClangScanDeps/modules-extern-submodule.c | 3 + .../ClangScanDeps/modules-extern-unrelated.m | 4 + .../modules-file-path-isolation.c | 1 + .../modules-fmodule-name-no-module-built.m| 1 + .../ClangScanDeps/modules-full-by-mod-name.c | 3 + clang/test/ClangScanDeps/modules-full.cpp | 3 + .../modules-implementation-private.m | 6 + .../modules-implicit-dot-private.m| 12 ++ .../modules-incomplete-umbrella.c | 25 clang/test/ClangScanDeps/modules-inferred.m | 6 + .../modules-no-undeclared-includes.c | 1 + .../modules-pch-common-submodule.c| 2 + .../modules-pch-common-via-submodule.c| 2 + clang/test/ClangScanDeps/modules-pch.c| 5 + .../ClangScanDeps/modules-priv-fw-from-pub.m | 13 ++ .../test/ClangScanDeps/modules-redefinition.m | 1 + .../ClangScanDeps/modules-symlink-dir-vfs.c | 6 + clang/test/ClangScanDeps/modules-transitive.c | 1 + .../optimize-canonicalize-macros.m| 2 + .../test/ClangScanDeps/optimize-fmodulemap.m | 2 + .../ClangScanDeps/optimize-system-warnings.m | 3 + clang/test/ClangScanDeps/optimize-vfs-leak.m | 5 +- clang/test/ClangScanDeps/optimize-vfs.m | 3 + clang/test/ClangScanDeps/removed-args.c | 2 + clang/test/ClangScanDeps/working-dir.m| 4 + clang/tools/clang-scan-deps/ClangScanDeps.cpp | 29 +++-- 36 files changed, 285 insertions(+), 9 deletions(-) create mode 100644 clang/test/ClangScanDeps/link-libraries.c diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h index da51292296a90..3de19d756da00 100644 --- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h +++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h @@ -10,6 +10,7 @@ #define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H #include "clang/Basic/LLVM.h" +#include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/Utils.h" @@ -138,6 +139,10 @@ struct ModuleDeps { /// determined that the differences are benign for this compilation. std::vector ClangModuleDeps; + /// The set of libraries or frameworks to link against when + /// an entity from this module is used. + llvm::SmallVector LinkLibraries; + /// Get (or compute) the compiler invocation that can be used to build this /// module. Does not include argv[0]. const std::vector &getBuildArguments(); diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index f46324ee9989e..370d834846859 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -578,6 +578,10 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) { MD.ID.ModuleName = M->getFullModuleName(); MD.IsSystem = M->IsSystem; + // For modules which use export_as link name, the linked product that of the + // corresponding export_as-named module. + if (!M->UseExportAsModuleLinkName) +MD.LinkLibraries = M->LinkLibraries; ModuleMap &ModMapInfo = MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); diff --git a/clang/test/ClangScanDeps/diagnostics.c b/clang/test/ClangScanDeps/diagnostics.c index 42aeca16cddc4..bc05594f7828d 100644 --- a/clang/test/ClangScanDeps/diagnostics.c +++ b/clang/test/ClangScanDeps/diagnostics.c @@ -37,6 +37,7 @@ module mod { header "mod.h" } // CHECK-NEXT: "[[PREFIX]]/mod.h" // CHECK-NEXT: "[[PREFIX]]/module.modulemap" // CHECK-NEXT: ], +// CHECK-NEXT: "link-libraries": [], // CHECK-NEXT: "name": "mod" // CHECK-NEXT: } // CHECK-NEXT: ], diff --git a/clang/test/ClangScanDeps/header-search-pruning-transitive.c b/cl
[clang] [clang][deps] Collect discovered module dependencies' Link Libraries (PR #93588)
https://github.com/artemcm edited https://github.com/llvm/llvm-project/pull/93588 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][deps] Collect discovered module dependencies' Link Libraries (PR #93588)
@@ -138,6 +139,14 @@ struct ModuleDeps { /// determined that the differences are benign for this compilation. std::vector ClangModuleDeps; + /// The set of libraries or frameworks to link against when + /// an entity from this module is used. + llvm::SmallVector LinkLibraries; + + /// Autolinking uses the framework name for linking purposes + /// when this is false and the export_as name otherwise. + bool UseExportAsModuleLinkName; artemcm wrote: It seems that `LinkLibraries` are still collected for a `Module` separately just in case it gets discovered/imported by a module matching a `export_as` name. So I can see why a separate flag was introduced. The logic for adding linker flags in CodeGen omits these modules if this flag (`UseExportAsModuleLinkName`) is set, and that matching the intent behind this change here, I think it would make sense to model the same in the scanner. i.e. omit `LinkLibraries` of such module, because by the time we've discovered all the dependencies we are guaranteed to have the required knowledge to make this decision. https://github.com/llvm/llvm-project/pull/93588 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][deps] Collect discovered module dependencies' Link Libraries (PR #93588)
@@ -138,6 +139,14 @@ struct ModuleDeps { /// determined that the differences are benign for this compilation. std::vector ClangModuleDeps; + /// The set of libraries or frameworks to link against when + /// an entity from this module is used. + llvm::SmallVector LinkLibraries; + + /// Autolinking uses the framework name for linking purposes + /// when this is false and the export_as name otherwise. + bool UseExportAsModuleLinkName; artemcm wrote: >If the idea is to drop the autolink of the current module, should we rework >that so that we remove it from the link libraries of the importer instead? Yeah, that's the thinking behind adding it here - the scanner is aggregating a set of link libraries for the root importer, and an assumption is made that a module with export_as link name set will be covered by a `LinkLibrary` of one of its dependents. e.g. `SomeKit` depends on `SomeKitCore` and the latter sets `export_as SomeKit`. And the scanner's client may only see `ModuleDeps`, and not this info, so it can use this bit to know to avoid processing its `LinkLibraries`. >From what I can tell the above scenario matches the circumstance where this >bit is set on a `Module` -> when a module with the `export_as` name has >already been found. Given this, I do not really see a reason to report `LinkLibraries` for such modules at all, what do you think that instead of having this bit here we instead just use it in the scanner to know to avoid populating `LinkLibraries` added here? https://github.com/llvm/llvm-project/pull/93588 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][deps] Collect discovered module dependencies' Link Libraries (PR #93588)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/93588 >From 034f567024c6766f68dcc73ddad9b0fe09b05baf Mon Sep 17 00:00:00 2001 From: artemcm Date: Fri, 24 May 2024 15:13:45 -0700 Subject: [PATCH] [clang][deps] Collect discovered module dependencies' Link Libraries This will allow scanner clients to be able to compute e.g. auto-linking dependencies of the scanned translation unit. --- .../DependencyScanning/ModuleDepCollector.h | 9 ++ .../DependencyScanning/ModuleDepCollector.cpp | 2 + clang/test/ClangScanDeps/diagnostics.c| 1 + .../header-search-pruning-transitive.c| 4 + .../ClangScanDeps/header-search-pruning.cpp | 3 + clang/test/ClangScanDeps/link-libraries.c | 121 ++ .../modules-canononical-module-map-case.c | 6 + .../test/ClangScanDeps/modules-context-hash.c | 2 + clang/test/ClangScanDeps/modules-dep-args.c | 2 + .../ClangScanDeps/modules-excluded-header.m | 1 + .../ClangScanDeps/modules-extern-submodule.c | 3 + .../ClangScanDeps/modules-extern-unrelated.m | 4 + .../modules-file-path-isolation.c | 1 + .../modules-fmodule-name-no-module-built.m| 1 + .../ClangScanDeps/modules-full-by-mod-name.c | 3 + clang/test/ClangScanDeps/modules-full.cpp | 3 + .../modules-implementation-private.m | 6 + .../modules-implicit-dot-private.m| 12 ++ .../modules-incomplete-umbrella.c | 25 clang/test/ClangScanDeps/modules-inferred.m | 6 + .../modules-no-undeclared-includes.c | 1 + .../modules-pch-common-submodule.c| 2 + .../modules-pch-common-via-submodule.c| 2 + clang/test/ClangScanDeps/modules-pch.c| 5 + .../ClangScanDeps/modules-priv-fw-from-pub.m | 13 ++ .../test/ClangScanDeps/modules-redefinition.m | 1 + .../ClangScanDeps/modules-symlink-dir-vfs.c | 6 + clang/test/ClangScanDeps/modules-transitive.c | 1 + .../optimize-canonicalize-macros.m| 2 + .../test/ClangScanDeps/optimize-fmodulemap.m | 2 + .../ClangScanDeps/optimize-system-warnings.m | 3 + clang/test/ClangScanDeps/optimize-vfs-leak.m | 5 +- clang/test/ClangScanDeps/optimize-vfs.m | 3 + clang/test/ClangScanDeps/removed-args.c | 2 + clang/test/ClangScanDeps/working-dir.m| 4 + clang/tools/clang-scan-deps/ClangScanDeps.cpp | 29 +++-- 36 files changed, 287 insertions(+), 9 deletions(-) create mode 100644 clang/test/ClangScanDeps/link-libraries.c diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h index da51292296a90..6c5ddef46e24d 100644 --- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h +++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h @@ -10,6 +10,7 @@ #define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H #include "clang/Basic/LLVM.h" +#include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/Utils.h" @@ -138,6 +139,14 @@ struct ModuleDeps { /// determined that the differences are benign for this compilation. std::vector ClangModuleDeps; + /// The set of libraries or frameworks to link against when + /// an entity from this module is used. + llvm::SmallVector LinkLibraries; + + /// Autolinking uses the framework name for linking purposes + /// when this is false and the export_as name otherwise. + bool UseExportAsModuleLinkName; + /// Get (or compute) the compiler invocation that can be used to build this /// module. Does not include argv[0]. const std::vector &getBuildArguments(); diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index f46324ee9989e..6b2ea1a67b96b 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -578,6 +578,8 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) { MD.ID.ModuleName = M->getFullModuleName(); MD.IsSystem = M->IsSystem; + MD.LinkLibraries = M->LinkLibraries; + MD.UseExportAsModuleLinkName = M->UseExportAsModuleLinkName; ModuleMap &ModMapInfo = MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); diff --git a/clang/test/ClangScanDeps/diagnostics.c b/clang/test/ClangScanDeps/diagnostics.c index 42aeca16cddc4..bc05594f7828d 100644 --- a/clang/test/ClangScanDeps/diagnostics.c +++ b/clang/test/ClangScanDeps/diagnostics.c @@ -37,6 +37,7 @@ module mod { header "mod.h" } // CHECK-NEXT: "[[PREFIX]]/mod.h" // CHECK-NEXT: "[[PREFIX]]/module.modulemap" // CHECK-NEXT: ], +// CHECK-NEXT: "link-libraries": [], // CHECK-NEXT: "name": "mod" // CHECK-NEXT: } // CHECK-NEXT: ], diff --git a/clan
[clang] [clang][deps] Collect discovered module dependencies' Link Libraries (PR #93588)
https://github.com/artemcm created https://github.com/llvm/llvm-project/pull/93588 This will allow scanner clients to be able to compute e.g. auto-linking dependencies of the scanned translation unit. >From 763e8e1ba75dd8122eba2ebcab77c45fc4dcb7c0 Mon Sep 17 00:00:00 2001 From: artemcm Date: Fri, 24 May 2024 15:13:45 -0700 Subject: [PATCH] [clang][deps] Collect discovered module dependencies' Link Libraries This will allow scanner clients to be able to compute e.g. auto-linking dependencies of the scanned translation unit. --- .../DependencyScanning/ModuleDepCollector.h | 9 ++ .../DependencyScanning/ModuleDepCollector.cpp | 2 + clang/test/ClangScanDeps/diagnostics.c| 1 + .../header-search-pruning-transitive.c| 4 + .../ClangScanDeps/header-search-pruning.cpp | 3 + clang/test/ClangScanDeps/link-libraries.c | 121 ++ .../modules-canononical-module-map-case.c | 6 + .../test/ClangScanDeps/modules-context-hash.c | 2 + clang/test/ClangScanDeps/modules-dep-args.c | 2 + .../ClangScanDeps/modules-excluded-header.m | 1 + .../ClangScanDeps/modules-extern-submodule.c | 3 + .../ClangScanDeps/modules-extern-unrelated.m | 4 + .../modules-file-path-isolation.c | 1 + .../modules-fmodule-name-no-module-built.m| 1 + .../ClangScanDeps/modules-full-by-mod-name.c | 3 + clang/test/ClangScanDeps/modules-full.cpp | 3 + .../modules-implementation-private.m | 6 + .../modules-implicit-dot-private.m| 12 ++ .../modules-incomplete-umbrella.c | 25 clang/test/ClangScanDeps/modules-inferred.m | 6 + .../modules-no-undeclared-includes.c | 1 + .../modules-pch-common-submodule.c| 2 + .../modules-pch-common-via-submodule.c| 2 + clang/test/ClangScanDeps/modules-pch.c| 5 + .../ClangScanDeps/modules-priv-fw-from-pub.m | 13 ++ .../test/ClangScanDeps/modules-redefinition.m | 1 + .../ClangScanDeps/modules-symlink-dir-vfs.c | 6 + clang/test/ClangScanDeps/modules-transitive.c | 1 + .../optimize-canonicalize-macros.m| 2 + .../test/ClangScanDeps/optimize-fmodulemap.m | 2 + .../ClangScanDeps/optimize-system-warnings.m | 3 + clang/test/ClangScanDeps/optimize-vfs-leak.m | 5 +- clang/test/ClangScanDeps/optimize-vfs.m | 3 + clang/test/ClangScanDeps/removed-args.c | 2 + clang/test/ClangScanDeps/working-dir.m| 4 + clang/tools/clang-scan-deps/ClangScanDeps.cpp | 15 +++ 36 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 clang/test/ClangScanDeps/link-libraries.c diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h index da51292296a90..5afb373b3462e 100644 --- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h +++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h @@ -11,6 +11,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Module.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" @@ -138,6 +139,14 @@ struct ModuleDeps { /// determined that the differences are benign for this compilation. std::vector ClangModuleDeps; + /// The set of libraries or frameworks to link against when + /// an entity from this module is used. + llvm::SmallVector LinkLibraries; + + /// Autolinking uses the framework name for linking purposes + /// when this is false and the export_as name otherwise. + bool UseExportAsModuleLinkName; + /// Get (or compute) the compiler invocation that can be used to build this /// module. Does not include argv[0]. const std::vector &getBuildArguments(); diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index f46324ee9989e..6b2ea1a67b96b 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -578,6 +578,8 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) { MD.ID.ModuleName = M->getFullModuleName(); MD.IsSystem = M->IsSystem; + MD.LinkLibraries = M->LinkLibraries; + MD.UseExportAsModuleLinkName = M->UseExportAsModuleLinkName; ModuleMap &ModMapInfo = MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); diff --git a/clang/test/ClangScanDeps/diagnostics.c b/clang/test/ClangScanDeps/diagnostics.c index 42aeca16cddc4..bc05594f7828d 100644 --- a/clang/test/ClangScanDeps/diagnostics.c +++ b/clang/test/ClangScanDeps/diagnostics.c @@ -37,6 +37,7 @@ module mod { header "mod.h" } // CHECK-NEXT: "[[PREFIX]]/mod.h" // CHECK-NEXT: "[[PREFIX]]/module.modulemap" // CHECK-NEXT: ], +// CHECK-NEXT: "link-libraries": [], // CHECK-
[clang] [NFC] Parameterize Initialization of `clang::CodeGenerator` on a `TargetInfo` instance which may differ from the one in the `ASTContext` (PR #88977)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88977 >From 04e826688a504e141f3407567616bcf5cce9e2cc Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Wed, 20 Dec 2023 10:56:42 -0800 Subject: [PATCH] [NFC] Parameterize Initialization of 'clang::CodeGenerator' on a TargetInfo instance which may differ from the one in the ASTContext As per https://github.com/apple/swift/pull/65930, Swift compiler's built-in Clang instance may require to perform type-checking against one OS version and compilation/code-generation against an earlier version. This change allows Swift to configure it's built-in Clang code-generator with a custom 'TargetInfo'. --- clang/include/clang/AST/ASTConsumer.h | 5 clang/lib/CodeGen/CodeGenModule.cpp | 29 +-- clang/lib/CodeGen/CodeGenModule.h | 3 +- clang/lib/CodeGen/ModuleBuilder.cpp | 21 +- .../ObjectFilePCHContainerOperations.cpp | 5 ++-- 5 files changed, 36 insertions(+), 27 deletions(-) diff --git a/clang/include/clang/AST/ASTConsumer.h b/clang/include/clang/AST/ASTConsumer.h index ebcd8059284d8d..774d19565e57b0 100644 --- a/clang/include/clang/AST/ASTConsumer.h +++ b/clang/include/clang/AST/ASTConsumer.h @@ -26,6 +26,7 @@ namespace clang { class VarDecl; class FunctionDecl; class ImportDecl; + class TargetInfo; /// ASTConsumer - This is an abstract interface that should be implemented by /// clients that read ASTs. This abstraction layer allows the client to be @@ -46,6 +47,10 @@ class ASTConsumer { /// ASTContext. virtual void Initialize(ASTContext &Context) {} + /// Initialize - This is called to initialize the consumer, providing the + /// ASTContext. + virtual void Initialize(ASTContext &Context, const TargetInfo &CodeGenTargetInfo) {} + /// HandleTopLevelDecl - Handle the specified top-level declaration. This is /// called by the parser to process every top-level Decl*. /// diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 0c447b20cef40d..8380b71ababe5b 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -333,14 +333,13 @@ CodeGenModule::CodeGenModule(ASTContext &C, IntrusiveRefCntPtr FS, const HeaderSearchOptions &HSO, const PreprocessorOptions &PPO, - const CodeGenOptions &CGO, llvm::Module &M, - DiagnosticsEngine &diags, + const CodeGenOptions &CGO, const TargetInfo &CGTI, + llvm::Module &M, DiagnosticsEngine &diags, CoverageSourceInfo *CoverageInfo) : Context(C), LangOpts(C.getLangOpts()), FS(FS), HeaderSearchOpts(HSO), PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags), - Target(C.getTargetInfo()), ABI(createCXXABI(*this)), - VMContext(M.getContext()), Types(*this), VTables(*this), - SanitizerMD(new SanitizerMetadata(*this)) { + Target(CGTI), ABI(createCXXABI(*this)), VMContext(M.getContext()), + Types(*this), VTables(*this), SanitizerMD(new SanitizerMetadata(*this)) { // Initialize the type cache. llvm::LLVMContext &LLVMContext = M.getContext(); @@ -353,20 +352,18 @@ CodeGenModule::CodeGenModule(ASTContext &C, BFloatTy = llvm::Type::getBFloatTy(LLVMContext); FloatTy = llvm::Type::getFloatTy(LLVMContext); DoubleTy = llvm::Type::getDoubleTy(LLVMContext); - PointerWidthInBits = C.getTargetInfo().getPointerWidth(LangAS::Default); + PointerWidthInBits = Target.getPointerWidth(LangAS::Default); PointerAlignInBytes = - C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(LangAS::Default)) + C.toCharUnitsFromBits(Target.getPointerAlign(LangAS::Default)) .getQuantity(); SizeSizeInBytes = - C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth()).getQuantity(); - IntAlignInBytes = -C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity(); - CharTy = -llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getCharWidth()); - IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth()); - IntPtrTy = llvm::IntegerType::get(LLVMContext, -C.getTargetInfo().getMaxPointerWidth()); - Int8PtrTy = llvm::PointerType::get(LLVMContext, 0); + C.toCharUnitsFromBits(Target.getMaxPointerWidth()).getQuantity(); + IntAlignInBytes = C.toCharUnitsFromBits(Target.getIntAlign()).getQuantity(); + CharTy = llvm::IntegerType::get(LLVMContext, Target.getCharWidth()); + IntTy = llvm::IntegerType::get(LLVMContext, Target.getIntWidth()); + IntPtrTy = llvm::IntegerType::get(LLVMContext, Target.getMaxPointerWidth()); + Int8PtrTy = Int8Ty->getPointerTo(0); + Int8PtrPtrTy = Int8PtrTy->getPointerTo(0); const llvm::DataLayout &DL = M.getDataLayout(); AllocaInt8PtrTy =
[clang] [NFC] Parameterize Initialization of `clang::CodeGenerator` on a `TargetInfo` instance which may differ from the one in the `ASTContext` (PR #88977)
https://github.com/artemcm created https://github.com/llvm/llvm-project/pull/88977 A client's Clang instance may require to perform type-checking against one OS version and compilation/code-generation against an earlier version. This change allows such clients to configure their built-in Clang code-generator with a custom `TargetInfo`. >From c86ee8d6fc2b0d3995f0dee4e7bc206ef6e05c8b Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Wed, 20 Dec 2023 10:56:42 -0800 Subject: [PATCH] [NFC] Parameterize Initialization of 'clang::CodeGenerator' on a TargetInfo instance which may differ from the one in the ASTContext As per https://github.com/apple/swift/pull/65930, Swift compiler's built-in Clang instance may require to perform type-checking against one OS version and compilation/code-generation against an earlier version. This change allows Swift to configure it's built-in Clang code-generator with a custom 'TargetInfo'. --- clang/include/clang/AST/ASTConsumer.h | 5 clang/lib/CodeGen/CodeGenModule.cpp | 23 +++ clang/lib/CodeGen/CodeGenModule.h | 4 +++- clang/lib/CodeGen/ModuleBuilder.cpp | 17 +- .../ObjectFilePCHContainerOperations.cpp | 3 ++- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/AST/ASTConsumer.h b/clang/include/clang/AST/ASTConsumer.h index ebcd8059284d8d..774d19565e57b0 100644 --- a/clang/include/clang/AST/ASTConsumer.h +++ b/clang/include/clang/AST/ASTConsumer.h @@ -26,6 +26,7 @@ namespace clang { class VarDecl; class FunctionDecl; class ImportDecl; + class TargetInfo; /// ASTConsumer - This is an abstract interface that should be implemented by /// clients that read ASTs. This abstraction layer allows the client to be @@ -46,6 +47,10 @@ class ASTConsumer { /// ASTContext. virtual void Initialize(ASTContext &Context) {} + /// Initialize - This is called to initialize the consumer, providing the + /// ASTContext. + virtual void Initialize(ASTContext &Context, const TargetInfo &CodeGenTargetInfo) {} + /// HandleTopLevelDecl - Handle the specified top-level declaration. This is /// called by the parser to process every top-level Decl*. /// diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 0c447b20cef40d..52ff65c0986931 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -333,12 +333,14 @@ CodeGenModule::CodeGenModule(ASTContext &C, IntrusiveRefCntPtr FS, const HeaderSearchOptions &HSO, const PreprocessorOptions &PPO, - const CodeGenOptions &CGO, llvm::Module &M, + const CodeGenOptions &CGO, + const TargetInfo &CGTI, + llvm::Module &M, DiagnosticsEngine &diags, CoverageSourceInfo *CoverageInfo) : Context(C), LangOpts(C.getLangOpts()), FS(FS), HeaderSearchOpts(HSO), PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags), - Target(C.getTargetInfo()), ABI(createCXXABI(*this)), + Target(CGTI), ABI(createCXXABI(*this)), VMContext(M.getContext()), Types(*this), VTables(*this), SanitizerMD(new SanitizerMetadata(*this)) { @@ -353,20 +355,21 @@ CodeGenModule::CodeGenModule(ASTContext &C, BFloatTy = llvm::Type::getBFloatTy(LLVMContext); FloatTy = llvm::Type::getFloatTy(LLVMContext); DoubleTy = llvm::Type::getDoubleTy(LLVMContext); - PointerWidthInBits = C.getTargetInfo().getPointerWidth(LangAS::Default); + PointerWidthInBits = Target.getPointerWidth(LangAS::Default); PointerAlignInBytes = - C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(LangAS::Default)) + C.toCharUnitsFromBits(Target.getPointerAlign(LangAS::Default)) .getQuantity(); SizeSizeInBytes = - C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth()).getQuantity(); +C.toCharUnitsFromBits(Target.getMaxPointerWidth()).getQuantity(); IntAlignInBytes = -C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity(); +C.toCharUnitsFromBits(Target.getIntAlign()).getQuantity(); CharTy = -llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getCharWidth()); - IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth()); +llvm::IntegerType::get(LLVMContext, Target.getCharWidth()); + IntTy = llvm::IntegerType::get(LLVMContext, Target.getIntWidth()); IntPtrTy = llvm::IntegerType::get(LLVMContext, -C.getTargetInfo().getMaxPointerWidth()); - Int8PtrTy = llvm::PointerType::get(LLVMContext, 0); +Target.getMaxPointerWidth()); + Int8PtrTy = Int8Ty->getPointerTo(0); + Int8PtrPtrTy = Int8PtrTy->getPointerTo(0); const llvm::DataLayout &DL = M.getDataLayout(); AllocaInt8PtrTy =
[clang] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From 1989bbbdb1d575e2e938ec319ad9ad23db6af6fc Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Tue, 9 Apr 2024 09:37:09 -0700 Subject: [PATCH] [clang][deps] Overload 'Filesystem::exists' in 'DependencyScanningFilesystem' to have it use cached `status` As-is, calls to `exists()` fallback on the implementation in 'ProxyFileSystem::exists' which explicitly calls out to the underlying `FS`, which for the 'DependencyScanningFilesystem' (overlay) is the real underlying filesystem. Instead, directly overloading 'exists' allows us to have it rely on the cached `status` behavior used elsewhere by the 'DependencyScanningFilesystem'. --- .../DependencyScanningFilesystem.h| 4 +++ .../DependencyScanningFilesystem.cpp | 11 .../DependencyScanningFilesystemTest.cpp | 27 +++ 3 files changed, 42 insertions(+) diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 8b6f149c7cb266..f7b4510d7f7beb 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -365,6 +365,10 @@ class DependencyScanningWorkerFilesystem /// false if not (i.e. this entry is not a file or its scan fails). bool ensureDirectiveTokensArePopulated(EntryRef Entry); + /// Check whether \p Path exists. By default checks cached result of \c + /// status(), and falls back on FS if unable to do so. + bool exists(const Twine &Path) override; + private: /// For a filename that's not yet associated with any entry in the caches, /// uses the underlying filesystem to either look up the entry based in the diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 84185c931b552c..0cab17a3424406 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -300,6 +300,17 @@ DependencyScanningWorkerFilesystem::status(const Twine &Path) { return Result->getStatus(); } +bool DependencyScanningWorkerFilesystem::exists(const Twine &Path) { + // While some VFS overlay filesystems may implement more-efficient + // mechanisms for `exists` queries, `DependencyScanningWorkerFilesystem` + // typically wraps `RealFileSystem` which does not specialize `exists`, + // so it is not likely to benefit from such optimizations. Instead, + // it is more-valuable to have this query go through the + // cached-`status` code-path of the `DependencyScanningWorkerFilesystem`. + llvm::ErrorOr Status = status(Path); + return Status && Status->exists(); +} + namespace { /// The VFS that is used by clang consumes the \c CachedFileSystemEntry using diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp index 697b7d70ff035a..87bb67cfd9327c 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp @@ -18,6 +18,7 @@ struct InstrumentingFilesystem : llvm::RTTIExtends { unsigned NumStatusCalls = 0; unsigned NumGetRealPathCalls = 0; + unsigned NumExistsCalls = 0; using llvm::RTTIExtends::RTTIExtends; @@ -32,6 +33,11 @@ struct InstrumentingFilesystem ++NumGetRealPathCalls; return ProxyFileSystem::getRealPath(Path, Output); } + + bool exists(const llvm::Twine &Path) override { +++NumExistsCalls; +return ProxyFileSystem::exists(Path); + } }; } // namespace @@ -147,3 +153,24 @@ TEST(DependencyScanningFilesystem, RealPathAndStatusInvariants) { DepFS.status("/bar"); } } + +TEST(DependencyScanningFilesystem, CacheStatOnExists) { + auto InMemoryFS = llvm::makeIntrusiveRefCnt(); + auto InstrumentingFS = + llvm::makeIntrusiveRefCnt(InMemoryFS); + InMemoryFS->setCurrentWorkingDirectory("/"); + InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer("")); + InMemoryFS->addFile("/bar", 0, llvm::MemoryBuffer::getMemBuffer("")); + DependencyScanningFilesystemSharedCache SharedCache; + DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS); + + DepFS.status("/foo"); + DepFS.status("/foo"); + DepFS.status("/bar"); + EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u); + + DepFS.exists("/foo"); + DepFS.exists("/bar"); + EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u); + EXPECT_EQ(InstrumentingFS->NumExistsCalls, 0u); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/c
[clang] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From b7c693011abd785bec0a58fe4b6011a84f1ea329 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Tue, 9 Apr 2024 09:37:09 -0700 Subject: [PATCH] [clang][deps] Overload 'Filesystem::exists' in 'DependencyScanningFilesystem' to have it use cached `status` As-is, calls to `exists()` fallback on the implementation in 'ProxyFileSystem::exists' which explicitly calls out to the underlying `FS`, which for the 'DependencyScanningFilesystem' (overlay) is the real underlying filesystem. Instead, directly overloading 'exists' allows us to have it rely on the cached `status` behavior used elsewhere by the 'DependencyScanningFilesystem'. --- .../DependencyScanningFilesystem.h| 4 +++ .../DependencyScanningFilesystem.cpp | 11 +++ .../DependencyScanningFilesystemTest.cpp | 30 +++ 3 files changed, 45 insertions(+) diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 8b6f149c7cb266..f7b4510d7f7beb 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -365,6 +365,10 @@ class DependencyScanningWorkerFilesystem /// false if not (i.e. this entry is not a file or its scan fails). bool ensureDirectiveTokensArePopulated(EntryRef Entry); + /// Check whether \p Path exists. By default checks cached result of \c + /// status(), and falls back on FS if unable to do so. + bool exists(const Twine &Path) override; + private: /// For a filename that's not yet associated with any entry in the caches, /// uses the underlying filesystem to either look up the entry based in the diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 84185c931b552c..0cab17a3424406 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -300,6 +300,17 @@ DependencyScanningWorkerFilesystem::status(const Twine &Path) { return Result->getStatus(); } +bool DependencyScanningWorkerFilesystem::exists(const Twine &Path) { + // While some VFS overlay filesystems may implement more-efficient + // mechanisms for `exists` queries, `DependencyScanningWorkerFilesystem` + // typically wraps `RealFileSystem` which does not specialize `exists`, + // so it is not likely to benefit from such optimizations. Instead, + // it is more-valuable to have this query go through the + // cached-`status` code-path of the `DependencyScanningWorkerFilesystem`. + llvm::ErrorOr Status = status(Path); + return Status && Status->exists(); +} + namespace { /// The VFS that is used by clang consumes the \c CachedFileSystemEntry using diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp index 697b7d70ff035a..71447f43f1e6ff 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp @@ -18,6 +18,7 @@ struct InstrumentingFilesystem : llvm::RTTIExtends { unsigned NumStatusCalls = 0; unsigned NumGetRealPathCalls = 0; + unsigned NumExistsCalls = 0; using llvm::RTTIExtends::RTTIExtends; @@ -32,6 +33,11 @@ struct InstrumentingFilesystem ++NumGetRealPathCalls; return ProxyFileSystem::getRealPath(Path, Output); } + + bool exists(const llvm::Twine &Path) override { +++NumExistsCalls; +return ProxyFileSystem::exists(Path); + } }; } // namespace @@ -147,3 +153,27 @@ TEST(DependencyScanningFilesystem, RealPathAndStatusInvariants) { DepFS.status("/bar"); } } + +TEST(DependencyScanningFilesystem, CacheStatOnExists) { + auto InMemoryFS = llvm::makeIntrusiveRefCnt(); + auto InstrumentingFS = + llvm::makeIntrusiveRefCnt(InMemoryFS); + InMemoryFS->setCurrentWorkingDirectory("/"); + InMemoryFS->addFile("/foo", 0, + llvm::MemoryBuffer::getMemBuffer("")); + InMemoryFS->addFile("/bar", 0, + llvm::MemoryBuffer::getMemBuffer("")); + DependencyScanningFilesystemSharedCache SharedCache; + DependencyScanningWorkerFilesystem DepFS(SharedCache, + InstrumentingFS); + + DepFS.status("/foo"); + DepFS.status("/foo"); + DepFS.status("/bar"); + EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u); + + DepFS.exists("/foo"); + DepFS.exists("/bar"); + EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u); + EXPECT_EQ(InstrumentingFS->NumExistsCalls, 0u); +} ___ cfe-commits
[clang] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From 1dd15b331795daaf2ac70cbd013f56f2d7677041 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Tue, 9 Apr 2024 09:37:09 -0700 Subject: [PATCH] [clang][deps] Overload 'Filesystem::exists' in 'DependencyScanningFilesystem' to have it use cached `status` As-is, calls to `exists()` fallback on the implementation in 'ProxyFileSystem::exists' which explicitly calls out to the underlying `FS`, which for the 'DependencyScanningFilesystem' (overlay) is the real underlying filesystem. Instead, directly overloading 'exists' allows us to have it rely on the cached `status` behavior used elsewhere by the 'DependencyScanningFilesystem'. --- .../DependencyScanningFilesystem.h| 4 ++ .../DependencyScanningFilesystem.cpp | 11 .../DependencyScanningFilesystemTest.cpp | 53 ++- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 8b6f149c7cb266..f7b4510d7f7beb 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -365,6 +365,10 @@ class DependencyScanningWorkerFilesystem /// false if not (i.e. this entry is not a file or its scan fails). bool ensureDirectiveTokensArePopulated(EntryRef Entry); + /// Check whether \p Path exists. By default checks cached result of \c + /// status(), and falls back on FS if unable to do so. + bool exists(const Twine &Path) override; + private: /// For a filename that's not yet associated with any entry in the caches, /// uses the underlying filesystem to either look up the entry based in the diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 84185c931b552c..0cab17a3424406 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -300,6 +300,17 @@ DependencyScanningWorkerFilesystem::status(const Twine &Path) { return Result->getStatus(); } +bool DependencyScanningWorkerFilesystem::exists(const Twine &Path) { + // While some VFS overlay filesystems may implement more-efficient + // mechanisms for `exists` queries, `DependencyScanningWorkerFilesystem` + // typically wraps `RealFileSystem` which does not specialize `exists`, + // so it is not likely to benefit from such optimizations. Instead, + // it is more-valuable to have this query go through the + // cached-`status` code-path of the `DependencyScanningWorkerFilesystem`. + llvm::ErrorOr Status = status(Path); + return Status && Status->exists(); +} + namespace { /// The VFS that is used by clang consumes the \c CachedFileSystemEntry using diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp index 697b7d70ff035a..256dd980b2118f 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp @@ -8,6 +8,7 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/VirtualFileSystem.h" #include "gtest/gtest.h" @@ -15,31 +16,36 @@ using namespace clang::tooling::dependencies; namespace { struct InstrumentingFilesystem -: llvm::RTTIExtends { +: llvm::RTTIExtends { unsigned NumStatusCalls = 0; unsigned NumGetRealPathCalls = 0; + unsigned NumExistsCalls = 0; using llvm::RTTIExtends::RTTIExtends; + llvm::vfs::InMemoryFileSystem>::RTTIExtends; llvm::ErrorOr status(const llvm::Twine &Path) override { ++NumStatusCalls; -return ProxyFileSystem::status(Path); +return InMemoryFileSystem::status(Path); } std::error_code getRealPath(const llvm::Twine &Path, llvm::SmallVectorImpl &Output) override { ++NumGetRealPathCalls; -return ProxyFileSystem::getRealPath(Path, Output); +return InMemoryFileSystem::getRealPath(Path, Output); + } + + bool exists(const llvm::Twine &Path) override { +++NumExistsCalls; +return InMemoryFileSystem::exists(Path); } }; + } // namespace TEST(DependencyScanningWorkerFilesystem, CacheStatusFailures) { - auto InMemoryFS = llvm::makeIntrusiveRefCnt(); - auto InstrumentingFS = - llvm::makeIntrusiveRefCnt(InMemoryFS); + llvm::makeIntrusiveRefCnt(); DependencyScanningFilesystemSharedCache SharedCache; DependencyScanningWorkerFilesystem DepFS(SharedC
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
artemcm wrote: > Clang test now looks good to me. Might be nice to drop > `InstrumentingInMemoryFilesystem` in favor of the existing > `InstrumentingFilesystem` (that I added just moments ago, sorry!) wrapped > around a normal `InMemoryFileSystem`, but I'm happy to do that myself in a > follow-up commit. I had to update the commit anyway. Unified on `InstrumentingFilesystem`. https://github.com/llvm/llvm-project/pull/88152 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From 8164aaf2e93dde4761789e6d574088d1cb0e97fc Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Tue, 9 Apr 2024 09:37:09 -0700 Subject: [PATCH] [clang][deps] Overload 'Filesystem::exists' in 'DependencyScanningFilesystem' to have it use cached `status` As-is, calls to `exists()` fallback on the implementation in 'ProxyFileSystem::exists' which explicitly calls out to the underlying `FS`, which for the 'DependencyScanningFilesystem' (overlay) is the real underlying filesystem. Instead, directly overloading 'exists' allows us to have it rely on the cached `status` behavior used elsewhere by the 'DependencyScanningFilesystem'. --- .../DependencyScanningFilesystem.h| 4 + .../DependencyScanningFilesystem.cpp | 11 ++ .../DependencyScanningFilesystemTest.cpp | 53 +-- .../Support/VirtualFileSystemTest.cpp | 140 +- 4 files changed, 125 insertions(+), 83 deletions(-) diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 8b6f149c7cb266..f7b4510d7f7beb 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -365,6 +365,10 @@ class DependencyScanningWorkerFilesystem /// false if not (i.e. this entry is not a file or its scan fails). bool ensureDirectiveTokensArePopulated(EntryRef Entry); + /// Check whether \p Path exists. By default checks cached result of \c + /// status(), and falls back on FS if unable to do so. + bool exists(const Twine &Path) override; + private: /// For a filename that's not yet associated with any entry in the caches, /// uses the underlying filesystem to either look up the entry based in the diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 84185c931b552c..0cab17a3424406 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -300,6 +300,17 @@ DependencyScanningWorkerFilesystem::status(const Twine &Path) { return Result->getStatus(); } +bool DependencyScanningWorkerFilesystem::exists(const Twine &Path) { + // While some VFS overlay filesystems may implement more-efficient + // mechanisms for `exists` queries, `DependencyScanningWorkerFilesystem` + // typically wraps `RealFileSystem` which does not specialize `exists`, + // so it is not likely to benefit from such optimizations. Instead, + // it is more-valuable to have this query go through the + // cached-`status` code-path of the `DependencyScanningWorkerFilesystem`. + llvm::ErrorOr Status = status(Path); + return Status && Status->exists(); +} + namespace { /// The VFS that is used by clang consumes the \c CachedFileSystemEntry using diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp index 697b7d70ff035a..256dd980b2118f 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp @@ -8,6 +8,7 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/VirtualFileSystem.h" #include "gtest/gtest.h" @@ -15,31 +16,36 @@ using namespace clang::tooling::dependencies; namespace { struct InstrumentingFilesystem -: llvm::RTTIExtends { +: llvm::RTTIExtends { unsigned NumStatusCalls = 0; unsigned NumGetRealPathCalls = 0; + unsigned NumExistsCalls = 0; using llvm::RTTIExtends::RTTIExtends; + llvm::vfs::InMemoryFileSystem>::RTTIExtends; llvm::ErrorOr status(const llvm::Twine &Path) override { ++NumStatusCalls; -return ProxyFileSystem::status(Path); +return InMemoryFileSystem::status(Path); } std::error_code getRealPath(const llvm::Twine &Path, llvm::SmallVectorImpl &Output) override { ++NumGetRealPathCalls; -return ProxyFileSystem::getRealPath(Path, Output); +return InMemoryFileSystem::getRealPath(Path, Output); + } + + bool exists(const llvm::Twine &Path) override { +++NumExistsCalls; +return InMemoryFileSystem::exists(Path); } }; + } // namespace TEST(DependencyScanningWorkerFilesystem, CacheStatusFailures) { - auto InMemoryFS = llvm::makeIntrusiveRefCnt(); - auto InstrumentingFS = - llvm::makeIntrusiveRefCnt(InMemoryFS); + llvm::makeIntrusiveRefCnt(); DependencyScanningFilesystemSharedCache Sha
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From e010a761a34692e5ca1959fc9022d0950e669664 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Tue, 9 Apr 2024 09:37:09 -0700 Subject: [PATCH] [clang][deps] Overload 'Filesystem::exists' in 'DependencyScanningFilesystem' to have it use cached `status` As-is, calls to `exists()` fallback on the implementation in 'ProxyFileSystem::exists' which explicitly calls out to the underlying `FS`, which for the 'DependencyScanningFilesystem' (overlay) is the real underlying filesystem. Instead, directly overloading 'exists' allows us to have it rely on the cached `status` behavior used elsewhere by the 'DependencyScanningFilesystem'. --- .../DependencyScanningFilesystem.h| 4 + .../DependencyScanningFilesystem.cpp | 11 ++ .../DependencyScanningFilesystemTest.cpp | 45 ++ .../Support/VirtualFileSystemTest.cpp | 140 +- 4 files changed, 130 insertions(+), 70 deletions(-) diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 8b6f149c7cb266..f7b4510d7f7beb 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -365,6 +365,10 @@ class DependencyScanningWorkerFilesystem /// false if not (i.e. this entry is not a file or its scan fails). bool ensureDirectiveTokensArePopulated(EntryRef Entry); + /// Check whether \p Path exists. By default checks cached result of \c + /// status(), and falls back on FS if unable to do so. + bool exists(const Twine &Path) override; + private: /// For a filename that's not yet associated with any entry in the caches, /// uses the underlying filesystem to either look up the entry based in the diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 84185c931b552c..0cab17a3424406 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -300,6 +300,17 @@ DependencyScanningWorkerFilesystem::status(const Twine &Path) { return Result->getStatus(); } +bool DependencyScanningWorkerFilesystem::exists(const Twine &Path) { + // While some VFS overlay filesystems may implement more-efficient + // mechanisms for `exists` queries, `DependencyScanningWorkerFilesystem` + // typically wraps `RealFileSystem` which does not specialize `exists`, + // so it is not likely to benefit from such optimizations. Instead, + // it is more-valuable to have this query go through the + // cached-`status` code-path of the `DependencyScanningWorkerFilesystem`. + llvm::ErrorOr Status = status(Path); + return Status && Status->exists(); +} + namespace { /// The VFS that is used by clang consumes the \c CachedFileSystemEntry using diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp index 697b7d70ff035a..ccc02b7b2f09dd 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp @@ -8,6 +8,7 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/VirtualFileSystem.h" #include "gtest/gtest.h" @@ -33,6 +34,27 @@ struct InstrumentingFilesystem return ProxyFileSystem::getRealPath(Path, Output); } }; + +struct InstrumentingInMemoryFilesystem +: llvm::RTTIExtends { + unsigned NumStatCalls = 0; + unsigned NumExistsCalls = 0; + + using llvm::RTTIExtends::RTTIExtends; + + llvm::ErrorOr status(const llvm::Twine &Path) override { +++NumStatCalls; +return InMemoryFileSystem::status(Path); + } + + bool exists(const llvm::Twine &Path) override { +++NumExistsCalls; +return InMemoryFileSystem::exists(Path); + } +}; + } // namespace TEST(DependencyScanningWorkerFilesystem, CacheStatusFailures) { @@ -147,3 +169,26 @@ TEST(DependencyScanningFilesystem, RealPathAndStatusInvariants) { DepFS.status("/bar"); } } + +TEST(DependencyScanningFilesystem, CacheStatOnExists) { + auto InMemoryInstrumentingFS = + llvm::makeIntrusiveRefCnt(); + InMemoryInstrumentingFS->setCurrentWorkingDirectory("/"); + InMemoryInstrumentingFS->addFile("/foo", 0, + llvm::MemoryBuffer::getMemBuffer("")); + InMemoryInstrumentingFS->addFile("/bar", 0, + llvm::MemoryBuffer::getMemBuffer("")); + DependencyScanningFilesystemSharedCache SharedCache; + DependencyS
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From 24e869df273b9d75bb4fdf85f4ee8ab2ddbccc2c Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Tue, 9 Apr 2024 09:37:09 -0700 Subject: [PATCH] [clang][deps] Overload 'Filesystem::exists' in 'DependencyScanningFilesystem' to have it use cached `status` As-is, calls to `exists()` fallback on the implementation in 'ProxyFileSystem::exists' which explicitly calls out to the underlying `FS`, which for the 'DependencyScanningFilesystem' (overlay) is the real underlying filesystem. Instead, directly overloading 'exists' allows us to have it rely on the cached `status` behavior used elsewhere by the 'DependencyScanningFilesystem'. --- .../DependencyScanningFilesystem.h| 4 + .../DependencyScanningFilesystem.cpp | 11 ++ .../DependencyScanningFilesystemTest.cpp | 46 ++ .../Support/VirtualFileSystemTest.cpp | 140 +- 4 files changed, 131 insertions(+), 70 deletions(-) diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 8b6f149c7cb266..f7b4510d7f7beb 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -365,6 +365,10 @@ class DependencyScanningWorkerFilesystem /// false if not (i.e. this entry is not a file or its scan fails). bool ensureDirectiveTokensArePopulated(EntryRef Entry); + /// Check whether \p Path exists. By default checks cached result of \c + /// status(), and falls back on FS if unable to do so. + bool exists(const Twine &Path) override; + private: /// For a filename that's not yet associated with any entry in the caches, /// uses the underlying filesystem to either look up the entry based in the diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 84185c931b552c..0cab17a3424406 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -300,6 +300,17 @@ DependencyScanningWorkerFilesystem::status(const Twine &Path) { return Result->getStatus(); } +bool DependencyScanningWorkerFilesystem::exists(const Twine &Path) { + // While some VFS overlay filesystems may implement more-efficient + // mechanisms for `exists` queries, `DependencyScanningWorkerFilesystem` + // typically wraps `RealFileSystem` which does not specialize `exists`, + // so it is not likely to benefit from such optimizations. Instead, + // it is more-valuable to have this query go through the + // cached-`status` code-path of the `DependencyScanningWorkerFilesystem`. + llvm::ErrorOr Status = status(Path); + return Status && Status->exists(); +} + namespace { /// The VFS that is used by clang consumes the \c CachedFileSystemEntry using diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp index 697b7d70ff035a..67f9ee1a3f97ce 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp @@ -8,6 +8,7 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/VirtualFileSystem.h" #include "gtest/gtest.h" @@ -33,6 +34,28 @@ struct InstrumentingFilesystem return ProxyFileSystem::getRealPath(Path, Output); } }; + + +struct InstrumentingInMemoryFilesystem +: llvm::RTTIExtends { + unsigned NumStatCalls = 0; + unsigned NumExistsCalls = 0; + + using llvm::RTTIExtends::RTTIExtends; + + llvm::ErrorOr status(const llvm::Twine &Path) override { +++NumStatCalls; +return InMemoryFileSystem::status(Path); + } + + bool exists(const llvm::Twine &Path) override { +++NumExistsCalls; +return InMemoryFileSystem::exists(Path); + } +}; + } // namespace TEST(DependencyScanningWorkerFilesystem, CacheStatusFailures) { @@ -147,3 +170,26 @@ TEST(DependencyScanningFilesystem, RealPathAndStatusInvariants) { DepFS.status("/bar"); } } + +TEST(DependencyScanningFilesystem, CacheStatOnExists) { + auto InMemoryInstrumentingFS = + llvm::makeIntrusiveRefCnt(); + InMemoryInstrumentingFS->setCurrentWorkingDirectory("/"); + InMemoryInstrumentingFS->addFile("/foo", 0, + llvm::MemoryBuffer::getMemBuffer("")); + InMemoryInstrumentingFS->addFile("/bar", 0, + llvm::MemoryBuffer::getMemBuffer("")); + DependencyScanningFilesystemSharedCache SharedCache; + Dependenc
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From 12621dc6344335375ac1a5c806d778f1ed15a5ce Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 9 Apr 2024 11:22:44 -0700 Subject: [PATCH 1/2] [llvm][vfs] Make vfs::FileSystem::exists() virtual NFC Allow a vfs::FileSystem to provide a more efficient implementation of exists() if they are able to. The existing FileSystem implementations continue to default to using status() except that overlay, proxy, and redirecting filesystems are taught to forward calls to exists() correctly to their wrapped/external filesystem. --- llvm/include/llvm/Support/VirtualFileSystem.h | 8 +- llvm/lib/Support/VirtualFileSystem.cpp| 56 ++ .../Support/VirtualFileSystemTest.cpp | 165 ++ 3 files changed, 227 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 4b1ca0c3d262b6..0113d6b7da25d3 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -300,8 +300,9 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase, virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output); - /// Check whether a file exists. Provided for convenience. - bool exists(const Twine &Path); + /// Check whether \p Path exists. By default this uses \c status(), but + /// filesystems may provide a more efficient implementation if available. + virtual bool exists(const Twine &Path); /// Is the file mounted on a local filesystem? virtual std::error_code isLocal(const Twine &Path, bool &Result); @@ -386,6 +387,7 @@ class OverlayFileSystem : public RTTIExtends { void pushOverlay(IntrusiveRefCntPtr FS); llvm::ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -439,6 +441,7 @@ class ProxyFileSystem : public RTTIExtends { llvm::ErrorOr status(const Twine &Path) override { return FS->status(Path); } + bool exists(const Twine &Path) override { return FS->exists(Path); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { return FS->openFileForRead(Path); @@ -1044,6 +1047,7 @@ class RedirectingFileSystem bool UseExternalNames, FileSystem &ExternalFS); ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 32b480028e71b4..921af30bfcde9f 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -438,6 +438,15 @@ ErrorOr OverlayFileSystem::status(const Twine &Path) { return make_error_code(llvm::errc::no_such_file_or_directory); } +bool OverlayFileSystem::exists(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { +if ((*I)->exists(Path)) + return true; + } + return false; +} + ErrorOr> OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // FIXME: handle symlinks that cross file systems @@ -2428,6 +2437,53 @@ ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { return S; } +bool RedirectingFileSystem::exists(const Twine &OriginalPath) { + SmallString<256> Path; + OriginalPath.toVector(Path); + + if (makeAbsolute(Path)) +return false; + + if (Redirection == RedirectKind::Fallback) { +// Attempt to find the original file first, only falling back to the +// mapped file if that fails. +if (ExternalFS->exists(Path)) + return true; + } + + ErrorOr Result = lookupPath(Path); + if (!Result) { +// Was not able to map file, fallthrough to using the original path if +// that was the specified redirection type. +if (Redirection == RedirectKind::Fallthrough && +isFileNotFound(Result.getError())) + return ExternalFS->exists(Path); +return false; + } + + std::optional ExtRedirect = Result->getExternalRedirect(); + if (!ExtRedirect) { +assert(isa(Result->E)); +return true; + } + + SmallString<256> RemappedPath((*ExtRedirect).str()); + if (makeAbsolute(RemappedPath)) +return false; + + if (ExternalFS->exists(RemappedPath)) +return true; + + if (Redirection == RedirectKind::Fallthrough) { +// Mapped the file but it wasn't found in the underlying filesystem, +// fallthrough to using the original path if that was the specified +// redirection type. +return ExternalFS->exists(Path); + } + + return false; +} + namespace { /// Provide a file wrapper with an overriden
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From c2b2cd03e1d8f92b1df814e6312158b8820b790d Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 9 Apr 2024 11:22:44 -0700 Subject: [PATCH 1/2] [llvm][vfs] Make vfs::FileSystem::exists() virtual NFC Allow a vfs::FileSystem to provide a more efficient implementation of exists() if they are able to. The existing FileSystem implementations continue to default to using status() except that overlay, proxy, and redirecting filesystems are taught to forward calls to exists() correctly to their wrapped/external filesystem. --- llvm/include/llvm/Support/VirtualFileSystem.h | 8 +- llvm/lib/Support/VirtualFileSystem.cpp| 56 ++ .../Support/VirtualFileSystemTest.cpp | 165 ++ 3 files changed, 227 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 770ca8764426a4..bdc98bfd7d2571 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -300,8 +300,9 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase, virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output) const; - /// Check whether a file exists. Provided for convenience. - bool exists(const Twine &Path); + /// Check whether \p Path exists. By default this uses \c status(), but + /// filesystems may provide a more efficient implementation if available. + virtual bool exists(const Twine &Path); /// Is the file mounted on a local filesystem? virtual std::error_code isLocal(const Twine &Path, bool &Result); @@ -386,6 +387,7 @@ class OverlayFileSystem : public RTTIExtends { void pushOverlay(IntrusiveRefCntPtr FS); llvm::ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -439,6 +441,7 @@ class ProxyFileSystem : public RTTIExtends { llvm::ErrorOr status(const Twine &Path) override { return FS->status(Path); } + bool exists(const Twine &Path) override { return FS->exists(Path); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { return FS->openFileForRead(Path); @@ -1044,6 +1047,7 @@ class RedirectingFileSystem bool UseExternalNames, FileSystem &ExternalFS); ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 057f8eae0552c6..272880ba602b84 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -439,6 +439,15 @@ ErrorOr OverlayFileSystem::status(const Twine &Path) { return make_error_code(llvm::errc::no_such_file_or_directory); } +bool OverlayFileSystem::exists(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { +if ((*I)->exists(Path)) + return true; + } + return false; +} + ErrorOr> OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // FIXME: handle symlinks that cross file systems @@ -2431,6 +2440,53 @@ ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { return S; } +bool RedirectingFileSystem::exists(const Twine &OriginalPath) { + SmallString<256> Path; + OriginalPath.toVector(Path); + + if (makeAbsolute(Path)) +return false; + + if (Redirection == RedirectKind::Fallback) { +// Attempt to find the original file first, only falling back to the +// mapped file if that fails. +if (ExternalFS->exists(Path)) + return true; + } + + ErrorOr Result = lookupPath(Path); + if (!Result) { +// Was not able to map file, fallthrough to using the original path if +// that was the specified redirection type. +if (Redirection == RedirectKind::Fallthrough && +isFileNotFound(Result.getError())) + return ExternalFS->exists(Path); +return false; + } + + std::optional ExtRedirect = Result->getExternalRedirect(); + if (!ExtRedirect) { +assert(isa(Result->E)); +return true; + } + + SmallString<256> RemappedPath((*ExtRedirect).str()); + if (makeAbsolute(RemappedPath)) +return false; + + if (ExternalFS->exists(RemappedPath)) +return true; + + if (Redirection == RedirectKind::Fallthrough) { +// Mapped the file but it wasn't found in the underlying filesystem, +// fallthrough to using the original path if that was the specified +// redirection type. +return ExternalFS->exists(Path); + } + + return false; +} + namespace { /// Provide a file wrapper with an over
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From c2b2cd03e1d8f92b1df814e6312158b8820b790d Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 9 Apr 2024 11:22:44 -0700 Subject: [PATCH 1/2] [llvm][vfs] Make vfs::FileSystem::exists() virtual NFC Allow a vfs::FileSystem to provide a more efficient implementation of exists() if they are able to. The existing FileSystem implementations continue to default to using status() except that overlay, proxy, and redirecting filesystems are taught to forward calls to exists() correctly to their wrapped/external filesystem. --- llvm/include/llvm/Support/VirtualFileSystem.h | 8 +- llvm/lib/Support/VirtualFileSystem.cpp| 56 ++ .../Support/VirtualFileSystemTest.cpp | 165 ++ 3 files changed, 227 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 770ca8764426a4..bdc98bfd7d2571 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -300,8 +300,9 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase, virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output) const; - /// Check whether a file exists. Provided for convenience. - bool exists(const Twine &Path); + /// Check whether \p Path exists. By default this uses \c status(), but + /// filesystems may provide a more efficient implementation if available. + virtual bool exists(const Twine &Path); /// Is the file mounted on a local filesystem? virtual std::error_code isLocal(const Twine &Path, bool &Result); @@ -386,6 +387,7 @@ class OverlayFileSystem : public RTTIExtends { void pushOverlay(IntrusiveRefCntPtr FS); llvm::ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -439,6 +441,7 @@ class ProxyFileSystem : public RTTIExtends { llvm::ErrorOr status(const Twine &Path) override { return FS->status(Path); } + bool exists(const Twine &Path) override { return FS->exists(Path); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { return FS->openFileForRead(Path); @@ -1044,6 +1047,7 @@ class RedirectingFileSystem bool UseExternalNames, FileSystem &ExternalFS); ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 057f8eae0552c6..272880ba602b84 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -439,6 +439,15 @@ ErrorOr OverlayFileSystem::status(const Twine &Path) { return make_error_code(llvm::errc::no_such_file_or_directory); } +bool OverlayFileSystem::exists(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { +if ((*I)->exists(Path)) + return true; + } + return false; +} + ErrorOr> OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // FIXME: handle symlinks that cross file systems @@ -2431,6 +2440,53 @@ ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { return S; } +bool RedirectingFileSystem::exists(const Twine &OriginalPath) { + SmallString<256> Path; + OriginalPath.toVector(Path); + + if (makeAbsolute(Path)) +return false; + + if (Redirection == RedirectKind::Fallback) { +// Attempt to find the original file first, only falling back to the +// mapped file if that fails. +if (ExternalFS->exists(Path)) + return true; + } + + ErrorOr Result = lookupPath(Path); + if (!Result) { +// Was not able to map file, fallthrough to using the original path if +// that was the specified redirection type. +if (Redirection == RedirectKind::Fallthrough && +isFileNotFound(Result.getError())) + return ExternalFS->exists(Path); +return false; + } + + std::optional ExtRedirect = Result->getExternalRedirect(); + if (!ExtRedirect) { +assert(isa(Result->E)); +return true; + } + + SmallString<256> RemappedPath((*ExtRedirect).str()); + if (makeAbsolute(RemappedPath)) +return false; + + if (ExternalFS->exists(RemappedPath)) +return true; + + if (Redirection == RedirectKind::Fallthrough) { +// Mapped the file but it wasn't found in the underlying filesystem, +// fallthrough to using the original path if that was the specified +// redirection type. +return ExternalFS->exists(Path); + } + + return false; +} + namespace { /// Provide a file wrapper with an over
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
@@ -270,6 +270,12 @@ DependencyScanningWorkerFilesystem::status(const Twine &Path) { return Result->getStatus(); } +bool +DependencyScanningWorkerFilesystem::exists(const Twine &Path) { + llvm::ErrorOr Status = status(Path); artemcm wrote: Which optimization are you referring to? https://github.com/llvm/llvm-project/pull/88152 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
@@ -0,0 +1,51 @@ +//===- DependencyScanningFilesystemTest.cpp ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/VirtualFileSystem.h" +#include "gtest/gtest.h" + +using namespace clang::tooling::dependencies; + +namespace { + struct InstrumentingFilesystem + : llvm::RTTIExtends { + unsigned NumStatCalls = 0; + + using llvm::RTTIExtends::RTTIExtends; + + llvm::ErrorOr status(const llvm::Twine &Path) override { + ++NumStatCalls; + return ProxyFileSystem::status(Path); + } + }; + } // namespace + + +TEST(DependencyScanningFilesystem, CacheStatOnExists) { + auto InMemoryFS = llvm::makeIntrusiveRefCnt(); + InMemoryFS->setCurrentWorkingDirectory("/"); + InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer("")); + InMemoryFS->addFile("/bar", 0, llvm::MemoryBuffer::getMemBuffer("")); + + auto InstrumentingFS = +llvm::makeIntrusiveRefCnt(InMemoryFS); + DependencyScanningFilesystemSharedCache SharedCache; + DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS); + + DepFS.status("/foo"); + DepFS.status("/foo"); + DepFS.status("/bar"); + EXPECT_EQ(InstrumentingFS->NumStatCalls, 2u); + + DepFS.exists("/foo"); + DepFS.exists("/bar"); + EXPECT_EQ(InstrumentingFS->NumStatCalls, 2u); artemcm wrote: Gah, was silly to use a ProxyFilesystem as the underlying FS. Fixed, thank you very much for catching. https://github.com/llvm/llvm-project/pull/88152 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From c2b2cd03e1d8f92b1df814e6312158b8820b790d Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 9 Apr 2024 11:22:44 -0700 Subject: [PATCH 1/2] [llvm][vfs] Make vfs::FileSystem::exists() virtual NFC Allow a vfs::FileSystem to provide a more efficient implementation of exists() if they are able to. The existing FileSystem implementations continue to default to using status() except that overlay, proxy, and redirecting filesystems are taught to forward calls to exists() correctly to their wrapped/external filesystem. --- llvm/include/llvm/Support/VirtualFileSystem.h | 8 +- llvm/lib/Support/VirtualFileSystem.cpp| 56 ++ .../Support/VirtualFileSystemTest.cpp | 165 ++ 3 files changed, 227 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 770ca8764426a4..bdc98bfd7d2571 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -300,8 +300,9 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase, virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output) const; - /// Check whether a file exists. Provided for convenience. - bool exists(const Twine &Path); + /// Check whether \p Path exists. By default this uses \c status(), but + /// filesystems may provide a more efficient implementation if available. + virtual bool exists(const Twine &Path); /// Is the file mounted on a local filesystem? virtual std::error_code isLocal(const Twine &Path, bool &Result); @@ -386,6 +387,7 @@ class OverlayFileSystem : public RTTIExtends { void pushOverlay(IntrusiveRefCntPtr FS); llvm::ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -439,6 +441,7 @@ class ProxyFileSystem : public RTTIExtends { llvm::ErrorOr status(const Twine &Path) override { return FS->status(Path); } + bool exists(const Twine &Path) override { return FS->exists(Path); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { return FS->openFileForRead(Path); @@ -1044,6 +1047,7 @@ class RedirectingFileSystem bool UseExternalNames, FileSystem &ExternalFS); ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 057f8eae0552c6..272880ba602b84 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -439,6 +439,15 @@ ErrorOr OverlayFileSystem::status(const Twine &Path) { return make_error_code(llvm::errc::no_such_file_or_directory); } +bool OverlayFileSystem::exists(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { +if ((*I)->exists(Path)) + return true; + } + return false; +} + ErrorOr> OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // FIXME: handle symlinks that cross file systems @@ -2431,6 +2440,53 @@ ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { return S; } +bool RedirectingFileSystem::exists(const Twine &OriginalPath) { + SmallString<256> Path; + OriginalPath.toVector(Path); + + if (makeAbsolute(Path)) +return false; + + if (Redirection == RedirectKind::Fallback) { +// Attempt to find the original file first, only falling back to the +// mapped file if that fails. +if (ExternalFS->exists(Path)) + return true; + } + + ErrorOr Result = lookupPath(Path); + if (!Result) { +// Was not able to map file, fallthrough to using the original path if +// that was the specified redirection type. +if (Redirection == RedirectKind::Fallthrough && +isFileNotFound(Result.getError())) + return ExternalFS->exists(Path); +return false; + } + + std::optional ExtRedirect = Result->getExternalRedirect(); + if (!ExtRedirect) { +assert(isa(Result->E)); +return true; + } + + SmallString<256> RemappedPath((*ExtRedirect).str()); + if (makeAbsolute(RemappedPath)) +return false; + + if (ExternalFS->exists(RemappedPath)) +return true; + + if (Redirection == RedirectKind::Fallthrough) { +// Mapped the file but it wasn't found in the underlying filesystem, +// fallthrough to using the original path if that was the specified +// redirection type. +return ExternalFS->exists(Path); + } + + return false; +} + namespace { /// Provide a file wrapper with an over
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From c2b2cd03e1d8f92b1df814e6312158b8820b790d Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 9 Apr 2024 11:22:44 -0700 Subject: [PATCH 1/2] [llvm][vfs] Make vfs::FileSystem::exists() virtual NFC Allow a vfs::FileSystem to provide a more efficient implementation of exists() if they are able to. The existing FileSystem implementations continue to default to using status() except that overlay, proxy, and redirecting filesystems are taught to forward calls to exists() correctly to their wrapped/external filesystem. --- llvm/include/llvm/Support/VirtualFileSystem.h | 8 +- llvm/lib/Support/VirtualFileSystem.cpp| 56 ++ .../Support/VirtualFileSystemTest.cpp | 165 ++ 3 files changed, 227 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 770ca8764426a4..bdc98bfd7d2571 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -300,8 +300,9 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase, virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output) const; - /// Check whether a file exists. Provided for convenience. - bool exists(const Twine &Path); + /// Check whether \p Path exists. By default this uses \c status(), but + /// filesystems may provide a more efficient implementation if available. + virtual bool exists(const Twine &Path); /// Is the file mounted on a local filesystem? virtual std::error_code isLocal(const Twine &Path, bool &Result); @@ -386,6 +387,7 @@ class OverlayFileSystem : public RTTIExtends { void pushOverlay(IntrusiveRefCntPtr FS); llvm::ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -439,6 +441,7 @@ class ProxyFileSystem : public RTTIExtends { llvm::ErrorOr status(const Twine &Path) override { return FS->status(Path); } + bool exists(const Twine &Path) override { return FS->exists(Path); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { return FS->openFileForRead(Path); @@ -1044,6 +1047,7 @@ class RedirectingFileSystem bool UseExternalNames, FileSystem &ExternalFS); ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 057f8eae0552c6..272880ba602b84 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -439,6 +439,15 @@ ErrorOr OverlayFileSystem::status(const Twine &Path) { return make_error_code(llvm::errc::no_such_file_or_directory); } +bool OverlayFileSystem::exists(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { +if ((*I)->exists(Path)) + return true; + } + return false; +} + ErrorOr> OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // FIXME: handle symlinks that cross file systems @@ -2431,6 +2440,53 @@ ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { return S; } +bool RedirectingFileSystem::exists(const Twine &OriginalPath) { + SmallString<256> Path; + OriginalPath.toVector(Path); + + if (makeAbsolute(Path)) +return false; + + if (Redirection == RedirectKind::Fallback) { +// Attempt to find the original file first, only falling back to the +// mapped file if that fails. +if (ExternalFS->exists(Path)) + return true; + } + + ErrorOr Result = lookupPath(Path); + if (!Result) { +// Was not able to map file, fallthrough to using the original path if +// that was the specified redirection type. +if (Redirection == RedirectKind::Fallthrough && +isFileNotFound(Result.getError())) + return ExternalFS->exists(Path); +return false; + } + + std::optional ExtRedirect = Result->getExternalRedirect(); + if (!ExtRedirect) { +assert(isa(Result->E)); +return true; + } + + SmallString<256> RemappedPath((*ExtRedirect).str()); + if (makeAbsolute(RemappedPath)) +return false; + + if (ExternalFS->exists(RemappedPath)) +return true; + + if (Redirection == RedirectKind::Fallthrough) { +// Mapped the file but it wasn't found in the underlying filesystem, +// fallthrough to using the original path if that was the specified +// redirection type. +return ExternalFS->exists(Path); + } + + return false; +} + namespace { /// Provide a file wrapper with an over
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
artemcm wrote: > I'd like to see a unit test specific to `DependencyScanningFilesystem`, > similar to what I have here: #68645. Done! Added one in `DependencyScanningFilesystemTest.cpp`. Thank you. https://github.com/llvm/llvm-project/pull/88152 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From c2b2cd03e1d8f92b1df814e6312158b8820b790d Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 9 Apr 2024 11:22:44 -0700 Subject: [PATCH 1/2] [llvm][vfs] Make vfs::FileSystem::exists() virtual NFC Allow a vfs::FileSystem to provide a more efficient implementation of exists() if they are able to. The existing FileSystem implementations continue to default to using status() except that overlay, proxy, and redirecting filesystems are taught to forward calls to exists() correctly to their wrapped/external filesystem. --- llvm/include/llvm/Support/VirtualFileSystem.h | 8 +- llvm/lib/Support/VirtualFileSystem.cpp| 56 ++ .../Support/VirtualFileSystemTest.cpp | 165 ++ 3 files changed, 227 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 770ca8764426a4..bdc98bfd7d2571 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -300,8 +300,9 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase, virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output) const; - /// Check whether a file exists. Provided for convenience. - bool exists(const Twine &Path); + /// Check whether \p Path exists. By default this uses \c status(), but + /// filesystems may provide a more efficient implementation if available. + virtual bool exists(const Twine &Path); /// Is the file mounted on a local filesystem? virtual std::error_code isLocal(const Twine &Path, bool &Result); @@ -386,6 +387,7 @@ class OverlayFileSystem : public RTTIExtends { void pushOverlay(IntrusiveRefCntPtr FS); llvm::ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -439,6 +441,7 @@ class ProxyFileSystem : public RTTIExtends { llvm::ErrorOr status(const Twine &Path) override { return FS->status(Path); } + bool exists(const Twine &Path) override { return FS->exists(Path); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { return FS->openFileForRead(Path); @@ -1044,6 +1047,7 @@ class RedirectingFileSystem bool UseExternalNames, FileSystem &ExternalFS); ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 057f8eae0552c6..272880ba602b84 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -439,6 +439,15 @@ ErrorOr OverlayFileSystem::status(const Twine &Path) { return make_error_code(llvm::errc::no_such_file_or_directory); } +bool OverlayFileSystem::exists(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { +if ((*I)->exists(Path)) + return true; + } + return false; +} + ErrorOr> OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // FIXME: handle symlinks that cross file systems @@ -2431,6 +2440,53 @@ ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { return S; } +bool RedirectingFileSystem::exists(const Twine &OriginalPath) { + SmallString<256> Path; + OriginalPath.toVector(Path); + + if (makeAbsolute(Path)) +return false; + + if (Redirection == RedirectKind::Fallback) { +// Attempt to find the original file first, only falling back to the +// mapped file if that fails. +if (ExternalFS->exists(Path)) + return true; + } + + ErrorOr Result = lookupPath(Path); + if (!Result) { +// Was not able to map file, fallthrough to using the original path if +// that was the specified redirection type. +if (Redirection == RedirectKind::Fallthrough && +isFileNotFound(Result.getError())) + return ExternalFS->exists(Path); +return false; + } + + std::optional ExtRedirect = Result->getExternalRedirect(); + if (!ExtRedirect) { +assert(isa(Result->E)); +return true; + } + + SmallString<256> RemappedPath((*ExtRedirect).str()); + if (makeAbsolute(RemappedPath)) +return false; + + if (ExternalFS->exists(RemappedPath)) +return true; + + if (Redirection == RedirectKind::Fallthrough) { +// Mapped the file but it wasn't found in the underlying filesystem, +// fallthrough to using the original path if that was the specified +// redirection type. +return ExternalFS->exists(Path); + } + + return false; +} + namespace { /// Provide a file wrapper with an over
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From c2b2cd03e1d8f92b1df814e6312158b8820b790d Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 9 Apr 2024 11:22:44 -0700 Subject: [PATCH 1/2] [llvm][vfs] Make vfs::FileSystem::exists() virtual NFC Allow a vfs::FileSystem to provide a more efficient implementation of exists() if they are able to. The existing FileSystem implementations continue to default to using status() except that overlay, proxy, and redirecting filesystems are taught to forward calls to exists() correctly to their wrapped/external filesystem. --- llvm/include/llvm/Support/VirtualFileSystem.h | 8 +- llvm/lib/Support/VirtualFileSystem.cpp| 56 ++ .../Support/VirtualFileSystemTest.cpp | 165 ++ 3 files changed, 227 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 770ca8764426a4..bdc98bfd7d2571 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -300,8 +300,9 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase, virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output) const; - /// Check whether a file exists. Provided for convenience. - bool exists(const Twine &Path); + /// Check whether \p Path exists. By default this uses \c status(), but + /// filesystems may provide a more efficient implementation if available. + virtual bool exists(const Twine &Path); /// Is the file mounted on a local filesystem? virtual std::error_code isLocal(const Twine &Path, bool &Result); @@ -386,6 +387,7 @@ class OverlayFileSystem : public RTTIExtends { void pushOverlay(IntrusiveRefCntPtr FS); llvm::ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -439,6 +441,7 @@ class ProxyFileSystem : public RTTIExtends { llvm::ErrorOr status(const Twine &Path) override { return FS->status(Path); } + bool exists(const Twine &Path) override { return FS->exists(Path); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { return FS->openFileForRead(Path); @@ -1044,6 +1047,7 @@ class RedirectingFileSystem bool UseExternalNames, FileSystem &ExternalFS); ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 057f8eae0552c6..272880ba602b84 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -439,6 +439,15 @@ ErrorOr OverlayFileSystem::status(const Twine &Path) { return make_error_code(llvm::errc::no_such_file_or_directory); } +bool OverlayFileSystem::exists(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { +if ((*I)->exists(Path)) + return true; + } + return false; +} + ErrorOr> OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // FIXME: handle symlinks that cross file systems @@ -2431,6 +2440,53 @@ ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { return S; } +bool RedirectingFileSystem::exists(const Twine &OriginalPath) { + SmallString<256> Path; + OriginalPath.toVector(Path); + + if (makeAbsolute(Path)) +return false; + + if (Redirection == RedirectKind::Fallback) { +// Attempt to find the original file first, only falling back to the +// mapped file if that fails. +if (ExternalFS->exists(Path)) + return true; + } + + ErrorOr Result = lookupPath(Path); + if (!Result) { +// Was not able to map file, fallthrough to using the original path if +// that was the specified redirection type. +if (Redirection == RedirectKind::Fallthrough && +isFileNotFound(Result.getError())) + return ExternalFS->exists(Path); +return false; + } + + std::optional ExtRedirect = Result->getExternalRedirect(); + if (!ExtRedirect) { +assert(isa(Result->E)); +return true; + } + + SmallString<256> RemappedPath((*ExtRedirect).str()); + if (makeAbsolute(RemappedPath)) +return false; + + if (ExternalFS->exists(RemappedPath)) +return true; + + if (Redirection == RedirectKind::Fallthrough) { +// Mapped the file but it wasn't found in the underlying filesystem, +// fallthrough to using the original path if that was the specified +// redirection type. +return ExternalFS->exists(Path); + } + + return false; +} + namespace { /// Provide a file wrapper with an over
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From c2b2cd03e1d8f92b1df814e6312158b8820b790d Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 9 Apr 2024 11:22:44 -0700 Subject: [PATCH 1/2] [llvm][vfs] Make vfs::FileSystem::exists() virtual NFC Allow a vfs::FileSystem to provide a more efficient implementation of exists() if they are able to. The existing FileSystem implementations continue to default to using status() except that overlay, proxy, and redirecting filesystems are taught to forward calls to exists() correctly to their wrapped/external filesystem. --- llvm/include/llvm/Support/VirtualFileSystem.h | 8 +- llvm/lib/Support/VirtualFileSystem.cpp| 56 ++ .../Support/VirtualFileSystemTest.cpp | 165 ++ 3 files changed, 227 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 770ca8764426a4..bdc98bfd7d2571 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -300,8 +300,9 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase, virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output) const; - /// Check whether a file exists. Provided for convenience. - bool exists(const Twine &Path); + /// Check whether \p Path exists. By default this uses \c status(), but + /// filesystems may provide a more efficient implementation if available. + virtual bool exists(const Twine &Path); /// Is the file mounted on a local filesystem? virtual std::error_code isLocal(const Twine &Path, bool &Result); @@ -386,6 +387,7 @@ class OverlayFileSystem : public RTTIExtends { void pushOverlay(IntrusiveRefCntPtr FS); llvm::ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -439,6 +441,7 @@ class ProxyFileSystem : public RTTIExtends { llvm::ErrorOr status(const Twine &Path) override { return FS->status(Path); } + bool exists(const Twine &Path) override { return FS->exists(Path); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { return FS->openFileForRead(Path); @@ -1044,6 +1047,7 @@ class RedirectingFileSystem bool UseExternalNames, FileSystem &ExternalFS); ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 057f8eae0552c6..272880ba602b84 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -439,6 +439,15 @@ ErrorOr OverlayFileSystem::status(const Twine &Path) { return make_error_code(llvm::errc::no_such_file_or_directory); } +bool OverlayFileSystem::exists(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { +if ((*I)->exists(Path)) + return true; + } + return false; +} + ErrorOr> OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // FIXME: handle symlinks that cross file systems @@ -2431,6 +2440,53 @@ ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { return S; } +bool RedirectingFileSystem::exists(const Twine &OriginalPath) { + SmallString<256> Path; + OriginalPath.toVector(Path); + + if (makeAbsolute(Path)) +return false; + + if (Redirection == RedirectKind::Fallback) { +// Attempt to find the original file first, only falling back to the +// mapped file if that fails. +if (ExternalFS->exists(Path)) + return true; + } + + ErrorOr Result = lookupPath(Path); + if (!Result) { +// Was not able to map file, fallthrough to using the original path if +// that was the specified redirection type. +if (Redirection == RedirectKind::Fallthrough && +isFileNotFound(Result.getError())) + return ExternalFS->exists(Path); +return false; + } + + std::optional ExtRedirect = Result->getExternalRedirect(); + if (!ExtRedirect) { +assert(isa(Result->E)); +return true; + } + + SmallString<256> RemappedPath((*ExtRedirect).str()); + if (makeAbsolute(RemappedPath)) +return false; + + if (ExternalFS->exists(RemappedPath)) +return true; + + if (Redirection == RedirectKind::Fallthrough) { +// Mapped the file but it wasn't found in the underlying filesystem, +// fallthrough to using the original path if that was the specified +// redirection type. +return ExternalFS->exists(Path); + } + + return false; +} + namespace { /// Provide a file wrapper with an over
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From c2b2cd03e1d8f92b1df814e6312158b8820b790d Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 9 Apr 2024 11:22:44 -0700 Subject: [PATCH 1/2] [llvm][vfs] Make vfs::FileSystem::exists() virtual NFC Allow a vfs::FileSystem to provide a more efficient implementation of exists() if they are able to. The existing FileSystem implementations continue to default to using status() except that overlay, proxy, and redirecting filesystems are taught to forward calls to exists() correctly to their wrapped/external filesystem. --- llvm/include/llvm/Support/VirtualFileSystem.h | 8 +- llvm/lib/Support/VirtualFileSystem.cpp| 56 ++ .../Support/VirtualFileSystemTest.cpp | 165 ++ 3 files changed, 227 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 770ca8764426a4..bdc98bfd7d2571 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -300,8 +300,9 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase, virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output) const; - /// Check whether a file exists. Provided for convenience. - bool exists(const Twine &Path); + /// Check whether \p Path exists. By default this uses \c status(), but + /// filesystems may provide a more efficient implementation if available. + virtual bool exists(const Twine &Path); /// Is the file mounted on a local filesystem? virtual std::error_code isLocal(const Twine &Path, bool &Result); @@ -386,6 +387,7 @@ class OverlayFileSystem : public RTTIExtends { void pushOverlay(IntrusiveRefCntPtr FS); llvm::ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -439,6 +441,7 @@ class ProxyFileSystem : public RTTIExtends { llvm::ErrorOr status(const Twine &Path) override { return FS->status(Path); } + bool exists(const Twine &Path) override { return FS->exists(Path); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { return FS->openFileForRead(Path); @@ -1044,6 +1047,7 @@ class RedirectingFileSystem bool UseExternalNames, FileSystem &ExternalFS); ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 057f8eae0552c6..272880ba602b84 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -439,6 +439,15 @@ ErrorOr OverlayFileSystem::status(const Twine &Path) { return make_error_code(llvm::errc::no_such_file_or_directory); } +bool OverlayFileSystem::exists(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { +if ((*I)->exists(Path)) + return true; + } + return false; +} + ErrorOr> OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // FIXME: handle symlinks that cross file systems @@ -2431,6 +2440,53 @@ ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { return S; } +bool RedirectingFileSystem::exists(const Twine &OriginalPath) { + SmallString<256> Path; + OriginalPath.toVector(Path); + + if (makeAbsolute(Path)) +return false; + + if (Redirection == RedirectKind::Fallback) { +// Attempt to find the original file first, only falling back to the +// mapped file if that fails. +if (ExternalFS->exists(Path)) + return true; + } + + ErrorOr Result = lookupPath(Path); + if (!Result) { +// Was not able to map file, fallthrough to using the original path if +// that was the specified redirection type. +if (Redirection == RedirectKind::Fallthrough && +isFileNotFound(Result.getError())) + return ExternalFS->exists(Path); +return false; + } + + std::optional ExtRedirect = Result->getExternalRedirect(); + if (!ExtRedirect) { +assert(isa(Result->E)); +return true; + } + + SmallString<256> RemappedPath((*ExtRedirect).str()); + if (makeAbsolute(RemappedPath)) +return false; + + if (ExternalFS->exists(RemappedPath)) +return true; + + if (Redirection == RedirectKind::Fallthrough) { +// Mapped the file but it wasn't found in the underlying filesystem, +// fallthrough to using the original path if that was the specified +// redirection type. +return ExternalFS->exists(Path); + } + + return false; +} + namespace { /// Provide a file wrapper with an over
[clang] [llvm] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm updated https://github.com/llvm/llvm-project/pull/88152 >From fdf95d6c9186b91cf39a988e3baaa21a9cabe6a1 Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Thu, 6 Oct 2022 15:58:23 -0700 Subject: [PATCH 1/2] [llvm][vfs] Make vfs::FileSystem::exists() virtual NFC Allow a vfs::FileSystem to provide a more efficient implementation of exists() if they are able to. The existing FileSystem implementations continue to default to using status() except that overlay, proxy, and redirecting filesystems are taught to forward calls to exists() correctly to their wrapped/external filesystem. --- llvm/include/llvm/Support/VirtualFileSystem.h | 8 +- llvm/lib/Support/VirtualFileSystem.cpp| 57 +++ .../Support/VirtualFileSystemTest.cpp | 160 ++ 3 files changed, 223 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 770ca8764426a4..bdc98bfd7d2571 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -300,8 +300,9 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase, virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output) const; - /// Check whether a file exists. Provided for convenience. - bool exists(const Twine &Path); + /// Check whether \p Path exists. By default this uses \c status(), but + /// filesystems may provide a more efficient implementation if available. + virtual bool exists(const Twine &Path); /// Is the file mounted on a local filesystem? virtual std::error_code isLocal(const Twine &Path, bool &Result); @@ -386,6 +387,7 @@ class OverlayFileSystem : public RTTIExtends { void pushOverlay(IntrusiveRefCntPtr FS); llvm::ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -439,6 +441,7 @@ class ProxyFileSystem : public RTTIExtends { llvm::ErrorOr status(const Twine &Path) override { return FS->status(Path); } + bool exists(const Twine &Path) override { return FS->exists(Path); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { return FS->openFileForRead(Path); @@ -1044,6 +1047,7 @@ class RedirectingFileSystem bool UseExternalNames, FileSystem &ExternalFS); ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 057f8eae0552c6..ee679f14bf2a37 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -439,6 +439,15 @@ ErrorOr OverlayFileSystem::status(const Twine &Path) { return make_error_code(llvm::errc::no_such_file_or_directory); } +bool OverlayFileSystem::exists(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { +if ((*I)->exists(Path)) + return true; + } + return false; +} + ErrorOr> OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // FIXME: handle symlinks that cross file systems @@ -2431,6 +2440,54 @@ ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { return S; } +bool RedirectingFileSystem::exists(const Twine &OriginalPath) { + SmallString<256> CanonicalPath; + OriginalPath.toVector(CanonicalPath); + + if (makeCanonical(CanonicalPath)) +return false; + + if (Redirection == RedirectKind::Fallback) { +// Attempt to find the original file first, only falling back to the +// mapped file if that fails. +if (ExternalFS->exists(CanonicalPath)) + return true; + } + + ErrorOr Result = + lookupPath(CanonicalPath); + if (!Result) { +// Was not able to map file, fallthrough to using the original path if +// that was the specified redirection type. +if (Redirection == RedirectKind::Fallthrough && +isFileNotFound(Result.getError())) + return ExternalFS->exists(CanonicalPath); +return false; + } + + Optional ExtRedirect = Result->getExternalRedirect(); + if (!ExtRedirect) { +assert(isa(Result->E)); +return true; + } + + SmallString<256> CanonicalRemappedPath((*ExtRedirect).str()); + if (makeCanonical(CanonicalRemappedPath)) +return false; + + if (ExternalFS->exists(CanonicalRemappedPath)) +return true; + + if (Redirection == RedirectKind::Fallthrough) { +// Mapped the file but it wasn't found in the underlying filesystem, +// fallthrough to using the original path if that was the specified +// redirection type. +return ExternalFS->exists(Canon
[clang] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (PR #88152)
https://github.com/artemcm created https://github.com/llvm/llvm-project/pull/88152 As-is, calls to `exists()` fallback on the implementation in `ProxyFileSystem::exists` which explicitly calls out to the underlying `FS`, which for the `DependencyScanningFilesystem` (overlay) is the real underlying filesystem. Instead, directly overloading `exists` allows us to have it rely on the cached `status` behavior used elsewhere by the `DependencyScanningFilesystem`. >From 8be194ac570d702b5df2fdcd42868122b0ae16dd Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Tue, 9 Apr 2024 09:37:09 -0700 Subject: [PATCH] [clang][deps] Overload 'Filesystem::exists' in 'DependencyScanningFilesystem' to have it use cached `status` As-is, calls to `exists()` fallback on the implementation in 'ProxyFileSystem::exists' which explicitly calls out to the underlying `FS`, which for the 'DependencyScanningFilesystem' (overlay) is the real underlying filesystem. Instead, directly overloading 'exists' allows us to have it rely on the cached `status` behavior used elsewhere by the 'DependencyScanningFilesystem'. --- .../DependencyScanning/DependencyScanningFilesystem.h | 4 .../DependencyScanning/DependencyScanningFilesystem.cpp | 6 ++ 2 files changed, 10 insertions(+) diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 9a522a3e2fe252..4fdfebada5b7f7 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -365,6 +365,10 @@ class DependencyScanningWorkerFilesystem return LocalCache.insertEntryForFilename(Filename, Entry); } + /// Check whether \p Path exists. By default checks cached result of \c status(), + /// and falls back on FS if unable to do so. + bool exists(const Twine &Path) override; + /// Returns entry associated with the filename in the shared cache if there is /// some. Otherwise, constructs new one with the given error code, associates /// it with the filename and returns the result. diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 9b7812a1adb9e3..174edc98da5877 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -270,6 +270,12 @@ DependencyScanningWorkerFilesystem::status(const Twine &Path) { return Result->getStatus(); } +bool +DependencyScanningWorkerFilesystem::exists(const Twine &Path) { + auto Status = status(Path); + return Status && Status->exists(); +} + namespace { /// The VFS that is used by clang consumes the \c CachedFileSystemEntry using ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][DependencyScanner] Remove unused -fmodule-map-file arguments (PR #80090)
https://github.com/artemcm approved this pull request. Nice. https://github.com/llvm/llvm-project/pull/80090 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits