[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