Skip to content

clang: Make the type_info builtin declaration a singleton #151277

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
Aug 4, 2025

Conversation

matts1
Copy link
Contributor

@matts1 matts1 commented Jul 30, 2025

This fixes an ambiguous type type_info when you try and reference the type_info type while using clang modulemaps with -fms-compatibility enabled

Fixes #38400

@matts1 matts1 force-pushed the push-sruqkvlnlwpk branch from 3c7dab0 to b35918a Compare July 30, 2025 05:42
@matts1 matts1 changed the title clang: Fix ambiguous type_info when using clang modules with clang: Fix ambiguous type_info when using clang modules with -fms-compatibility Jul 30, 2025
@matts1
Copy link
Contributor Author

matts1 commented Jul 30, 2025

@atetubou FYI

@matts1 matts1 changed the title clang: Fix ambiguous type_info when using clang modules with -fms-compatibility clang: Make the type_info builtin declaration a singleton Jul 30, 2025
@matts1 matts1 force-pushed the push-sruqkvlnlwpk branch 2 times, most recently from 4e8387c to 47d44b2 Compare July 30, 2025 06:46
@matts1 matts1 marked this pull request as ready for review July 30, 2025 06:46
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules labels Jul 30, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 30, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-modules

Author: Matt (matts1)

Changes

This fixes an ambiguous type type_info when you try and reference the type_info type while using clang modulemaps with -fms-compatibility enabled

Fixes #38400


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

6 Files Affected:

  • (modified) clang/include/clang/AST/ASTContext.h (+12)
  • (modified) clang/include/clang/AST/DeclID.h (+3)
  • (modified) clang/lib/Sema/Sema.cpp (+1-3)
  • (modified) clang/lib/Serialization/ASTReader.cpp (+3)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (+2)
  • (added) clang/test/Modules/pr151277.cpp (+15)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 0273109f8a698..3d70654314939 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1290,6 +1290,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
   // Implicitly-declared type 'struct _GUID'.
   mutable TagDecl *MSGuidTagDecl = nullptr;
 
+  // Implicitly-declared type 'struct type_info'.
+  mutable TagDecl *MSTypeInfoTagDecl = nullptr;
+
   /// Keep track of CUDA/HIP device-side variables ODR-used by host code.
   /// This does not include extern shared variables used by device host
   /// functions as addresses of shared variables are per warp, therefore
@@ -2381,6 +2384,15 @@ class ASTContext : public RefCountedBase<ASTContext> {
     return getTagDeclType(MSGuidTagDecl);
   }
 
+  /// Retrieve the implicitly-predeclared 'struct type_info' declaration.
+  TagDecl *getMSTypeInfoTagDecl() const {
+    // Lazily create this type on demand - it's only needed for MS builds.
+    if (!MSTypeInfoTagDecl) {
+      MSTypeInfoTagDecl = buildImplicitRecord("type_info");
+    }
+    return MSTypeInfoTagDecl;
+  }
+
   /// Return whether a declaration to a builtin is allowed to be
   /// overloaded/redeclared.
   bool canBuiltinBeRedeclared(const FunctionDecl *) const;
