This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch to clean up uses of default_function_array_conversion


This patch cleans up the C front end handling of the conversion of
functions and arrays to pointers.  Previously, default_conversion did
both this conversion (which needs to be done on almost all
expressions) and the integer promotions (only on operands of certain
operators) and some other operations; there were also calls to
default_function_array_conversion spread about in various places.
After this patch, default_conversion no longer calls
default_function_array_conversion; instead it is called from the
parser as required.

A logically next cleanup would be to remove
decl_constant_value_for_broken_optimization and the associated attempt
in default_conversion to optimize references to const variables.  This
would allow various calls to default_conversion where integer
promotions are not required to be removed.  It is however possible to
construct cases where not doing this early optimization of const
variables leads to certain optimizations in folding not getting done
because the const values are only visible later in tree-ssa and we
lack a tree combiner to enable all the optimizations at that stage
which fold does on more complicated trees; but I doubt this would lead
to a significant difference in practice justifying retaining
decl_constant_value_for_broken_optimization.

The purpose of this particular cleanup is as another incremental stage
towards recording lvalueness in the c_expr structure and so stopping
the C front end from depending on fold preserving non-lvalueness of
trees, so that NON_LVALUE_EXPR can eventually be removed.  Various
functions calling default_function_array_conversion (directly or
indirectly) receive only trees rather than c_expr structures and are
difficult to make receive c_expr structures (e.g. because of being
called by common C/C++ code, because of receiving a TREE_LIST of
expressions or because of being involved in initialization and called
both when parsing and later with stored initializer fragments which
are just trees).  The idea is that subsequent cleanups will split out
from default_function_array_conversion the actual conversion of
functions or arrays to pointers, leaving the checking of whether
arrays are lvalues in default_function_array_conversion.  The
remaining places outside the parser which still call
default_function_array_conversion after this patch can then call those
other functions on trees so default_function_array_conversion can
then take a c_expr.  Thus only the parser will deal with whether
arrays which might or might not be lvalues should be converted to
pointer, and only a few other functions which require lvalues will
need to receive c_expr structures at this stage.

The following places call default_function_array_conversion outside
the parser after this patch: build_function_call for better handling
of calls to named functions which may be overloaded built-in functions
(the old comment about not being able to use
default_function_array_conversion to take the address was wrong:
marking an inline function addressable does not now cause it to be
output if not needed); build_unary_op (taking addresses of ARRAY_REF),
digest_init/output_init_element (for string literals and compound
literals which might initialize arrays so can't be converted to
pointers in the parser).  In addition, arrays aren't converted to
pointers before calling build_array_ref, or in some other places where
both arrays/functions and the pointers to which they are converted
would be equally invalid, although perhaps we should do the
conversions in such cases anyway.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  Applied
to mainline.

-- 
Joseph S. Myers               http://www.srcf.ucam.org/~jsm28/gcc/
    jsm@polyomino.org.uk (personal mail)
    joseph@codesourcery.com (CodeSourcery mail)
    jsm28@gcc.gnu.org (Bugzilla assignments and CCs)

2005-06-15  Joseph S. Myers  <joseph@codesourcery.com>

	* c-tree.h (default_function_array_conversion): Declare.
	* c-typeck.c (default_function_array_conversion): Export.  Correct
	comment.
	(default_conversion): Do not call
	default_function_array_conversion.  Do not allow FUNCTION_TYPE.
	(build_function_call): Call default_function_array_conversion on
	the function.
	(convert_arguments): Do not call it on the function arguments.
	(build_unary_op): Do not allow ARRAY_TYPE or FUNCTION_TYPE for
	TRUTH_NOT_EXPR.  Call default_function_array_conversion for taking
	address of ARRAY_REF.
	(build_compound_expr): Do not call
	default_function_array_conversion.
	(build_c_cast): Do not call default_function_array_conversion.
	(convert_for_assignment): Do not call default_conversion.
	(digest_init): Call default_function_array_conversion to convert
	string constants and compound literals to pointers, but not
	otherwise.
	(output_init_element): Likewise.
	(build_asm_expr): Do not call default_function_array_conversion.
	(c_process_expr_stmt): Likewise.
	(c_objc_common_truthvalue_conversion): Likewise.  Do not allow
	FUNCTION_TYPE.
	* c-parser.c (c_parser_expression_conv): New.
	(c_parser_asm_operands, c_parser_expr_list): Add convert_p
	argument.  All callers changed.  Call
	default_function_array_conversion if convert_p.
	(c_parser_initializer, c_parser_initval): Call
	default_function_array_conversion except for string constants and
	compound literals.
	(c_parser_initelt): Call default_function_array_conversion for
	ObjC expression received.
	(c_parser_statement_after_labels): Call c_parser_expression_conv
	for return and expression statements.
	(c_parser_paren_condition, c_parser_for_statement,
	c_parser_conditional_expression): Call c_parser_expression_conv.
	(c_parser_expr_no_commas, c_parser_conditional_expression,
	c_parser_binary_expression, c_parser_cast_expression,
	c_parser_unary_expression): Call
	default_function_array_conversion.

