Make sure the destructor is called if needed.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
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. |
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. |
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? |
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. |
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.
DiagnoseUnusedExprResult diagnoses unused expressions in Sema, so we can modify the PseudoObjectExprs when it's called.
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.