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 <yedeng.yd@linux.alibaba.com>
This commit is contained in:
parent
be94bfd615
commit
475f71e8fa
@ -163,6 +163,16 @@ public:
|
||||
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
|
||||
|
||||
@ -310,6 +310,17 @@ public:
|
||||
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
|
||||
|
||||
@ -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".
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -965,9 +965,15 @@ private:
|
||||
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 @@ public:
|
||||
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(
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
14
clang/test/PCH/pragma-redefine-extname.c
Normal file
14
clang/test/PCH/pragma-redefine-extname.c
Normal file
@ -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'}}
|
||||
5
clang/test/PCH/pragma-redefine-extname.h
Normal file
5
clang/test/PCH/pragma-redefine-extname.h
Normal file
@ -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
|
||||
@ -582,6 +582,13 @@ public:
|
||||
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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user