objc:
2005-06-15  Joseph S. Myers  <joseph@codesourcery.com>

	* objc-act.c (my_build_string_pointer): New.
	(objc_get_class_reference, get_super_receiver): Call
	my_build_string_pointer instead of my_build_string when building
	function arguments.

testsuite:
2005-06-15  Joseph S. Myers  <joseph@codesourcery.com>

	* gcc.dg/noncompile/20040203-3.c: Update expected message.

diff -rupN GCC.orig/gcc/c-parser.c GCC/gcc/c-parser.c
--- GCC.orig/gcc/c-parser.c	2005-06-08 16:22:05.000000000 +0000
+++ GCC/gcc/c-parser.c	2005-06-15 11:58:11.000000000 +0000
@@ -904,7 +904,7 @@ static void c_parser_while_statement (c_
 static void c_parser_do_statement (c_parser *);
 static void c_parser_for_statement (c_parser *);
 static tree c_parser_asm_statement (c_parser *);
-static tree c_parser_asm_operands (c_parser *);
+static tree c_parser_asm_operands (c_parser *, bool);
 static tree c_parser_asm_clobbers (c_parser *);
 static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
 static struct c_expr c_parser_conditional_expression (c_parser *,
@@ -920,7 +920,8 @@ static struct c_expr c_parser_postfix_ex
 static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
 								struct c_expr);
 static struct c_expr c_parser_expression (c_parser *);
-static tree c_parser_expr_list (c_parser *);
+static struct c_expr c_parser_expression_conv (c_parser *);
+static tree c_parser_expr_list (c_parser *, bool);
 
 /* These Objective-C parser functions are only ever called when
    compiling Objective-C.  */
@@ -2749,7 +2750,7 @@ c_parser_attributes (c_parser *parser)
 		{
 		  c_parser_consume_token (parser);
 		  attr_args = tree_cons (NULL_TREE, arg1,
-					 c_parser_expr_list (parser));
+					 c_parser_expr_list (parser, false));
 		}
 	    }
 	  else
@@ -2757,7 +2758,7 @@ c_parser_attributes (c_parser *parser)
 	      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
 		attr_args = NULL_TREE;
 	      else
-		attr_args = c_parser_expr_list (parser);
+		attr_args = c_parser_expr_list (parser, false);
 	    }
 	  attr = build_tree_list (attr_name, attr_args);
 	  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
@@ -2874,7 +2875,14 @@ c_parser_initializer (c_parser *parser)
   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
     return c_parser_braced_init (parser, NULL_TREE, false);
   else
