https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80794
Michael Matz <matz at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |matz at gcc dot gnu.org --- Comment #4 from Michael Matz <matz at gcc dot gnu.org> --- You are right about const objects not being modifiable (in C and C++), so your function foo could indeed be optimized because it directly accesses such object and there's no path any of its (non-mutable) subobjects could be modified. This is not the case for your bar: void bar (const S &s) { int i = s.i; s.f (); int j = s.i; if (i != j) __builtin_abort (); } Here 's' is not a const object. It's a const reference to some object. You cannot change that object _through this reference_. You can very well change it through some other reference or pointer that's non-const. Say, in this example: S the_s; S *ps = &the_s; void S::f(void) { ps->i++; } ... bar(the_s); ... Then bar() can't assume that s.i didn't change (the object itself isn't const, only the ref is). The only thing that might save you in this case is that you declared S::f as being const, but then the argument that s.i can't have changed is not because s is a const reference to some object, but rather that S::f can't modify memory.