This is an archive of the discontinued LLVM Phabricator instance.

[CodeGen][ObjC] Fix a memory leak that occurs when a non-trivial C struct property is set using dot notation
ClosedPublic

Authored by ahatanak on Oct 24 2022, 2:29 PM.

Details

Summary

Make sure the destructor is called if needed.

Diff Detail

Event Timeline

ahatanak created this revision.Oct 24 2022, 2:29 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 24 2022, 2:29 PM
ahatanak requested review of this revision.Oct 24 2022, 2:29 PM
rjmccall added inline comments.Oct 25 2022, 12:07 PM
clang/test/CodeGenObjC/nontrivial-c-struct-property.m
89

It looks like we're copying a into a temporary and then copying out of that temporary into the argument slot. I don't see any reason the extra copy is required.

Also, aren't non-trivial structs consumed as arguments? If so, this would be an over-release.

ahatanak added inline comments.Dec 16 2022, 6:50 PM
clang/test/CodeGenObjC/nontrivial-c-struct-property.m
89

It isn't an over-release because, if the receiver isn't nil, temporary AGG_TMP is destructed in the callee and, if the receiver isn't nil, the temporary is destructed in the caller (by the call to @__destructor_8_s0(ptr %[[AGG_TMP]])).

As you pointed out, the copy isn't needed if the result of the assignment isn't used.

rjmccall added inline comments.Dec 16 2022, 11:05 PM
clang/test/CodeGenObjC/nontrivial-c-struct-property.m
89

Oh, is this second destructor call in conditionally-executed code? Can we test for that, at least?

ahatanak updated this revision to Diff 483973.Dec 19 2022, 8:15 AM
ahatanak marked an inline comment as done.

Check that the destructor is called conditionally.

ahatanak added inline comments.Dec 19 2022, 8:24 AM
clang/test/CodeGenObjC/nontrivial-c-struct-property.m
89

The first copy constructor call is emitted when emitPseudoObjectExpr evaluates the OpaqueValueExpr that is the result expression. The second copy constructor call is emitted to copy the argument *a to the argument temporary.

Since the result expression isn't used in this case, there isn't any reason to emit the first copy constructor call. If Sema marks the OpaqueValueExpr for the result expression as unique when the result is unused, CodeGen avoids emitting the first copy constructor.

rjmccall accepted this revision.Dec 19 2022, 9:37 PM

Oh, I see. That's a really unfortunate way to end up emitting this code pattern, since ignoring the result is so common. To fix that, we'd have to either figure out the result was unused in Sema or do a relatively complex analysis in IRGen, though.

Anyway, not something we have to do in this patch. LGTM.

We should reconsider the rules we use for temporary destruction one of these days, though. The current pattern is very error-prone, especially in the presence of exceptions.

This revision is now accepted and ready to land.Dec 19 2022, 9:37 PM

Oh, I see. That's a really unfortunate way to end up emitting this code pattern, since ignoring the result is so common. To fix that, we'd have to either figure out the result was unused in Sema or do a relatively complex analysis in IRGen, though.

DiagnoseUnusedExprResult diagnoses unused expressions in Sema, so we can modify the PseudoObjectExprs when it's called.

This revision was landed with ongoing or failed builds.Jan 5 2023, 8:03 PM
This revision was automatically updated to reflect the committed changes.