https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70096
Patrick Palka <ppalka at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |ppalka at gcc dot gnu.org --- Comment #3 from Patrick Palka <ppalka at gcc dot gnu.org> --- The problem ultimately seems to be that the invariant DECL_MODE (x) == TYPE_MODE (TREE_TYPE (fptr)) is violated during substitution due to a change in the TREE_TYPE of fptr from OFFSET_TYPE to TYPE_PTRMEMFUNC_P. We first give the VAR_DECL fptr F Holder::* fptr = ...; a type of OFFSET_TYPE because we can't tell until instantiation whether fptr will be a pointer-to-member-function or a pointer-to-data-member. We later call layout_decl on this VAR_DECL which sets its mode to DImode because the size of an OFFSET_TYPE is 8 bytes. During instantiation, in tsubst_decl, after substitution we see that fptr is a pointer-to-member-function so we create a copy of the fptr and give it the proper type. Then we call layout_decl on it again. But its mode stays DImode even though its size is now 16 bytes. We forget to clear the DECL_MODE of the copied decl in tsubst_decl [VAR_DECL]. I haven't looked into why r229018 causes this regression. I suppose that r229018 somehow exposed this latent bug.