diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6b03b42ff0fe..b38240c70a70 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2009-12-17  Shujing Zhao  <pearly.zhao@oracle.com>
+
+	PR c/40885
+	* c-common.h (ref_operator): New type.
+	(build_indirect_ref): Adjust prototype with new argument.
+	* c-typeck.c (build_indirect_ref): Accept ref_operator as argument and
+	emit the diagnostics for easy translation.
+	(build_array_ref): Update calls to build_indirect_ref.
+	* c-omp.c (c_finish_omp_atomic): Likewise.
+	* c-parser.c (c_parser_unary_expression,
+	c_parser_postfix_expression_after_primary): Likewise.
+
 2009-12-16  Richard Guenther  <rguenther@suse.de>
 
 	PR lto/42392
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 5830d7b93352..6f8d832d455a 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -391,6 +391,20 @@ extern c_language_kind c_language;
 #define c_dialect_cxx()		((c_language & clk_cxx) != 0)
 #define c_dialect_objc()	((c_language & clk_objc) != 0)
 
+/* The various name of operator that appears in error messages. */
+typedef enum ref_operator {
+  /* NULL */
+  RO_NULL,
+  /* array indexing */
+  RO_ARRAY_INDEXING,
+  /* unary * */
+  RO_UNARY_STAR,
+  /* -> */
+  RO_ARROW,
+  /* implicit conversion */
+  RO_IMPLICIT_CONVERSION
+} ref_operator;
+
 /* Information about a statement tree.  */
 
 struct GTY(()) stmt_tree_s {
@@ -448,7 +462,7 @@ extern tree pushdecl_top_level (tree);
 extern tree pushdecl (tree);
 extern tree build_modify_expr (location_t, tree, tree, enum tree_code,
 			       location_t, tree, tree);
-extern tree build_indirect_ref (location_t, tree, const char *);
+extern tree build_indirect_ref (location_t, tree, ref_operator);
 
 extern int c_expand_decl (tree);
 
diff --git a/gcc/c-omp.c b/gcc/c-omp.c
index 6f1cb99720e5..eb6f3ef78de5 100644
--- a/gcc/c-omp.c
+++ b/gcc/c-omp.c
@@ -145,7 +145,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs)
       DECL_CONTEXT (var) = current_function_decl;
       addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
     }
-  lhs = build_indirect_ref (loc, addr, NULL);
+  lhs = build_indirect_ref (loc, addr, RO_NULL);
 
   /* There are lots of warnings, errors, and conversions that need to happen
      in the course of interpreting a statement.  Use the normal mechanisms
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 37f779635132..bf66a584ba8e 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -5102,7 +5102,7 @@ c_parser_unary_expression (c_parser *parser)
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = default_function_array_conversion (exp_loc, op);
-      ret.value = build_indirect_ref (op_loc, op.value, "unary *");
+      ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
       return ret;
     case CPP_PLUS:
       if (!c_dialect_objc () && !in_system_header)
@@ -5947,7 +5947,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
 	  expr.value = build_component_ref (op_loc,
 					    build_indirect_ref (op_loc,
 								expr.value,
-								"->"),
+								RO_ARROW),
 					    ident);
 	  expr.original_code = ERROR_MARK;
 	  if (TREE_CODE (expr.value) != COMPONENT_REF)
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 184b4063709d..dbaddd684666 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -2107,7 +2107,7 @@ build_component_ref (location_t loc, tree datum, tree component)
    LOC is the location to use for the generated tree.  */
 
 tree
-build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
+build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
 {
   tree pointer = default_conversion (ptr);
   tree type = TREE_TYPE (pointer);
@@ -2165,8 +2165,26 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
 	}
     }
   else if (TREE_CODE (pointer) != ERROR_MARK)
-    error_at (loc,
-	      "invalid type argument of %qs (have %qT)", errorstring, type);
+    switch (errstring)
+      {
+         case RO_ARRAY_INDEXING:
+           error_at (loc,
+                     "invalid type argument of array indexing (have %qT)",
+                     type);
+           break;
+         case RO_UNARY_STAR:
+           error_at (loc,
+                     "invalid type argument of unary %<*%> (have %qT)",
+                     type);
+           break;
+         case RO_ARROW:
+           error_at (loc,
+                     "invalid type argument of %<->%> (have %qT)",
+                     type);
+           break;
+         default:
+           gcc_unreachable ();
+      }
   return error_mark_node;
 }
 
@@ -2301,7 +2319,7 @@ build_array_ref (location_t loc, tree array, tree index)
 
       return build_indirect_ref
 	(loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
-	 "array indexing");
+	 RO_ARRAY_INDEXING);
     }
 }
 
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8d2663ba23ea..4a756cf33d36 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,30 @@
+2009-12-17  Shujing Zhao  <pearly.zhao@oracle.com>
+
+	* typeck.c (build_indirect_ref): Update the argument.
+	(build_x_indirect_ref): Likewise.
+	(cp_build_indirect_ref): Update the argument and emit the diagnostics
+	for easy translation.
+	(build_class_member_access_expr, build_array_ref,
+	get_member_function_from_ptrfunc): Update calls.
+	* cp-tree.h (build_x_indirect_ref, cp_build_indirect_ref): Update
+	prototypes.
+	* call.c (build_new_op, convert_like_real, build_x_va_arg,
+	build_over_call): Update calls.
+	* class.c (build_base_path, build_simple_base_path, build_vfn_ref):
+	Likewise.
+	* decl.c (start_preparsed_function): Likewise.
+	* except.c (expand_start_catch_block, build_throw): Likewise.
+	* init.c (emit_mem_initializers, expand_virtual_init,
+	expand_virtual_init, build_new_1, build_vec_init, build_delete,
+	build_vec_delete): Likewise.
+	* parser.c (cp_parser_unary_expression): Likewise.
+	* pt.c (tsubst_copy_and_build): Likewise.
+	* rtti.c (build_headof, get_tinfo_decl_dynamic, get_typeid): Likewise.
+	* semantics.c (finish_non_static_data_member, thisify_lambda_field):
+	Likewise.
+	* tree.c (build_dummy_object, stabilize_expr): Likewise.
+	* typeck2.c (build_x_arrow): Likewise.
+
 2009-12-16  Jason Merrill  <jason@redhat.com>
 
 	PR c++/42387
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 1f171800ffd9..d375302e722c 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4464,7 +4464,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
       return cp_build_modify_expr (arg1, code2, arg2, complain);
 
     case INDIRECT_REF:
-      return cp_build_indirect_ref (arg1, "unary *", complain);
+      return cp_build_indirect_ref (arg1, RO_UNARY_STAR, complain);
 
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
@@ -4509,7 +4509,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
       return build_array_ref (input_location, arg1, arg2);
 
     case MEMBER_REF:
-      return build_m_component_ref (cp_build_indirect_ref (arg1, NULL, 
+      return build_m_component_ref (cp_build_indirect_ref (arg1, RO_NULL, 
                                                            complain), 
                                     arg2);
 
@@ -5024,7 +5024,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  expr = cp_build_unary_op (ADDR_EXPR, expr, 0, complain);
 	  expr = convert_to_base (expr, build_pointer_type (totype),
 				  !c_cast_p, /*nonnull=*/true);
-	  expr = cp_build_indirect_ref (expr, "implicit conversion", complain);
+	  expr = cp_build_indirect_ref (expr, RO_IMPLICIT_CONVERSION, complain);
 	  return expr;
 	}
 
@@ -5242,7 +5242,7 @@ build_x_va_arg (tree expr, tree type)
       error ("cannot receive objects of non-trivially-copyable type %q#T "
 	     "through %<...%>; ", type);
       expr = convert (build_pointer_type (type1), null_node);
-      expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
+      expr = cp_build_indirect_ref (expr, RO_NULL, tf_warning_or_error);
       return expr;
     }
 
@@ -5739,7 +5739,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       if (targ)
 	arg = targ;
       else
