Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c	(revision 161369)
+++ gcc/tree-cfg.c	(working copy)
@@ -2533,6 +2533,49 @@ gimple_split_edge (edge edge_in)
   return new_bb;
 }
 
+
+/* Verify properties of the address expression T with base object BASE.  */
+
+static tree
+verify_address (tree t, tree base)
+{
+  bool old_constant;
+  bool old_side_effects;
+  bool new_constant;
+  bool new_side_effects;
+
+  old_constant = TREE_CONSTANT (t);
+  old_side_effects = TREE_SIDE_EFFECTS (t);
+
+  recompute_tree_invariant_for_addr_expr (t);
+  new_side_effects = TREE_SIDE_EFFECTS (t);
+  new_constant = TREE_CONSTANT (t);
+
+  if (old_constant != new_constant)
+    {
+      error ("constant not recomputed when ADDR_EXPR changed");
+      return t;
+    }
+  if (old_side_effects != new_side_effects)
+    {
+      error ("side effects not recomputed when ADDR_EXPR changed");
+      return t;
+    }
+
+  if (!(TREE_CODE (base) == VAR_DECL
+	|| TREE_CODE (base) == PARM_DECL
+	|| TREE_CODE (base) == RESULT_DECL))
+    return NULL_TREE;
+
+  if (DECL_GIMPLE_REG_P (base))
+    {
+      error ("DECL_GIMPLE_REG_P set on a variable with address taken");
+      return base;
+    }
+
+  return NULL_TREE;
+}
+
 /* Callback for walk_tree, check that all elements with address taken are
    properly noticed as such.  The DATA is an int* that is 1 if TP was seen
    inside a PHI node.  */
@@ -2561,28 +2604,26 @@ verify_expr (tree *tp, int *walk_subtree
       break;
 
     case INDIRECT_REF:
-      x = TREE_OPERAND (t, 0);
-      if (!is_gimple_reg (x) && !is_gimple_min_invariant (x))
-	{
-	  error ("Indirect reference's operand is not a register or a constant.");
-	  return x;
-	}
-      break;
+      error ("INDIRECT_REF in gimple IL");
+      return t;
 
     case MEM_REF:
       x = TREE_OPERAND (t, 0);
-      if (!is_gimple_reg (x) && !is_gimple_min_invariant (x))
+      if (!is_gimple_mem_ref_addr (x))
 	{
-	  error ("MEM_REFs operand is not a register or a constant.");
+	  error ("Invalid first operand of MEM_REF.");
 	  return x;
 	}
-      if (TREE_CODE (x) == ADDR_EXPR
-	  && !DECL_P (TREE_OPERAND (x, 0))
-	  && !CONSTANT_CLASS_P (TREE_OPERAND (x, 0)))
+      if (TREE_CODE (TREE_OPERAND (t, 1)) != INTEGER_CST
+	  || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 1))))
 	{
-	  error ("Invalid address operand of MEM_REF.");
-	  return x;
+	  error ("Invalid offset operand of MEM_REF.");
+	  return TREE_OPERAND (t, 1);
 	}
+      if (TREE_CODE (x) == ADDR_EXPR
+	  && (x = verify_address (x, TREE_OPERAND (x, 0))))
+	return x;
+      *walk_subtrees = 0;
       break;
 
     case ASSERT_EXPR:
@@ -2600,31 +2641,10 @@ verify_expr (tree *tp, int *walk_subtree
 
     case ADDR_EXPR:
       {
-	bool old_constant;
-	bool old_side_effects;
-	bool new_constant;
-	bool new_side_effects;
+	tree tem;
 
 	gcc_assert (is_gimple_address (t));
 
-	old_constant = TREE_CONSTANT (t);
-	old_side_effects = TREE_SIDE_EFFECTS (t);
-
-	recompute_tree_invariant_for_addr_expr (t);
-	new_side_effects = TREE_SIDE_EFFECTS (t);
-	new_constant = TREE_CONSTANT (t);
-
-        if (old_constant != new_constant)
-	  {
-	    error ("constant not recomputed when ADDR_EXPR changed");
-	    return t;
-	  }
-	if (old_side_effects != new_side_effects)
-	  {
-	    error ("side effects not recomputed when ADDR_EXPR changed");
-	    return t;
-	  }
-
 	/* Skip any references (they will be checked when we recurse down the
 	   tree) and ensure that any variable used as a prefix is marked
 	   addressable.  */
@@ -2633,23 +2653,19 @@ verify_expr (tree *tp, int *walk_subtree
 	     x = TREE_OPERAND (x, 0))
 	  ;
 
+	if ((tem = verify_address (t, x)))
+	  return tem;
+
 	if (!(TREE_CODE (x) == VAR_DECL
 	      || TREE_CODE (x) == PARM_DECL
 	      || TREE_CODE (x) == RESULT_DECL))
 	  return NULL;
-#if 0
-	/* FIXME.  */
+
 	if (!TREE_ADDRESSABLE (x))
 	  {
 	    error ("address taken, but ADDRESSABLE bit not set");
 	    return x;
 	  }
-#endif
-	if (DECL_GIMPLE_REG_P (x))
-	  {
-	    error ("DECL_GIMPLE_REG_P set on a variable with address taken");
-	    return x;
-	  }
 
 	break;
       }
@@ -2854,16 +2870,7 @@ verify_types_in_gimple_min_lval (tree ex
       debug_generic_stmt (op);
       return true;
     }
-#if 0
-  if (!useless_type_conversion_p (TREE_TYPE (expr),
-				  TREE_TYPE (TREE_TYPE (op))))
-    {
-      error ("type mismatch in indirect reference");
-      debug_generic_stmt (TREE_TYPE (expr));
-      debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
-      return true;
-    }
-#endif
+  /* Memory references now generally can involve a value conversion.  */
 
   return false;
 }
@@ -2966,20 +2973,16 @@ verify_types_in_gimple_reference (tree e
 
   if (TREE_CODE (expr) == MEM_REF)
     {
-      if (!is_gimple_val (TREE_OPERAND (expr, 0))
-	  || TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST
-	  || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
+      if (!is_gimple_mem_ref_addr (TREE_OPERAND (expr, 0)))
 	{
-	  error ("Invalid operands in MEM_REF.");
+	  error ("Invalid address operand in MEM_REF.");
 	  debug_generic_stmt (expr);
 	  return true;
 	}
-      if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR
-	  && !DECL_P (TREE_OPERAND (TREE_OPERAND (expr, 0), 0))
-	  /* ???  FIXME.  We should always fold these.  */
-	  && !CONSTANT_CLASS_P (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)))
+      if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST
+	  || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
 	{
-	  error ("Invalid address operand for MEM_REF.");
+	  error ("Invalid offset operand in MEM_REF.");
 	  debug_generic_stmt (expr);
 	  return true;
 	}
