[PATCH] D137562: [clang][Interp] Start supporting virtual base classes

Timm Bäder via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 7 08:59:53 PST 2022


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.

As discussed on IRC. This is just the bare minimum to support virtual base classes.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D137562

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/Descriptor.cpp
  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
@@ -335,3 +335,24 @@
                                        // expected-error {{must be initialized by a constant expression}}
                                        // FIXME: Missing reason for rejection.
 };
+
+namespace VirtBases {
+  struct VB {
+    int a;
+  };
+
+  struct S : virtual VB {}; // ref-note {{struct with virtual base class is not a literal type}} \
+                            // expected-note {{struct with virtual base class is not a literal type}} \
+                            // ref-note {{virtual base class declared here}} \
+                            // expected-note {{virtual base class declared here}}
+
+
+  constexpr S s; // ref-error {{cannot have non-literal type 'const S'}} \
+                 // expected-error {{cannot have non-literal type 'const S'}}
+
+  S s2;
+  constexpr VB *v = &s2;
+//  static_assert(v->a); FIXME: Loading from s should error out, since
+//                              it's not a constant expression.
+
+};
Index: clang/lib/AST/Interp/Descriptor.cpp
===================================================================
--- clang/lib/AST/Interp/Descriptor.cpp
+++ clang/lib/AST/Interp/Descriptor.cpp
@@ -122,7 +122,8 @@
 static void ctorRecord(Block *B, char *Ptr, bool IsConst, bool IsMutable,
                        bool IsActive, Descriptor *D) {
   const bool IsUnion = D->ElemRecord->isUnion();
-  auto CtorSub = [=](unsigned SubOff, Descriptor *F, bool IsBase) {
+  auto CtorSub = [=](unsigned SubOff, Descriptor *F, bool IsBase,
+                     bool Recurse = true) {
     auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + SubOff) - 1;
     Desc->Offset = SubOff;
     Desc->Desc = F;
@@ -131,6 +132,10 @@
     Desc->IsActive = IsActive && !IsUnion;
     Desc->IsConst = IsConst || F->IsConst;
     Desc->IsMutable = IsMutable || F->IsMutable;
+
+    if (!Recurse)
+      return;
+
     if (auto Fn = F->CtorFn)
       Fn(B, Ptr + SubOff, Desc->IsConst, Desc->IsMutable, Desc->IsActive, F);
   };
@@ -139,7 +144,7 @@
   for (const auto &F : D->ElemRecord->fields())
     CtorSub(F.Offset, F.Desc, /*isBase=*/false);
   for (const auto &V : D->ElemRecord->virtual_bases())
-    CtorSub(V.Offset, V.Desc, /*isBase=*/true);
+    CtorSub(V.Offset, V.Desc, /*isBase=*/true, false);
 }
 
 static void dtorRecord(Block *B, char *Ptr, Descriptor *D) {
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -119,9 +119,13 @@
     const CXXRecordDecl *ToDecl = getRecordDecl(CE);
     assert(ToDecl);
     const Record *R = getRecord(FromDecl);
-    const Record::Base *ToBase = R->getBase(ToDecl);
-    assert(ToBase);
+    const Record::Base *ToBase;
+    if (FromDecl->isVirtuallyDerivedFrom(ToDecl))
+      ToBase = R->getVirtualBase(ToDecl);
+    else
+      ToBase = R->getBase(ToDecl);
 
+    assert(ToBase);
     return this->emitGetPtrBase(ToBase->Offset, CE);
   }
 
@@ -515,7 +519,9 @@
   if (const auto *FD = dyn_cast<FieldDecl>(Member)) {
     const RecordDecl *RD = FD->getParent();
     const Record *R = getRecord(RD);
+    assert(R);
     const Record::Field *F = R->getField(FD);
+    assert(F);
     // Leave a pointer to the field on the stack.
     if (F->Decl->getType()->isReferenceType())
       return this->emitGetFieldPop(PT_Ptr, F->Offset, E);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D137562.473691.patch
Type: text/x-patch
Size: 3592 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20221107/642b9bf3/attachment.bin>


More information about the cfe-commits mailing list