This revision was automatically updated to reflect the committed changes. tbaeder marked an inline comment as done. Closed by commit rG0ccff030f3b4: [clang][Interp] Fix record members of reference type (authored by tbaeder).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D136012/new/ https://reviews.llvm.org/D136012 Files: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeStmtGen.cpp clang/lib/AST/Interp/Interp.h clang/test/AST/Interp/references.cpp Index: clang/test/AST/Interp/references.cpp =================================================================== --- clang/test/AST/Interp/references.cpp +++ 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, ""); Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ 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 <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 @@ 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>(); Index: clang/lib/AST/Interp/ByteCodeStmtGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ 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<PrimType> T = this->classify(InitExpr->getType())) { + if (Optional<PrimType> T = this->classify(InitExpr)) { if (!this->emitThis(InitExpr)) return false; Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ 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<PrimType> T = classify(Init->getType())) { + if (Optional<PrimType> T = classify(Init)) { if (!this->visit(Init)) return false;
Index: clang/test/AST/Interp/references.cpp =================================================================== --- clang/test/AST/Interp/references.cpp +++ 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, ""); Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ 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 <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 @@ 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>(); Index: clang/lib/AST/Interp/ByteCodeStmtGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ 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<PrimType> T = this->classify(InitExpr->getType())) { + if (Optional<PrimType> T = this->classify(InitExpr)) { if (!this->emitThis(InitExpr)) return false; Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ 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<PrimType> T = classify(Init->getType())) { + if (Optional<PrimType> T = classify(Init)) { if (!this->visit(Init)) return false;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits