[clang] [clang][bytecode] Change the way we do init chains (PR #122871)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 14 01:03:08 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
See the comment in Compiler<>::VisitCXXThisExpr.
We need to mark the InitList explicitly, so we later know what to refer to when the init chain is active.
---
Full diff: https://github.com/llvm/llvm-project/pull/122871.diff
4 Files Affected:
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+41-3)
- (modified) clang/lib/AST/ByteCode/Compiler.h (+2)
- (modified) clang/test/AST/ByteCode/records.cpp (+6)
- (modified) clang/test/AST/ByteCode/unions.cpp (+20)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 036f9608bf3ca1..b97d54ece4e598 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -90,6 +90,8 @@ bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const {
if (!Ctx->emitConstUint32(Offset, E))
return false;
return Ctx->emitArrayElemPtrPopUint32(E);
+ case K_InitList:
+ return true;
default:
llvm_unreachable("Unhandled InitLink kind");
}
@@ -1717,6 +1719,8 @@ bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
template <class Emitter>
bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
const Expr *ArrayFiller, const Expr *E) {
+ InitLinkScope<Emitter> ILS(this, InitLink::InitList());
+
QualType QT = E->getType();
if (const auto *AT = QT->getAs<AtomicType>())
QT = AT->getValueType();
@@ -1754,6 +1758,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
auto initPrimitiveField = [=](const Record::Field *FieldToInit,
const Expr *Init, PrimType T) -> bool {
InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init));
+ InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset));
if (!this->visit(Init))
return false;
@@ -1766,6 +1771,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
const Expr *Init) -> bool {
InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init));
InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset));
+
// Non-primitive case. Get a pointer to the field-to-initialize
// on the stack and recurse into visitInitializer().
if (!this->emitGetPtrField(FieldToInit->Offset, Init))
@@ -3812,6 +3818,7 @@ template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
if (!this->emitGetPtrLocal(*LocalIndex, E))
return false;
+ InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
return this->visitInitializer(E);
}
@@ -4848,18 +4855,49 @@ bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
// instance pointer of the current function frame, but e.g. to the declaration
// currently being initialized. Here we emit the necessary instruction(s) for
// this scenario.
- if (!InitStackActive || !E->isImplicit())
+ if (!InitStackActive)
return this->emitThis(E);
- if (InitStackActive && !InitStack.empty()) {
+ if (!InitStack.empty()) {
+ // If our init stack is, for example:
+ // 0 Stack: 3 (decl)
+ // 1 Stack: 6 (init list)
+ // 2 Stack: 1 (field)
+ // 3 Stack: 6 (init list)
+ // 4 Stack: 1 (field)
+ //
+ // We want to find the LAST element in it that's an init list,
+ // which is marked with the K_InitList marker. The index right
+ // before that points to an init list. We need to find the
+ // elements before the K_InitList element that point to a base
+ // (e.g. a decl or This), optionally followed by field, elem, etc.
+ // In the example above, we want to emit elements [0..2].
unsigned StartIndex = 0;
+ unsigned EndIndex = 0;
+ // Findteh init list.
for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {
+ if (InitStack[StartIndex].Kind == InitLink::K_InitList ||
+ InitStack[StartIndex].Kind == InitLink::K_This) {
+ EndIndex = StartIndex;
+ --StartIndex;
+ break;
+ }
+ }
+
+ // Walk backwards to find the base.
+ for (; StartIndex > 0; --StartIndex) {
+ if (InitStack[StartIndex].Kind == InitLink::K_InitList)
+ continue;
+
if (InitStack[StartIndex].Kind != InitLink::K_Field &&
InitStack[StartIndex].Kind != InitLink::K_Elem)
break;
}
- for (unsigned I = StartIndex, N = InitStack.size(); I != N; ++I) {
+ // Emit the instructions.
+ for (unsigned I = StartIndex; I != EndIndex; ++I) {
+ if (InitStack[I].Kind == InitLink::K_InitList)
+ continue;
if (!InitStack[I].template emit<Emitter>(this, E))
return false;
}
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 71765b18cb1a90..2d5b76f789543e 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -51,9 +51,11 @@ struct InitLink {
K_Temp = 2,
K_Decl = 3,
K_Elem = 5,
+ K_InitList = 6
};
static InitLink This() { return InitLink{K_This}; }
+ static InitLink InitList() { return InitLink{K_InitList}; }
static InitLink Field(unsigned Offset) {
InitLink IL{K_Field};
IL.Offset = Offset;
diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp
index 4601aface135ee..d329219264d893 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -1678,3 +1678,9 @@ namespace NonConst {
static_assert(s.getSize() == 10, "");
}
}
+
+namespace ExplicitThisInTemporary {
+ struct B { B *p = this; };
+ constexpr bool g(B b) { return &b == b.p; }
+ static_assert(g({}), "");
+}
diff --git a/clang/test/AST/ByteCode/unions.cpp b/clang/test/AST/ByteCode/unions.cpp
index 7b39bb1bb9316e..e90b123c90de0e 100644
--- a/clang/test/AST/ByteCode/unions.cpp
+++ b/clang/test/AST/ByteCode/unions.cpp
@@ -401,4 +401,24 @@ namespace UnionInBase {
// both-note {{subobject 'y' is not initialized}}
static_assert(return_uninit().a.x == 2);
}
+
+/// FIXME: Our diagnostic here is a little off.
+namespace One {
+ struct A { long x; };
+
+ union U;
+ constexpr A foo(U *up);
+ union U {
+ A a = foo(this); // both-note {{in call to 'foo(&u)'}}
+ int y;
+ };
+
+ constexpr A foo(U *up) {
+ return {up->y}; // both-note {{read of member 'y' of union}}
+ }
+
+ constinit U u = {}; // both-error {{constant init}} \
+ // both-note {{constinit}}
+}
+
#endif
``````````
</details>
https://github.com/llvm/llvm-project/pull/122871
More information about the cfe-commits
mailing list