[PATCH] D143480: [clang][Interp] Fix derived-to-base casts for >1 levels

2023-04-03 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG968b4172f6a9: [clang][Interp] Fix derived-to-base casts for 
1 levels (authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D143480?vs=504022=510435#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143480/new/

https://reviews.llvm.org/D143480

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/test/AST/Interp/records.cpp


Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -250,6 +250,21 @@
 constexpr S s;
 static_assert(s.m() == 1, "");
 
+#if __cplusplus >= 201703L
+namespace BaseInit {
+  class A {public: int a;};
+  class B : public A {};
+  class C : public A {};
+  class D : public B, public C {};
+
+  // FIXME: Enable this once we support the initialization.
+  // This initializes D::B::A::a and not D::C::A::a.
+  //constexpr D d{12};
+  //static_assert(d.B::a == 12);
+  //static_assert(d.C::a == 0);
+};
+#endif
+
 namespace MI {
   class A {
   public:
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -260,6 +260,8 @@
   }
 
   bool emitRecordDestruction(const Descriptor *Desc);
+  bool emitDerivedToBaseCasts(const RecordType *DerivedType,
+  const RecordType *BaseType, const Expr *E);
 
 protected:
   /// Variable to storage mapping.
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -85,15 +85,8 @@
 if (!this->visit(SubExpr))
   return false;
 
-const CXXRecordDecl *FromDecl = getRecordDecl(SubExpr);
-assert(FromDecl);
-const CXXRecordDecl *ToDecl = getRecordDecl(CE);
-assert(ToDecl);
-const Record *R = getRecord(FromDecl);
-const Record::Base *ToBase = R->getBase(ToDecl);
-assert(ToBase);
-
-return this->emitGetPtrBasePop(ToBase->Offset, CE);
+return this->emitDerivedToBaseCasts(getRecordTy(SubExpr->getType()),
+getRecordTy(CE->getType()), CE);
   }
 
   case CK_FloatingCast: {
@@ -1873,6 +1866,38 @@
 C->emitDestruction();
 }
 
+template 
+bool ByteCodeExprGen::emitDerivedToBaseCasts(
+const RecordType *DerivedType, const RecordType *BaseType, const Expr *E) {
+  // Pointer of derived type is already on the stack.
+  const auto *FinalDecl = cast(BaseType->getDecl());
+  const RecordDecl *CurDecl = DerivedType->getDecl();
+  const Record *CurRecord = getRecord(CurDecl);
+  assert(CurDecl && FinalDecl);
+  for (;;) {
+assert(CurRecord->getNumBases() > 0);
+// One level up
+for (const Record::Base  : CurRecord->bases()) {
+  const auto *BaseDecl = cast(B.Decl);
+
+  if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
+// This decl will lead us to the final decl, so emit a base cast.
+if (!this->emitGetPtrBasePop(B.Offset, E))
+  return false;
+
+CurRecord = B.R;
+CurDecl = BaseDecl;
+break;
+  }
+}
+if (CurDecl == FinalDecl)
+  return true;
+  }
+
+  llvm_unreachable("Couldn't find the base class?");
+  return false;
+}
+
 /// When calling this, we have a pointer of the local-to-destroy
 /// on the stack.
 /// Emit destruction of record types (or arrays of record types).


Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -250,6 +250,21 @@
 constexpr S s;
 static_assert(s.m() == 1, "");
 
+#if __cplusplus >= 201703L
+namespace BaseInit {
+  class A {public: int a;};
+  class B : public A {};
+  class C : public A {};
+  class D : public B, public C {};
+
+  // FIXME: Enable this once we support the initialization.
+  // This initializes D::B::A::a and not D::C::A::a.
+  //constexpr D d{12};
+  //static_assert(d.B::a == 12);
+  //static_assert(d.C::a == 0);
+};
+#endif
+
 namespace MI {
   class A {
   public:
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -260,6 +260,8 @@
   }
 
   bool emitRecordDestruction(const Descriptor *Desc);
+  bool emitDerivedToBaseCasts(const RecordType *DerivedType,
+  const RecordType *BaseType, const Expr *E);
 
 protected:
   /// Variable to storage mapping.
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp

[PATCH] D143480: [clang][Interp] Fix derived-to-base casts for >1 levels

2023-03-10 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman accepted this revision.
aaron.ballman added a comment.
This revision is now accepted and ready to land.

LGTM!


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143480/new/

https://reviews.llvm.org/D143480

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143480: [clang][Interp] Fix derived-to-base casts for >1 levels

2023-03-09 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/test/AST/Interp/records.cpp:266
 };
 #endif
 

