"std::vector<int> v {a, b}" seems to make a huge difference with gcc trunk. But still not a simple add. godbolt.org/z/DDrOCO
Conversation
In general, I don't think either Clang or GCC is capable of getting rid of malloc/free or new/delete outside of a special case for completely dead stores. They aren't capable of doing escape analysis and lowering it to a stack allocation / virtual registers so it won't go away.
2
1
They're happy to get rid of them in cases where doing do is an invalid transformation, like p=malloc(-1); if(p) puts("bad"); free(p);
1
1
In general, they make up their own semantics for C standard library functions. A good example is that Clang doesn't support floating point rounding modes or signalling NaN. It explicitly chooses to implement optimizations incompatible with an implementation of those features.
1
1
GCC has -frounding-math -fsignaling-nans to make those work, but Clang just doesn't implement it. Another example is Clang optimizing out calls to pure functions even if they would have never returned. They don't have an always_return attribute yet but do the optimization anyway.
1
2
For their virtual definition of malloc used by the optimizer, it's allowed to be treated as if it may always succeed and is also treated as having no external side effects outside the program. Neither of those is really true, but that's the C virtual machine they implement.
2
How so? The memory model and address space aren't something defined. Pointers aren't inherently limited to addressing only the space reflected by their size. In practice, that call cannot succeed, but those semantics aren't what is standardized or implemented by compilers at all.
2
By deciding they can remove malloc(4), they've decided that the side effects or potential for failure don't need to be treated as observable. It's not that much further for them to then decide to use a virtual definition of it where it can be treated as potentially succeeding.
1
There are a lot of things that are explicitly undefined in the standard specifically to permit odd implementations of C with (mostly) precise garbage collection, etc. Pointers aren't really defined as addresses either and int conversions / arithmetic are very constrained by that.
1
Convert a pointer to an integer. Write the integer to a pipe, read it from the other end of the pipe and convert it back to a pointer. Dereferencing that pointer or even just doing any arithmetic on it is undefined and will even be broken by Clang / GCC optimization in practice.
I don't think the language implemented by them is usable in practice but it's what they choose to implement based on their (in my opinion mostly fair) reading of the standard. Some things are bugs (pure function removal), others are just very aggressive/cruel interpretations.
1
The standard leaves out a lot of things that should really be talked about, like exhaustion of space for local variables / function calls. They would just respond to most issues of underspecification / vagueness / ambiguity by making things more explicitly undefined anyway.
1
Show replies
I see your sentiments, but the above is incorrect or glossing over something important. Pointer escaping via write() is no different from escaping via any other function. Note how this is different from e.g. obtaining a not-escaping pointer value with a debugger.
1
1
You're trying to reason about it as a logical system providing native semantics which it isn't. The compilers have knowledge about standard library functions and they don't simply act the way they're defined in the library. My example is just something they consider undefined.
1
Show replies
This is false. Pointer escaping via fprintf and recovery by fscanf is explicitly supported by the language. Via write, it's just a roundabout way of implementing your own memcpy via representation access, which is also permitted.
1
2