-	arg = cp_build_indirect_ref (arg, 0, complain);
+	arg = cp_build_indirect_ref (arg, RO_NULL, complain);
 
       if (TREE_CODE (arg) == TARGET_EXPR
 	  && TARGET_EXPR_LIST_INIT_P (arg))
@@ -5774,7 +5774,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	       || (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))
 		   && !move_fn_p (fn)))
 	{
-	  tree to = stabilize_reference (cp_build_indirect_ref (fa, 0,
+	  tree to = stabilize_reference (cp_build_indirect_ref (fa, RO_NULL,
 								complain));
 
 	  val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
@@ -5786,14 +5786,14 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	   && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
     {
       tree to = stabilize_reference
-	(cp_build_indirect_ref (argarray[0], 0, complain));
+	(cp_build_indirect_ref (argarray[0], RO_NULL, complain));
       tree type = TREE_TYPE (to);
       tree as_base = CLASSTYPE_AS_BASE (type);
       tree arg = argarray[1];
 
       if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
 	{
-	  arg = cp_build_indirect_ref (arg, 0, complain);
+	  arg = cp_build_indirect_ref (arg, RO_NULL, complain);
 	  val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg);
 	}
       else
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index fff438033d35..16d566682a6d 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -297,7 +297,7 @@ build_base_path (enum tree_code code,
     {
       expr = build_nop (build_pointer_type (target_type), expr);
       if (!want_pointer)
-	expr = build_indirect_ref (EXPR_LOCATION (expr), expr, NULL);
+	expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
       return expr;
     }
 
@@ -343,7 +343,7 @@ build_base_path (enum tree_code code,
 	 interesting to the optimizers anyway.  */
       && !has_empty)
     {
-      expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
+      expr = cp_build_indirect_ref (expr, RO_NULL, tf_warning_or_error);
       expr = build_simple_base_path (expr, binfo);
       if (want_pointer)
 	expr = build_address (expr);
@@ -368,11 +368,11 @@ build_base_path (enum tree_code code,
 	  t = TREE_TYPE (TYPE_VFIELD (current_class_type));
 	  t = build_pointer_type (t);
 	  v_offset = convert (t, current_vtt_parm);
-	  v_offset = cp_build_indirect_ref (v_offset, NULL, 
+	  v_offset = cp_build_indirect_ref (v_offset, RO_NULL, 
                                             tf_warning_or_error);
 	}
       else
-	v_offset = build_vfield_ref (cp_build_indirect_ref (expr, NULL,
+	v_offset = build_vfield_ref (cp_build_indirect_ref (expr, RO_NULL,
                                                             tf_warning_or_error),
 				     TREE_TYPE (TREE_TYPE (expr)));
 
@@ -381,7 +381,7 @@ build_base_path (enum tree_code code,
       v_offset = build1 (NOP_EXPR,
 			 build_pointer_type (ptrdiff_type_node),
 			 v_offset);
-      v_offset = cp_build_indirect_ref (v_offset, NULL, tf_warning_or_error);
+      v_offset = cp_build_indirect_ref (v_offset, RO_NULL, tf_warning_or_error);
       TREE_CONSTANT (v_offset) = 1;
 
       offset = convert_to_integer (ptrdiff_type_node,
@@ -424,7 +424,7 @@ build_base_path (enum tree_code code,
     null_test = NULL;
 
   if (!want_pointer)
-    expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
+    expr = cp_build_indirect_ref (expr, RO_NULL, tf_warning_or_error);
 
  out:
   if (null_test)
@@ -458,7 +458,7 @@ build_simple_base_path (tree expr, tree binfo)
 	 in the back end.  */
       temp = unary_complex_lvalue (ADDR_EXPR, expr);
       if (temp)
-	expr = cp_build_indirect_ref (temp, NULL, tf_warning_or_error);
+	expr = cp_build_indirect_ref (temp, RO_NULL, tf_warning_or_error);
 
       return expr;
     }
@@ -646,7 +646,7 @@ build_vfn_ref (tree instance_ptr, tree idx)
 {
   tree aref;
 
-  aref = build_vtbl_ref_1 (cp_build_indirect_ref (instance_ptr, 0,
+  aref = build_vtbl_ref_1 (cp_build_indirect_ref (instance_ptr, RO_NULL,
                                                   tf_warning_or_error), 
                            idx);
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4e32f9bccc05..469dcecb1841 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5297,9 +5297,9 @@ extern tree build_class_member_access_expr      (tree, tree, tree, bool,
 						 tsubst_flags_t);
 extern tree finish_class_member_access_expr     (tree, tree, bool, 
 						 tsubst_flags_t);
-extern tree build_x_indirect_ref		(tree, const char *, 
+extern tree build_x_indirect_ref		(tree, ref_operator, 
                                                  tsubst_flags_t);
-extern tree cp_build_indirect_ref		(tree, const char *,
+extern tree cp_build_indirect_ref		(tree, ref_operator,
                                                  tsubst_flags_t);
 extern tree build_array_ref			(location_t, tree, tree);
 extern tree get_member_function_from_ptrfunc	(tree *, tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1c3f2efe32a5..a83d39f3fd8e 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11916,7 +11916,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
       gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE);
 
       cp_function_chain->x_current_class_ref
-	= cp_build_indirect_ref (t, NULL, tf_warning_or_error);
+	= cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error);
       cp_function_chain->x_current_class_ptr = t;
 
       /* Constructors and destructors need to know whether they're "in
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 66dc14eaefbc..83164c86a7eb 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -442,7 +442,7 @@ expand_start_catch_block (tree decl)
 		    fold_build1_loc (input_location,
 				 NEGATE_EXPR, sizetype,
 			 	 TYPE_SIZE_UNIT (TREE_TYPE (exp))));
-      exp = cp_build_indirect_ref (exp, NULL, tf_warning_or_error);
+      exp = cp_build_indirect_ref (exp, RO_NULL, tf_warning_or_error);
       initialize_handler_parm (decl, exp);
       return type;
     }
@@ -718,7 +718,7 @@ build_throw (tree exp)
       allocate_expr = get_target_expr (allocate_expr);
       ptr = TARGET_EXPR_SLOT (allocate_expr);
       object = build_nop (build_pointer_type (temp_type), ptr);
-      object = cp_build_indirect_ref (object, NULL, tf_warning_or_error);
+      object = cp_build_indirect_ref (object, RO_NULL, tf_warning_or_error);
 
       elided = (TREE_CODE (exp) == TARGET_EXPR);
 
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index e6397446b023..1bd80ffa0f86 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -834,7 +834,7 @@ emit_mem_initializers (tree mem_inits)
 	  base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
 				       subobject, 1);
 	  expand_aggr_init_1 (subobject, NULL_TREE,
-			      cp_build_indirect_ref (base_addr, NULL,
+			      cp_build_indirect_ref (base_addr, RO_NULL,
                                                      tf_warning_or_error),
 			      arguments,
 			      LOOKUP_NORMAL,
@@ -918,7 +918,7 @@ expand_virtual_init (tree binfo, tree decl)
 		      TREE_TYPE (vtt_parm),
 		      vtt_parm,
 		      vtt_index);
-      vtbl2 = cp_build_indirect_ref (vtbl2, NULL, tf_warning_or_error);
+      vtbl2 = cp_build_indirect_ref (vtbl2, RO_NULL, tf_warning_or_error);
       vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
 
       /* The actual initializer is the VTT value only in the subobject
@@ -933,7 +933,7 @@ expand_virtual_init (tree binfo, tree decl)
     }
 
   /* Compute the location of the vtpr.  */
-  vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, NULL, 
+  vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, RO_NULL, 
                                                       tf_warning_or_error),
 			       TREE_TYPE (binfo));
   gcc_assert (vtbl_ptr != error_mark_node);
@@ -2055,7 +2055,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
 				alloc_node, cookie_ptr);
       size_ptr_type = build_pointer_type (sizetype);
       cookie_ptr = fold_convert (size_ptr_type, cookie_ptr);
-      cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain);
+      cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
 
       cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts);
 
@@ -2067,7 +2067,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
 					    NEGATE_EXPR, sizetype,
 					    size_in_bytes (sizetype)));
 
-	  cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain);
+	  cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
 	  cookie = build2 (MODIFY_EXPR, sizetype, cookie,
 			   size_in_bytes (elt_type));
 	  cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
@@ -2154,7 +2154,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
 	}
       else
 	{
-	  init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
+	  init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain);
 
 	  if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
 	    {
@@ -2949,7 +2949,7 @@ build_vec_init (tree base, tree maxindex, tree init,
     {
       atype = build_pointer_type (atype);
       stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
-      stmt_expr = cp_build_indirect_ref (stmt_expr, NULL, complain);
+      stmt_expr = cp_build_indirect_ref (stmt_expr, RO_NULL, complain);
       TREE_NO_WARNING (stmt_expr) = 1;
     }
 
@@ -3144,7 +3144,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
 				/*alloc_fn=*/NULL_TREE);
 	}
 
-      expr = build_dtor_call (cp_build_indirect_ref (addr, NULL, 
+      expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, 
                                                      tf_warning_or_error),
 			      auto_delete, flags);
       if (do_delete)
@@ -3298,7 +3298,7 @@ build_vec_delete (tree base, tree maxindex,
 			    size_ptr_type,
 			    fold_convert (size_ptr_type, base),
 			    cookie_addr);
-      maxindex = cp_build_indirect_ref (cookie_addr, NULL, tf_warning_or_error);
+      maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, tf_warning_or_error);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f65dda48cc73..ee4fece68180 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -5628,7 +5628,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
 	{
 	case INDIRECT_REF:
 	  non_constant_p = "%<*%>";
-	  expression = build_x_indirect_ref (cast_expression, "unary *",
+	  expression = build_x_indirect_ref (cast_expression, RO_UNARY_STAR,
                                              tf_warning_or_error);
 	  break;
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 24852dd22553..395a026311c5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11858,7 +11858,7 @@ tsubst_copy_and_build (tree t,
 	      r = convert_from_reference (r);
 	  }
 	else
-	  r = build_x_indirect_ref (r, "unary *", complain);
+	  r = build_x_indirect_ref (r, RO_UNARY_STAR, complain);
 	return r;
       }
 
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 7378f89fd1aa..0f7225fc5426 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -188,7 +188,7 @@ build_headof (tree exp)
   index = build_int_cst (NULL_TREE,
 			 -2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
 
-  offset = build_vtbl_ref (cp_build_indirect_ref (exp, NULL, 
+  offset = build_vtbl_ref (cp_build_indirect_ref (exp, RO_NULL, 
                                                   tf_warning_or_error), 
                            index);
 
@@ -277,7 +277,7 @@ get_tinfo_decl_dynamic (tree exp)
     /* Otherwise return the type_info for the static type of the expr.  */
     t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
 
-  return cp_build_indirect_ref (t, NULL, tf_warning_or_error);
+  return cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error);
 }
 
 static bool
@@ -483,7 +483,7 @@ get_typeid (tree type)
   if (!type)
     return error_mark_node;
 
-  return cp_build_indirect_ref (get_tinfo_ptr (type), NULL, 
+  return cp_build_indirect_ref (get_tinfo_ptr (type), RO_NULL, 
                                 tf_warning_or_error);
 }
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 841efc8fafc6..547e89934c1c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1458,7 +1458,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
     object = cp_build_indirect_ref (lambda_expr_this_capture
 				    (CLASSTYPE_LAMBDA_EXPR
 				     (TREE_TYPE (object))),
-                                    /*errorstring=*/"",
+                                    RO_NULL,
                                     /*complain=*/tf_warning_or_error);
 
   if (current_class_ptr)
@@ -5689,7 +5689,7 @@ thisify_lambda_field (tree decl)
 {
   tree context = lambda_function (DECL_CONTEXT (decl));
   tree object = cp_build_indirect_ref (DECL_ARGUMENTS (context),
-				       /*errorstring*/"",
+				       RO_NULL,
 				       tf_warning_or_error);
   return finish_non_static_data_member (decl, object,
 					/*qualifying_scope*/NULL_TREE);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 7097f8c68b61..865abbcfdd3f 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2292,7 +2292,7 @@ tree
 build_dummy_object (tree type)
 {
   tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
-  return cp_build_indirect_ref (decl, NULL, tf_warning_or_error);
+  return cp_build_indirect_ref (decl, RO_NULL, tf_warning_or_error);
 }
 
 /* We've gotten a reference to a member of TYPE.  Return *this if appropriate,
@@ -2956,7 +2956,7 @@ stabilize_expr (tree exp, tree* initp)
       exp = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error);
       init_expr = get_target_expr (exp);
       exp = TARGET_EXPR_SLOT (init_expr);
-      exp = cp_build_indirect_ref (exp, 0, tf_warning_or_error);
+      exp = cp_build_indirect_ref (exp, RO_NULL, tf_warning_or_error);
     }
   *initp = init_expr;
 
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 782502d2734f..2a036e391edb 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2092,7 +2092,7 @@ build_class_member_access_expr (tree object, tree member,
   {
     tree temp = unary_complex_lvalue (ADDR_EXPR, object);
     if (temp)
-      object = cp_build_indirect_ref (temp, NULL, complain);
+      object = cp_build_indirect_ref (temp, RO_NULL, complain);
   }
 
   /* In [expr.ref], there is an explicit list of the valid choices for
@@ -2592,7 +2592,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
    Must also handle REFERENCE_TYPEs for C++.  */
 
 tree
-build_x_indirect_ref (tree expr, const char *errorstring, 
+build_x_indirect_ref (tree expr, ref_operator errorstring, 
                       tsubst_flags_t complain)
 {
   tree orig_expr = expr;
@@ -2623,13 +2623,13 @@ build_x_indirect_ref (tree expr, const char *errorstring,
 /* Helper function called from c-common.  */
 tree
 build_indirect_ref (location_t loc __attribute__ ((__unused__)),
-		    tree ptr, const char *errorstring)
+		    tree ptr, ref_operator errorstring)
 {
   return cp_build_indirect_ref (ptr, errorstring, tf_warning_or_error);
 }
 
 tree
-cp_build_indirect_ref (tree ptr, const char *errorstring, 
+cp_build_indirect_ref (tree ptr, ref_operator errorstring, 
                        tsubst_flags_t complain)
 {
   tree pointer, type;
@@ -2697,14 +2697,38 @@ cp_build_indirect_ref (tree ptr, const char *errorstring,
   /* `pointer' won't be an error_mark_node if we were given a
      pointer to member, so it's cool to check for this here.  */
   else if (TYPE_PTR_TO_MEMBER_P (type))
-    error ("invalid use of %qs on pointer to member", errorstring);
+    switch (errorstring)
+      {
+         case RO_ARRAY_INDEXING:
+           error ("invalid use of array indexing on pointer to member");
+           break;
+         case RO_UNARY_STAR:
+           error ("invalid use of unary %<*%> on pointer to member");
+           break;
+         case RO_IMPLICIT_CONVERSION:
+           error ("invalid use of implicit conversion on pointer to member");
+           break;
+         default:
+           gcc_unreachable ();
+      }
   else if (pointer != error_mark_node)
-    {
-      if (errorstring)
-	error ("invalid type argument of %qs", errorstring);
-      else
-	error ("invalid type argument");
-    }
+    switch (errorstring)
+      {
+         case RO_NULL:
+           error ("invalid type argument");
+           break;
+         case RO_ARRAY_INDEXING:
+           error ("invalid type argument of array indexing");
+           break;
+         case RO_UNARY_STAR:
+           error ("invalid type argument of unary %<*%>");
+           break;
+         case RO_IMPLICIT_CONVERSION:
+           error ("invalid type argument of implicit conversion");
+           break;
+         default:
+           gcc_unreachable ();
+      }
   return error_mark_node;
 }
 
@@ -2871,7 +2895,7 @@ build_array_ref (location_t loc, tree array, tree idx)
     ret = cp_build_indirect_ref (cp_build_binary_op (input_location,
 						     PLUS_EXPR, ar, ind,
 						     tf_warning_or_error),
-                                 "array indexing",
+                                 RO_ARRAY_INDEXING,
                                  tf_warning_or_error);
     protected_set_expr_location (ret, loc);
     return ret;
@@ -2980,7 +3004,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
       /* Next extract the vtable pointer from the object.  */
       vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
 		     instance_ptr);
-      vtbl = cp_build_indirect_ref (vtbl, NULL, tf_warning_or_error);
+      vtbl = cp_build_indirect_ref (vtbl, RO_NULL, tf_warning_or_error);
       /* If the object is not dynamic the access invokes undefined
 	 behavior.  As it is not executed in this case silence the
 	 spurious warnings it may provoke.  */
@@ -2990,7 +3014,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
       e2 = fold_build2_loc (input_location,
 			POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
 			fold_convert (sizetype, idx));
-      e2 = cp_build_indirect_ref (e2, NULL, tf_warning_or_error);
+      e2 = cp_build_indirect_ref (e2, RO_NULL, tf_warning_or_error);
       TREE_CONSTANT (e2) = 1;
 
       /* When using function descriptors, the address of the
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 348c6576c111..a4bd3811ead0 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1434,7 +1434,7 @@ build_x_arrow (tree expr)
 	  return expr;
 	}
 
-      return cp_build_indirect_ref (last_rval, NULL, tf_warning_or_error);
+      return cp_build_indirect_ref (last_rval, RO_NULL, tf_warning_or_error);
     }
 
   if (types_memoized)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e960cd098e67..f162037a99d7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2009-12-17  Shujing Zhao  <pearly.zhao@oracle.com>
+
+	* g++.old-deja/g++.mike/net31.C: Make expected dg-error strings
+	explicit.
+	* g++.old-deja/g++.bugs/900213_02.C: Likewise.
+	* g++.old-deja/g++.bugs/900215_02.C: Likewise.
+
 2009-12-16  Richard Guenther  <rguenther@suse.de>
 
 	PR lto/42392
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900213_02.C b/gcc/testsuite/g++.old-deja/g++.bugs/900213_02.C
index c6415e1ac0d4..9b9ae994de91 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900213_02.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900213_02.C
@@ -16,7 +16,7 @@ int struct0::*dmp;
 
 void global_function_0 ()
 {
-  i = *dmp;			// { dg-error "" } causes abort
+  i = *dmp;			// { dg-error "invalid use of unary '\\\*' on pointer to member" } causes abort
 }
 
 int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900215_02.C b/gcc/testsuite/g++.old-deja/g++.bugs/900215_02.C
index 6802299b6b04..3309c886384a 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900215_02.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900215_02.C
@@ -41,8 +41,8 @@ void struct0::function_member ()
   i = (this->*fmp) ();		// perfectly legal - for both cfront and g++
   i = this->*dmp;		// perfectly legal - for both cfront and g++
 
-  i = (*fmp) ();		// { dg-error "" } 
-  i = *dmp;			// { dg-error "" } 
+  i = (*fmp) ();		// { dg-error "invalid use of unary '\\\*' on pointer to member" } 
+  i = *dmp;			// { dg-error "invalid use of unary '\\\*' on pointer to member" } 
 }
 
 int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/net31.C b/gcc/testsuite/g++.old-deja/g++.mike/net31.C
index 6565a3697a9a..8bc159b136ea 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/net31.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/net31.C
@@ -40,7 +40,7 @@ foo_b& foo_c<TP>::bug_func(int x) {
         static foo_b retval(m);
         retval.bar_a(m);
         for (register int i = 0; i < m; i++)
-	  retval(i) = (*(operator()(i)))(x);		// { dg-error "" } 
+	  retval(i) = (*(operator()(i)))(x);		// { dg-error "invalid use of unary '\\\*'" } 
         return retval;
 }