From 6b8b9e4262617040a6879600a8e411f95ec30b1b Mon Sep 17 00:00:00 2001
From: Richard Guenther <rguenther@suse.de>
Date: Wed, 26 Aug 2009 13:23:04 +0000
Subject: [PATCH] re PR c/41163 (verify_gimple fails)

2009-08-26  Richard Guenther  <rguenther@suse.de>

	PR middle-end/41163
	* gimplify.c (gimplify_addr_expr): Canonicalize ADDR_EXPRs if
	the types to not match.
	* tree-cfg.c (verify_gimple_assign_single): Adjust ADDR_EXPR
	verification.
	* tree-ssa.c (useless_type_conversion_p): Conversions to
	pointers to unprototyped functions are useless.

	* gcc.c-torture/compile/pr41163.c: New testcase.
	* gcc.dg/pr35899.c: Adjust.

From-SVN: r151122
---
 gcc/ChangeLog                                 | 10 ++++++++++
 gcc/gimplify.c                                | 16 ++++++++++++++--
 gcc/testsuite/ChangeLog                       |  6 ++++++
 gcc/testsuite/gcc.c-torture/compile/pr41163.c | 10 ++++++++++
 gcc/testsuite/gcc.dg/pr35899.c                |  2 +-
 gcc/tree-cfg.c                                |  9 +++++----
 gcc/tree-ssa.c                                | 12 ++++++++++--
 7 files changed, 56 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr41163.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 85f1015f7b99..f50b14c18ade 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2009-08-26  Richard Guenther  <rguenther@suse.de>
+
+	PR middle-end/41163
+	* gimplify.c (gimplify_addr_expr): Canonicalize ADDR_EXPRs if
+	the types to not match.
+	* tree-cfg.c (verify_gimple_assign_single): Adjust ADDR_EXPR
+	verification.
+	* tree-ssa.c (useless_type_conversion_p): Conversions to
+	pointers to unprototyped functions are useless.
+
 2009-08-26  Richard Guenther  <rguenther@suse.de>
 
 	* tree-ssa-structalias.c (create_variable_info_for): Remove
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index bdb64ea88c89..7f1dc4ae94bd 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4725,10 +4725,22 @@ gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
       if (TREE_CODE (op0) == INDIRECT_REF)
 	goto do_indirect_ref;
 
+      mark_addressable (TREE_OPERAND (expr, 0));
+
+      /* The FEs may end up building ADDR_EXPRs early on a decl with
+	 an incomplete type.  Re-build ADDR_EXPRs in canonical form
+	 here.  */
+      if (!types_compatible_p (TREE_TYPE (op0), TREE_TYPE (TREE_TYPE (expr))))
+	*expr_p = build_fold_addr_expr (op0);
+
       /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly.  */
-      recompute_tree_invariant_for_addr_expr (expr);
+      recompute_tree_invariant_for_addr_expr (*expr_p);
+
+      /* If we re-built the ADDR_EXPR add a conversion to the original type
+         if required.  */
+      if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
+	*expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
 
-      mark_addressable (TREE_OPERAND (expr, 0));
       break;
     }
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e11a926dda95..9ed0d6dde851 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2009-08-26  Richard Guenther  <rguenther@suse.de>
+
+	PR middle-end/41163
+	* gcc.c-torture/compile/pr41163.c: New testcase.
+	* gcc.dg/pr35899.c: Adjust.
+
 2009-08-26  Richard Guenther  <rguenther@suse.de>
 
 	* gcc.dg/tree-ssa/restrict-4.c: New testcase.
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr41163.c b/gcc/testsuite/gcc.c-torture/compile/pr41163.c
new file mode 100644
index 000000000000..c22483783769
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr41163.c
@@ -0,0 +1,10 @@
+struct option {
+    void *value;
+};
+void parse_options (struct option *);
+void cmd_grep(void)
+{
+  struct option options[] = { { &options } };
+  parse_options(options);
+}
+
diff --git a/gcc/testsuite/gcc.dg/pr35899.c b/gcc/testsuite/gcc.dg/pr35899.c
index 0dc4ffaa3171..fca3a3d86217 100644
--- a/gcc/testsuite/gcc.dg/pr35899.c
+++ b/gcc/testsuite/gcc.dg/pr35899.c
@@ -5,7 +5,7 @@
 int
 foo (void)
 {
-  int a = bar ();	/* { dg-error "returning 'void'" } */
+  int a = bar ();
   return a;
 }
 
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 3b99d6c5a309..639c4ec710cf 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3889,12 +3889,13 @@ verify_gimple_assign_single (gimple stmt)
 	    return true;
 	  }
 
-	if (!one_pointer_to_useless_type_conversion_p (lhs_type,
-						       TREE_TYPE (op)))
+	if (!types_compatible_p (TREE_TYPE (op), TREE_TYPE (TREE_TYPE (rhs1)))
+	    && !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1),
+							  TREE_TYPE (op)))
 	  {
 	    error ("type mismatch in address expression");
-	    debug_generic_stmt (lhs_type);
-	    debug_generic_stmt (TYPE_POINTER_TO (TREE_TYPE (op)));
+	    debug_generic_stmt (TREE_TYPE (rhs1));
+	    debug_generic_stmt (TREE_TYPE (op));
 	    return true;
 	  }
 
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 76e4e8b7f1b3..51b168991211 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -875,13 +875,21 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
       && POINTER_TYPE_P (outer_type))
     {
       /* If the outer type is (void *) or a pointer to an incomplete
-	 record type, then the conversion is not necessary.  */
+	 record type or a pointer to an unprototyped function,
+	 then the conversion is not necessary.  */
       if (VOID_TYPE_P (TREE_TYPE (outer_type))
 	  || (AGGREGATE_TYPE_P (TREE_TYPE (outer_type))
 	      && TREE_CODE (TREE_TYPE (outer_type)) != ARRAY_TYPE
 	      && (TREE_CODE (TREE_TYPE (outer_type))
 		  == TREE_CODE (TREE_TYPE (inner_type)))
-	      && !COMPLETE_TYPE_P (TREE_TYPE (outer_type))))
+	      && !COMPLETE_TYPE_P (TREE_TYPE (outer_type)))
+	  || ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
+	       || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
+	      && (TREE_CODE (TREE_TYPE (outer_type))
+		  == TREE_CODE (TREE_TYPE (inner_type)))
+	      && !TYPE_ARG_TYPES (TREE_TYPE (outer_type))
+	      && useless_type_conversion_p (TREE_TYPE (TREE_TYPE (outer_type)),
+					    TREE_TYPE (TREE_TYPE (inner_type)))))
 	return true;
 
       /* Do not lose casts to restrict qualified pointers.  */
-- 
GitLab