Skip to content

release/20.x: [PATCH] [clang][modules] Fix serialization and de-serialization of PCH module file refs (#105994) (#132802) #133198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 1, 2025

Conversation

llvmbot
Copy link
Member

@llvmbot llvmbot commented Mar 27, 2025

Backport cca0f81

Requested by: @ChuanqiXu9

@llvmbot
Copy link
Member Author

llvmbot commented Mar 27, 2025

@ChuanqiXu9 What do you think about merging this PR to the release branch?

@llvmbot llvmbot requested a review from ChuanqiXu9 March 27, 2025 02:43
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:modules C++20 modules and Clang Header Modules labels Mar 27, 2025
@llvmbot
Copy link
Member Author

llvmbot commented Mar 27, 2025

@llvm/pr-subscribers-clang

Author: None (llvmbot)

Changes

Backport cca0f81

Requested by: @ChuanqiXu9


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

2 Files Affected:

  • (modified) clang/lib/Serialization/ASTReader.cpp (+3-3)
  • (added) clang/test/Modules/MixedModulePrecompile.cpp (+63)
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f524251c48ddd..427b3c82c4737 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -9616,9 +9616,9 @@ ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &M, unsigned ID) const {
     return I == GlobalSubmoduleMap.end() ? nullptr : I->second;
   } else {
     // It's a prefix (preamble, PCH, ...). Look it up by index.
-    unsigned IndexFromEnd = ID >> 1;
+   int IndexFromEnd = static_cast<int>(ID >> 1);
     assert(IndexFromEnd && "got reference to unknown module file");
-    return getModuleManager().pch_modules().end()[-IndexFromEnd];
+    return getModuleManager().pch_modules().end()[-static_cast<int>(IndexFromEnd)];
   }
 }
 
@@ -9636,7 +9636,7 @@ unsigned ASTReader::getModuleFileID(ModuleFile *M) {
   auto PCHModules = getModuleManager().pch_modules();
   auto I = llvm::find(PCHModules, M);
   assert(I != PCHModules.end() && "emitting reference to unknown file");
-  return (I - PCHModules.end()) << 1;
+  return std::distance(I, PCHModules.end()) << 1;
 }
 
 std::optional<ASTSourceDescriptor> ASTReader::getSourceDescriptor(unsigned ID) {
diff --git a/clang/test/Modules/MixedModulePrecompile.cpp b/clang/test/Modules/MixedModulePrecompile.cpp
new file mode 100644
index 0000000000000..473817ef71de6
--- /dev/null
+++ b/clang/test/Modules/MixedModulePrecompile.cpp
@@ -0,0 +1,63 @@
+// Tests mixed usage of precompiled headers and modules.
+//
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -x c++-header -emit-pch %t/a.hpp \
+// RUN: -o %t/a.pch
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Part1.cppm \
+// RUN: -include-pch %t/a.pch -o %t/Part1.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Part2.cppm \
+// RUN: -include-pch %t/a.pch -o %t/Part2.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Part3.cppm \
+// RUN: -include-pch %t/a.pch -o %t/Part3.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Part4.cppm \
+// RUN: -include-pch %t/a.pch -o %t/Part4.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface \
+// RUN: -fmodule-file=mod:part1=%t/Part1.pcm \
+// RUN: -fmodule-file=mod:part2=%t/Part2.pcm \
+// RUN: -fmodule-file=mod:part3=%t/Part3.pcm \
+// RUN: -fmodule-file=mod:part4=%t/Part4.pcm \
+// RUN: %t/Mod.cppm \
+// RUN: -include-pch %t/a.pch -o %t/Mod.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj \
+// RUN: -main-file-name Mod.cppm \
+// RUN: -fmodule-file=mod:part1=%t/Part1.pcm \
+// RUN: -fmodule-file=mod:part2=%t/Part2.pcm \
+// RUN: -fmodule-file=mod:part3=%t/Part3.pcm \
+// RUN: -fmodule-file=mod:part4=%t/Part4.pcm \
+// RUN: -x pcm %t/Mod.pcm \
+// RUN: -include-pch %t/a.pch -o %t/Mod.o
+
+
+//--- a.hpp
+#pragma once
+
+class a {
+  virtual ~a();
+  a() {}
+};
+
+//--- Part1.cppm
+export module mod:part1;
+
+//--- Part2.cppm
+export module mod:part2;
+
+//--- Part3.cppm
+export module mod:part3;
+
+//--- Part4.cppm
+export module mod:part4;
+
+//--- Mod.cppm
+export module mod;
+export import :part1;
+export import :part2;
+export import :part3;
+export import :part4;
+

@llvmbot
Copy link
Member Author

llvmbot commented Mar 27, 2025

@llvm/pr-subscribers-clang-modules

Author: None (llvmbot)

Changes

Backport cca0f81

Requested by: @ChuanqiXu9


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

2 Files Affected:

  • (modified) clang/lib/Serialization/ASTReader.cpp (+3-3)
  • (added) clang/test/Modules/MixedModulePrecompile.cpp (+63)
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f524251c48ddd..427b3c82c4737 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -9616,9 +9616,9 @@ ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &M, unsigned ID) const {
     return I == GlobalSubmoduleMap.end() ? nullptr : I->second;
   } else {
     // It's a prefix (preamble, PCH, ...). Look it up by index.
-    unsigned IndexFromEnd = ID >> 1;
+   int IndexFromEnd = static_cast<int>(ID >> 1);
     assert(IndexFromEnd && "got reference to unknown module file");
-    return getModuleManager().pch_modules().end()[-IndexFromEnd];
+    return getModuleManager().pch_modules().end()[-static_cast<int>(IndexFromEnd)];
   }
 }
 
