Skip to content

Commit fb8ee3a

Browse files
authored
[clang][bytecode] Move pointers from extern globals to new decls (#154273)
1 parent d9d5090 commit fb8ee3a

File tree

4 files changed

+33
-11
lines changed

4 files changed

+33
-11
lines changed

clang/lib/AST/ByteCode/InterpBlock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class Block final {
149149
friend class DeadBlock;
150150
friend class InterpState;
151151
friend class DynamicAllocator;
152+
friend class Program;
152153

153154
Block(unsigned EvalID, const Descriptor *Desc, bool IsExtern, bool IsStatic,
154155
bool IsWeak, bool IsDummy, bool IsDead)

clang/lib/AST/ByteCode/Pointer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,7 @@ class Pointer {
804804
friend class InterpState;
805805
friend struct InitMap;
806806
friend class DynamicAllocator;
807+
friend class Program;
807808

808809
/// Returns the embedded descriptor preceding a field.
809810
InlineDescriptor *getInlineDesc() const {

clang/lib/AST/ByteCode/Program.cpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -213,19 +213,32 @@ std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
213213

214214
// Register all previous declarations as well. For extern blocks, just replace
215215
// the index with the new variable.
216-
if (auto Idx =
217-
createGlobal(VD, VD->getType(), IsStatic, IsExtern, IsWeak, Init)) {
218-
for (const Decl *P = VD; P; P = P->getPreviousDecl()) {
219-
unsigned &PIdx = GlobalIndices[P];
220-
if (P != VD) {
221-
if (Globals[PIdx]->block()->isExtern())
222-
Globals[PIdx] = Globals[*Idx];
216+
std::optional<unsigned> Idx =
217+
createGlobal(VD, VD->getType(), IsStatic, IsExtern, IsWeak, Init);
218+
if (!Idx)
219+
return std::nullopt;
220+
221+
Global *NewGlobal = Globals[*Idx];
222+
for (const Decl *Redecl : VD->redecls()) {
223+
unsigned &PIdx = GlobalIndices[Redecl];
224+
if (Redecl != VD) {
225+
if (Block *RedeclBlock = Globals[PIdx]->block();
226+
RedeclBlock->isExtern()) {
227+
Globals[PIdx] = NewGlobal;
228+
// All pointers pointing to the previous extern decl now point to the
229+
// new decl.
230+
for (Pointer *Ptr = RedeclBlock->Pointers; Ptr;
231+
Ptr = Ptr->PointeeStorage.BS.Next) {
232+
RedeclBlock->removePointer(Ptr);
233+
Ptr->PointeeStorage.BS.Pointee = NewGlobal->block();
234+
NewGlobal->block()->addPointer(Ptr);
235+
}
223236
}
224-
PIdx = *Idx;
225237
}
226-
return *Idx;
238+
PIdx = *Idx;
227239
}
228-
return std::nullopt;
240+
241+
return *Idx;
229242
}
230243

231244
std::optional<unsigned> Program::createGlobal(const Expr *E) {
@@ -264,7 +277,7 @@ std::optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty,
264277
Ctx.getEvalID(), getCurrentDecl(), Desc, IsStatic, IsExtern, IsWeak);
265278
G->block()->invokeCtor();
266279

267-
// Initialize InlineDescriptor fields.
280+
// Initialize GlobalInlineDescriptor fields.
268281
auto *GD = new (G->block()->rawData()) GlobalInlineDescriptor();
269282
if (!Init)
270283
GD->InitState = GlobalInitState::NoInitializer;

clang/test/AST/ByteCode/literals.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,3 +1428,10 @@ namespace OnePastEndCmp {
14281428
constexpr const int *q = &s.a + 1;
14291429
static_assert(p != q, "");
14301430
}
1431+
1432+
namespace ExternRedecl {
1433+
extern const int a;
1434+
constexpr const int *p = &a;
1435+
constexpr int a = 10;
1436+
static_assert(*p == 10, "");
1437+
}

0 commit comments

Comments
 (0)