rjmccall added inline comments.

================
Comment at: lib/Sema/SemaDecl.cpp:12053
+                            NTCUC_UninitAutoVar);
     }
+
----------------
ahatanak wrote:
> rjmccall wrote:
> > Please add a comment explaining why this is specific to local variables.
> I was trying to explain why this should be specific to local variables and 
> realized that it's not clear to me whether it should be.
> 
> Suppose there is a union with two fields that are both non-trivial:
> 
> ```
> union U {
>   Type A a;
>   Type B a;
> };
> 
> U global;
> ```
> 
> In this case, is value-initialization (which is essentially 
> default-initialization plus a bunch of zero-initialization as per our 
> previous discussion) used to initialize `global`? If so, should we reject the 
> code since it requires default-initialization? It should be fine if we can 
> assume default-initialization means zero-initialization for non-trivial types 
> in C, but what if `TypeA` or `TypeB` requires initializing to a non-zero 
> value?
Yeah, the default-initialization dimension of this problem is interesting.  The 
C++ rule makes sense for C++ because default initialization of a C++ class 
requires an actual, arbitrary-side-effects constructor call, which of course 
you can't reasonably do implicitly for a union member.  As discussed 
previously, non-trivial C types can presumably always be default-initialized 
with a constant bit pattern.  That means that, as long as we can do any 
initialization work at all, then it's in principle not a problem as long as the 
bit pattern is the same for all the union members requiring non-trivial 
initialization (and in particular if there's only one such member).  So it's 
just like you say, we *could* just initialize such unions conservatively as 
long as two different members don't require inconsistent patterns, which in 
practice they currently never do.  That's all true independent of storage 
duration — if we can write that pattern into a global, we can write into a 
local.  The only caveat is that a semantic need for non-trivial default 
initialization almost certainly means that there's a semantic need for 
non-trivial destruction as well, which of course can't be done on a local union 
(but isn't a problem for a global because we just don't destroy them).

On the other hand, on a language level it's much simpler to just say that we 
can't default-initialize a union of any storage duration if it has a 
non-trivial member, and then the language rule doesn't depend on bit-level 
representations.  If there's interest, we can look into weakening that rule 
later by saying that e.g. it's possible to default-initialize a union with at 
most one non-trivial member.

Apropos, do we consider unions with non-trivial members to be non-trivial 
members for the purposes of enclosing unions?  Seems like we should.  Probably 
the most sensible way to handle that is to also flag the union as being 
non-trivial in a dimension if it has a member that's non-trivial in that 
dimension (which might also let you fast-path some of the checking you need to 
do).  Essentially, we'd consider the case where copying is impossible to be a 
subset of the case where copying is non-trivial.


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

Reply via email to