Author: divVerent Date: 2026-03-30T09:37:45Z New Revision: 475f71e8fa15ee71f99e450a0e1c90d3961005f9
URL: https://github.com/llvm/llvm-project/commit/475f71e8fa15ee71f99e450a0e1c90d3961005f9 DIFF: https://github.com/llvm/llvm-project/commit/475f71e8fa15ee71f99e450a0e1c90d3961005f9.diff LOG: Serialize `#pragma redefine_extname` into precompiled headers. (#186755) Also deserialize them back again on reading. The implementation is based on the existing implementation of `#pragma weak` serialization. Fixes issue #186742. --------- Co-authored-by: Chuanqi Xu <[email protected]> Added: clang/test/PCH/pragma-redefine-extname.c clang/test/PCH/pragma-redefine-extname.h Modified: clang/include/clang/Sema/ExternalSemaSource.h clang/include/clang/Sema/MultiplexExternalSemaSource.h clang/include/clang/Sema/Sema.h clang/include/clang/Serialization/ASTBitCodes.h clang/include/clang/Serialization/ASTReader.h clang/lib/Sema/MultiplexExternalSemaSource.cpp clang/lib/Sema/Sema.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h Removed: ################################################################################ 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 4e6058b8e5f79..1b8a9803be472 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 4e8fe1d32d42e..2c394fd03e8ef 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 d6f75e5973c45..e66fd3d1eccb7 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 0799d1f039f9f..ee750284e4266 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1089,6 +1089,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 2951fd09294d8..0094eae27f0ed 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8241,6 +8241,8 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } + LoadExternalExtnameUndeclaredIdentifiers(); + if (Expr *E = D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); @@ -10545,6 +10547,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 7c3a6fceb3623..4ecdb563a1de2 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" @@ -4032,6 +4033,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]; @@ -9691,6 +9713,27 @@ 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; I += 3) { + IdentifierInfo *NameId = + DecodeIdentifierInfo(ExtnameUndeclaredIdentifiers[I]); + IdentifierInfo *ExtnameId = + DecodeIdentifierInfo(ExtnameUndeclaredIdentifiers[I+1]); + SourceLocation Loc = + SourceLocation::getFromRawEncoding(ExtnameUndeclaredIdentifiers[I+2]); + 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 9f05daaf65850..20a01f86e95ac 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); @@ -6097,6 +6098,22 @@ 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 && !isWritingStdCXXNamedModules()) { + ASTContext &Context = SemaPtr->Context; + ASTRecordWriter ExtnameUndeclaredIdentifiersWriter( + Context, *this, ExtnameUndeclaredIdentifiers); + for (const auto &[II, AL] : SemaPtr->ExtnameUndeclaredIdentifiers) { + ExtnameUndeclaredIdentifiersWriter.AddIdentifierRef(II); + ExtnameUndeclaredIdentifiersWriter.AddIdentifierRef( + &Context.Idents.get(AL->getLabel())); + ExtnameUndeclaredIdentifiersWriter.AddSourceLocation(AL->getLocation()); + } + } + // Form the record of special types. RecordData SpecialTypes; if (SemaPtr) { @@ -6244,6 +6261,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..5404cc69ec948 --- /dev/null +++ b/clang/test/PCH/pragma-redefine-extname.c @@ -0,0 +1,14 @@ +/// 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. +// 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: 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 +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) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
