[PATCH] [ms-cxxabi] Destroy temporary record arguments in the callee
Reid Kleckner
rnk at google.com
Thu Jun 6 13:28:14 PDT 2013
On Thu, Jun 6, 2013 at 4:06 PM, John McCall <rjmccall at apple.com> wrote:
> On Jun 6, 2013, at 9:32 AM, Reid Kleckner <rnk at google.com> wrote:
> > Itanium destroys them in the caller at the end of the full expression,
>
> Um. This is standard-dictated behavior. If the MS ABI really gets this
> wrong, that is a very serious divergence.
>
Yep.
> > but MSVC destroys them in the callee..
>
>
> > This should help clang compile MSVC's debug iterators more correctly.
> > There is still an outstanding issue of a memcpy emitted by the LLVM
> > backend, which is not correct for C++ records.
>
> + // In the Microsoft C++ ABI, all aggregate arguments are destructed by
> the
> + // callee, no matter how they are passed at the machine level.
> + bool calleeDestructed =
> + getTarget().getCXXABI().isTemporaryDestroyedByCallee();
> +
> if (E->isGLValue()) {
> assert(E->getObjectKind() == OK_Ordinary);
> - return args.add(EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0),
> - type);
> + return args.add(EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0,
> + calleeDestructed), type);
>
> This is not correct. There is no way that the Microsoft ABI causes the
> callee to destroy arbitrary objects that were passed to it by reference.
>
This is just poorly written. I have tests to ensure that references aren't
destroyed by the callee. This bool only kicks in if the argument has an
aggregate evaluation kind, which references don't have.
> --- lib/CodeGen/CGDecl.cpp
> +++ lib/CodeGen/CGDecl.cpp
> @@ -1621,6 +1621,14 @@
> if (!Ty->isConstantSizeType() ||
> !CodeGenFunction::hasScalarEvaluationKind(Ty)) {
> DeclPtr = Arg;
> + // Push a destructor cleanup for this parameter if the ABI requires
> it.
> + if (!hasScalarEvaluationKind(Ty) &&
>
> You are immediately dominated by this check already.
>
It's an ||, not an &&?
> -RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E) {
> +RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E, bool
> ExternallyDestructed) {
>
> There's already an IsDestructed_t; please use it.
>
OK. It seemed like an internal detail of AggValueSlot.
> These tricks with externally-destructed aren't really suffiicient; you
> need to
> push an EH-only cleanup for the object and then disable it when the call
> occurs.
>
So, something like, take a stable iterator to the cleanup stack, emit the
args, then delete any unnecessary cleanups? I can't think of an easy way
to identify which cleanups were passed to args and which were not.
> The appropriate solution here is not to propagate IsExternallyDestructed
> through umpteen layers of API; you'll need to check for this case
> specifically
> when emitting an argument and do all the appropriate management.
I am doing the check in CodeGenFunction::EmitCallArg(). Maybe I should be
propagating a bool InArgumentContext or something instead?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130606/e5d3ae09/attachment.html>
More information about the cfe-commits
mailing list