aaron.ballman created this revision.
aaron.ballman added reviewers: erichkeane, rjmccall, efriedma, 
clang-language-wg.
Herald added a project: All.
aaron.ballman requested review of this revision.
Herald added a project: clang.

Clang currently crashes when lowering a consteval list initialization of a 
temporary. This is partially working around an issue in the template 
instantiation code (`TreeTransform::TransformCXXTemporaryObjectExpr()`) that 
does not yet know how to handle list initialization of temporaries in all 
cases. However, it's also helping reduce fragility by ensuring we always have a 
valid `QualType` when trying to emit a constant expression during IR generation.

Fixes #55871


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131194

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/test/CodeGenCXX/cxx20-consteval-crash.cpp


Index: clang/test/CodeGenCXX/cxx20-consteval-crash.cpp
===================================================================
--- clang/test/CodeGenCXX/cxx20-consteval-crash.cpp
+++ clang/test/CodeGenCXX/cxx20-consteval-crash.cpp
@@ -56,3 +56,18 @@
 // CHECK: define{{.*}} signext i8 @_ZN10Issue545782f2IcEEcT_(
 // CHECK: ret i8 4
 }
+
+namespace Issue55871 {
+struct Item {
+  consteval Item(char c) :_char{c}{}
+  char _char;
+};
+
+int function(const Item& item1, const Item& item2) {
+  return 0;
+}
+
+int foo() {
+  return function(Item{'a'}, Item{'a'});
+}
+} // namespace Issue58871
Index: clang/lib/CodeGen/CGExprConstant.cpp
===================================================================
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -1396,11 +1396,24 @@
   if (!CE->hasAPValueResult())
     return nullptr;
   const Expr *Inner = CE->getSubExpr()->IgnoreImplicit();
-  QualType RetType;
+
+  // In a call below, emitAbstract() calls tryEmitPrivate() and *some parts* of
+  // that call will use the RetType we pass in here. The parts which do make
+  // use of it expect that the QualType is valid, which is why we give it a
+  // default value here and reset the type only as needed.
+  QualType RetType = Inner->getType();
   if (auto *Call = dyn_cast<CallExpr>(Inner))
     RetType = Call->getCallReturnType(CGM.getContext());
   else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Inner))
     RetType = Ctor->getType();
+  else if (auto *Cast = dyn_cast<CXXFunctionalCastExpr>(Inner)) {
+    // FIXME: This is working around a deficiency in template instantiation;
+    // see TreeTransform::TransformCXXTemporaryObjectExpr and GitHub Issue
+    // #55871 for more details.
+    RetType = Cast->getType();
+  }
+
+  assert(!RetType.isNull() && "Not certain of the constant expression's type");
   llvm::Constant *Res =
       emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
   return Res;
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -60,6 +60,9 @@
 - No longer assert/miscompile when trying to make a vectorized ``_BitInt`` type
   using the ``ext_vector_type`` attribute (the ``vector_size`` attribute was
   already properly diagnosing this case).
+- Fixed a crash-on-valid with consteval evaluation of a list-initialized
+  constructor for a temporary object. This fixes
+  `Issue 55871 <https://github.com/llvm/llvm-project/issues/55871>`_.
 
 Improvements to Clang's diagnostics
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


Index: clang/test/CodeGenCXX/cxx20-consteval-crash.cpp
===================================================================
--- clang/test/CodeGenCXX/cxx20-consteval-crash.cpp
+++ clang/test/CodeGenCXX/cxx20-consteval-crash.cpp
@@ -56,3 +56,18 @@
 // CHECK: define{{.*}} signext i8 @_ZN10Issue545782f2IcEEcT_(
 // CHECK: ret i8 4
 }
+
+namespace Issue55871 {
+struct Item {
+  consteval Item(char c) :_char{c}{}
+  char _char;
+};
+
+int function(const Item& item1, const Item& item2) {
+  return 0;
+}
+
+int foo() {
+  return function(Item{'a'}, Item{'a'});
+}
+} // namespace Issue58871
Index: clang/lib/CodeGen/CGExprConstant.cpp
===================================================================
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -1396,11 +1396,24 @@
   if (!CE->hasAPValueResult())
     return nullptr;
   const Expr *Inner = CE->getSubExpr()->IgnoreImplicit();
-  QualType RetType;
+
+  // In a call below, emitAbstract() calls tryEmitPrivate() and *some parts* of
+  // that call will use the RetType we pass in here. The parts which do make
+  // use of it expect that the QualType is valid, which is why we give it a
+  // default value here and reset the type only as needed.
+  QualType RetType = Inner->getType();
   if (auto *Call = dyn_cast<CallExpr>(Inner))
     RetType = Call->getCallReturnType(CGM.getContext());
   else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Inner))
     RetType = Ctor->getType();
+  else if (auto *Cast = dyn_cast<CXXFunctionalCastExpr>(Inner)) {
+    // FIXME: This is working around a deficiency in template instantiation;
+    // see TreeTransform::TransformCXXTemporaryObjectExpr and GitHub Issue
+    // #55871 for more details.
+    RetType = Cast->getType();
+  }
+
+  assert(!RetType.isNull() && "Not certain of the constant expression's type");
   llvm::Constant *Res =
       emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
   return Res;
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -60,6 +60,9 @@
 - No longer assert/miscompile when trying to make a vectorized ``_BitInt`` type
   using the ``ext_vector_type`` attribute (the ``vector_size`` attribute was
   already properly diagnosing this case).
+- Fixed a crash-on-valid with consteval evaluation of a list-initialized
+  constructor for a temporary object. This fixes
+  `Issue 55871 <https://github.com/llvm/llvm-project/issues/55871>`_.
 
 Improvements to Clang's diagnostics
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to