]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Fix explicit instantiation of const variable templates after earlier implicit...
authorJakub Jelinek <jakub@redhat.com>
Wed, 28 Feb 2024 22:20:13 +0000 (23:20 +0100)
committerJakub Jelinek <jakub@redhat.com>
Wed, 28 Feb 2024 22:20:13 +0000 (23:20 +0100)
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.

gcc/cp/decl.cc
gcc/testsuite/g++.dg/cpp1y/var-templ87.C [new file with mode: 0644]

index d19d09adde43b713b6c4149f0c3c4ed901f9d3d1..05e4600c7bb9c61499af1579744a5962b55d48a3 100644 (file)
@@ -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 (file)
index 0000000..e62d06d
--- /dev/null
@@ -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 ()
+{
+}