aaron.ballman wrote:
> I think it'd be good to add test coverage for cases like: 
> https://godbolt.org/z/GnPnP4z76
That even worked :)


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143480/new/

https://reviews.llvm.org/D143480

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143480: [clang][Interp] Fix derived-to-base casts for >1 levels

2023-03-09 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 504022.
tbaeder marked 2 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143480/new/

https://reviews.llvm.org/D143480

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/test/AST/Interp/records.cpp


Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -260,6 +260,20 @@
   constexpr _C c{12};
   constexpr const _B  = c;
   static_assert(b.a == 12);
+
+  // Cast from A to C.
+  constexpr _A a = c;
+  static_assert(a.a == 12);
+
+  class A {public: int a;};
+  class B : public A {};
+  class C : public A {};
+  class D : public B, public C {};
+
+  // This initializes D::B::A::a and not D::C::A::a.
+  constexpr D d{12};
+  static_assert(d.B::a == 12);
+  static_assert(d.C::a == 0);
 };
 #endif
 
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -263,6 +263,8 @@
   }
 
   bool emitRecordDestruction(const Descriptor *Desc);
+  bool emitDerivedToBaseCasts(const RecordType *DerivedType,
+  const RecordType *BaseType, const Expr *E);
 
 protected:
   /// Variable to storage mapping.
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -88,15 +88,8 @@
 if (!this->visit(SubExpr))
   return false;
 
-const CXXRecordDecl *FromDecl = getRecordDecl(SubExpr);
-assert(FromDecl);
-const CXXRecordDecl *ToDecl = getRecordDecl(CE);
-assert(ToDecl);
-const Record *R = getRecord(FromDecl);
-const Record::Base *ToBase = R->getBase(ToDecl);
-assert(ToBase);
-
-return this->emitGetPtrBasePop(ToBase->Offset, CE);
+return this->emitDerivedToBaseCasts(getRecordTy(SubExpr->getType()),
+getRecordTy(CE->getType()), CE);
   }
 
   case CK_FloatingCast: {
@@ -1956,6 +1949,38 @@
 C->emitDestruction();
 }
 
+template 
+bool ByteCodeExprGen::emitDerivedToBaseCasts(
+const RecordType *DerivedType, const RecordType *BaseType, const Expr *E) {
+  // Pointer of derived type is already on the stack.
+  const auto *FinalDecl = cast(BaseType->getDecl());
+  const RecordDecl *CurDecl = DerivedType->getDecl();
+  const Record *CurRecord = getRecord(CurDecl);
+  assert(CurDecl && FinalDecl);
+  for (;;) {
+assert(CurRecord->getNumBases() > 0);
+// One level up
+for (const Record::Base  : CurRecord->bases()) {
+  const auto *BaseDecl = cast(B.Decl);
+
+  if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
+// This decl will lead us to the final decl, so emit a base cast.
+if (!this->emitGetPtrBasePop(B.Offset, E))
+  return false;
+
+CurRecord = B.R;
+CurDecl = BaseDecl;
+break;
+  }
+}
+if (CurDecl == FinalDecl)
+  return true;
+  }
+
+  llvm_unreachable("Couldn't find the base class?");
+  return false;
+}
+
 /// When calling this, we have a pointer of the local-to-destroy
 /// on the stack.
 /// Emit destruction of record types (or arrays of record types).


Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -260,6 +260,20 @@
   constexpr _C c{12};
   constexpr const _B  = c;
   static_assert(b.a == 12);
+
+  // Cast from A to C.
+  constexpr _A a = c;
+  static_assert(a.a == 12);
+
+  class A {public: int a;};
+  class B : public A {};
+  class C : public A {};
+  class D : public B, public C {};
+
+  // This initializes D::B::A::a and not D::C::A::a.
+  constexpr D d{12};
+  static_assert(d.B::a == 12);
+  static_assert(d.C::a == 0);
 };
 #endif
 
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -263,6 +263,8 @@
   }
 
   bool emitRecordDestruction(const Descriptor *Desc);
+  bool emitDerivedToBaseCasts(const RecordType *DerivedType,
+  const RecordType *BaseType, const Expr *E);
 
 protected:
   /// Variable to storage mapping.
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -88,15 +88,8 @@
 if (!this->visit(SubExpr))
   return false;
 
-const CXXRecordDecl *FromDecl = getRecordDecl(SubExpr);
-assert(FromDecl);
-const CXXRecordDecl *ToDecl = getRecordDecl(CE);
-assert(ToDecl);
-

[PATCH] D143480: [clang][Interp] Fix derived-to-base casts for >1 levels

