]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Diagnose taking addresses of hard reg vars in their initializers [PR122860]
authorJakub Jelinek <jakub@redhat.com>
Tue, 2 Dec 2025 13:36:49 +0000 (14:36 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 2 Dec 2025 13:36:49 +0000 (14:36 +0100)
DECL_HARD_REGISTER is set only in cp_finish_decl together with
set_user_assembler_name.  If user attempts to take address of
such a var later, cxx_mark_addressable diagnoses it.
But if as in the following testcase the address is taken in its
initializer, we just ICE during expansion.

The following patch fixes it by emitting errors if TREE_ADDRESABLE
at the point we'd otherwise set DECL_HARD_REGISTER on it.

2025-12-02  Jakub Jelinek  <jakub@redhat.com>

PR c++/122860
* decl.cc (make_rtl_for_nonlocal_decl): Diagnose taking address
of a hard register decl in its initializer.
(cp_finish_decl): Likewise.

* g++.dg/ext/pr122860.C: New test.

gcc/cp/decl.cc
gcc/testsuite/g++.dg/ext/pr122860.C [new file with mode: 0644]

index 974fa8598a651a4040f549c48d44c4a88c699d3e..74c862ec1c7d6eab29f1c2f35cc4cae4a518a4a5 100644 (file)
@@ -8654,8 +8654,15 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
         placed in a particular register.  */
       if (VAR_P (decl) && DECL_REGISTER (decl))
        {
-         set_user_assembler_name (decl, asmspec);
-         DECL_HARD_REGISTER (decl) = 1;
+         if (TREE_ADDRESSABLE (decl))
+           error_at (DECL_SOURCE_LOCATION (decl),
+                     "address of explicit register variable %qD requested",
+                     decl);
+         else
+           {
+             set_user_assembler_name (decl, asmspec);
+             DECL_HARD_REGISTER (decl) = 1;
+           }
        }
       else
        {
@@ -9656,8 +9663,15 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
 
       if (VAR_P (decl) && DECL_REGISTER (decl) && asmspec)
        {
-         set_user_assembler_name (decl, asmspec);
-         DECL_HARD_REGISTER (decl) = 1;
+         if (TREE_ADDRESSABLE (decl))
+           error_at (DECL_SOURCE_LOCATION (decl),
+                     "address of explicit register variable %qD requested",
+                     decl);
+         else
+           {
+             set_user_assembler_name (decl, asmspec);
+             DECL_HARD_REGISTER (decl) = 1;
+           }
        }
       return;
     }
diff --git a/gcc/testsuite/g++.dg/ext/pr122860.C b/gcc/testsuite/g++.dg/ext/pr122860.C
new file mode 100644 (file)
index 0000000..b0604f0
--- /dev/null
@@ -0,0 +1,30 @@
+// PR c++/122860
+// { dg-do compile }
+// { dg-options "-Wno-register" }
+
+void
+foo ()
+{
+  register __UINTPTR_TYPE__ val asm ("1") = (__UINTPTR_TYPE__) &val;   // { dg-error "address of explicit register variable 'val' requested" }
+}
+
+template <typename T>
+void
+bar ()
+{
+  register T val asm ("1") = (T) &val; // { dg-error "address of explicit register variable 'val' requested" }
+}
+
+template <typename T>
+void
+baz ()
+{
+  register __UINTPTR_TYPE__ val asm ("1") = (__UINTPTR_TYPE__) &val;   // { dg-error "address of explicit register variable 'val' requested" }
+}
+
+void
+qux ()
+{
+  bar <__UINTPTR_TYPE__> ();
+  baz <int> ();
+}