[gcc(refs/users/mikael/heads/refactor_descriptor_v203.05)] gimplify: reject non_lvalue as assignment lhs [PR122521]

Mikael Morin via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:079c1670216c67d546b3735774717aa561a9ea86

commit 079c1670216c67d546b3735774717aa561a9ea86
Author: Mikael Morin <[email protected]>
Date:   Tue Feb 11 21:34:11 2025 +0100

    gimplify: reject non_lvalue as assignment lhs [PR122521]
    
    Regression tested on TODO.
    
    -- >8 --
    
    The previous patch made fortran array descriptor getters return references
    wrapped in a non_lvalue.  The goal was to reject their usage on the left of
    an assignment, but they are actually accepted by gimplification which just
    unwraps the non_lvalue.
    
    This change rejects usage of some cases of non_lvalue on the left hand side
    of an assignment, making the invalid API usage more visible.  Not all cases
    are rejected because rejecting all of them causes testsuite failures:
      FAIL: g++.target/powerpc/altivec-cell-1.C (test for excess errors)
      FAIL: g++.target/powerpc/altivec-cell-4.C (test for excess errors)
    for generated code that looks like this:
      NLE <VCE <short int[8]>(TARGET_EXPR <D.4160, a>)[b & 7]> = (short int) b
    where NLE stands for NON_LVALUE_EXPR and VCE for VIEW_CONVERT_EXPR.
    
            PR fortran/122521
    
    gcc/ChangeLog:
    
            * fold-const.cc (maybe_lvalue_p): Make non-static.
            * fold-const.h (maybe_lvalue_p): New declaration.
            * gimplify.cc (is_modifiable_expr): New helper function.
            (gimplify_modify_expr): Throw an error if the left hand side is
            a non_lvalue.

Diff:
---
 gcc/fold-const.cc |  2 +-
 gcc/fold-const.h  |  1 +
 gcc/gimplify.cc   | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 1d0ed62a82fe..e27cbdd50397 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -2689,7 +2689,7 @@ fold_convert_loc (location_t loc, tree type, tree arg)
 /* Return false if expr can be assumed not to be an lvalue, true
    otherwise.  */
 
-static bool
+bool
 maybe_lvalue_p (const_tree x)
 {
   /* We only need to wrap lvalue tree codes.  */
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 8c0c3edba178..fbf2d6a76168 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -96,6 +96,7 @@ extern bool fold_convertible_p (const_tree, const_tree);
 #define fold_convert(T1,T2)\
    fold_convert_loc (UNKNOWN_LOCATION, T1, T2)
 extern tree fold_convert_loc (location_t, tree, tree);
+extern bool maybe_lvalue_p (const_tree);
 extern tree fold_ignored_result (tree);
 extern tree fold_abs_const (tree, tree);
 extern tree fold_indirect_ref_1 (location_t, tree, tree);
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 6c5d182ffab2..f23b4bddd9ba 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -7201,6 +7201,35 @@ gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
   return GS_ALL_DONE;
 }
 
+
+/* Return true if EXPR is a data reference that can be used on the left hand
+   side of an assignment.  */
+
+static bool
+is_modifiable_expr (tree expr)
+{
+  if (maybe_lvalue_p (expr))
+    return true;
+
+  /* Conversions are not lvalues according to the C standard, but gcc accepts
+     them as extension.  */
+  if (TREE_CODE (expr) == NOP_EXPR)
+    return is_modifiable_expr (TREE_OPERAND (expr, 0));
+
+  /* We can generate a NON_LVALUE_EXPR to represent an array reference of a
+     vector.  See PR63764.  */
+  if (TREE_CODE (expr) == NON_LVALUE_EXPR)
+    {
+      tree op0 = TREE_OPERAND (expr, 0);
+      return (TREE_CODE (op0) == ARRAY_REF
+	      && TREE_CODE (TREE_OPERAND (op0, 0)) == VIEW_CONVERT_EXPR
+	      && is_modifiable_expr (TREE_OPERAND (TREE_OPERAND (op0, 0), 0)));
+    }
+
+  return false;
+}
+
+
 /* Gimplify the MODIFY_EXPR node pointed to by EXPR_P.
 
       modify_expr
@@ -7233,6 +7262,12 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
 	      || TREE_CODE (*expr_p) == INIT_EXPR);
 
+  if (!is_modifiable_expr (*to_p))
+    {
+      error ("non-lvalue used as lhs in %qD", *expr_p);
+      return GS_ERROR;
+    }
+
   /* Trying to simplify a clobber using normal logic doesn't work,
      so handle it here.  */
   if (TREE_CLOBBER_P (*from_p))
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.