summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp15
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.
OpenPOWER on IntegriCloud