https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56955
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2014-05-21 CC| |rguenth at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #15 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Dan Gohman from comment #4) > (In reply to comment #3) > > Well, it _is_ actually about the content. There must be no way to compute > > a valid pointer to another object from the contents of the pointed-to > > memory. > > Oh wow. That's a subtlety that completely escaped me. > > > So if you initialize the memory to {0, 1, 2, 3, 4 ...} thus > > every possible byte value is somewhere and then do > > > > void *p = (void *)(mem[3] << 24 | mem[58] << 16 | ...); > > > > then points-to analysis assumes that from the contents of 'mem' you > > can only compute pointers to nothing (NULL). > > Is that example fundamentally different than something like this: > > void *q = (void *)(mem[0] + 0xb1ab1ab1a); > > In both cases, the information of the pointer value is in the expression, > not in the memory. It's exactly the same. > Is it the case that the memory must be either actually zeros or > uninitialized? Or could it contain other data which merely transmits no > information about pointer values? There must be no way to "compute" a pointer to an object by _just_ combining bits and bytes of that memory cleverly. So for example initializing the memory to -1 (all bits set) would not work as you can compute a zero from 1 ^ 1 and thus any possible pointer value. That's not possible for zero. Oh wait, you can do ~0. Hmm ... subtle ;) Ok, we ignore pointer values computed from FP values as well, thus I guess technically only undefined content is really really valid. Practically memory with non-pointer values is ok unless you play evil (or very evil) games outlined above. > > Technically for targets > > where NULL is a valid poiner to an object calloc () may not be marked > > with malloc. > > > > That is, read it in the way that the code assumes the memory _may_ be > > zero-initialized (but only zero-initialized) or uninitialized. > > If this is what it means, then I request that the text be updated to say > this. I'd be willing to propose a wording, once I understand the intent, if > that'd be helpful. > > What should we say about the fact that GLIBC uses the malloc attribute on > strdup (and similar things)? strdup actually could be used to transmit > information about pointer values. True. See above though. Note that the actual implementation (as opposed to what would be allowed by the documentation) does: /* If this is not a real malloc call assume the memory was initialized and thus may point to global memory. All builtin functions with the malloc attribute behave in a sane way. */ if (!fndecl || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL) make_constraint_from (vi, nonlocal_id); and thus restricts this to "known" functions (not only malloc, but also strdup which we just expect you don't use to transfer pointers ...). As of 'realloc' - yes we can special-case that in the compiler (we don't do that), but we can't really re-use the existing 'malloc' attribute for that. The proposed revised documentation looks like a good improvement to me, Paul, can you post it to gcc-patches@?