-    return c_parser_expr_no_commas (parser, NULL);
+    {
+      struct c_expr ret;
+      ret = c_parser_expr_no_commas (parser, NULL);
+      if (TREE_CODE (ret.value) != STRING_CST
+	  && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
+	ret.value = default_function_array_conversion (ret.value);
+      return ret;
+    }
 }
 
 /* Parse a braced initializer list.  TYPE is the type specified for a
@@ -3031,6 +3039,7 @@ c_parser_initelt (c_parser *parser)
 		      tree next;
 		      c_parser_consume_token (parser);
 		      next = c_parser_expr_no_commas (parser, NULL).value;
+		      next = default_function_array_conversion (next);
 		      rec = build_compound_expr (rec, next);
 		    }
 		parse_message_args:
@@ -3116,7 +3125,13 @@ c_parser_initval (c_parser *parser, stru
   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
     init = c_parser_braced_init (parser, NULL_TREE, true);
   else
-    init = c_parser_expr_no_commas (parser, after);
+    {
+      init = c_parser_expr_no_commas (parser, after);
+      if (init.value != NULL_TREE
+	  && TREE_CODE (init.value) != STRING_CST
+	  && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
+	init.value = default_function_array_conversion (init.value);
+    }
   process_init_element (init);
 }
 
@@ -3498,7 +3513,7 @@ c_parser_statement_after_labels (c_parse
 	    }
 	  else
 	    {
-	      stmt = c_finish_return (c_parser_expression (parser).value);
+	      stmt = c_finish_return (c_parser_expression_conv (parser).value);
 	      goto expect_semicolon;
 	    }
 	  break;
@@ -3546,7 +3561,7 @@ c_parser_statement_after_labels (c_parse
       break;
     default:
     expr_stmt:
-      stmt = c_finish_expr_stmt (c_parser_expression (parser).value);
+      stmt = c_finish_expr_stmt (c_parser_expression_conv (parser).value);
     expect_semicolon:
       c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
       break;
@@ -3579,7 +3594,7 @@ c_parser_paren_condition (c_parser *pars
     return error_mark_node;
   loc = c_parser_peek_token (parser)->location;
   cond = c_objc_common_truthvalue_conversion
-    (c_parser_expression (parser).value);
+    (c_parser_expression_conv (parser).value);
   if (EXPR_P (cond))
     SET_EXPR_LOCATION (cond, loc);
   c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -3814,7 +3829,7 @@ c_parser_for_statement (c_parser *parser
 	}
       else
 	{
-	  tree ocond = c_parser_expression (parser).value;
+	  tree ocond = c_parser_expression_conv (parser).value;
 	  cond = c_objc_common_truthvalue_conversion (ocond);
 	  if (EXPR_P (cond))
 	    SET_EXPR_LOCATION (cond, loc);
@@ -3910,7 +3925,7 @@ c_parser_asm_statement (c_parser *parser
       || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
     outputs = NULL_TREE;
   else
-    outputs = c_parser_asm_operands (parser);
+    outputs = c_parser_asm_operands (parser, false);
   if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
     {
       inputs = NULL_TREE;
@@ -3928,7 +3943,7 @@ c_parser_asm_statement (c_parser *parser
       || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
     inputs = NULL_TREE;
   else
-    inputs = c_parser_asm_operands (parser);
+    inputs = c_parser_asm_operands (parser, true);
   if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
     {
       clobbers = NULL_TREE;
@@ -3956,7 +3971,9 @@ c_parser_asm_statement (c_parser *parser
   return ret;
 }
 
-/* Parse asm operands, a GNU extension.
+/* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
+   not outputs), apply the default conversion of functions and arrays
+   to pointers.
 
    asm-operands:
      asm-operand
@@ -3968,7 +3985,7 @@ c_parser_asm_statement (c_parser *parser
 */
 
 static tree
-c_parser_asm_operands (c_parser *parser)
+c_parser_asm_operands (c_parser *parser, bool convert_p)
 {
   tree list = NULL_TREE;
   while (true)
@@ -4005,6 +4022,8 @@ c_parser_asm_operands (c_parser *parser)
 	  return NULL_TREE;
 	}
       expr = c_parser_expression (parser).value;
