[clang] 0ccff03 - [clang][Interp] Fix record members of reference type
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 28 07:36:23 PDT 2022
Author: Timm Bäder
Date: 2022-10-28T16:34:45+02:00
New Revision: 0ccff030f3b4145bd658e362a63db9aae2942bee
URL: https://github.com/llvm/llvm-project/commit/0ccff030f3b4145bd658e362a63db9aae2942bee
DIFF: https://github.com/llvm/llvm-project/commit/0ccff030f3b4145bd658e362a63db9aae2942bee.diff
LOG: [clang][Interp] Fix record members of reference type
When assigning to them, we can't classify the expression type, because
that doesn't contain the right information.
And when reading from them, we need to do the extra deref, just like we
do when reading from a DeclRefExpr.
Differential Revision: https://reviews.llvm.org/D136012
Added:
Modified:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeStmtGen.cpp
clang/lib/AST/Interp/Interp.h
clang/test/AST/Interp/references.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 2ec14afdf9ac1..cbbd6f33e685d 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -343,6 +343,8 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
const Record *R = getRecord(RD);
const Record::Field *F = R->getField(FD);
// Leave a pointer to the field on the stack.
+ if (F->Decl->getType()->isReferenceType())
+ return this->emitGetFieldPop(PT_Ptr, F->Offset, E);
return this->emitGetPtrField(F->Offset, E);
}
@@ -809,7 +811,7 @@ bool ByteCodeExprGen<Emitter>::visitRecordInitializer(const Expr *Initializer) {
if (!this->emitDupPtr(Initializer))
return false;
- if (Optional<PrimType> T = classify(Init->getType())) {
+ if (Optional<PrimType> T = classify(Init)) {
if (!this->visit(Init))
return false;
diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
index bdb072c3b0aa0..bbe4d04c8974b 100644
--- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
@@ -105,7 +105,7 @@ bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
if (const FieldDecl *Member = Init->getMember()) {
const Record::Field *F = R->getField(Member);
- if (Optional<PrimType> T = this->classify(InitExpr->getType())) {
+ if (Optional<PrimType> T = this->classify(InitExpr)) {
if (!this->emitThis(InitExpr))
return false;
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 73b1bc9bb406b..8e53a76d563f4 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -470,6 +470,8 @@ bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
return true;
}
+/// 1) Peeks a pointer on the stack
+/// 2) Pushes the value of the pointer's field on the stack
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetField(InterpState &S, CodePtr OpPC, uint32_t I) {
const Pointer &Obj = S.Stk.peek<Pointer>();
@@ -499,6 +501,8 @@ bool SetField(InterpState &S, CodePtr OpPC, uint32_t I) {
return true;
}
+/// 1) Pops a pointer from the stack
+/// 2) Pushes the value of the pointer's field on the stack
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetFieldPop(InterpState &S, CodePtr OpPC, uint32_t I) {
const Pointer &Obj = S.Stk.pop<Pointer>();
diff --git a/clang/test/AST/Interp/references.cpp b/clang/test/AST/Interp/references.cpp
index 7d2ed6058361a..0e6d5532ba0e8 100644
--- a/clang/test/AST/Interp/references.cpp
+++ b/clang/test/AST/Interp/references.cpp
@@ -88,3 +88,29 @@ constexpr int RefToMemberExpr() {
return j;
}
static_assert(RefToMemberExpr() == 11, "");
+
+struct Ref {
+ int &a;
+};
+
+constexpr int RecordWithRef() {
+ int m = 100;
+ Ref r{m};
+ m = 200;
+ return r.a;
+}
+static_assert(RecordWithRef() == 200, "");
+
+
+struct Ref2 {
+ int &a;
+ constexpr Ref2(int &a) : a(a) {}
+};
+
+constexpr int RecordWithRef2() {
+ int m = 100;
+ Ref2 r(m);
+ m = 200;
+ return r.a;
+}
+static_assert(RecordWithRef2() == 200, "");
More information about the cfe-commits
mailing list