From C99's longjmp description:
All accessible objects have values, and all other components of the abstract
machine218) have state, as of the time the longjmp function was called, except
that the values of objects of automatic storage duration that are local to the
function containing the invocation of the corresponding setjmp macro that do not
have volatile-qualified type and have been changed between the setjmp invocation
and longjmp call are indeterminate.
If you make newEnviron a volatile object, this paragraph indicates that newEnviron will not be clobbered by longjmp. The specification or implementation of vfork might have a similar caveat.
--EDIT--
Because you have optimizations enabled and because newEnviron is non-volatile and because it is not accessed after its use in the ternary conditional operator, one optimization the implementation could perform for your conditional operator would be to actually re-assign newEnviron with the value of environ. Something like:
execve(args[0], args, (newEnviron = newEnviron ? newEnviron : environ));
But we know from the manual for vfork that modifying most objects before the execve results in undefined behaviour.
args doesn't suffer from the same concern because there is no such conditional test.
Your if statement has more sequence points and besides that, might not be as easily recognized as an optimization opportunity. However, I'd hazard a guess that the sequence points play a strong role in the optimization.
The optimization, by the way, is that the storage for newEnviron is repurposed for the result of the conditional operator, meaning neither another register is used (if registers would normally be used) nor additional stack-space is required (for systems using stacks).
I'll bet that if you were able to convince gcc that you needed to access the value of newEnviron after the execve line, the optimization would not be possible and your warning would disappear.
But of course, using volatile is a simple solution, too.