Skip to content

Conversation

@cyndyishida
Copy link
Member

When debugging issues related to invalidation for implicit module compilations, it can be helpful to consult the PCM to see what the saved mtime was.

…file-info"

When debugging issues related to invalidation for implicit module
compilations, it can be helpful to consult the pcm what the saved mtime
was.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:modules C++20 modules and Clang Header Modules labels Dec 19, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 19, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-modules

Author: Cyndy Ishida (cyndyishida)

Changes

When debugging issues related to invalidation for implicit module compilations, it can be helpful to consult the PCM to see what the saved mtime was.


Full diff: https://github.com/llvm/llvm-project/pull/173120.diff

6 Files Affected:

  • (modified) clang/include/clang/Serialization/ASTReader.h (+1-1)
  • (modified) clang/lib/DependencyScanning/DependencyScannerImpl.cpp (+1-1)
  • (modified) clang/lib/Frontend/FrontendActions.cpp (+4-1)
  • (modified) clang/lib/Serialization/ASTReader.cpp (+2)
  • (added) clang/test/Modules/module-file-info-mtime.m (+24)
  • (modified) clang/test/Modules/module_file_info.m (+9-9)
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index d276f0d21b958..d0f7de873c178 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -254,7 +254,7 @@ class ASTReaderListener {
   /// \returns true to continue receiving the next input file, false to stop.
   virtual bool visitInputFileAsRequested(StringRef FilenameAsRequested,
                                          StringRef Filename, bool isSystem,
-                                         bool isOverridden,
+                                         bool isOverridden, time_t StoredTime,
                                          bool isExplicitModule) {
     return true;
   }
diff --git a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp
index 201230d7d6a8e..6fdccb65c1626 100644
--- a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp
+++ b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp
@@ -111,7 +111,7 @@ class PrebuiltModuleListener : public ASTReaderListener {
   /// considered stable.
   bool visitInputFileAsRequested(StringRef FilenameAsRequested,
                                  StringRef Filename, bool isSystem,
-                                 bool isOverridden,
+                                 bool isOverridden, time_t StoredTime,
                                  bool isExplicitModule) override {
     if (StableDirs.empty())
       return false;
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index e0c1d304e8290..f03b14058db40 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -798,7 +798,7 @@ namespace {
     /// \returns true to continue receiving the next input file, false to stop.
     bool visitInputFileAsRequested(StringRef FilenameAsRequested,
                                    StringRef Filename, bool isSystem,
-                                   bool isOverridden,
+                                   bool isOverridden, time_t StoredTime,
                                    bool isExplicitModule) override {
 
       Out.indent(2) << "Input file: " << FilenameAsRequested;
@@ -823,6 +823,9 @@ namespace {
 
       Out << "\n";
 
+      if (StoredTime > 0)
+        Out.indent(4) << "MTime: " << llvm::itostr(StoredTime) << "\n";
+
       return true;
     }
 
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index aec61322fb8be..f8067005a2752 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -5980,6 +5980,7 @@ bool ASTReader::readASTFileControlBlock(
         case INPUT_FILE_HASH:
           break;
         case INPUT_FILE:
+          time_t StoredTime = static_cast<time_t>(Record[2]);
           bool Overridden = static_cast<bool>(Record[3]);
           auto [UnresolvedFilenameAsRequested, UnresolvedFilename] =
               getUnresolvedInputFilenames(Record, Blob);
@@ -5995,6 +5996,7 @@ bool ASTReader::readASTFileControlBlock(
           }
           shouldContinue = Listener.visitInputFileAsRequested(
               *FilenameAsRequestedBuf, Filename, isSystemFile, Overridden,
+              StoredTime,
               /*IsExplicitModule=*/false);
           break;
         }
diff --git a/clang/test/Modules/module-file-info-mtime.m b/clang/test/Modules/module-file-info-mtime.m
new file mode 100644
index 0000000000000..c577207ef4287
--- /dev/null
+++ b/clang/test/Modules/module-file-info-mtime.m
@@ -0,0 +1,24 @@
+// Hardcode the mtime for a input file & check that is emitted in pcm during a implicit module invocation.
+
+// RUN: rm -fr %t
+// RUN: split-file %s %t
+// RUN: touch -m -a -t 202508011501 %t/BuildDir/A/A.h
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fdisable-module-hash -fimplicit-module-maps %t/client.m -fsyntax-only -I%t/BuildDir
+// RUN: %clang_cc1 -module-file-info %t/cache/A.pcm | FileCheck %s
+
+// CHECK: Module name: A
+// CHECK: Module map file: {{.*}}module.modulemap
+// CHECK: Input file: {{.*}}A.h
+// CHECK-NEXT: MTime: 1754085660
+
+
+//--- BuildDir/A/module.modulemap
+module A [system] {
+  umbrella "."
+}
+
+//--- BuildDir/A/A.h
+typedef int local_t;
+
+//--- client.m
+#import <A/A.h>
diff --git a/clang/test/Modules/module_file_info.m b/clang/test/Modules/module_file_info.m
index f5ba25d54b97c..2aa6c3feb3c6b 100644
--- a/clang/test/Modules/module_file_info.m
+++ b/clang/test/Modules/module_file_info.m
@@ -48,15 +48,15 @@
 // MACROS-NEXT: -DBLARG
 // MACROS-NEXT: -DWIBBLE=WOBBLE
 // CHECK: Input file: {{.*}}module.modulemap
-// CHECK-NEXT: Input file: {{.*}}module.private.modulemap
-// CHECK-NEXT: Input file: {{.*}}DependsOnModule.h
-// CHECK-NEXT: Input file: {{.*}}module.modulemap
-// CHECK-NEXT: Input file: {{.*}}other.h
-// CHECK-NEXT: Input file: {{.*}}not_cxx.h
-// CHECK-NEXT: Input file: {{.*}}not_coroutines.h
-// CHECK-NEXT: Input file: {{.*}}SubFramework.h
-// CHECK-NEXT: Input file: {{.*}}Other.h
-// CHECK-NEXT: Input file: {{.*}}DependsOnModulePrivate.h
+// CHECK: Input file: {{.*}}module.private.modulemap
+// CHECK: Input file: {{.*}}DependsOnModule.h
+// CHECK: Input file: {{.*}}module.modulemap
+// CHECK: Input file: {{.*}}other.h
+// CHECK: Input file: {{.*}}not_cxx.h
+// CHECK: Input file: {{.*}}not_coroutines.h
+// CHECK: Input file: {{.*}}SubFramework.h
+// CHECK: Input file: {{.*}}Other.h
+// CHECK: Input file: {{.*}}DependsOnModulePrivate.h
 
 // CHECK: Diagnostic options:
 // CHECK:   IgnoreWarnings: Yes

@github-actions
Copy link

github-actions bot commented Dec 19, 2025

🐧 Linux x64 Test Results

  • 112138 tests passed
  • 4531 tests skipped

✅ The build succeeded and all tests passed.

@github-actions
Copy link

github-actions bot commented Dec 19, 2025

🪟 Windows x64 Test Results

  • 53107 tests passed
  • 2091 tests skipped

✅ The build succeeded and all tests passed.

@cyndyishida cyndyishida merged commit 36c27c6 into llvm:main Dec 20, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants