From ec1e6069deb5c5ed161942089457ee05386d692e Mon Sep 17 00:00:00 2001 From: Matt Stark Date: Wed, 30 Jul 2025 15:26:44 +1000 Subject: [PATCH] [clang][modules] Make the type_info builtin declaration a singleton. 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 #38400 --- clang/docs/ReleaseNotes.rst | 2 ++ clang/include/clang/AST/ASTContext.h | 12 ++++++++++++ clang/include/clang/AST/DeclID.h | 3 +++ clang/lib/Sema/Sema.cpp | 4 +--- clang/lib/Serialization/ASTReader.cpp | 3 +++ clang/lib/Serialization/ASTWriter.cpp | 2 ++ clang/test/Modules/pr151277.cpp | 15 +++++++++++++++ 7 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 clang/test/Modules/pr151277.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 9d9a0008e0001..93e18132b279a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -137,6 +137,8 @@ Bug Fixes in This Version Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Fix an ambiguous reference to the builtin `type_info` (available when using + `-fms-compatibility`) with modules. (#GH38400) Bug Fixes to Attribute Support ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 { // 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 { 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; +