@@ -9636,7 +9636,7 @@ unsigned ASTReader::getModuleFileID(ModuleFile *M) {
   auto PCHModules = getModuleManager().pch_modules();
   auto I = llvm::find(PCHModules, M);
   assert(I != PCHModules.end() && "emitting reference to unknown file");
-  return (I - PCHModules.end()) << 1;
+  return std::distance(I, PCHModules.end()) << 1;
 }
 
 std::optional<ASTSourceDescriptor> ASTReader::getSourceDescriptor(unsigned ID) {
diff --git a/clang/test/Modules/MixedModulePrecompile.cpp b/clang/test/Modules/MixedModulePrecompile.cpp
new file mode 100644
index 0000000000000..473817ef71de6
--- /dev/null
+++ b/clang/test/Modules/MixedModulePrecompile.cpp
@@ -0,0 +1,63 @@
+// Tests mixed usage of precompiled headers and modules.
+//
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -x c++-header -emit-pch %t/a.hpp \
+// RUN: -o %t/a.pch
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Part1.cppm \
+// RUN: -include-pch %t/a.pch -o %t/Part1.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Part2.cppm \
+// RUN: -include-pch %t/a.pch -o %t/Part2.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Part3.cppm \
+// RUN: -include-pch %t/a.pch -o %t/Part3.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Part4.cppm \
+// RUN: -include-pch %t/a.pch -o %t/Part4.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface \
+// RUN: -fmodule-file=mod:part1=%t/Part1.pcm \
+// RUN: -fmodule-file=mod:part2=%t/Part2.pcm \
+// RUN: -fmodule-file=mod:part3=%t/Part3.pcm \
+// RUN: -fmodule-file=mod:part4=%t/Part4.pcm \
+// RUN: %t/Mod.cppm \
+// RUN: -include-pch %t/a.pch -o %t/Mod.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj \
+// RUN: -main-file-name Mod.cppm \
+// RUN: -fmodule-file=mod:part1=%t/Part1.pcm \
+// RUN: -fmodule-file=mod:part2=%t/Part2.pcm \
+// RUN: -fmodule-file=mod:part3=%t/Part3.pcm \
+// RUN: -fmodule-file=mod:part4=%t/Part4.pcm \
+// RUN: -x pcm %t/Mod.pcm \
+// RUN: -include-pch %t/a.pch -o %t/Mod.o
+
+
+//--- a.hpp
+#pragma once
+
+class a {
+  virtual ~a();
+  a() {}
+};
+
+//--- Part1.cppm
+export module mod:part1;
+
+//--- Part2.cppm
+export module mod:part2;
+
+//--- Part3.cppm
+export module mod:part3;
+
+//--- Part4.cppm
+export module mod:part4;
+
+//--- Mod.cppm
+export module mod;
+export import :part1;
+export import :part2;
+export import :part3;
+export import :part4;
+

@ChuanqiXu9
Copy link
Member

This is a simple fix to a problem with a (relatively) long history. I think it is good to backport this.

@tstellar tstellar moved this from Needs Triage to Needs Review in LLVM Release Status Mar 28, 2025
@tstellar tstellar moved this from Needs Review to Needs Merge in LLVM Release Status Mar 31, 2025
…H module file refs (llvm#105994) (llvm#132802)

The File ID is incorrectly calculated, resulting in an out-of-bounds
access. The test code is more complex because the File fetching only
happens in specific scenarios.

---------

Co-authored-by: ShaderKeeper <no-reply@shaderkeeper.com>
Co-authored-by: Chuanqi Xu <yedeng.yd@linux.alibaba.com>
(cherry picked from commit cca0f81)
@tstellar tstellar merged commit e740675 into llvm:release/20.x Apr 1, 2025
7 of 10 checks passed
@github-project-automation github-project-automation bot moved this from Needs Merge to Done in LLVM Release Status Apr 1, 2025
Copy link

github-actions bot commented Apr 1, 2025

@ChuanqiXu9 (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR.

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
Development

Successfully merging this pull request may close these issues.

4 participants