diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index e82b6defa6b..4428b963162 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2286,16 +2286,23 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee. // However, we still have to push an EH-only cleanup in case we unwind before // we make it to the call. - if (HasAggregateEvalKind && args.isUsingInAlloca()) { - assert(getTarget().getTriple().getArch() == llvm::Triple::x86); - AggValueSlot Slot = createPlaceholderSlot(*this, type); + if (HasAggregateEvalKind && + CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { + // If we're using inalloca, use the argument memory. Otherwise, use a + // temporary. Either way, the aggregate is destroyed externally in the + // callee. + AggValueSlot Slot; + if (args.isUsingInAlloca()) + Slot = createPlaceholderSlot(*this, type); + else + Slot = CreateAggTemp(type, "agg.tmp"); Slot.setExternallyDestructed(); EmitAggExpr(E, Slot); RValue RV = Slot.asRValue(); args.add(RV, type); const CXXRecordDecl *RD = type->getAsCXXRecordDecl(); - if (RD->hasNonTrivialDestructor()) { + if (RD && RD->hasNonTrivialDestructor()) { // Create a no-op GEP between the placeholder and the cleanup so we can // RAUW it successfully. It also serves as a marker of the first // instruction where the cleanup is active. |