[Bug c++/113976] [11/12/13/14 Regression] explicit instantiation of const variable template following implicit instantiation is assembled in .rodata instead of .bss since r8-2857-g2ec399d8a6c9c2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113976 --- Comment #11 from GCC Commits --- The master branch has been updated by Jakub Jelinek : https://gcc.gnu.org/g:29ac92436aa5c702e9e02c206e7590ebd806398e commit r14-9227-g29ac92436aa5c702e9e02c206e7590ebd806398e Author: Jakub Jelinek Date: Wed Feb 28 23:20:13 2024 +0100 c++: Fix explicit instantiation of const variable templates after earlier implicit instantation [PR113976] Already previously instantiated const variable templates had cp_apply_type_quals_to_decl called when they were instantiated, but if they need runtime initialization, their TREE_READONLY flag has been subsequently cleared. Explicit variable template instantiation calls grokdeclarator which calls cp_apply_type_quals_to_decl on them again, setting TREE_READONLY flag again, but nothing clears it afterwards, so we emit such instantiations into rodata sections and segfault when the dynamic initialization attempts to initialize them. The following patch fixes that by not calling cp_apply_type_quals_to_decl on already instantiated variable declarations. 2024-02-28 Jakub Jelinek Patrick Palka PR c++/113976 * decl.cc (grokdeclarator): Don't call cp_apply_type_quals_to_decl on DECL_TEMPLATE_INSTANTIATED VAR_DECLs. * g++.dg/cpp1y/var-templ87.C: New test.
[Bug c++/113976] [11/12/13/14 Regression] explicit instantiation of const variable template following implicit instantiation is assembled in .rodata instead of .bss since r8-2857-g2ec399d8a6c9c2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113976 --- Comment #10 from Patrick Palka --- (In reply to Jakub Jelinek from comment #8) > E.g. > --- gcc/cp/decl.cc.jj 2024-02-15 09:51:34.460065992 +0100 > +++ gcc/cp/decl.cc2024-02-19 18:20:23.423410659 +0100 > @@ -15263,7 +15263,14 @@ grokdeclarator (const cp_declarator *dec > /* Record constancy and volatility on the DECL itself . There's > no need to do this when processing a template; we'll do this > for the instantiated declaration based on the type of DECL. */ > -if (!processing_template_decl) > +if (!processing_template_decl > + /* Don't do it for instantiated variable templates either, > +cp_apply_type_quals_to_decl should have been called on it > +already and might have have been overridden in cp_finish_decl > +if initializer needs runtime initialization. */ > + && (!VAR_P (decl) > + || DECL_LANG_SPECIFIC (decl) == NULL > + || !DECL_USE_TEMPLATE (decl))) Maybe checking !DECL_TEMPLATE_INSTANTIATED would be better, since that's set only when the specialization's definition is instantiated from instantiate_body as opposed to DECL_USE_TEMPLATE which gets set when the specialization is formed? >cp_apply_type_quals_to_decl (type_quals, decl); > > return decl; > fixes it, but it is just a random shot in the dark. I think we want to > differentiate > between freshly created VAR_DECL from the grokdeclarator vs. existing > VAR_DECL grokdeclarator just looked up.
[Bug c++/113976] [11/12/13/14 Regression] explicit instantiation of const variable template following implicit instantiation is assembled in .rodata instead of .bss since r8-2857-g2ec399d8a6c9c2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113976 --- Comment #9 from Jakub Jelinek --- Note, adjusted testcase: struct S { int a, b; }; int foo () { return 42; } template const S a = { 42, foo () }; const S *b = &a <0>; template const S c = { 42, foo () }; template const S c <0>; template const S d = { 42, foo () }; const S *e = &d <0>; template const S d <0>; template const S f = { 42, foo () }; template const S f <0>; const S *g = &f <0>; int main () {} started crashing with r6-1525-g350562a75dfb4ac658adf620665871eb47166652 (before that commit it failed to link). When there is partly constant and partly dynamic initializer, we were never considering putting it into .bss section.
[Bug c++/113976] [11/12/13/14 Regression] explicit instantiation of const variable template following implicit instantiation is assembled in .rodata instead of .bss since r8-2857-g2ec399d8a6c9c2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113976 --- Comment #8 from Jakub Jelinek --- E.g. --- gcc/cp/decl.cc.jj 2024-02-15 09:51:34.460065992 +0100 +++ gcc/cp/decl.cc 2024-02-19 18:20:23.423410659 +0100 @@ -15263,7 +15263,14 @@ grokdeclarator (const cp_declarator *dec /* Record constancy and volatility on the DECL itself . There's no need to do this when processing a template; we'll do this for the instantiated declaration based on the type of DECL. */ -if (!processing_template_decl) +if (!processing_template_decl + /* Don't do it for instantiated variable templates either, + cp_apply_type_quals_to_decl should have been called on it + already and might have have been overridden in cp_finish_decl + if initializer needs runtime initialization. */ + && (!VAR_P (decl) + || DECL_LANG_SPECIFIC (decl) == NULL + || !DECL_USE_TEMPLATE (decl))) cp_apply_type_quals_to_decl (type_quals, decl); return decl; fixes it, but it is just a random shot in the dark. I think we want to differentiate between freshly created VAR_DECL from the grokdeclarator vs. existing VAR_DECL grokdeclarator just looked up.
[Bug c++/113976] [11/12/13/14 Regression] explicit instantiation of const variable template following implicit instantiation is assembled in .rodata instead of .bss since r8-2857-g2ec399d8a6c9c2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113976 Jakub Jelinek changed: What|Removed |Added Keywords|needs-bisection | CC||jason at gcc dot gnu.org, ||mpolacek at gcc dot gnu.org, ||ppalka at gcc dot gnu.org --- Comment #7 from Jakub Jelinek --- So, what happens is that during the implicit instantiation we first set TREE_READONLY on the just created decl: #0 c_apply_type_quals_to_decl (type_quals=1, decl=) at ../../gcc/c-family/c-common.cc:3851 #1 0x0089a73a in cp_apply_type_quals_to_decl (type_quals=1, decl=) at ../../gcc/cp/typeck.cc:11747 #2 0x0078d061 in tsubst_decl (t=, args=, complain=3, use_spec_table=false) at ../../gcc/cp/pt.cc:15609 #3 0x007b0faf in instantiate_template (tmpl=, orig_args=, complain=3) at ../../gcc/cp/pt.cc:22100 #4 0x0076dc12 in finish_template_variable (var=, complain=3) at ../../gcc/cp/pt.cc:10521 then clear it because it has a non-const initializer: #0 cp_finish_decl (decl=, init=, init_const_expr_p=false, asmspec_tree=, flags=4, decomp=0x0) at ../../gcc/cp/decl.cc:8945 #1 0x007c64f5 in instantiate_body (pattern=, args=, d=, nested_p=false) at ../../gcc/cp/pt.cc:27006 #2 0x007c838f in instantiate_decl (d=, defer_ok=false, expl_inst_class_mem_p=false) at ../../gcc/cp/pt.cc:27323 #3 0x005a1145 in mark_used (decl=, complain=3) at ../../gcc/cp/decl2.cc:6008 but then mark it TREE_READONLY again in #0 c_apply_type_quals_to_decl (type_quals=1, decl=) at ../../gcc/c-family/c-common.cc:3851 #1 0x0089a73a in cp_apply_type_quals_to_decl (type_quals=1, decl=) at ../../gcc/cp/typeck.cc:11747 #2 0x00566b7c in grokdeclarator (declarator=0x3ebfa00, declspecs=0x7fffd9e0, decl_context=NORMAL, initialized=0, attrlist=0x7fffda50) at ../../gcc/cp/decl.cc:15267 #3 0x006dc206 in cp_parser_explicit_instantiation (parser=0x7fffea2dea80) at ../../gcc/cp/parser.cc:19864 Perhaps that /* Record constancy and volatility on the DECL itself . There's no need to do this when processing a template; we'll do this for the instantiated declaration based on the type of DECL. */ if (!processing_template_decl) cp_apply_type_quals_to_decl (type_quals, decl); at the end of grokdeclarator needs some further guarding, not do it if it has been already implicitly instantiated or something similar. Because I'm afraid by that point I'm afraid information that the var needs to be runtime initialized isn't present on the VAR_DECL anymore (except in cleared TREE_READONLY).
[Bug c++/113976] [11/12/13/14 Regression] explicit instantiation of const variable template following implicit instantiation is assembled in .rodata instead of .bss since r8-2857-g2ec399d8a6c9c2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113976 --- Comment #6 from Jakub Jelinek --- Testcase showing that it is just this case of implicit instantiation followed by explicit that is problematic: int foo () { return 42; } template const int a = foo (); const int *b = &a <0>; template const int c = foo (); template const int c <0>; template const int d = foo (); const int *e = &d <0>; template const int d <0>; template const int f = foo (); template const int f <0>; const int *g = &f <0>; int main () {}
[Bug c++/113976] [11/12/13/14 Regression] explicit instantiation of const variable template following implicit instantiation is assembled in .rodata instead of .bss since r8-2857-g2ec399d8a6c9c2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113976 Richard Biener changed: What|Removed |Added Priority|P3 |P2
[Bug c++/113976] [11/12/13/14 Regression] explicit instantiation of const variable template following implicit instantiation is assembled in .rodata instead of .bss since r8-2857-g2ec399d8a6c9c2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113976 Jakub Jelinek changed: What|Removed |Added CC||jakub at gcc dot gnu.org --- Comment #5 from Jakub Jelinek --- That sounds like a FE bug to me, rather than middle-end.
[Bug c++/113976] [11/12/13/14 Regression] explicit instantiation of const variable template following implicit instantiation is assembled in .rodata instead of .bss since r8-2857-g2ec399d8a6c9c2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113976 --- Comment #4 from Andrew Pinski --- (In reply to Jeffrey A. Law from comment #3) > What does the standard say about changing const objects? It says it is undefined. Note there is no changing const object in this code; just the const variable is dynamically initialized which is 100% defined.
[Bug c++/113976] [11/12/13/14 Regression] explicit instantiation of const variable template following implicit instantiation is assembled in .rodata instead of .bss since r8-2857-g2ec399d8a6c9c2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113976 --- Comment #3 from Jeffrey A. Law --- What does the standard say about changing const objects?