diff --git a/clang/include/clang/Sema/ExternalSemaSource.h b/clang/include/clang/Sema/ExternalSemaSource.h index 11cd69df88d1..e7e66bea8c6b 100644 --- a/clang/include/clang/Sema/ExternalSemaSource.h +++ b/clang/include/clang/Sema/ExternalSemaSource.h @@ -163,6 +163,16 @@ public: virtual void ReadWeakUndeclaredIdentifiers( SmallVectorImpl > &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> &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 8bcaa121b303..12015724b39f 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -310,6 +310,17 @@ public: void ReadWeakUndeclaredIdentifiers( SmallVectorImpl > &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> &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 4e6058b8e5f7..1b8a9803be47 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -968,6 +968,10 @@ public: /// 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 4e8fe1d32d42..2c394fd03e8e 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 d6f75e5973c4..e66fd3d1eccb 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -965,9 +965,15 @@ private: SmallVector 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 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 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 @@ public: void ReadWeakUndeclaredIdentifiers( SmallVectorImpl> &WeakIDs) override; + void ReadExtnameUndeclaredIdentifiers( + SmallVectorImpl> &ExtnameIDs) + override; + void ReadUsedVTables(SmallVectorImpl &VTables) override; void ReadPendingInstantiations( diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 1f040c879d72..be9582ce501f 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> &EI) { + for (size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadExtnameUndeclaredIdentifiers(EI); +} + void MultiplexExternalSemaSource::ReadUsedVTables( SmallVectorImpl &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 0799d1f039f9..ee750284e426 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, 4> ExtnameIDs; + ExternalSource->ReadExtnameUndeclaredIdentifiers(ExtnameIDs); + for (auto &ExtnameID : ExtnameIDs) + ExtnameUndeclaredIdentifiers[ExtnameID.first] = ExtnameID.second; +} typedef llvm::DenseMap RecordCompleteMap; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2951fd09294d..0094eae27f0e 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(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 7c3a6fceb362..4ecdb563a1de 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> &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 &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 9f05daaf6585..20a01f86e95a 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 000000000000..5404cc69ec94 --- /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 000000000000..426baad7f363 --- /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 61ca63c81d2d..cbb7380c56fa 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h @@ -582,6 +582,13 @@ public: Source->ReadWeakUndeclaredIdentifiers(WI); } + void ReadExtnameUndeclaredIdentifiers( + llvm::SmallVectorImpl> &EI) override { + for (auto &Source : Sources) + Source->ReadExtnameUndeclaredIdentifiers(EI); + } + void ReadUsedVTables( llvm::SmallVectorImpl &VTables) override { for (auto &Source : Sources)