[clang] [lldb] Serialize `#pragma redefine_extname` into precompiled headers. (PR #186755)

via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 25 05:33:46 PDT 2026


https://github.com/divVerent updated https://github.com/llvm/llvm-project/pull/186755

>From 0c19e37c2528172c221b2a7ae4da4762ef8fbfd4 Mon Sep 17 00:00:00 2001
From: Rudolf Polzer <rpolzer at google.com>
Date: Fri, 13 Mar 2026 04:18:35 -0700
Subject: [PATCH 1/5] Serialize #pragma redefine_extname into precompiled
 headers.

Also deserialize them back again on reading.
---
 clang/include/clang/Sema/ExternalSemaSource.h | 10 +++++
 .../clang/Sema/MultiplexExternalSemaSource.h  | 11 +++++
 clang/include/clang/Sema/Sema.h               |  4 ++
 .../include/clang/Serialization/ASTBitCodes.h |  3 ++
 clang/include/clang/Serialization/ASTReader.h | 12 ++++-
 .../lib/Sema/MultiplexExternalSemaSource.cpp  |  6 +++
 clang/lib/Sema/Sema.cpp                       |  9 ++++
 clang/lib/Sema/SemaDecl.cpp                   |  4 ++
 clang/lib/Serialization/ASTReader.cpp         | 44 +++++++++++++++++++
 clang/lib/Serialization/ASTWriter.cpp         | 26 +++++++++++
 clang/test/PCH/pragma-redefine-extname.c      | 14 ++++++
 clang/test/PCH/pragma-redefine-extname.h      |  5 +++
 .../Plugins/ExpressionParser/Clang/ASTUtils.h |  7 +++
 13 files changed, 154 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/PCH/pragma-redefine-extname.c
 create mode 100644 clang/test/PCH/pragma-redefine-extname.h

diff --git a/clang/include/clang/Sema/ExternalSemaSource.h b/clang/include/clang/Sema/ExternalSemaSource.h
index 11cd69df88d1c..e7e66bea8c6bd 100644
--- a/clang/include/clang/Sema/ExternalSemaSource.h
+++ b/clang/include/clang/Sema/ExternalSemaSource.h
@@ -163,6 +163,16 @@ class ExternalSemaSource : public ExternalASTSource {
   virtual void ReadWeakUndeclaredIdentifiers(
                  SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) {}
 
+  /// Read the set of #pragma redefine_extname'd, undeclared identifiers known
+  /// to the external Sema source.
+  ///
+  /// The external source should append its own #pragma redefine_extname'd,
+  /// undeclared identifiers to the given vector. Note that this routine may be
+  /// invoked multiple times; the external source should take care not to
+  /// introduce the same identifiers repeatedly.
+  virtual void ReadExtnameUndeclaredIdentifiers(
+      SmallVectorImpl<std::pair<IdentifierInfo *, AsmLabelAttr *>> &EI) {}
+
   /// Read the set of used vtables known to the external Sema source.
   ///
   /// The external source should append its own used vtables to the given
diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h
index 8bcaa121b3039..12015724b39f4 100644
--- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -310,6 +310,17 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {
   void ReadWeakUndeclaredIdentifiers(
            SmallVectorImpl<std::pair<IdentifierInfo*, WeakInfo> > &WI) override;
 
+  /// Read the set of #pragma redefine_extname'd, undeclared identifiers known
+  /// to the external Sema source.
+  ///
+  /// The external source should append its own #pragma redefine_extname'd,
+  /// undeclared identifiers to the given vector. Note that this routine may be
+  /// invoked multiple times; the external source should take care not to
+  /// introduce the same identifiers repeatedly.
+  void ReadExtnameUndeclaredIdentifiers(
+      SmallVectorImpl<std::pair<IdentifierInfo *, AsmLabelAttr *>> &EI)
+      override;
+
   /// Read the set of used vtables known to the external Sema source.
   ///
   /// The external source should append its own used vtables to the given
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 832e46286194a..638c1be16f835 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -968,6 +968,10 @@ class Sema final : public SemaBase {
   /// Load weak undeclared identifiers from the external source.
   void LoadExternalWeakUndeclaredIdentifiers();
 
+  /// Load #pragma redefine_extname'd undeclared identifiers from the external
+  /// source.
+  void LoadExternalExtnameUndeclaredIdentifiers();
+
   /// Determine if VD, which must be a variable or function, is an external
   /// symbol that nonetheless can't be referenced from outside this translation
   /// unit because its type has no linkage and it's not extern "C".
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 5db0b08f877ce..e44c2b55df1f9 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -748,6 +748,9 @@ enum ASTRecordTypes {
 
   /// Record code for #pragma clang riscv intrinsic vector.
   RISCV_VECTOR_INTRINSICS_PRAGMA = 78,
+
+  /// Record code for extname-redefined undeclared identifiers.
+  EXTNAME_UNDECLARED_IDENTIFIERS = 79,
 };
 
 /// Record types used within a source manager block.
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index 14f7d8a69a1b3..9bcf6459c7e56 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -965,9 +965,15 @@ class ASTReader
   SmallVector<serialization::SelectorID, 64> ReferencedSelectorsData;
 
   /// A snapshot of Sema's weak undeclared identifier tracking, for
-  /// generating warnings.
+  /// generating warnings. Note that this vector has 3n entries, being triplets
+  /// of the form C name, alias if any, and source location.
   SmallVector<serialization::IdentifierID, 64> WeakUndeclaredIdentifiers;
 
+  /// A snapshot of Sema's #redefine_extname'd undeclared identifier tracking,
+  /// for generating warnings. Note that this vector has 3n entries, being
+  /// triplets in the order of C name, asm name, and source location.
+  SmallVector<serialization::IdentifierID, 64> ExtnameUndeclaredIdentifiers;
+
   /// The IDs of type aliases for ext_vectors that exist in the chain.
   ///
   /// Used by Sema for finding sugared names for ext_vectors in diagnostics.
@@ -2356,6 +2362,10 @@ class ASTReader
   void ReadWeakUndeclaredIdentifiers(
       SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo>> &WeakIDs) override;
 
+  void ReadExtnameUndeclaredIdentifiers(
+      SmallVectorImpl<std::pair<IdentifierInfo *, AsmLabelAttr *>> &ExtnameIDs)
+      override;
+
   void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override;
 
   void ReadPendingInstantiations(
diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index 1f040c879d724..be9582ce501fe 100644
--- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -317,6 +317,12 @@ void MultiplexExternalSemaSource::ReadWeakUndeclaredIdentifiers(
     Sources[i]->ReadWeakUndeclaredIdentifiers(WI);
 }
 
+void MultiplexExternalSemaSource::ReadExtnameUndeclaredIdentifiers(
+    SmallVectorImpl<std::pair<IdentifierInfo *, AsmLabelAttr *>> &EI) {
+  for (size_t i = 0; i < Sources.size(); ++i)
+    Sources[i]->ReadExtnameUndeclaredIdentifiers(EI);
+}
+
 void MultiplexExternalSemaSource::ReadUsedVTables(
                                   SmallVectorImpl<ExternalVTableUse> &VTables) {
   for(size_t i = 0; i < Sources.size(); ++i)
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 8b1d0398cf65d..7eeffc0c73ce4 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1083,6 +1083,15 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() {
     (void)WeakUndeclaredIdentifiers[WeakID.first].insert(WeakID.second);
 }
 
+void Sema::LoadExternalExtnameUndeclaredIdentifiers() {
+  if (!ExternalSource)
+    return;
+
+  SmallVector<std::pair<IdentifierInfo *, AsmLabelAttr *>, 4> ExtnameIDs;
+  ExternalSource->ReadExtnameUndeclaredIdentifiers(ExtnameIDs);
+  for (auto &ExtnameID : ExtnameIDs)
+    ExtnameUndeclaredIdentifiers[ExtnameID.first] = ExtnameID.second;
+}
 
 typedef llvm::DenseMap<const CXXRecordDecl*, bool> RecordCompleteMap;
 
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 054b664ca0a8b..96175dc1acc34 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8232,6 +8232,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
     }
   }
 
+  LoadExternalExtnameUndeclaredIdentifiers();
+
   if (Expr *E = D.getAsmLabel()) {
     // The parser guarantees this is a string.
     StringLiteral *SE = cast<StringLiteral>(E);
@@ -10536,6 +10538,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
                        isMemberSpecialization ||
                        isFunctionTemplateSpecialization);
 
+  LoadExternalExtnameUndeclaredIdentifiers();
+
   // Handle GNU asm-label extension (encoded as an attribute).
   if (Expr *E = D.getAsmLabel()) {
     // The parser guarantees this is a string.
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 515eaf8d1caed..1c395c2f5dd92 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -19,6 +19,7 @@
 #include "clang/AST/ASTStructuralEquivalence.h"
 #include "clang/AST/ASTUnresolvedSet.h"
 #include "clang/AST/AbstractTypeReader.h"
+#include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
@@ -4028,6 +4029,27 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
       }
       break;
 
+    case EXTNAME_UNDECLARED_IDENTIFIERS:
+      if (Record.size() % 3 != 0)
+        return llvm::createStringError(std::errc::illegal_byte_sequence,
+                                       "invalid extname identifiers record");
+
+      // FIXME: Ignore #pragma redefine_extname'd, undeclared identifiers from
+      // non-original PCH files. This isn't the way to do it :)
+      ExtnameUndeclaredIdentifiers.clear();
+
+      // Translate the #pragma redefine_extname'd, undeclared identifiers into
+      // global IDs.
+      for (unsigned I = 0, N = Record.size(); I < N; /* in loop */) {
+        ExtnameUndeclaredIdentifiers.push_back(
+            getGlobalIdentifierID(F, Record[I++]));
+        ExtnameUndeclaredIdentifiers.push_back(
+            getGlobalIdentifierID(F, Record[I++]));
+        ExtnameUndeclaredIdentifiers.push_back(
+            ReadSourceLocation(F, Record, I).getRawEncoding());
+      }
+      break;
+
     case SELECTOR_OFFSETS: {
       F.SelectorOffsets = (const uint32_t *)Blob.data();
       F.LocalNumSelectors = Record[0];
@@ -9687,6 +9709,28 @@ void ASTReader::ReadWeakUndeclaredIdentifiers(
   WeakUndeclaredIdentifiers.clear();
 }
 
+void ASTReader::ReadExtnameUndeclaredIdentifiers(
+    SmallVectorImpl<std::pair<IdentifierInfo *, AsmLabelAttr *>> &ExtnameIDs) {
+  if (ExtnameUndeclaredIdentifiers.empty())
+    return;
+
+  for (unsigned I = 0, N = ExtnameUndeclaredIdentifiers.size(); I < N;
+       /*none*/) {
+    IdentifierInfo *NameId =
+        DecodeIdentifierInfo(ExtnameUndeclaredIdentifiers[I++]);
+    IdentifierInfo *ExtnameId =
+        DecodeIdentifierInfo(ExtnameUndeclaredIdentifiers[I++]);
+    SourceLocation Loc =
+        SourceLocation::getFromRawEncoding(ExtnameUndeclaredIdentifiers[I++]);
+    AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
+        getContext(), ExtnameId->getName(),
+        AttributeCommonInfo(ExtnameId, SourceRange(Loc),
+                            AttributeCommonInfo::Form::Pragma()));
+    ExtnameIDs.push_back(std::make_pair(NameId, Attr));
+  }
+  ExtnameUndeclaredIdentifiers.clear();
+}
+
 void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {
   for (unsigned Idx = 0, N = VTableUses.size(); Idx < N; /* In loop */) {
     ExternalVTableUse VT;
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index e21a86b688dbf..bdbf6676c83a0 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -941,6 +941,7 @@ void ASTWriter::WriteBlockInfoBlock() {
   RECORD(TU_UPDATE_LEXICAL);
   RECORD(SEMA_DECL_REFS);
   RECORD(WEAK_UNDECLARED_IDENTIFIERS);
+  RECORD(EXTNAME_UNDECLARED_IDENTIFIERS);
   RECORD(PENDING_IMPLICIT_INSTANTIATIONS);
   RECORD(UPDATE_VISIBLE);
   RECORD(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD);
@@ -6058,6 +6059,25 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema *SemaPtr, StringRef isysroot,
     }
   }
 
+  // Write the set of #pragma redefine_extname'd, undeclared identifiers. We
+  // always write the entire table, since later PCH files in a PCH chain are
+  // only interested in the results at the end of the chain.
+  RecordData ExtnameUndeclaredIdentifiers;
+  if (SemaPtr) {
+    ASTContext &Context = SemaPtr->Context;
+    ASTRecordWriter ExtnameUndeclaredIdentifiersWriter(
+        Context, *this, ExtnameUndeclaredIdentifiers);
+    for (const auto &ExtnameUndeclaredIdentifierList :
+         SemaPtr->ExtnameUndeclaredIdentifiers) {
+      const IdentifierInfo *const II = ExtnameUndeclaredIdentifierList.first;
+      const AsmLabelAttr *const AL = ExtnameUndeclaredIdentifierList.second;
+      ExtnameUndeclaredIdentifiersWriter.AddIdentifierRef(II);
+      ExtnameUndeclaredIdentifiersWriter.AddIdentifierRef(
+          &Context.Idents.get(AL->getLabel()));
+      ExtnameUndeclaredIdentifiersWriter.AddSourceLocation(AL->getLocation());
+    }
+  }
+
   // Form the record of special types.
   RecordData SpecialTypes;
   if (SemaPtr) {
@@ -6205,6 +6225,12 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema *SemaPtr, StringRef isysroot,
     Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS,
                       WeakUndeclaredIdentifiers);
 
+  // Write the record containing #pragma redefine_extname'd undeclared
+  // identifiers.
+  if (!ExtnameUndeclaredIdentifiers.empty())
+    Stream.EmitRecord(EXTNAME_UNDECLARED_IDENTIFIERS,
+                      ExtnameUndeclaredIdentifiers);
+
   if (!WritingModule) {
     // Write the submodules that were imported, if any.
     struct ModuleInfo {
diff --git a/clang/test/PCH/pragma-redefine-extname.c b/clang/test/PCH/pragma-redefine-extname.c
new file mode 100644
index 0000000000000..79542f07a435c
--- /dev/null
+++ b/clang/test/PCH/pragma-redefine-extname.c
@@ -0,0 +1,14 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/pragma-redefine-extname.h %s -verify -emit-llvm -o - | FileCheck %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x c-header -emit-pch -o %t %S/pragma-redefine-extname.h
+// RUN: %clang_cc1 -include-pch %t %s -verify -emit-llvm -o - | FileCheck %s
+
+// CHECK-DAG: define void @"\01redeffunc2_ext"
+// CHECK-DAG: call void @"\01redeffunc1_ext"
+
+///////////// Issue #186742: check that #pragma redefine_extname exports into PCHs even if the header contains no declaration of the symbol
+void undecfunc1(void);
+void undecfunc2(void) { undecfunc1(); }
+static void undecfunc3(void) {} // expected-warning {{#pragma redefine_extname is applicable to external C declarations only; not applied to function 'undecfunc3'}}
diff --git a/clang/test/PCH/pragma-redefine-extname.h b/clang/test/PCH/pragma-redefine-extname.h
new file mode 100644
index 0000000000000..426baad7f363e
--- /dev/null
+++ b/clang/test/PCH/pragma-redefine-extname.h
@@ -0,0 +1,5 @@
+// Header for PCH test pragma-redefine-extname.c
+
+#pragma redefine_extname undecfunc1 redeffunc1_ext
+#pragma redefine_extname undecfunc2 redeffunc2_ext
+#pragma redefine_extname undecfunc3 redeffunc3_ext
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h
index 61ca63c81d2d8..cbb7380c56fa8 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h
@@ -582,6 +582,13 @@ class SemaSourceWithPriorities : public clang::ExternalSemaSource {
       Source->ReadWeakUndeclaredIdentifiers(WI);
   }
 
+  void ReadExtnameUndeclaredIdentifiers(
+      llvm::SmallVectorImpl<std::pair<clang::IdentifierInfo *,
+                                      clang::AsmLabelAttr *>> &EI) override {
+    for (auto &Source : Sources)
+      Source->ReadExtnameUndeclaredIdentifiers(EI);
+  }
+
   void ReadUsedVTables(
       llvm::SmallVectorImpl<clang::ExternalVTableUse> &VTables) override {
     for (auto &Source : Sources)

>From e682e5a692c88a0e37bbbb06d0c11c380fd68a24 Mon Sep 17 00:00:00 2001
From: Rudolf Polzer <rpolzer at google.com>
Date: Tue, 17 Mar 2026 06:27:09 -0700
Subject: [PATCH 2/5] Fix tests to pass equally on macOS and Linux.

---
 clang/test/PCH/pragma-redefine-extname.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/test/PCH/pragma-redefine-extname.c b/clang/test/PCH/pragma-redefine-extname.c
index 79542f07a435c..7ead6b3efddc5 100644
--- a/clang/test/PCH/pragma-redefine-extname.c
+++ b/clang/test/PCH/pragma-redefine-extname.c
@@ -1,12 +1,12 @@
 // Test this without pch.
-// RUN: %clang_cc1 -include %S/pragma-redefine-extname.h %s -verify -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux -include %S/pragma-redefine-extname.h %s -verify -emit-llvm -o - | FileCheck %s
 
 // Test with pch.
-// RUN: %clang_cc1 -x c-header -emit-pch -o %t %S/pragma-redefine-extname.h
-// RUN: %clang_cc1 -include-pch %t %s -verify -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux -x c-header -emit-pch -o %t %S/pragma-redefine-extname.h
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux -include-pch %t %s -verify -emit-llvm -o - | FileCheck %s
 
-// CHECK-DAG: define void @"\01redeffunc2_ext"
-// CHECK-DAG: call void @"\01redeffunc1_ext"
+// CHECK-DAG: define dso_local void @redeffunc2_ext
+// CHECK-DAG: call void @redeffunc1_ext
 
 ///////////// Issue #186742: check that #pragma redefine_extname exports into PCHs even if the header contains no declaration of the symbol
 void undecfunc1(void);

>From 1ab46dd68ed893e139c4000810611bce1bfc8e38 Mon Sep 17 00:00:00 2001
From: Rudolf Polzer <rpolzer at google.com>
Date: Mon, 23 Mar 2026 08:39:42 -0700
Subject: [PATCH 3/5] Update to review comments.

---
 clang/lib/Serialization/ASTReader.cpp    |  9 ++++-----
 clang/lib/Serialization/ASTWriter.cpp    |  5 +----
 clang/test/PCH/pragma-redefine-extname.c | 10 +++++-----
 3 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 1c395c2f5dd92..0c9e0134a0276 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -9714,14 +9714,13 @@ void ASTReader::ReadExtnameUndeclaredIdentifiers(
   if (ExtnameUndeclaredIdentifiers.empty())
     return;
 
-  for (unsigned I = 0, N = ExtnameUndeclaredIdentifiers.size(); I < N;
-       /*none*/) {
+  for (unsigned I = 0, N = ExtnameUndeclaredIdentifiers.size(); I < N; I += 3) {
     IdentifierInfo *NameId =
-        DecodeIdentifierInfo(ExtnameUndeclaredIdentifiers[I++]);
+        DecodeIdentifierInfo(ExtnameUndeclaredIdentifiers[I]);
     IdentifierInfo *ExtnameId =
-        DecodeIdentifierInfo(ExtnameUndeclaredIdentifiers[I++]);
+        DecodeIdentifierInfo(ExtnameUndeclaredIdentifiers[I+1]);
     SourceLocation Loc =
-        SourceLocation::getFromRawEncoding(ExtnameUndeclaredIdentifiers[I++]);
+        SourceLocation::getFromRawEncoding(ExtnameUndeclaredIdentifiers[I+2]);
     AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
         getContext(), ExtnameId->getName(),
         AttributeCommonInfo(ExtnameId, SourceRange(Loc),
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index bdbf6676c83a0..b8c61850f9874 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -6067,10 +6067,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema *SemaPtr, StringRef isysroot,
     ASTContext &Context = SemaPtr->Context;
     ASTRecordWriter ExtnameUndeclaredIdentifiersWriter(
         Context, *this, ExtnameUndeclaredIdentifiers);
-    for (const auto &ExtnameUndeclaredIdentifierList :
-         SemaPtr->ExtnameUndeclaredIdentifiers) {
-      const IdentifierInfo *const II = ExtnameUndeclaredIdentifierList.first;
-      const AsmLabelAttr *const AL = ExtnameUndeclaredIdentifierList.second;
+    for (const auto &[II, AL] : SemaPtr->ExtnameUndeclaredIdentifiers) {
       ExtnameUndeclaredIdentifiersWriter.AddIdentifierRef(II);
       ExtnameUndeclaredIdentifiersWriter.AddIdentifierRef(
           &Context.Idents.get(AL->getLabel()));
diff --git a/clang/test/PCH/pragma-redefine-extname.c b/clang/test/PCH/pragma-redefine-extname.c
index 7ead6b3efddc5..5404cc69ec948 100644
--- a/clang/test/PCH/pragma-redefine-extname.c
+++ b/clang/test/PCH/pragma-redefine-extname.c
@@ -1,14 +1,14 @@
-// Test this without pch.
+/// Test this without pch.
 // RUN: %clang_cc1 -triple=x86_64-unknown-linux -include %S/pragma-redefine-extname.h %s -verify -emit-llvm -o - | FileCheck %s
 
-// Test with pch.
+/// Test with pch.
 // RUN: %clang_cc1 -triple=x86_64-unknown-linux -x c-header -emit-pch -o %t %S/pragma-redefine-extname.h
 // RUN: %clang_cc1 -triple=x86_64-unknown-linux -include-pch %t %s -verify -emit-llvm -o - | FileCheck %s
 
-// CHECK-DAG: define dso_local void @redeffunc2_ext
-// CHECK-DAG: call void @redeffunc1_ext
+// CHECK: define dso_local void @redeffunc2_ext
+// CHECK: call void @redeffunc1_ext
 
-///////////// Issue #186742: check that #pragma redefine_extname exports into PCHs even if the header contains no declaration of the symbol
+/// Issue #186742: check that #pragma redefine_extname exports into PCHs even if the header contains no declaration of the symbol
 void undecfunc1(void);
 void undecfunc2(void) { undecfunc1(); }
 static void undecfunc3(void) {} // expected-warning {{#pragma redefine_extname is applicable to external C declarations only; not applied to function 'undecfunc3'}}

>From 20555331656793c7b6e8e253e85ee53a6ea6286f Mon Sep 17 00:00:00 2001
From: Rudolf Polzer <rpolzer at google.com>
Date: Tue, 24 Mar 2026 06:33:54 -0700
Subject: [PATCH 4/5] Omit `#pragma redefine_extname` in modules.

Still include both in PCHs and header units.
---
 clang/lib/Serialization/ASTWriter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 76ebbeb05d1c8..6785c06e10839 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -6102,7 +6102,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema *SemaPtr, StringRef isysroot,
   // always write the entire table, since later PCH files in a PCH chain are
   // only interested in the results at the end of the chain.
   RecordData ExtnameUndeclaredIdentifiers;
-  if (SemaPtr) {
+  if (SemaPtr && !(isModule && !WritingModule->isHeaderUnit())) {
     ASTContext &Context = SemaPtr->Context;
     ASTRecordWriter ExtnameUndeclaredIdentifiersWriter(
         Context, *this, ExtnameUndeclaredIdentifiers);

>From 3a6376db19762fce4e59cf0a998896bf4b6ad22d Mon Sep 17 00:00:00 2001
From: divVerent <divVerent at gmail.com>
Date: Wed, 25 Mar 2026 13:31:01 +0100
Subject: [PATCH 5/5] Update clang/lib/Serialization/ASTWriter.cpp

Use isWritingStdCXXNamedModules.

Co-authored-by: Chuanqi Xu <yedeng.yd at linux.alibaba.com>
---
 clang/lib/Serialization/ASTWriter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 6785c06e10839..5fe82df835eb5 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -6102,7 +6102,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema *SemaPtr, StringRef isysroot,
   // always write the entire table, since later PCH files in a PCH chain are
   // only interested in the results at the end of the chain.
   RecordData ExtnameUndeclaredIdentifiers;
-  if (SemaPtr && !(isModule && !WritingModule->isHeaderUnit())) {
+  if (SemaPtr && !isWritingStdCXXNamedModules()) {
     ASTContext &Context = SemaPtr->Context;
     ASTRecordWriter ExtnameUndeclaredIdentifiersWriter(
         Context, *this, ExtnameUndeclaredIdentifiers);



More information about the cfe-commits mailing list