Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/lib/AST/ByteCode/InterpBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ class Block final {
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)
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ByteCode/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,7 @@ class Pointer {
friend class InterpState;
friend struct InitMap;
friend class DynamicAllocator;
friend class Program;

/// Returns the embedded descriptor preceding a field.
InlineDescriptor *getInlineDesc() const {
Expand Down
35 changes: 24 additions & 11 deletions clang/lib/AST/ByteCode/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions clang/test/AST/ByteCode/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1430,3 +1430,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, "");
}