aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-02-28 23:20:13 +0100
committerJakub Jelinek <jakub@redhat.com>2024-02-28 23:20:13 +0100
commit29ac92436aa5c702e9e02c206e7590ebd806398e (patch)
treea3f10e8430c3ee256c2090f028b6766e17dbf92d
parentbfecc907373addbdd6969e49caea6ff5d3ce1dc7 (diff)
downloadgcc-29ac92436aa5c702e9e02c206e7590ebd806398e.zip
gcc-29ac92436aa5c702e9e02c206e7590ebd806398e.tar.gz
gcc-29ac92436aa5c702e9e02c206e7590ebd806398e.tar.bz2
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 <jakub@redhat.com> Patrick Palka <ppalka@redhat.com> 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.
-rw-r--r--gcc/cp/decl.cc7
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/var-templ87.C43
2 files changed, 49 insertions, 1 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index d19d09a..05e4600 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -15259,7 +15259,12 @@ grokdeclarator (const cp_declarator *declarator,
/* 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 been overridden in cp_finish_decl
+ if initializer needs runtime initialization. */
+ && (!VAR_P (decl) || !DECL_TEMPLATE_INSTANTIATED (decl)))
cp_apply_type_quals_to_decl (type_quals, decl);
return decl;
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ87.C b/gcc/testsuite/g++.dg/cpp1y/var-templ87.C
new file mode 100644
index 0000000..e62d06d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ87.C
@@ -0,0 +1,43 @@
+// PR c++/113976
+// { dg-do run { target c++14 } }
+
+int
+foo ()
+{
+ return 42;
+}
+
+template <int N>
+const int a = foo ();
+const int *b = &a <0>;
+template <int N>
+const int c = foo ();
+template const int c <0>;
+template <int N>
+const int d = foo ();
+const int *e = &d <0>;
+template const int d <0>;
+template <int N>
+const int f = foo ();
+template const int f <0>;
+const int *g = &f <0>;
+struct S { int a, b; };
+template <int N>
+const S h = { 42, foo () };
+const S *i = &h <0>;
+template <int N>
+const S j = { 42, foo () };
+template const S j <0>;
+template <int N>
+const S k = { 42, foo () };
+const S *l = &k <0>;
+template const S k <0>;
+template <int N>
+const S m = { 42, foo () };
+template const S m <0>;
+const S *n = &m <0>;
+
+int
+main ()
+{
+}