https://gcc.gnu.org/g:00ac906e7a9a58811fc3cebc9d389d87b62e8c83

commit r16-5835-g00ac906e7a9a58811fc3cebc9d389d87b62e8c83
Author: Jakub Jelinek <[email protected]>
Date:   Tue Dec 2 14:36:49 2025 +0100

    c++: Diagnose taking addresses of hard reg vars in their initializers 
[PR122860]
    
    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  <[email protected]>
    
            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.

Diff:
---
 gcc/cp/decl.cc                      | 22 ++++++++++++++++++----
 gcc/testsuite/g++.dg/ext/pr122860.C | 30 ++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 974fa8598a65..74c862ec1c7d 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -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
index 000000000000..b0604f0baad0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/pr122860.C
@@ -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> ();
+}

Reply via email to