@@ -134,6 +134,34 @@ static void optimizeDiagnosticOpts(DiagnosticOptions &Opts,
134134 Opts.Remarks .clear ();
135135}
136136
137+ static void optimizeCWD (CowCompilerInvocation &BuildInvocation, StringRef CWD) {
138+ BuildInvocation.getMutFileSystemOpts ().WorkingDir .clear ();
139+ if (BuildInvocation.getCodeGenOpts ().DwarfVersion ) {
140+ // It is necessary to explicitly set the DebugCompilationDir
141+ // to a common directory (e.g. root) if IgnoreCWD is true.
142+ // When IgnoreCWD is true, the module's content should not
143+ // depend on the current working directory. However, if dwarf
144+ // information is needed (when CGOpts.DwarfVersion is
145+ // non-zero), then CGOpts.DebugCompilationDir must be
146+ // populated, because otherwise the current working directory
147+ // will be automatically embedded in the dwarf information in
148+ // the pcm, contradicting the assumption that it is safe to
149+ // ignore the CWD. Thus in such cases,
150+ // CGOpts.DebugCompilationDir is explicitly set to a common
151+ // directory.
152+ // FIXME: It is still excessive to create a copy of
153+ // CodeGenOpts for each module. Since we do not modify the
154+ // CodeGenOpts otherwise per module, the following code
155+ // ends up generating identical CodeGenOpts for each module
156+ // with DebugCompilationDir pointing to the root directory.
157+ // We can optimize this away by creating a _single_ copy of
158+ // CodeGenOpts whose DebugCompilationDir points to the root
159+ // directory and reuse it across modules.
160+ BuildInvocation.getMutCodeGenOpts ().DebugCompilationDir =
161+ llvm::sys::path::root_path (CWD);
162+ }
163+ }
164+
137165static std::vector<std::string> splitString (std::string S, char Separator) {
138166 SmallVector<StringRef> Segments;
139167 StringRef (S).split (Segments, Separator, /* MaxSplit=*/ -1 , /* KeepEmpty=*/ false );
@@ -534,14 +562,12 @@ static std::string getModuleContextHash(const ModuleDeps &MD,
534562 HashBuilder.add (getClangFullRepositoryVersion ());
535563 HashBuilder.add (serialization::VERSION_MAJOR, serialization::VERSION_MINOR);
536564 llvm::ErrorOr<std::string> CWD = VFS.getCurrentWorkingDirectory ();
537- auto &FSOpts = const_cast <FileSystemOptions &>(CI.getFileSystemOpts ());
538565 if (CWD && !IgnoreCWD)
539566 HashBuilder.add (*CWD);
540- else
541- FSOpts.WorkingDir .clear ();
542567
543568 // Save and restore options that should not affect the hash, e.g. the exact
544569 // contents of input files, or prefix mappings.
570+ auto &FSOpts = const_cast <FileSystemOptions &>(CI.getFileSystemOpts ());
545571 auto &FEOpts = const_cast <FrontendOptions &>(CI.getFrontendOpts ());
546572 auto &CASOpts = const_cast <CASOptions &>(CI.getCASOpts ());
547573 llvm::SaveAndRestore RestoreCASFSRootID (FSOpts.CASFileSystemRootID , {});
@@ -594,9 +620,7 @@ static void checkCompileCacheKeyMatch(cas::ObjectStore &CAS,
594620#endif
595621
596622void ModuleDepCollector::associateWithContextHash (
597- const CowCompilerInvocation &CI, ModuleDeps &Deps) {
598- bool IgnoreCWD = any (OptimizeArgs & ScanningOptimizations::IgnoreCWD) &&
599- isSafeToIgnoreCWD (CI);
623+ const CowCompilerInvocation &CI, bool IgnoreCWD, ModuleDeps &Deps) {
600624 Deps.ID .ContextHash =
601625 getModuleContextHash (Deps, CI, EagerLoadModules, IgnoreCWD,
602626 ScanInstance.getVirtualFileSystem ());
@@ -810,6 +834,7 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
810834 }
811835 }
812836
837+ bool IgnoreCWD = false ;
813838 CowCompilerInvocation CI =
814839 MDC.getInvocationAdjustedForModuleBuildWithoutOutputs (
815840 MD, [&](CowCompilerInvocation &BuildInvocation) {
@@ -819,10 +844,22 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
819844 *MDC.ScanInstance .getASTReader (), *MF,
820845 MDC.PrebuiltModuleVFSMap ,
821846 MDC.OptimizeArgs );
847+
822848 if (any (MDC.OptimizeArgs & ScanningOptimizations::SystemWarnings))
823849 optimizeDiagnosticOpts (
824850 BuildInvocation.getMutDiagnosticOpts (),
825851 BuildInvocation.getFrontendOpts ().IsSystemModule );
852+
853+ IgnoreCWD =
854+ any (MDC.OptimizeArgs & ScanningOptimizations::IgnoreCWD) &&
855+ isSafeToIgnoreCWD (BuildInvocation);
856+ if (IgnoreCWD) {
857+ llvm::ErrorOr<std::string> CWD =
858+ MDC.ScanInstance .getVirtualFileSystem ()
859+ .getCurrentWorkingDirectory ();
860+ if (CWD)
861+ optimizeCWD (BuildInvocation, *CWD);
862+ }
826863 });
827864
828865 auto &Diags = MDC.ScanInstance .getDiagnostics ();
@@ -837,7 +874,7 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
837874 MD.ModuleCacheKey = Key->toString ();
838875 }
839876
840- MDC.associateWithContextHash (CI, MD);
877+ MDC.associateWithContextHash (CI, IgnoreCWD, MD);
841878
842879 // Finish the compiler invocation. Requires dependencies and the context hash.
843880 MDC.addOutputPaths (CI, MD);
0 commit comments