https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82910
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |missed-optimization Status|UNCONFIRMED |NEW Last reconfirmed| |2017-11-09 CC| |rguenth at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> --- With public members the C++ FE emits ;; Function pair my::get(const other&) (null) ;; enabled by -tree-original <<cleanup_point <<< Unknown tree: expr_stmt (void) (*NON_LVALUE_EXPR <((struct my *) this)->target> = *(struct pair &) &TARGET_EXPR <D.2297, other::get ((const struct other *) other)>) >>>>>; <<cleanup_point return <retval> = TARGET_EXPR <D.2337, ((struct my *) this)->current>>>; while with private members we end up with <<cleanup_point <<< Unknown tree: expr_stmt MEM[(struct pair *)NON_LVALUE_EXPR <((struct my *) this)->target>] = MEM[(struct pair *)(struct pair &) &TARGET_EXPR <D.2301, other::get ((const struct other *) other)>];, <<< Unknown tree: void_cst >>> >>>>>; <<cleanup_point return <retval> = TARGET_EXPR <D.2341, ((struct my *) this)->current>>>; that is, the only difference is we use a different type. That's enough to trigger gimplification differences - with private members we emit pair my::get(const other&) (struct my * const this, const struct other & other) { struct pair D.2301; struct pair D.2343; D.2301 = other::get (other); try { _1 = this->target; MEM[(struct pair *)_1] = MEM[(struct pair *)&D.2301]; } finally { D.2301 = {CLOBBER}; } D.2343 = this->current; return D.2343; } while with public: pair my::get(const other&) (struct my * const this, const struct other & other) { struct pair D.2339; _1 = this->target; *_1 = other::get (other); D.2339 = this->current; return D.2339; } so we have an extra temporary forced upon us. Not sure if middle-end gimplification is confused by the different GENERIC or FE gimplification.