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