[clang][bytecode] Move pointers from extern globals to new decls (#154273)

This commit is contained in:
Timm Baeder 2025-08-19 10:54:33 +02:00 committed by GitHub
parent d9d5090b03
commit fb8ee3adb6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 33 additions and 11 deletions

View File

@ -149,6 +149,7 @@ private:
friend class DeadBlock;
friend class InterpState;
friend class DynamicAllocator;
friend class Program;
Block(unsigned EvalID, const Descriptor *Desc, bool IsExtern, bool IsStatic,
bool IsWeak, bool IsDummy, bool IsDead)

View File

@ -804,6 +804,7 @@ private:
friend class InterpState;
friend struct InitMap;
friend class DynamicAllocator;
friend class Program;
/// Returns the embedded descriptor preceding a field.
InlineDescriptor *getInlineDesc() const {

View File

@ -213,19 +213,32 @@ std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
// Register all previous declarations as well. For extern blocks, just replace
// the index with the new variable.
if (auto Idx =
createGlobal(VD, VD->getType(), IsStatic, IsExtern, IsWeak, Init)) {
for (const Decl *P = VD; P; P = P->getPreviousDecl()) {
unsigned &PIdx = GlobalIndices[P];
if (P != VD) {
if (Globals[PIdx]->block()->isExtern())
Globals[PIdx] = Globals[*Idx];
std::optional<unsigned> Idx =
createGlobal(VD, VD->getType(), IsStatic, IsExtern, IsWeak, Init);
if (!Idx)
return std::nullopt;
Global *NewGlobal = Globals[*Idx];
for (const Decl *Redecl : VD->redecls()) {
unsigned &PIdx = GlobalIndices[Redecl];
if (Redecl != VD) {
if (Block *RedeclBlock = Globals[PIdx]->block();
RedeclBlock->isExtern()) {
Globals[PIdx] = NewGlobal;
// All pointers pointing to the previous extern decl now point to the
// new decl.
for (Pointer *Ptr = RedeclBlock->Pointers; Ptr;
Ptr = Ptr->PointeeStorage.BS.Next) {
RedeclBlock->removePointer(Ptr);
Ptr->PointeeStorage.BS.Pointee = NewGlobal->block();
NewGlobal->block()->addPointer(Ptr);
}
}
PIdx = *Idx;
}
return *Idx;
PIdx = *Idx;
}
return std::nullopt;
return *Idx;
}
std::optional<unsigned> Program::createGlobal(const Expr *E) {
@ -264,7 +277,7 @@ std::optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty,
Ctx.getEvalID(), getCurrentDecl(), Desc, IsStatic, IsExtern, IsWeak);
G->block()->invokeCtor();
// Initialize InlineDescriptor fields.
// Initialize GlobalInlineDescriptor fields.
auto *GD = new (G->block()->rawData()) GlobalInlineDescriptor();
if (!Init)
GD->InitState = GlobalInitState::NoInitializer;

View File

@ -1428,3 +1428,10 @@ namespace OnePastEndCmp {
constexpr const int *q = &s.a + 1;
static_assert(p != q, "");
}
namespace ExternRedecl {
extern const int a;
constexpr const int *p = &a;
constexpr int a = 10;
static_assert(*p == 10, "");
}