[clang][codegen] Fix emission of consteval constructor of derived type
authorMariya Podchishchaeva <mariya.podchishchaeva@intel.com>
Thu, 9 Feb 2023 09:34:26 +0000 (04:34 -0500)
committerMariya Podchishchaeva <mariya.podchishchaeva@intel.com>
Thu, 9 Feb 2023 09:43:48 +0000 (04:43 -0500)
For simple derived type ConstantEmitter returns a struct of the same
size but different type which is then stored field-by-field into memory
via pointer to derived type. In case base type has more fields than derived,
the incorrect GEP is emitted. So, just cast pointer to derived type to
appropriate type with enough fields.

Fixes https://github.com/llvm/llvm-project/issues/60166

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D142534

clang/docs/ReleaseNotes.rst
clang/lib/CodeGen/CGExprAgg.cpp
clang/test/CodeGenCXX/cxx20-consteval-crash.cpp

index 35c3fa5..4d52dbb 100644 (file)
@@ -64,6 +64,9 @@ Bug Fixes
   driver mode and emit an error which suggests using ``/TC`` or ``/TP``
   ``clang-cl`` options instead. This fixes
   `Issue 59307 <https://github.com/llvm/llvm-project/issues/59307>`_.
+- Fix crash when evaluating consteval constructor of derived class whose base
+  has more than one field. This fixes
+  `Issue 60166 <https://github.com/llvm/llvm-project/issues/60166>`_.
 
 Improvements to Clang's diagnostics
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 34e535a..b7fe7fe 100644 (file)
@@ -131,7 +131,14 @@ public:
     EnsureDest(E->getType());
 
     if (llvm::Value *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E)) {
-      CGF.EmitAggregateStore(Result, Dest.getAddress(),
+      Address StoreDest = Dest.getAddress();
+      // The emitted value is guaranteed to have the same size as the
+      // destination but can have a different type. Just do a bitcast in this
+      // case to avoid incorrect GEPs.
+      if (Result->getType() != StoreDest.getType())
+        StoreDest =
+            CGF.Builder.CreateElementBitCast(StoreDest, Result->getType());
+      CGF.EmitAggregateStore(Result, StoreDest,
                              E->getType().isVolatileQualified());
       return;
     }
index 4451359..ebd7eaf 100644 (file)
@@ -92,3 +92,27 @@ int foo() {
 }
 } // namespace Issue55065
 
+namespace GH60166 {
+
+struct Base {
+   void* one = nullptr;
+   void* two = nullptr;
+};
+
+struct Derived : Base {
+   void* three = nullptr;
+   consteval Derived() = default;
+};
+
+void method() {
+  // CHECK: %agg.tmp.ensured = alloca %"struct.GH60166::Derived"
+  // CHECK: %0 = getelementptr inbounds { ptr, ptr, ptr }, ptr %agg.tmp.ensured, i32 0, i32 0
+  // CHECK: store ptr null, ptr %0, align 8
+  // CHECK: %1 = getelementptr inbounds { ptr, ptr, ptr }, ptr %agg.tmp.ensured, i32 0, i32 1
+  // CHECK: store ptr null, ptr %1, align 8
+  // CHECK: %2 = getelementptr inbounds { ptr, ptr, ptr }, ptr %agg.tmp.ensured, i32 0, i32 2
+  // CHECK: store ptr null, ptr %2, align 8
+   (void)Derived();
+}
+
+} // namespace GH60166