https://gcc.gnu.org/g:6ece2d7274059265468833fb491db44bd90de72a

commit r16-3286-g6ece2d7274059265468833fb491db44bd90de72a
Author: Andrew Pinski <andrew.pin...@oss.qualcomm.com>
Date:   Mon Aug 18 13:33:59 2025 -0700

    middle-end: Fix malloc like functions when calling with void "return" 
[PR120024]
    
    When expanding malloc like functions, we copy the return register into a 
temporary
    and then mark that temporary register with a noalias regnote and the 
alignment.
    This works fine unless you are calling the function with a return type of 
void.
    At this point then the valreg will be null and a crash will happen.
    
    A few cleanups are included in this patch because it was easier to do the 
fix
    with the cleanups added.
    The start_sequence/end_sequence for ECF_MALLOC is no longer needed; I can't 
tell
    if it was ever needed.
    The emit_move_insn function returns the last emitted instruction anyways so
    there is no reason to call get_last_insn as we can just use the return value
    of emit_move_insn. This has been true since this code was originally added
    so I don't understand why it was done that way beforehand.
    
    Bootstrapped and tested on x86_64-linux-gnu.
    
            PR middle-end/120024
    
    gcc/ChangeLog:
    
            * calls.cc (expand_call): Remove start_sequence/end_sequence
            for ECF_MALLOC.
            Check valreg before deferencing it when it comes to malloc like
            functions. Use the return value of emit_move_insn instead of
            calling get_last_insn.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/torture/malloc-1.c: New test.
            * gcc.dg/torture/malloc-2.c: New test.
    
    Signed-off-by: Andrew Pinski <andrew.pin...@oss.qualcomm.com>

Diff:
---
 gcc/calls.cc                            | 19 ++++++-------------
 gcc/testsuite/gcc.dg/torture/malloc-1.c | 10 ++++++++++
 gcc/testsuite/gcc.dg/torture/malloc-2.c | 12 ++++++++++++
 3 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/gcc/calls.cc b/gcc/calls.cc
index 2711c4ebe325..bb8a6d09f825 100644
--- a/gcc/calls.cc
+++ b/gcc/calls.cc
@@ -3235,11 +3235,6 @@ expand_call (tree exp, rtx target, int ignore)
       if (pass)
        precompute_arguments (num_actuals, args);
 
-      /* Now we are about to start emitting insns that can be deleted
-        if a libcall is deleted.  */
-      if (pass && (flags & ECF_MALLOC))
-       start_sequence ();
-
       /* Check the canary value for sibcall or function which doesn't
         return and could throw.  */
       if ((pass == 0
@@ -3771,25 +3766,23 @@ expand_call (tree exp, rtx target, int ignore)
          valreg = gen_rtx_REG (TYPE_MODE (rettype), REGNO (valreg));
        }
 
-      if (pass && (flags & ECF_MALLOC))
+      /* If the return register exists, for malloc like
+        function calls, mark the return register with the
+        alignment and noalias reg note.  */
+      if (pass && (flags & ECF_MALLOC) && valreg)
        {
          rtx temp = gen_reg_rtx (GET_MODE (valreg));
-         rtx_insn *last, *insns;
+         rtx_insn *last;
 
          /* The return value from a malloc-like function is a pointer.  */
          if (TREE_CODE (rettype) == POINTER_TYPE)
            mark_reg_pointer (temp, MALLOC_ABI_ALIGNMENT);
 
-         emit_move_insn (temp, valreg);
+         last = emit_move_insn (temp, valreg);
 
          /* The return value from a malloc-like function cannot alias
             anything else.  */
-         last = get_last_insn ();
          add_reg_note (last, REG_NOALIAS, temp);
-
-         /* Write out the sequence.  */
-         insns = end_sequence ();
-         emit_insn (insns);
          valreg = temp;
        }
 
diff --git a/gcc/testsuite/gcc.dg/torture/malloc-1.c 
b/gcc/testsuite/gcc.dg/torture/malloc-1.c
new file mode 100644
index 000000000000..ba24153c4f03
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/malloc-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* PR middle-end/120024 */
+
+void *f(unsigned) __attribute__((malloc));
+void g()
+{
+  void *(*g)(unsigned) = f;
+  void (*h)(unsigned) = (void (*)(unsigned))g;
+  h(1);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/malloc-2.c 
b/gcc/testsuite/gcc.dg/torture/malloc-2.c
new file mode 100644
index 000000000000..8eeca9d7add9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/malloc-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* PR middle-end/120024 */
+
+void *f(unsigned) __attribute__((malloc));
+void h1(void);
+void g(void)
+{
+  void *(*g)(unsigned) = f;
+  void (*h)(unsigned) = (void (*)(unsigned))g;
+  h(1);
+  h1();
+}

Reply via email to