Fix crash-on-valid with consteval temporary construction through list initialization

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

Differential Revision: https://reviews.llvm.org/D131194
This commit is contained in:
Aaron Ballman 2022-08-11 13:42:47 -04:00
parent 57f334d817
commit b48fb85fe6
3 changed files with 24 additions and 10 deletions

View File

@ -65,7 +65,9 @@ Bug Fixes
- Fix a crash when evaluating a multi-dimensional array's array filler - Fix a crash when evaluating a multi-dimensional array's array filler
expression is element-dependent. This fixes expression is element-dependent. This fixes
`Issue 50601 <https://github.com/llvm/llvm-project/issues/56016>`_. `Issue 50601 <https://github.com/llvm/llvm-project/issues/56016>`_.
- 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 Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1395,15 +1395,12 @@ ConstantEmitter::tryEmitAbstract(const APValue &value, QualType destType) {
llvm::Constant *ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *CE) { llvm::Constant *ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *CE) {
if (!CE->hasAPValueResult()) if (!CE->hasAPValueResult())
return nullptr; return nullptr;
const Expr *Inner = CE->getSubExpr()->IgnoreImplicit();
QualType RetType; QualType RetType = CE->getType();
if (auto *Call = dyn_cast<CallExpr>(Inner)) if (CE->isGLValue())
RetType = Call->getCallReturnType(CGM.getContext()); RetType = CGM.getContext().getLValueReferenceType(RetType);
else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Inner))
RetType = Ctor->getType(); return emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
llvm::Constant *Res =
emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
return Res;
} }
llvm::Constant * llvm::Constant *

View File

@ -56,3 +56,18 @@ int foo() {
// CHECK: define{{.*}} signext i8 @_ZN10Issue545782f2IcEEcT_( // CHECK: define{{.*}} signext i8 @_ZN10Issue545782f2IcEEcT_(
// CHECK: ret i8 4 // 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