llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: None (schittir)

<details>
<summary>Changes</summary>

This is an x86_64 MSVC issue where "Negative store size!" assert fails when 
SplitAfterSize is negative, because the memory regions after second (or 
subsequent) vbptrs are calculated incorrectly.

The old calculation was:
    SplitAfterSize = LastStoreSize - SplitAfterOffset;

The correct size should be:
    SplitAfterSize = (LastStoreOffset + LastStoreSize) -
SplitAfterOffset;

Since all store regions extend to the end of the non-virtual portion (NVSize), 
this patch simplifies it to:
    SplitAfterSize = NVSize - SplitAfterOffset;

---
Full diff: https://github.com/llvm/llvm-project/pull/184558.diff


2 Files Affected:

- (modified) clang/lib/CodeGen/CGExprCXX.cpp (+1-2) 
- (added) clang/test/CodeGenCXX/microsoft-abi-multiple-vbptrs.cpp (+86) 


``````````diff
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 074c124dbf01b..c202d3612f734 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -539,7 +539,6 @@ static void EmitNullBaseClassInitialization(CodeGenFunction 
&CGF,
       break;
     std::pair<CharUnits, CharUnits> LastStore = Stores.pop_back_val();
     CharUnits LastStoreOffset = LastStore.first;
-    CharUnits LastStoreSize = LastStore.second;
 
     CharUnits SplitBeforeOffset = LastStoreOffset;
     CharUnits SplitBeforeSize = VBPtrOffset - SplitBeforeOffset;
@@ -548,7 +547,7 @@ static void EmitNullBaseClassInitialization(CodeGenFunction 
&CGF,
       Stores.emplace_back(SplitBeforeOffset, SplitBeforeSize);
 
     CharUnits SplitAfterOffset = VBPtrOffset + VBPtrWidth;
-    CharUnits SplitAfterSize = LastStoreSize - SplitAfterOffset;
+    CharUnits SplitAfterSize = NVSize - SplitAfterOffset;
     assert(!SplitAfterSize.isNegative() && "negative store size!");
     if (!SplitAfterSize.isZero())
       Stores.emplace_back(SplitAfterOffset, SplitAfterSize);
diff --git a/clang/test/CodeGenCXX/microsoft-abi-multiple-vbptrs.cpp 
b/clang/test/CodeGenCXX/microsoft-abi-multiple-vbptrs.cpp
new file mode 100644
index 0000000000000..f89c1a3f5c3a0
--- /dev/null
+++ b/clang/test/CodeGenCXX/microsoft-abi-multiple-vbptrs.cpp
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -std=c++11 -emit-llvm -o - %s | 
FileCheck %s
+
+// Test for the fix in EmitNullBaseClassInitialization where the calculation
+// of SplitAfterSize was incorrect when multiple vbptrs are present.
+
+struct VBase1 {
+  virtual ~VBase1();
+  int x;
+};
+
+struct VBase2 {
+  virtual ~VBase2();
+  int y;
+};
+
+// Base class with two virtual base classes.
+struct Base : virtual VBase1, virtual VBase2 {
+  int data;
+};
+
+// Derived class that needs to initialize Base.
+// The constructor will call EmitNullBaseClassInitialization for Base.
+struct Derived : Base {
+  Derived();
+  int more_data;
+};
+
+// CHECK-LABEL: define dso_local noundef ptr @"??0Derived@@QEAA@XZ"
+// Check that memory initialization (memset or memcpy) correctly covers
+// the non-virtual portion of the base class, properly handling vbptrs.
+
+// CHECK: call void @llvm.memset
+
+Derived::Derived() : Base() {
+  // Constructor body
+  data = 42;
+  more_data = 100;
+}
+
+// Test case with three virtual bases.
+struct VBase3 {
+  virtual ~VBase3();
+  int z;
+};
+
+struct ComplexBase : virtual VBase1, virtual VBase2, virtual VBase3 {
+  int a, b, c;
+};
+
+struct ComplexDerived : ComplexBase {
+  ComplexDerived();
+  int d;
+};
+
+// CHECK-LABEL: define dso_local noundef ptr @"??0ComplexDerived@@QEAA@XZ"
+// CHECK: call void @llvm.memset
+
+ComplexDerived::ComplexDerived() : ComplexBase() {
+  a = 1;
+  b = 2;
+  c = 3;
+  d = 4;
+}
+
+// Test case with data members initialized using memcpy
+struct VBase4 {
+  virtual ~VBase4();
+  int w;
+};
+
+struct BaseWithPtrToMember : virtual VBase1, virtual VBase4 {
+  int Base::*member_ptr;
+  int value;
+};
+
+struct DerivedWithPtrToMember : BaseWithPtrToMember {
+  DerivedWithPtrToMember();
+};
+
+// CHECK-LABEL: define dso_local noundef ptr 
@"??0DerivedWithPtrToMember@@QEAA@XZ"
+// This should use memcpy instead of memset due to the pointer-to-member.
+// CHECK: call void @llvm.memcpy
+
+DerivedWithPtrToMember::DerivedWithPtrToMember() : BaseWithPtrToMember() {
+  value = 50;
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/184558
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to