diff options
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/c-parser.c | 79 | ||||
-rw-r--r-- | gcc/c-tree.h | 2 | ||||
-rw-r--r-- | gcc/c-typeck.c | 207 |
4 files changed, 171 insertions, 134 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ed408af..91e2631 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2005-06-29 Joseph S. Myers <joseph@codesourcery.com> + + * c-tree.h (default_function_array_conversion): Take and return + struct c_expr. + * c-typeck.c (default_function_array_conversion): Split into + array_to_pointer_conversion and function_to_pointer_conversion. + Take and return struct c_expr. + (array_to_pointer_conversion): Do not handle type qualifiers or + COMPOUND_EXPRs specially. + (build_function_call): Call function_to_pointer_conversion for + function designators. + (build_unary_op): Call array_to_pointer_conversion, not + default_function_array_conversion. + (digest_init, output_init_element): Likewise. + * c-parser.c: All callers of default_function_array_conversion + changed. + 2005-06-29 Ziemowit Laski <zlaski@apple.com> * config/darwin.c (machopic_select_section): constant ObjC string diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 0e8babf..9a67994 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -2880,7 +2880,7 @@ c_parser_initializer (c_parser *parser) 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); + ret = default_function_array_conversion (ret); return ret; } } @@ -3036,11 +3036,11 @@ c_parser_initelt (c_parser *parser) rec = first; while (c_parser_next_token_is (parser, CPP_COMMA)) { - tree next; + struct c_expr next; c_parser_consume_token (parser); - next = c_parser_expr_no_commas (parser, NULL).value; + next = c_parser_expr_no_commas (parser, NULL); next = default_function_array_conversion (next); - rec = build_compound_expr (rec, next); + rec = build_compound_expr (rec, next.value); } parse_message_args: /* Now parse the objc-message-args. */ @@ -3130,7 +3130,7 @@ c_parser_initval (c_parser *parser, struct c_expr *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); + init = default_function_array_conversion (init); } process_init_element (init); } @@ -3990,7 +3990,8 @@ c_parser_asm_operands (c_parser *parser, bool convert_p) tree list = NULL_TREE; while (true) { - tree name, str, expr; + tree name, str; + struct c_expr expr; if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) { c_parser_consume_token (parser); @@ -4021,7 +4022,7 @@ c_parser_asm_operands (c_parser *parser, bool convert_p) c_lex_string_translate = 0; return NULL_TREE; } - expr = c_parser_expression (parser).value; + expr = c_parser_expression (parser); if (convert_p) expr = default_function_array_conversion (expr); c_lex_string_translate = 0; @@ -4031,7 +4032,7 @@ c_parser_asm_operands (c_parser *parser, bool convert_p) return NULL_TREE; } list = chainon (list, build_tree_list (build_tree_list (name, str), - expr)); + expr.value)); if (c_parser_next_token_is (parser, CPP_COMMA)) c_parser_consume_token (parser); else @@ -4129,7 +4130,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after) } c_parser_consume_token (parser); rhs = c_parser_expr_no_commas (parser, NULL); - rhs.value = default_function_array_conversion (rhs.value); + rhs = default_function_array_conversion (rhs); ret.value = build_modify_expr (lhs.value, code, rhs.value); if (code == NOP_EXPR) ret.original_code = MODIFY_EXPR; @@ -4163,7 +4164,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after) 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); + cond = default_function_array_conversion (cond); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_COLON)) { @@ -4192,7 +4193,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after) return ret; } exp2 = c_parser_conditional_expression (parser, NULL); - exp2.value = default_function_array_conversion (exp2.value); + exp2 = default_function_array_conversion (exp2); skip_evaluation -= cond.value == truthvalue_true_node; ret.value = build_conditional_expr (cond.value, exp1.value, exp2.value); ret.original_code = ERROR_MARK; @@ -4316,10 +4317,10 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) 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 \ + = default_function_array_conversion (stack[sp - 1].expr); \ + stack[sp].expr \ + = default_function_array_conversion (stack[sp].expr); \ stack[sp - 1].expr = parser_build_binary_op (stack[sp].op, \ stack[sp - 1].expr, \ stack[sp].expr); \ @@ -4420,15 +4421,15 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) switch (ocode) { case TRUTH_ANDIF_EXPR: - stack[sp].expr.value - = default_function_array_conversion (stack[sp].expr.value); + stack[sp].expr + = default_function_array_conversion (stack[sp].expr); 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 + = default_function_array_conversion (stack[sp].expr); stack[sp].expr.value = c_objc_common_truthvalue_conversion (default_conversion (stack[sp].expr.value)); skip_evaluation += stack[sp].expr.value == truthvalue_true_node; @@ -4472,7 +4473,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after) { struct c_type_name *type_name; struct c_expr ret; - tree expr; + struct c_expr expr; c_parser_consume_token (parser); type_name = c_parser_type_name (parser); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -4485,9 +4486,9 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after) if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) return c_parser_postfix_expression_after_paren_type (parser, type_name); - expr = c_parser_cast_expression (parser, NULL).value; + expr = c_parser_cast_expression (parser, NULL); expr = default_function_array_conversion (expr); - ret.value = c_cast_expr (type_name, expr); + ret.value = c_cast_expr (type_name, expr.value); ret.original_code = ERROR_MARK; return ret; } @@ -4532,12 +4533,12 @@ c_parser_unary_expression (c_parser *parser) case CPP_PLUS_PLUS: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); - op.value = default_function_array_conversion (op.value); + op = default_function_array_conversion (op); return parser_build_unary_op (PREINCREMENT_EXPR, op); case CPP_MINUS_MINUS: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); - op.value = default_function_array_conversion (op.value); + op = default_function_array_conversion (op); return parser_build_unary_op (PREDECREMENT_EXPR, op); case CPP_AND: c_parser_consume_token (parser); @@ -4546,7 +4547,7 @@ c_parser_unary_expression (c_parser *parser) case CPP_MULT: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); - op.value = default_function_array_conversion (op.value); + op = default_function_array_conversion (op); ret.value = build_indirect_ref (op.value, "unary *"); ret.original_code = ERROR_MARK; return ret; @@ -4556,22 +4557,22 @@ c_parser_unary_expression (c_parser *parser) warning (OPT_Wtraditional, "traditional C rejects the unary plus operator"); op = c_parser_cast_expression (parser, NULL); - op.value = default_function_array_conversion (op.value); + op = default_function_array_conversion (op); return parser_build_unary_op (CONVERT_EXPR, op); case CPP_MINUS: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); - op.value = default_function_array_conversion (op.value); + op = default_function_array_conversion (op); return parser_build_unary_op (NEGATE_EXPR, op); case CPP_COMPL: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); - op.value = default_function_array_conversion (op.value); + op = default_function_array_conversion (op); return parser_build_unary_op (BIT_NOT_EXPR, op); case CPP_NOT: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); - op.value = default_function_array_conversion (op.value); + op = default_function_array_conversion (op); return parser_build_unary_op (TRUTH_NOT_EXPR, op); case CPP_AND_AND: /* Refer to the address of a label as a pointer. */ @@ -4605,12 +4606,12 @@ c_parser_unary_expression (c_parser *parser) case RID_REALPART: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); - op.value = default_function_array_conversion (op.value); + op = default_function_array_conversion (op); return parser_build_unary_op (REALPART_EXPR, op); case RID_IMAGPART: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); - op.value = default_function_array_conversion (op.value); + op = default_function_array_conversion (op); return parser_build_unary_op (IMAGPART_EXPR, op); default: return c_parser_postfix_expression (parser); @@ -5250,7 +5251,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser, case CPP_DOT: /* Structure element reference. */ c_parser_consume_token (parser); - expr.value = default_function_array_conversion (expr.value); + expr = default_function_array_conversion (expr); if (c_parser_next_token_is (parser, CPP_NAME)) ident = c_parser_peek_token (parser)->value; else @@ -5267,7 +5268,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser, case CPP_DEREF: /* Structure element reference. */ c_parser_consume_token (parser); - expr.value = default_function_array_conversion (expr.value); + expr = default_function_array_conversion (expr); if (c_parser_next_token_is (parser, CPP_NAME)) ident = c_parser_peek_token (parser)->value; else @@ -5285,14 +5286,14 @@ c_parser_postfix_expression_after_primary (c_parser *parser, case CPP_PLUS_PLUS: /* Postincrement. */ c_parser_consume_token (parser); - expr.value = default_function_array_conversion (expr.value); + expr = default_function_array_conversion (expr); 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 = default_function_array_conversion (expr); expr.value = build_unary_op (POSTDECREMENT_EXPR, expr.value, 0); expr.original_code = ERROR_MARK; break; @@ -5319,7 +5320,7 @@ 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); + next = default_function_array_conversion (next); expr.value = build_compound_expr (expr.value, next.value); expr.original_code = COMPOUND_EXPR; } @@ -5334,7 +5335,7 @@ c_parser_expression_conv (c_parser *parser) { struct c_expr expr; expr = c_parser_expression (parser); - expr.value = default_function_array_conversion (expr.value); + expr = default_function_array_conversion (expr); return expr; } @@ -5353,14 +5354,14 @@ c_parser_expr_list (c_parser *parser, bool convert_p) tree ret, cur; expr = c_parser_expr_no_commas (parser, NULL); if (convert_p) - expr.value = default_function_array_conversion (expr.value); + expr = default_function_array_conversion (expr); 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); + expr = default_function_array_conversion (expr); cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value); } return ret; diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 77d01b2..e92006c 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -523,7 +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 struct c_expr default_function_array_conversion (struct c_expr); extern tree composite_type (tree, tree); extern tree build_component_ref (tree, tree); extern tree build_indirect_ref (tree, const char *); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 34f94d1..64ec126 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1259,103 +1259,116 @@ decl_constant_value_for_broken_optimization (tree decl) return ret; } - -/* Perform the default conversion of arrays and functions to pointers. - Return the result of converting EXP. For any other expression, just - return EXP after removing NOPs. */ - -tree -default_function_array_conversion (tree exp) +/* Convert the array expression EXP to a pointer. */ +static tree +array_to_pointer_conversion (tree exp) { - tree orig_exp; + tree orig_exp = exp; tree type = TREE_TYPE (exp); - enum tree_code code = TREE_CODE (type); - int not_lvalue = 0; + tree adr; + tree restype = TREE_TYPE (type); + tree ptrtype; - /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as - an lvalue. + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); - Do not use STRIP_NOPS here! It will remove conversions from pointer - to integer and cause infinite recursion. */ - orig_exp = exp; - while (TREE_CODE (exp) == NON_LVALUE_EXPR - || (TREE_CODE (exp) == NOP_EXPR - && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp))) - { - if (TREE_CODE (exp) == NON_LVALUE_EXPR) - not_lvalue = 1; - exp = TREE_OPERAND (exp, 0); - } + STRIP_TYPE_NOPS (exp); if (TREE_NO_WARNING (orig_exp)) TREE_NO_WARNING (exp) = 1; - if (code == FUNCTION_TYPE) + ptrtype = build_pointer_type (restype); + + if (TREE_CODE (exp) == INDIRECT_REF) + return convert (ptrtype, TREE_OPERAND (exp, 0)); + + if (TREE_CODE (exp) == VAR_DECL) { - return build_unary_op (ADDR_EXPR, exp, 0); + /* We are making an ADDR_EXPR of ptrtype. This is a valid + ADDR_EXPR because it's the best way of representing what + happens in C when we take the address of an array and place + it in a pointer to the element type. */ + adr = build1 (ADDR_EXPR, ptrtype, exp); + if (!c_mark_addressable (exp)) + return error_mark_node; + TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */ + return adr; } - if (code == ARRAY_TYPE) - { - tree adr; - tree restype = TREE_TYPE (type); - tree ptrtype; - int constp = 0; - int volatilep = 0; - int lvalue_array_p; - if (REFERENCE_CLASS_P (exp) || DECL_P (exp)) - { - constp = TREE_READONLY (exp); - volatilep = TREE_THIS_VOLATILE (exp); - } + /* This way is better for a COMPONENT_REF since it can + simplify the offset for a component. */ + adr = build_unary_op (ADDR_EXPR, exp, 1); + return convert (ptrtype, adr); +} - if (TYPE_QUALS (type) || constp || volatilep) - restype - = c_build_qualified_type (restype, - TYPE_QUALS (type) - | (constp * TYPE_QUAL_CONST) - | (volatilep * TYPE_QUAL_VOLATILE)); +/* Convert the function expression EXP to a pointer. */ +static tree +function_to_pointer_conversion (tree exp) +{ + tree orig_exp = exp; - if (TREE_CODE (exp) == INDIRECT_REF) - return convert (build_pointer_type (restype), - TREE_OPERAND (exp, 0)); + gcc_assert (TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE); - if (TREE_CODE (exp) == COMPOUND_EXPR) - { - tree op1 = default_conversion (TREE_OPERAND (exp, 1)); - return build2 (COMPOUND_EXPR, TREE_TYPE (op1), - TREE_OPERAND (exp, 0), op1); - } + STRIP_TYPE_NOPS (exp); - lvalue_array_p = !not_lvalue && lvalue_p (exp); - if (!flag_isoc99 && !lvalue_array_p) - { - /* Before C99, non-lvalue arrays do not decay to pointers. - Normally, using such an array would be invalid; but it can - be used correctly inside sizeof or as a statement expression. - Thus, do not give an error here; an error will result later. */ - return exp; - } + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp) = 1; - ptrtype = build_pointer_type (restype); + return build_unary_op (ADDR_EXPR, exp, 0); +} - if (TREE_CODE (exp) == VAR_DECL) - { - /* We are making an ADDR_EXPR of ptrtype. This is a valid - ADDR_EXPR because it's the best way of representing what - happens in C when we take the address of an array and place - it in a pointer to the element type. */ - adr = build1 (ADDR_EXPR, ptrtype, exp); - if (!c_mark_addressable (exp)) - return error_mark_node; - TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */ - return adr; - } - /* This way is better for a COMPONENT_REF since it can - simplify the offset for a component. */ - adr = build_unary_op (ADDR_EXPR, exp, 1); - return convert (ptrtype, adr); +/* Perform the default conversion of arrays and functions to pointers. + Return the result of converting EXP. For any other expression, just + return EXP after removing NOPs. */ + +struct c_expr +default_function_array_conversion (struct c_expr exp) +{ + tree orig_exp = exp.value; + tree type = TREE_TYPE (exp.value); + enum tree_code code = TREE_CODE (type); + + switch (code) + { + case ARRAY_TYPE: + { + bool not_lvalue = false; + bool lvalue_array_p; + + while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR + || TREE_CODE (exp.value) == NOP_EXPR) + && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type) + { + if (TREE_CODE (exp.value) == NON_LVALUE_EXPR) + not_lvalue = true; + exp.value = TREE_OPERAND (exp.value, 0); + } + + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp.value) = 1; + + lvalue_array_p = !not_lvalue && lvalue_p (exp.value); + if (!flag_isoc99 && !lvalue_array_p) + { + /* Before C99, non-lvalue arrays do not decay to pointers. + Normally, using such an array would be invalid; but it can + be used correctly inside sizeof or as a statement expression. + Thus, do not give an error here; an error will result later. */ + return exp; + } + + exp.value = array_to_pointer_conversion (exp.value); + } + break; + case FUNCTION_TYPE: + exp.value = function_to_pointer_conversion (exp.value); + break; + default: + STRIP_TYPE_NOPS (exp.value); + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp.value) = 1; + break; } + return exp; } @@ -1992,7 +2005,8 @@ build_function_call (tree function, tree params) name = DECL_NAME (function); fundecl = function; } - function = default_function_array_conversion (function); + if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE) + function = function_to_pointer_conversion (function); /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF expressions, like those used for ObjC messenger dispatches. */ @@ -2730,11 +2744,13 @@ build_unary_op (enum tree_code code, tree xarg, int flag) /* For &x[y], return x+y */ if (TREE_CODE (arg) == ARRAY_REF) { - if (!c_mark_addressable (TREE_OPERAND (arg, 0))) + tree op0 = TREE_OPERAND (arg, 0); + if (!c_mark_addressable (op0)) return error_mark_node; return build_binary_op (PLUS_EXPR, - default_function_array_conversion - (TREE_OPERAND (arg, 0)), + (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE + ? array_to_pointer_conversion (op0) + : op0), TREE_OPERAND (arg, 1), 1); } @@ -4367,16 +4383,18 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) { if (code == POINTER_TYPE) { - 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) { - error_init ("invalid use of non-lvalue array"); - return error_mark_node; + if (TREE_CODE (inside_init) == STRING_CST + || TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR) + inside_init = array_to_pointer_conversion (inside_init); + else + { + error_init ("invalid use of non-lvalue array"); + return error_mark_node; + } } - } + } if (code == VECTOR_TYPE) /* Although the types are compatible, we may require a @@ -4436,9 +4454,10 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE || code == VECTOR_TYPE) { - if (TREE_CODE (init) == STRING_CST - || TREE_CODE (init) == COMPOUND_LITERAL_EXPR) - init = default_function_array_conversion (init); + if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE + && (TREE_CODE (init) == STRING_CST + || TREE_CODE (init) == COMPOUND_LITERAL_EXPR)) + init = array_to_pointer_conversion (init); inside_init = convert_for_assignment (type, init, ic_init, NULL_TREE, NULL_TREE, 0); @@ -5796,7 +5815,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field, && INTEGRAL_TYPE_P (TREE_TYPE (type))) && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)), TYPE_MAIN_VARIANT (type))) - value = default_function_array_conversion (value); + value = array_to_pointer_conversion (value); if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR && require_constant_value && !flag_isoc99 && pending) |