2023-03-09 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: clang/lib/AST/Interp/ByteCodeExprGen.cpp:1949
+  // Pointer of derived type is already on the stack.
+  const CXXRecordDecl *FinalDecl = cast(BaseType->getDecl());
+  const RecordDecl *CurDecl = DerivedType->getDecl();





Comment at: clang/test/AST/Interp/records.cpp:266
 };
 #endif
 

I think it'd be good to add test coverage for cases like: 
https://godbolt.org/z/GnPnP4z76


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143480/new/

https://reviews.llvm.org/D143480

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143480: [clang][Interp] Fix derived-to-base casts for >1 levels

2023-03-01 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143480/new/

https://reviews.llvm.org/D143480

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143480: [clang][Interp] Fix derived-to-base casts for >1 levels

2023-02-07 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

  The GetPtrBasePop op we were using only works for direct base classes.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D143480

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/test/AST/Interp/records.cpp


Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -258,6 +258,10 @@
   class _B : public _A {};
   class _C : public _B {};
   constexpr _C c{12};
+
+  // Cast from A to C.
+  constexpr _A a = c;
+  static_assert(a.a == 12);
 };
 #endif
 
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -263,6 +263,8 @@
   }
 
   bool emitRecordDestruction(const Descriptor *Desc);
+  bool emitDerivedToBaseCasts(const RecordType *DerivedType,
+  const RecordType *BaseType, const Expr *E);
 
 protected:
   /// Variable to storage mapping.
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -88,15 +88,8 @@
 if (!this->visit(SubExpr))
   return false;
 
-const CXXRecordDecl *FromDecl = getRecordDecl(SubExpr);
-assert(FromDecl);
-const CXXRecordDecl *ToDecl = getRecordDecl(CE);
-assert(ToDecl);
-const Record *R = getRecord(FromDecl);
-const Record::Base *ToBase = R->getBase(ToDecl);
-assert(ToBase);
-
-return this->emitGetPtrBasePop(ToBase->Offset, CE);
+return this->emitDerivedToBaseCasts(getRecordTy(SubExpr->getType()),
+getRecordTy(CE->getType()), CE);
   }
 
   case CK_FloatingCast: {
@@ -1949,6 +1942,38 @@
 C->emitDestruction();
 }
 
+template 
+bool ByteCodeExprGen::emitDerivedToBaseCasts(
+const RecordType *DerivedType, const RecordType *BaseType, const Expr *E) {
+  // Pointer of derived type is already on the stack.
+  const CXXRecordDecl *FinalDecl = cast(BaseType->getDecl());
+  const RecordDecl *CurDecl = DerivedType->getDecl();
+  const Record *CurRecord = getRecord(CurDecl);
+  assert(CurDecl && FinalDecl);
+  for (;;) {
+assert(CurRecord->getNumBases() > 0);
+// One level up
+for (const Record::Base  : CurRecord->bases()) {
+  const CXXRecordDecl *BaseDecl = cast(B.Decl);
+
+  if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
+// This decl will lead us to the final decl, so emit a base cast.
+if (!this->emitGetPtrBasePop(B.Offset, E))
+  return false;
+
+CurRecord = B.R;
+CurDecl = BaseDecl;
+break;
+  }
+}
+if (CurDecl == FinalDecl)
+  return true;
+  }
+
+  llvm_unreachable("Couldn't find the base class?");
+  return false;
+}
+
 /// When calling this, we have a pointer of the local-to-destroy
 /// on the stack.
 /// Emit destruction of record types (or arrays of record types).


Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -258,6 +258,10 @@
   class _B : public _A {};
   class _C : public _B {};
   constexpr _C c{12};
+
+  // Cast from A to C.
+  constexpr _A a = c;
+  static_assert(a.a == 12);
 };
 #endif
 
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -263,6 +263,8 @@
   }
 
   bool emitRecordDestruction(const Descriptor *Desc);
+  bool emitDerivedToBaseCasts(const RecordType *DerivedType,
+  const RecordType *BaseType, const Expr *E);
 
 protected:
   /// Variable to storage mapping.
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -88,15 +88,8 @@
 if (!this->visit(SubExpr))
   return false;
 
-const CXXRecordDecl *FromDecl = getRecordDecl(SubExpr);
-assert(FromDecl);
-const CXXRecordDecl *ToDecl = getRecordDecl(CE);
-assert(ToDecl);
-const Record *R = getRecord(FromDecl);
-const Record::Base *ToBase = R->getBase(ToDecl);
-assert(ToBase);
-
-return this->emitGetPtrBasePop(ToBase->Offset, CE);
+return this->emitDerivedToBaseCasts(getRecordTy(SubExpr->getType()),
+