[clang] [lldb] Serialize `#pragma redefine_extname` into precompiled headers. (PR #186755)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 16 02:19:26 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-modules
Author: None (divVerent)
<details>
<summary>Changes</summary>
Also deserialize them back again on reading.
The implementation is based on the existing implementation of `#pragma weak` serialization.
Fixes issue #<!-- -->186742.
---
Full diff: https://github.com/llvm/llvm-project/pull/186755.diff
13 Files Affected:
- (modified) clang/include/clang/Sema/ExternalSemaSource.h (+10)
- (modified) clang/include/clang/Sema/MultiplexExternalSemaSource.h (+11)
- (modified) clang/include/clang/Sema/Sema.h (+4)
- (modified) clang/include/clang/Serialization/ASTBitCodes.h (+3)
- (modified) clang/include/clang/Serialization/ASTReader.h (+11-1)
- (modified) clang/lib/Sema/MultiplexExternalSemaSource.cpp (+6)
- (modified) clang/lib/Sema/Sema.cpp (+9)
- (modified) clang/lib/Sema/SemaDecl.cpp (+4)
- (modified) clang/lib/Serialization/ASTReader.cpp (+44)
- (modified) clang/lib/Serialization/ASTWriter.cpp (+26)
- (added) clang/test/PCH/pragma-redefine-extname.c (+14)
- (added) clang/test/PCH/pragma-redefine-extname.h (+5)
- (modified) lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h (+7)
``````````diff
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)
``````````
</details>
https://github.com/llvm/llvm-project/pull/186755
More information about the cfe-commits
mailing list