+      if (convert_p)
+	expr = default_function_array_conversion (expr);
       c_lex_string_translate = 0;
       if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
 	{
@@ -4110,6 +4129,7 @@ c_parser_expr_no_commas (c_parser *parse
     }
   c_parser_consume_token (parser);
   rhs = c_parser_expr_no_commas (parser, NULL);
+  rhs.value = default_function_array_conversion (rhs.value);
   ret.value = build_modify_expr (lhs.value, code, rhs.value);
   if (code == NOP_EXPR)
     ret.original_code = MODIFY_EXPR;
@@ -4143,6 +4163,7 @@ c_parser_conditional_expression (c_parse
   cond = c_parser_binary_expression (parser, after);
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
     return cond;
+  cond.value = default_function_array_conversion (cond.value);
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
@@ -4159,7 +4180,7 @@ c_parser_conditional_expression (c_parse
 	= c_objc_common_truthvalue_conversion
 	(default_conversion (cond.value));
       skip_evaluation += cond.value == truthvalue_false_node;
-      exp1 = c_parser_expression (parser);
+      exp1 = c_parser_expression_conv (parser);
       skip_evaluation += ((cond.value == truthvalue_true_node)
 			  - (cond.value == truthvalue_false_node));
     }
@@ -4171,6 +4192,7 @@ c_parser_conditional_expression (c_parse
       return ret;
     }
   exp2 = c_parser_conditional_expression (parser, NULL);
+  exp2.value = default_function_array_conversion (exp2.value);
   skip_evaluation -= cond.value == truthvalue_true_node;
   ret.value = build_conditional_expr (cond.value, exp1.value, exp2.value);
   ret.original_code = ERROR_MARK;
@@ -4294,6 +4316,10 @@ c_parser_binary_expression (c_parser *pa
       default:								      \
 	break;								      \
       }									      \
+    stack[sp - 1].expr.value						      \
+      = default_function_array_conversion (stack[sp - 1].expr.value);	      \
+    stack[sp].expr.value						      \
+      = default_function_array_conversion (stack[sp].expr.value);	      \
     stack[sp - 1].expr = parser_build_binary_op (stack[sp].op,		      \
 						 stack[sp - 1].expr,	      \
 						 stack[sp].expr);	      \
@@ -4394,11 +4420,15 @@ c_parser_binary_expression (c_parser *pa
       switch (ocode)
 	{
 	case TRUTH_ANDIF_EXPR:
+	  stack[sp].expr.value
+	    = default_function_array_conversion (stack[sp].expr.value);
 	  stack[sp].expr.value = c_objc_common_truthvalue_conversion
 	    (default_conversion (stack[sp].expr.value));
 	  skip_evaluation += stack[sp].expr.value == truthvalue_false_node;
 	  break;
 	case TRUTH_ORIF_EXPR:
+	  stack[sp].expr.value
+	    = default_function_array_conversion (stack[sp].expr.value);
 	  stack[sp].expr.value = c_objc_common_truthvalue_conversion
 	    (default_conversion (stack[sp].expr.value));
 	  skip_evaluation += stack[sp].expr.value == truthvalue_true_node;
@@ -4456,6 +4486,7 @@ c_parser_cast_expression (c_parser *pars
 	return c_parser_postfix_expression_after_paren_type (parser,
 							     type_name);
       expr = c_parser_cast_expression (parser, NULL).value;
+      expr = default_function_array_conversion (expr);
       ret.value = c_cast_expr (type_name, expr);
       ret.original_code = ERROR_MARK;
       return ret;
@@ -4495,26 +4526,28 @@ static struct c_expr
 c_parser_unary_expression (c_parser *parser)
 {
   int ext;
-  struct c_expr ret;
+  struct c_expr ret, op;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_PLUS_PLUS:
       c_parser_consume_token (parser);
-      return parser_build_unary_op (PREINCREMENT_EXPR,
-				    c_parser_cast_expression (parser, NULL));
+      op = c_parser_cast_expression (parser, NULL);
+      op.value = default_function_array_conversion (op.value);
+      return parser_build_unary_op (PREINCREMENT_EXPR, op);
     case CPP_MINUS_MINUS:
       c_parser_consume_token (parser);
-      return parser_build_unary_op (PREDECREMENT_EXPR,
-				    c_parser_cast_expression (parser, NULL));
+      op = c_parser_cast_expression (parser, NULL);
+      op.value = default_function_array_conversion (op.value);
+      return parser_build_unary_op (PREDECREMENT_EXPR, op);
     case CPP_AND:
       c_parser_consume_token (parser);
       return parser_build_unary_op (ADDR_EXPR,
 				    c_parser_cast_expression (parser, NULL));
     case CPP_MULT:
       c_parser_consume_token (parser);
-      ret.value
-	= build_indirect_ref (c_parser_cast_expression (parser, NULL).value,
-			      "unary *");
+      op = c_parser_cast_expression (parser, NULL);
+      op.value = default_function_array_conversion (op.value);
+      ret.value = build_indirect_ref (op.value, "unary *");
       ret.original_code = ERROR_MARK;
       return ret;
     case CPP_PLUS:
@@ -4522,20 +4555,24 @@ c_parser_unary_expression (c_parser *par
       if (!c_dialect_objc () && !in_system_header)
 	warning (OPT_Wtraditional,
 		 "traditional C rejects the unary plus operator");
-      return parser_build_unary_op (CONVERT_EXPR,
-				    c_parser_cast_expression (parser, NULL));
+      op = c_parser_cast_expression (parser, NULL);
+      op.value = default_function_array_conversion (op.value);
+      return parser_build_unary_op (CONVERT_EXPR, op);
     case CPP_MINUS:
       c_parser_consume_token (parser);
-      return parser_build_unary_op (NEGATE_EXPR,
-				    c_parser_cast_expression (parser, NULL));
+      op = c_parser_cast_expression (parser, NULL);
+      op.value = default_function_array_conversion (op.value);
+      return parser_build_unary_op (NEGATE_EXPR, op);
     case CPP_COMPL:
       c_parser_consume_token (parser);
-      return parser_build_unary_op (BIT_NOT_EXPR,
-				    c_parser_cast_expression (parser, NULL));
+      op = c_parser_cast_expression (parser, NULL);
+      op.value = default_function_array_conversion (op.value);
+      return parser_build_unary_op (BIT_NOT_EXPR, op);
     case CPP_NOT:
       c_parser_consume_token (parser);
-      return parser_build_unary_op (TRUTH_NOT_EXPR,
-				    c_parser_cast_expression (parser, NULL));
+      op = c_parser_cast_expression (parser, NULL);
+      op.value = default_function_array_conversion (op.value);
+      return parser_build_unary_op (TRUTH_NOT_EXPR, op);
     case CPP_AND_AND:
       /* Refer to the address of a label as a pointer.  */
       c_parser_consume_token (parser);
@@ -4567,14 +4604,14 @@ c_parser_unary_expression (c_parser *par
 	  return ret;
 	case RID_REALPART:
 	  c_parser_consume_token (parser);
-	  return parser_build_unary_op (REALPART_EXPR,
-					c_parser_cast_expression (parser,
-								  NULL));
+	  op = c_parser_cast_expression (parser, NULL);
+	  op.value = default_function_array_conversion (op.value);
+	  return parser_build_unary_op (REALPART_EXPR, op);
 	case RID_IMAGPART:
 	  c_parser_consume_token (parser);
-	  return parser_build_unary_op (IMAGPART_EXPR,
-					c_parser_cast_expression (parser,
-								  NULL));
+	  op = c_parser_cast_expression (parser, NULL);
+	  op.value = default_function_array_conversion (op.value);
+	  return parser_build_unary_op (IMAGPART_EXPR, op);
 	default:
 	  return c_parser_postfix_expression (parser);
 	}
@@ -5204,7 +5241,7 @@ c_parser_postfix_expression_after_primar
 	  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
 	    exprlist = NULL_TREE;
 	  else
-	    exprlist = c_parser_expr_list (parser);
+	    exprlist = c_parser_expr_list (parser, true);
 	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
 				     "expected %<)%>");
 	  expr.value = build_function_call (expr.value, exprlist);
@@ -5213,6 +5250,7 @@ c_parser_postfix_expression_after_primar
 	case CPP_DOT:
 	  /* Structure element reference.  */
 	  c_parser_consume_token (parser);
+	  expr.value = default_function_array_conversion (expr.value);
 	  if (c_parser_next_token_is (parser, CPP_NAME))
 	    ident = c_parser_peek_token (parser)->value;
 	  else
@@ -5229,6 +5267,7 @@ c_parser_postfix_expression_after_primar
 	case CPP_DEREF:
 	  /* Structure element reference.  */
 	  c_parser_consume_token (parser);
+	  expr.value = default_function_array_conversion (expr.value);
 	  if (c_parser_next_token_is (parser, CPP_NAME))
 	    ident = c_parser_peek_token (parser)->value;
 	  else
@@ -5246,12 +5285,14 @@ c_parser_postfix_expression_after_primar
 	case CPP_PLUS_PLUS:
 	  /* Postincrement.  */
 	  c_parser_consume_token (parser);
+	  expr.value = default_function_array_conversion (expr.value);
 	  expr.value = build_unary_op (POSTINCREMENT_EXPR, expr.value, 0);
 	  expr.original_code = ERROR_MARK;
 	  break;
 	case CPP_MINUS_MINUS:
 	  /* Postdecrement.  */
 	  c_parser_consume_token (parser);
+	  expr.value = default_function_array_conversion (expr.value);
 	  expr.value = build_unary_op (POSTDECREMENT_EXPR, expr.value, 0);
 	  expr.original_code = ERROR_MARK;
 	  break;
@@ -5278,13 +5319,27 @@ c_parser_expression (c_parser *parser)
       struct c_expr next;
       c_parser_consume_token (parser);
       next = c_parser_expr_no_commas (parser, NULL);
+      next.value = default_function_array_conversion (next.value);
       expr.value = build_compound_expr (expr.value, next.value);
       expr.original_code = COMPOUND_EXPR;
     }
   return expr;
 }
 
-/* Parse a non-empty list of expressions.
+/* Parse an expression and convert functions or arrays to
+   pointers.  */
+
+static struct c_expr
+c_parser_expression_conv (c_parser *parser)
+{
+  struct c_expr expr;
+  expr = c_parser_expression (parser);
+  expr.value = default_function_array_conversion (expr.value);
+  return expr;
+}
+
+/* Parse a non-empty list of expressions.  If CONVERT_P, convert
+   functions and arrays to pointers.
 
    nonempty-expr-list:
      assignment-expression
@@ -5292,16 +5347,20 @@ c_parser_expression (c_parser *parser)
 */
 
 static tree
-c_parser_expr_list (c_parser *parser)
+c_parser_expr_list (c_parser *parser, bool convert_p)
 {
   struct c_expr expr;
   tree ret, cur;
   expr = c_parser_expr_no_commas (parser, NULL);
+  if (convert_p)
+    expr.value = default_function_array_conversion (expr.value);
   ret = cur = build_tree_list (NULL_TREE, expr.value);
   while (c_parser_next_token_is (parser, CPP_COMMA))
     {
       c_parser_consume_token (parser);
       expr = c_parser_expr_no_commas (parser, NULL);
+      if (convert_p)
+	expr.value = default_function_array_conversion (expr.value);
       cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value);
     }
   return ret;
@@ -6162,7 +6221,7 @@ c_parser_objc_message_args (c_parser *pa
 static tree
 c_parser_objc_keywordexpr (c_parser *parser)
 {
-  tree list = c_parser_expr_list (parser);
+  tree list = c_parser_expr_list (parser, true);
   if (TREE_CHAIN (list) == NULL_TREE)
     {
       /* Just return the expression, remove a level of
diff -rupN GCC.orig/gcc/c-tree.h GCC/gcc/c-tree.h
--- GCC.orig/gcc/c-tree.h	2005-05-09 21:55:57.000000000 +0000
+++ GCC/gcc/c-tree.h	2005-06-14 21:14:04.000000000 +0000
@@ -523,6 +523,7 @@ extern bool c_mark_addressable (tree);
 extern void c_incomplete_type_error (tree, tree);
 extern tree c_type_promotes_to (tree);
 extern tree default_conversion (tree);
+extern tree default_function_array_conversion (tree);
 extern tree composite_type (tree, tree);
 extern tree build_component_ref (tree, tree);
 extern tree build_indirect_ref (tree, const char *);
diff -rupN GCC.orig/gcc/c-typeck.c GCC/gcc/c-typeck.c
--- GCC.orig/gcc/c-typeck.c	2005-06-13 01:23:19.000000000 +0000
+++ GCC/gcc/c-typeck.c	2005-06-15 00:30:22.000000000 +0000
@@ -80,7 +80,6 @@ static int comp_target_types (tree, tree
 static int function_types_compatible_p (tree, tree);
 static int type_lists_compatible_p (tree, tree);
 static tree decl_constant_value_for_broken_optimization (tree);
-static tree default_function_array_conversion (tree);
 static tree lookup_field (tree, tree);
 static tree convert_arguments (tree, tree, tree, tree);
 static tree pointer_diff (tree, tree);
@@ -1263,9 +1262,9 @@ decl_constant_value_for_broken_optimizat
 
 /* Perform the default conversion of arrays and functions to pointers.
    Return the result of converting EXP.  For any other expression, just
-   return EXP.  */
+   return EXP after removing NOPs.  */
 
-static tree
+tree
 default_function_array_conversion (tree exp)
 {
   tree orig_exp;
@@ -1410,8 +1409,7 @@ perform_integral_promotions (tree exp)
 
 
 /* Perform default promotions for C data used in expressions.
-   Arrays and functions are converted to pointers;
-   enumeral types or short or char, to int.
+   Enumeral types or short or char are converted to int.
    In addition, manifest constants symbols are replaced by their values.  */
 
 tree
@@ -1421,8 +1419,10 @@ default_conversion (tree exp)
   tree type = TREE_TYPE (exp);
   enum tree_code code = TREE_CODE (type);
 
-  if (code == FUNCTION_TYPE || code == ARRAY_TYPE)
-    return default_function_array_conversion (exp);
+  /* Functions and arrays have been converted during parsing.  */
+  gcc_assert (code != FUNCTION_TYPE);
+  if (code == ARRAY_TYPE)
+    return exp;
 
   /* Constants can be used directly unless they're not loadable.  */
   if (TREE_CODE (exp) == CONST_DECL)
@@ -1990,18 +1990,8 @@ build_function_call (tree function, tree
 	return tem;
 
       name = DECL_NAME (function);
-
-      /* Differs from default_conversion by not setting TREE_ADDRESSABLE
-	 (because calling an inline function does not mean the function
-	 needs to be separately compiled).  */
-      fntype = build_type_variant (TREE_TYPE (function),
-				   TREE_READONLY (function),
-				   TREE_THIS_VOLATILE (function));
-      fundecl = function;
-      function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
     }
-  else
-    function = default_conversion (function);
+  function = default_function_array_conversion (function);
 
   /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
      expressions, like those used for ObjC messenger dispatches.  */
@@ -2163,8 +2153,6 @@ convert_arguments (tree typelist, tree v
 
       STRIP_TYPE_NOPS (val);
 
-      val = default_function_array_conversion (val);
-
       val = require_complete_type (val);
 
       if (type != 0)
@@ -2589,13 +2577,9 @@ build_unary_op (enum tree_code code, tre
       break;
 
     case TRUTH_NOT_EXPR:
-      /* ??? Why do most validation here but that for non-lvalue arrays
-	 in c_objc_common_truthvalue_conversion?  */
       if (typecode != INTEGER_TYPE
 	  && typecode != REAL_TYPE && typecode != POINTER_TYPE
-	  && typecode != COMPLEX_TYPE
-	  /* These will convert to a pointer.  */
-	  && typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE)
+	  && typecode != COMPLEX_TYPE)
 	{
 	  error ("wrong type argument to unary exclamation mark");
 	  return error_mark_node;
@@ -2736,7 +2720,9 @@ build_unary_op (enum tree_code code, tre
 	{
 	  if (!c_mark_addressable (TREE_OPERAND (arg, 0)))
 	    return error_mark_node;
-	  return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
+	  return build_binary_op (PLUS_EXPR,
+				  default_function_array_conversion
+				    (TREE_OPERAND (arg, 0)),
 				  TREE_OPERAND (arg, 1), 1);
 	}
 
@@ -3115,9 +3101,6 @@ build_conditional_expr (tree ifexp, tree
 tree
 build_compound_expr (tree expr1, tree expr2)
 {
-  /* Convert arrays and functions to pointers.  */
-  expr2 = default_function_array_conversion (expr2);
-
   if (!TREE_SIDE_EFFECTS (expr1))
     {
       /* The left-hand operand of a comma expression is like an expression
@@ -3189,7 +3172,6 @@ build_c_cast (tree type, tree expr)
   else if (TREE_CODE (type) == UNION_TYPE)
     {
       tree field;
-      value = default_function_array_conversion (value);
 
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
 	if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
@@ -3217,14 +3199,9 @@ build_c_cast (tree type, tree expr)
     {
       tree otype, ovalue;
 
-      /* If casting to void, avoid the error that would come
-	 from default_conversion in the case of a non-lvalue array.  */
       if (type == void_type_node)
 	return build1 (CONVERT_EXPR, type, value);
 
-      /* Convert functions and arrays to pointers,
-	 but don't convert any other types.  */
-      value = default_function_array_conversion (value);
       otype = TREE_TYPE (value);
 
       /* Optionally warn about potentially worrisome casts.  */
@@ -3558,10 +3535,8 @@ convert_for_assignment (tree type, tree 
 
   STRIP_TYPE_NOPS (rhs);
 
-  if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
-      || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE)
-    rhs = default_conversion (rhs);
-  else if (optimize && TREE_CODE (rhs) == VAR_DECL)
+  if (optimize && TREE_CODE (rhs) == VAR_DECL
+	   && TREE_CODE (TREE_TYPE (rhs)) != ARRAY_TYPE)
     rhs = decl_constant_value_for_broken_optimization (rhs);
 
   rhstype = TREE_TYPE (rhs);
@@ -4373,15 +4348,13 @@ digest_init (tree type, tree init, bool 
 	  || (code == POINTER_TYPE
 	      && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
 	      && comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
-			    TREE_TYPE (type)))
-	  || (code == POINTER_TYPE
-	      && TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE
-	      && comptypes (TREE_TYPE (inside_init),
 			    TREE_TYPE (type)))))
     {
       if (code == POINTER_TYPE)
 	{
-	  inside_init = default_function_array_conversion (inside_init);
+	  if (TREE_CODE (inside_init) == STRING_CST
+	      || TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
+	    inside_init = default_function_array_conversion (inside_init);
 
 	  if (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE)
 	    {
@@ -4448,9 +4421,9 @@ digest_init (tree type, tree init, bool 
       || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
       || code == VECTOR_TYPE)
     {
-      /* Note that convert_for_assignment calls default_conversion
-	 for arrays and functions.  We must not call it in the
-	 case where inside_init is a null pointer constant.  */
+      if (TREE_CODE (init) == STRING_CST
+	  || TREE_CODE (init) == COMPOUND_LITERAL_EXPR)
+	init = default_function_array_conversion (init);
       inside_init
 	= convert_for_assignment (type, init, ic_init,
 				  NULL_TREE, NULL_TREE, 0);
@@ -5800,14 +5773,15 @@ output_init_element (tree value, bool st
       constructor_erroneous = 1;
       return;
     }
-  if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
-      || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
-	  && !(TREE_CODE (value) == STRING_CST
-	       && TREE_CODE (type) == ARRAY_TYPE
-	       && INTEGRAL_TYPE_P (TREE_TYPE (type)))
-	  && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
-			 TYPE_MAIN_VARIANT (type))))
-    value = default_conversion (value);
+  if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
+      && (TREE_CODE (value) == STRING_CST
+	  || TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
+      && !(TREE_CODE (value) == STRING_CST
+	   && TREE_CODE (type) == ARRAY_TYPE
+	   && INTEGRAL_TYPE_P (TREE_TYPE (type)))
+      && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
+		     TYPE_MAIN_VARIANT (type)))
+    value = default_function_array_conversion (value);
 
   if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
       && require_constant_value && !flag_isoc99 && pending)
@@ -6519,9 +6493,6 @@ build_asm_expr (tree string, tree output
       TREE_VALUE (tail) = output;
     }
 
-  /* Perform default conversions on array and function inputs.
-     Don't do this for other types as it would screw up operands
-     expected to be in memory.  */
   for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail))
     {
       tree input;
@@ -6529,8 +6500,6 @@ build_asm_expr (tree string, tree output
       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
       input = TREE_VALUE (tail);
 
-      input = default_function_array_conversion (input);
-
       if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
 				  oconstraints, &allows_mem, &allows_reg))
 	{
@@ -7084,13 +7053,6 @@ c_process_expr_stmt (tree expr)
   if (!expr)
     return NULL_TREE;
 
-  /* Do default conversion if safe and possibly important,
-     in case within ({...}).  */
-  if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
-       && (flag_isoc99 || lvalue_p (expr)))
-      || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
-    expr = default_conversion (expr);
-
   if (warn_sequence_point)
     verify_sequence_points (expr);
 
@@ -8096,12 +8058,11 @@ build_binary_op (enum tree_code code, tr
 
 
 /* Convert EXPR to be a truth-value, validating its type for this
-   purpose.  Passes EXPR to default_function_array_conversion.  */
+   purpose.  */
 
 tree
 c_objc_common_truthvalue_conversion (tree expr)
 {
-  expr = default_function_array_conversion (expr);
   switch (TREE_CODE (TREE_TYPE (expr)))
     {
     case ARRAY_TYPE:
@@ -8116,6 +8077,9 @@ c_objc_common_truthvalue_conversion (tre
       error ("used union type value where scalar is required");
       return error_mark_node;
 
+    case FUNCTION_TYPE:
+      gcc_unreachable ();
+
     default:
       break;
     }
diff -rupN GCC.orig/gcc/objc/objc-act.c GCC/gcc/objc/objc-act.c
--- GCC.orig/gcc/objc/objc-act.c	2005-05-26 10:54:22.000000000 +0000
+++ GCC/gcc/objc/objc-act.c	2005-06-15 01:21:49.000000000 +0000
@@ -1722,6 +1722,16 @@ my_build_string (int len, const char *st
   return fix_string_type (build_string (len, str));
 }
 
+/* Build a string with contents STR and length LEN and convert it to a
+   pointer.  */
+
+static tree
+my_build_string_pointer (int len, const char *str)
+{
+  tree string = my_build_string (len, str);
+  tree ptrtype = build_pointer_type (TREE_TYPE (TREE_TYPE (string)));
+  return build1 (ADDR_EXPR, ptrtype, string);
+}
 
 static hashval_t
 string_hash (const void *ptr)
@@ -2699,8 +2709,9 @@ objc_get_class_reference (tree ident)
       add_class_reference (ident);
 
       params = build_tree_list (NULL_TREE,
-				my_build_string (IDENTIFIER_LENGTH (ident) + 1,
-						 IDENTIFIER_POINTER (ident)));
+				my_build_string_pointer
+				(IDENTIFIER_LENGTH (ident) + 1,
+				 IDENTIFIER_POINTER (ident)));
 
       assemble_external (objc_get_class_decl);
       return build_function_call (objc_get_class_decl, params);
@@ -8641,8 +8652,9 @@ get_super_receiver (void)
 		  (super_class,
 		   build_tree_list
 		   (NULL_TREE,
-		    my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
-				     IDENTIFIER_POINTER (super_name))));
+		    my_build_string_pointer
+		    (IDENTIFIER_LENGTH (super_name) + 1,
+		     IDENTIFIER_POINTER (super_name))));
 	    }
 
 	  super_expr
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/noncompile/20040203-3.c GCC/gcc/testsuite/gcc.dg/noncompile/20040203-3.c
--- GCC.orig/gcc/testsuite/gcc.dg/noncompile/20040203-3.c	2004-02-03 13:38:28.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/noncompile/20040203-3.c	2005-06-15 12:01:36.000000000 +0000
@@ -12,5 +12,5 @@ int bug_or(void) { return (f().c || 1); 
 int bug_and(void) { return (f().c && 1); }  /* { dg-error "array that cannot be converted" } */
 int bug_cond(void) { return (f().c ? 1 : 0); }  /* { dg-error "array that cannot be converted" } */
 int bug_cond2(void) { return (f().c ? : 0); }  /* { dg-error "array that cannot be converted" } */
-int bug_not(void) { return !f().c; }  /* { dg-error "array that cannot be converted" } */
+int bug_not(void) { return !f().c; }  /* { dg-error "wrong type argument to unary exclamation mark" } */
 int bug_bool(void) { return (_Bool) f().c; }  /* { dg-error "array that cannot be converted" } */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]