[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
This commit is contained in:
parent
8b87cb4853
commit
0ccff030f3
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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, "");
|
||||
|
|
Loading…
Reference in New Issue