diff --git a/clang/include/clang/AST/DeclID.h b/clang/include/clang/AST/DeclID.h
index 384f7b031e007..47ae05b2747ae 100644
--- a/clang/include/clang/AST/DeclID.h
+++ b/clang/include/clang/AST/DeclID.h
@@ -77,6 +77,9 @@ enum PredefinedDeclIDs {
   /// The internal '__NSConstantString' tag type.
   PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID,
 
+  /// The predeclared 'type_info' struct.
+  PREDEF_DECL_BUILTIN_MS_TYPE_INFO_TAG_ID,
+
 #define BuiltinTemplate(BTName) PREDEF_DECL##BTName##_ID,
 #include "clang/Basic/BuiltinTemplates.inc"
 
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index d50eeff0e4b3b..a1f707e601db3 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -443,9 +443,7 @@ void Sema::Initialize() {
   if (getLangOpts().MSVCCompat) {
     if (getLangOpts().CPlusPlus &&
         IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end())
-      PushOnScopeChains(
-          Context.buildImplicitRecord("type_info", TagTypeKind::Class),
-          TUScope);
+      PushOnScopeChains(Context.getMSTypeInfoTagDecl(), TUScope);
 
     addImplicitTypedef("size_t", Context.getSizeType());
   }
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f896f9f11c2b3..44b48b9b4711a 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -8318,6 +8318,9 @@ Decl *ASTReader::getPredefinedDecl(PredefinedDeclIDs ID) {
     NewLoaded = Context.getCFConstantStringTagDecl();
     break;
 
+  case PREDEF_DECL_BUILTIN_MS_TYPE_INFO_TAG_ID:
+    return Context.getMSTypeInfoTagDecl();
+
 #define BuiltinTemplate(BTName)                                                \
   case PREDEF_DECL##BTName##_ID:                                               \
     if (Context.Decl##BTName)                                                  \
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index a6957e54b66f1..2b40be3b7349d 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -5618,6 +5618,8 @@ void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {
                      PREDEF_DECL_BUILTIN_MS_VA_LIST_ID);
   RegisterPredefDecl(Context.MSGuidTagDecl,
                      PREDEF_DECL_BUILTIN_MS_GUID_ID);
+  RegisterPredefDecl(Context.MSTypeInfoTagDecl,
+                     PREDEF_DECL_BUILTIN_MS_TYPE_INFO_TAG_ID);
   RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID);
   RegisterPredefDecl(Context.CFConstantStringTypeDecl,
                      PREDEF_DECL_CF_CONSTANT_STRING_ID);
diff --git a/clang/test/Modules/pr151277.cpp b/clang/test/Modules/pr151277.cpp
new file mode 100644
index 0000000000000..2428e854d6edf
--- /dev/null
+++ b/clang/test/Modules/pr151277.cpp
@@ -0,0 +1,15 @@
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -I%t -emit-module -o %t/a.pcm -fmodules %t/module.modulemap -fno-implicit-modules -fmodule-name=a -x c++-header -fms-compatibility
+// RUN: %clang_cc1 -I%t -emit-module -o %t/b.pcm -fmodules %t/module.modulemap -fno-implicit-modules -fmodule-name=b -x c++-header -fms-compatibility -fmodule-file=%t/a.pcm
+
+//--- module.modulemap
+module a { header "a.h" }
+module b { header "b.h" }
+
+//--- a.h
+type_info* foo;
+
+//--- b.h
+type_info* bar;
+

This solves the "reference to `type_info` is ambiguous" error you get when attempting to reference `type_info` while depending on a module with `-fms-compatibility` enabled.

Fixes llvm#38400
@matts1 matts1 force-pushed the push-sruqkvlnlwpk branch from 47d44b2 to ec1e606 Compare July 30, 2025 06:52
@shafik shafik requested review from AaronBallman, erichkeane and ChuanqiXu9 and removed request for AaronBallman July 30, 2025 18:19
Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems completely reasonable to me, though Aaron should take a look. We typically don't maintain serialization/module compatibility between released versions, so I don't think this is an issue.

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@matts1
Copy link
Contributor Author

matts1 commented Aug 4, 2025

What's required to get this merged? It's blocking some of my work so I'd prefer it merged sooner rather than later.

@erichkeane
Copy link
Collaborator

What's required to get this merged? It's blocking some of my work so I'd prefer it merged sooner rather than later.

Sorry, wasn't clear you didn't have commit rights already. I'll merge this for you.

@erichkeane erichkeane merged commit 2e404d1 into llvm:main Aug 4, 2025
10 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Aug 4, 2025

LLVM Buildbot has detected a new failure on builder openmp-offload-amdgpu-runtime-2 running on rocm-worker-hw-02 while building clang at step 6 "test-openmp".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/10/builds/10818

Here is the relevant piece of the build log for the reference
Step 6 (test-openmp) failure: test (failure)
******************** TEST 'libarcher :: races/critical-unrelated.c' FAILED ********************
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 13
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/./bin/clang -fopenmp  -gdwarf-4 -O1 -fsanitize=thread  -I /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests -I /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src   /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/critical-unrelated.c -o /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/critical-unrelated.c.tmp -latomic && env TSAN_OPTIONS='ignore_noninstrumented_modules=0:ignore_noninstrumented_modules=1' /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/deflake.bash /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/critical-unrelated.c.tmp 2>&1 | tee /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/critical-unrelated.c.tmp.log | /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/./bin/FileCheck /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/critical-unrelated.c
# executed command: /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/./bin/clang -fopenmp -gdwarf-4 -O1 -fsanitize=thread -I /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests -I /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/runtime/src /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/critical-unrelated.c -o /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/critical-unrelated.c.tmp -latomic
# note: command had no output on stdout or stderr
# executed command: env TSAN_OPTIONS=ignore_noninstrumented_modules=0:ignore_noninstrumented_modules=1 /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/deflake.bash /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/critical-unrelated.c.tmp
# note: command had no output on stdout or stderr
# executed command: tee /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/runtimes/runtimes-bins/openmp/tools/archer/tests/races/Output/critical-unrelated.c.tmp.log
# note: command had no output on stdout or stderr
# executed command: /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/./bin/FileCheck /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/critical-unrelated.c
# .---command stderr------------
# | /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/critical-unrelated.c:41:11: error: CHECK: expected string not found in input
# | // CHECK: ThreadSanitizer: reported {{[1-7]}} warnings
# |           ^
# | <stdin>:23:5: note: scanning from here
# | DONE
# |     ^
# | <stdin>:24:1: note: possible intended match here
# | ThreadSanitizer: thread T4 finished with ignores enabled, created at:
# | ^
# | 
# | Input file: <stdin>
# | Check file: /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/critical-unrelated.c
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |             .
# |             .
# |             .
# |            18:  #0 pthread_create /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp:1090:3 (critical-unrelated.c.tmp+0xa33fa) 
# |            19:  #1 __kmp_create_worker z_Linux_util.cpp (libomp.so+0xcb352) 
# |            20:  
# |            21: SUMMARY: ThreadSanitizer: data race /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/openmp/tools/archer/tests/races/critical-unrelated.c:29:8 in main.omp_outlined_debug__ 
# |            22: ================== 
# |            23: DONE 
# | check:41'0         X error: no match found
# |            24: ThreadSanitizer: thread T4 finished with ignores enabled, created at: 
# | check:41'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:41'1     ?                                                                      possible intended match
# |            25:  #0 pthread_create /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp:1090:3 (critical-unrelated.c.tmp+0xa33fa) 
# | check:41'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            26:  #1 __kmp_create_worker z_Linux_util.cpp (libomp.so+0xcb352) 
# | check:41'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            27:  
...

@matts1 matts1 deleted the push-sruqkvlnlwpk branch August 4, 2025 23:42
@bolshakov-a
Copy link
Contributor

bolshakov-a commented Aug 5, 2025

I've noticed that this PR changed the tag type kind of the implicit type_info from class to struct. I don't know if it has any bad consequences, but it looks inconsistent with the definition of std::type_info.

Seems like it is a class in MSVC: https://godbolt.org/z/zj9asdE1a

erichkeane added a commit that referenced this pull request Aug 5, 2025
It was brought up on #151277 that the patch changes type_info from class
to struct. While I couldn't find a way to test/notice this, this patch
changes it to a class.

While I'm here, I am also removing unnecessary/against coding standard
curley brackets.
@erichkeane
Copy link
Collaborator

I've noticed that this PR changed the tag type kind of the implicit type_info from class to struct. I don't know if it has any bad consequences, but it looks inconsistent with the definition of std::type_info.

Seems like it is a class in MSVC: https://godbolt.org/z/zj9asdE1a

Oh, interesting! class vs struct can mangle differently in certain ABIs (and IIRC, Windows is one that it does!). That said, we mangle type_info special, so there is no real way I could find to notice the difference between class-vs-struct here.

Either way, fixed here: 16766b3

@bolshakov-a
Copy link
Contributor

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" 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.

[Modules TS] MSVC std library produces ambiguous type_info reference when including module with ms-compatibility
7 participants