From 455c08cb645ee4c1e64faa02e1d5e137bd66619a Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@redhat.com>
Date: Sun, 7 Aug 2005 12:01:09 -0700
Subject: [PATCH] re PR middle-end/21894 (Invalid operand to binary operator
 with nested function)

        PR 21894
        * tree-nested.c (convert_local_reference): Save and restore val_only
        around component_ref and friends.  Clear walk_subtrees by default.

From-SVN: r102832
---
 gcc/ChangeLog                                 |  6 +++
 .../gcc.c-torture/compile/nested-2.c          | 16 ++++++
 gcc/tree-nested.c                             | 51 ++++++++++---------
 3 files changed, 48 insertions(+), 25 deletions(-)
 create mode 100644 gcc/testsuite/gcc.c-torture/compile/nested-2.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index be5749bdc79a..f4e7a4f3f0ca 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2005-08-06  Richard Henderson  <rth@redhat.com>
+
+	PR 21894
+	* tree-nested.c (convert_local_reference): Save and restore val_only
+	around component_ref and friends.  Clear walk_subtrees by default.
+
 2005-08-06  Peter O'Gorman  <peter@pogma.com>
 
 	PR 21366
diff --git a/gcc/testsuite/gcc.c-torture/compile/nested-2.c b/gcc/testsuite/gcc.c-torture/compile/nested-2.c
new file mode 100644
index 000000000000..6e61b323b6ff
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/nested-2.c
@@ -0,0 +1,16 @@
+/* PR 21105 */
+
+void
+CheckFile ()
+{
+  char tagname[10];
+  char *a = tagname;
+
+  int validate ()
+  {
+    return (a == tagname + 4);
+  }
+
+  if (a == tagname)
+    validate ();
+}
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 4f6ec71c40e0..45c9bfee2e00 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -950,7 +950,9 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
   struct walk_stmt_info *wi = data;
   struct nesting_info *info = wi->info;
   tree t = *tp, field, x;
+  bool save_val_only;
 
+  *walk_subtrees = 0;
   switch (TREE_CODE (t))
     {
     case VAR_DECL:
@@ -989,34 +991,31 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
       break;
 
     case ADDR_EXPR:
-      {
-	bool save_val_only = wi->val_only;
-
-	wi->val_only = false;
-	wi->is_lhs = false;
-	wi->changed = false;
-	walk_tree (&TREE_OPERAND (t, 0), convert_local_reference, wi, NULL);
-	wi->val_only = save_val_only;
+      save_val_only = wi->val_only;
+      wi->val_only = false;
+      wi->is_lhs = false;
+      wi->changed = false;
+      walk_tree (&TREE_OPERAND (t, 0), convert_local_reference, wi, NULL);
+      wi->val_only = save_val_only;
 
-	/* If we converted anything ... */
-	if (wi->changed)
-	  {
-	    tree save_context;
+      /* If we converted anything ... */
+      if (wi->changed)
+	{
+	  tree save_context;
 
-	    /* Then the frame decl is now addressable.  */
-	    TREE_ADDRESSABLE (info->frame_decl) = 1;
+	  /* Then the frame decl is now addressable.  */
+	  TREE_ADDRESSABLE (info->frame_decl) = 1;
 	    
-	    save_context = current_function_decl;
-	    current_function_decl = info->context;
-	    recompute_tree_invarant_for_addr_expr (t);
-	    current_function_decl = save_context;
-
-	    /* If we are in a context where we only accept values, then
-	       compute the address into a temporary.  */
-	    if (save_val_only)
-	      *tp = tsi_gimplify_val (wi->info, t, &wi->tsi);
-	  }
-      }
+	  save_context = current_function_decl;
+	  current_function_decl = info->context;
+	  recompute_tree_invarant_for_addr_expr (t);
+	  current_function_decl = save_context;
+
+	  /* If we are in a context where we only accept values, then
+	     compute the address into a temporary.  */
+	  if (save_val_only)
+	    *tp = tsi_gimplify_val (wi->info, t, &wi->tsi);
+	}
       break;
 
     case REALPART_EXPR:
@@ -1028,6 +1027,7 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
       /* Go down this entire nest and just look at the final prefix and
 	 anything that describes the references.  Otherwise, we lose track
 	 of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value.  */
+      save_val_only = wi->val_only;
       wi->val_only = true;
       wi->is_lhs = false;
       for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp)
@@ -1055,6 +1055,7 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
 	}
       wi->val_only = false;
       walk_tree (tp, convert_local_reference, wi, NULL);
+      wi->val_only = save_val_only;
       break;
 
     default:
-- 
GitLab