rjmccall added inline comments.
================ Comment at: lib/Sema/SemaExpr.cpp:16218 + checkNonTrivialCUnion(E->getType(), E->getExprLoc(), + Sema::NTCUC_LValueToRValueVolatile); + ---------------- ahatanak wrote: > rjmccall wrote: > > It looks like you're generally warning about this based on the specific > > context that forced an lvalue-to-rvalue conversion. I'm not sure > > `volatile` is special except that we actually perform the load even in > > unused-value contexts. Is the assumption that you've exhaustively covered > > all the other contexts of lvalue-to-rvalue conversions whose values will > > actually be used? That seems questionable to me. > Yes, that was my assumption. All the other contexts where lvalue-to-rvalue > conversion is performed and the result is used are already covered by other > calls sites of `checkNonTrivialCUnion`, which informs the users that the > struct/union is being used in an invalid context. > > Do you have a case in mind that I didn't think of where a lvalue-to-rvalue > conversion requires a non-trivial initialization/destruction/copying of a > union but clang fails to emit any diagnostics? > > Also I realized that lvalue-to-rvalue conversion of volatile types doesn't > always require non-trivial destruction, so I think `CheckDestruct` shouldn't > be set in this case. > > ``` > void foo(U0 *a, volatile U0 *b) { > // this doesn't require destruction. > // this is perfectly valid if U0 is non-trivial to destruct but trivial to > copy. > *a = *b; > } > ``` > > For the same reason, I think `CheckDestruct` shouldn't be set for function > returns (but it should be set for function parameters since they are > destructed by the callee). There are a *lot* of places that trigger lvalue-to-rvalue conversion. Many of them aren't legal with structs (in C), but I'm worried about approving a pattern with the potential to be wrong by default just because we didn't think about some weird case. As an example, casts can trigger lvalue-to-rvalue conversion; I think the only casts allowed with structs are the identity cast and the cast to `void`, but those are indeed allowed. Now, a cast to `void` means the value is ignored, so we can elide a non-volatile load in the operand, and an identity cast isn't terminal; if the idea is that we're checking all the *terminal* uses of a struct r-value, then we're in much more restricted territory (and don't need to worry about things like commas and conditional operators that can propagate values out). But this still worries me. I'm not sure we need to be super-pedantic about destructibility vs. copyability in some of this checking. It's certain possible in C++, but I can't imagine what sort of *primitive* type would be trivially copyable but not trivially destructible. (The reverse isn't true: something like a relative pointer would be non-trivially copyable but still trivially destructible.) Is there any way to make this check cheaper so that we can immediately avoid any further work for types that are obviously copyable/destructible? All the restricted types are (possibly arrays of) record types, right? Repository: rC Clang CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63753/new/ https://reviews.llvm.org/D63753 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits