diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -343,6 +343,8 @@ 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 @@ if (!this->emitDupPtr(Initializer)) return false; - if (Optional T = classify(Init->getType())) { + if (Optional 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 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -105,7 +105,7 @@ if (const FieldDecl *Member = Init->getMember()) { const Record::Field *F = R->getField(Member); - if (Optional T = this->classify(InitExpr->getType())) { + if (Optional 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 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -470,6 +470,8 @@ return true; } +/// 1) Peeks a pointer on the stack +/// 2) Pushes the value of the pointer's field on the stack template ::T> bool GetField(InterpState &S, CodePtr OpPC, uint32_t I) { const Pointer &Obj = S.Stk.peek(); @@ -499,6 +501,8 @@ return true; } +/// 1) Pops a pointer from the stack +/// 2) Pushes the value of the pointer's field on the stack template ::T> bool GetFieldPop(InterpState &S, CodePtr OpPC, uint32_t I) { const Pointer &Obj = S.Stk.pop(); diff --git a/clang/test/AST/Interp/references.cpp b/clang/test/AST/Interp/references.cpp --- a/clang/test/AST/Interp/references.cpp +++ b/clang/test/AST/Interp/references.cpp @@ -88,3 +88,29 @@ 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, "");