X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=d6ffc87cf3999ff708f49a6a7ee18676d404d10e;hb=3ac15270c9e8eaacc82d5ef15ed8df6c3ca4b7bf;hp=fed17f2484532d86b5f5ec27f6c97d6c6be9bcf2;hpb=aebc8537fd59ab4cd6e0cea7b784acdf17b03745;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index fed17f24845..d6ffc87cf39 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -64,6 +64,8 @@ int in_sizeof; /* The level of nesting inside "typeof". */ int in_typeof; +struct c_label_context *label_context_stack; + /* Nonzero if we've already printed a "missing braces around initializer" message within this initializer. */ static int missing_braces_mentioned; @@ -100,6 +102,8 @@ static void set_nonincremental_init (void); static void set_nonincremental_init_from_string (tree); static tree find_init_member (tree); static void readonly_error (tree, enum lvalue_use); +static int lvalue_or_else (tree, enum lvalue_use); +static int lvalue_p (tree); static void record_maybe_used_decl (tree); /* Do `exp = require_complete_type (exp);' to make sure exp @@ -136,8 +140,7 @@ c_incomplete_type_error (tree value, tree type) if (value != 0 && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL)) - error ("%qs has an incomplete type", - IDENTIFIER_POINTER (DECL_NAME (value))); + error ("%qD has an incomplete type", value); else { retry: @@ -180,12 +183,11 @@ c_incomplete_type_error (tree value, tree type) } if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) - error ("invalid use of undefined type %<%s %s%>", - type_code_string, IDENTIFIER_POINTER (TYPE_NAME (type))); + error ("invalid use of undefined type %<%s %E%>", + type_code_string, TYPE_NAME (type)); else /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */ - error ("invalid use of incomplete typedef %qs", - IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); + error ("invalid use of incomplete typedef %qD", TYPE_NAME (type)); } } @@ -375,29 +377,51 @@ composite_type (tree t1, tree t2) && TREE_VALUE (p1) != TREE_VALUE (p2)) { tree memb; + tree mv2 = TREE_VALUE (p2); + if (mv2 && mv2 != error_mark_node + && TREE_CODE (mv2) != ARRAY_TYPE) + mv2 = TYPE_MAIN_VARIANT (mv2); for (memb = TYPE_FIELDS (TREE_VALUE (p1)); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2))) - { - TREE_VALUE (n) = TREE_VALUE (p2); - if (pedantic) - pedwarn ("function types not truly compatible in ISO C"); - goto parm_done; - } + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes (mv3, mv2)) + { + TREE_VALUE (n) = composite_type (TREE_TYPE (memb), + TREE_VALUE (p2)); + if (pedantic) + pedwarn ("function types not truly compatible in ISO C"); + goto parm_done; + } + } } if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE && TREE_VALUE (p2) != TREE_VALUE (p1)) { tree memb; + tree mv1 = TREE_VALUE (p1); + if (mv1 && mv1 != error_mark_node + && TREE_CODE (mv1) != ARRAY_TYPE) + mv1 = TYPE_MAIN_VARIANT (mv1); for (memb = TYPE_FIELDS (TREE_VALUE (p2)); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1))) - { - TREE_VALUE (n) = TREE_VALUE (p1); - if (pedantic) - pedwarn ("function types not truly compatible in ISO C"); - goto parm_done; - } + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes (mv3, mv1)) + { + TREE_VALUE (n) = composite_type (TREE_TYPE (memb), + TREE_VALUE (p1)); + if (pedantic) + pedwarn ("function types not truly compatible in ISO C"); + goto parm_done; + } + } } TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2)); parm_done: ; @@ -470,8 +494,8 @@ common_pointer_type (tree t1, tree t2) This is the type for the result of most arithmetic operations if the operands have the given two types. */ -tree -common_type (tree t1, tree t2) +static tree +c_common_type (tree t1, tree t2) { enum tree_code code1; enum tree_code code2; @@ -522,7 +546,7 @@ common_type (tree t1, tree t2) { tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1; tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2; - tree subtype = common_type (subtype1, subtype2); + tree subtype = c_common_type (subtype1, subtype2); if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) return t1; @@ -592,6 +616,18 @@ common_type (tree t1, tree t2) return t2; } +/* Wrapper around c_common_type that is used by c-common.c. ENUMERAL_TYPEs + are allowed here and are converted to their compatible integer types. */ +tree +common_type (tree t1, tree t2) +{ + if (TREE_CODE (t1) == ENUMERAL_TYPE) + t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1); + if (TREE_CODE (t2) == ENUMERAL_TYPE) + t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1); + return c_common_type (t1, t2); +} + /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment or various other operations. Return 2 if they are compatible but a warning may be needed if you use them together. */ @@ -1110,8 +1146,14 @@ type_lists_compatible_p (tree args1, tree args2) tree memb; for (memb = TYPE_FIELDS (a1); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), a2)) - break; + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes (mv3, mv2)) + break; + } if (memb == 0) return 0; } @@ -1125,8 +1167,14 @@ type_lists_compatible_p (tree args1, tree args2) tree memb; for (memb = TYPE_FIELDS (a2); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), a1)) - break; + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes (mv3, mv1)) + break; + } if (memb == 0) return 0; } @@ -1306,47 +1354,17 @@ default_function_array_conversion (tree exp) return 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. - In addition, manifest constants symbols are replaced by their values. */ + +/* EXP is an expression of integer type. Apply the integer promotions + to it and return the promoted value. */ tree -default_conversion (tree exp) +perform_integral_promotions (tree exp) { - tree orig_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); - - /* Constants can be used directly unless they're not loadable. */ - if (TREE_CODE (exp) == CONST_DECL) - exp = DECL_INITIAL (exp); - - /* Replace a nonvolatile const static variable with its value unless - it is an array, in which case we must be sure that taking the - address of the array produces consistent results. */ - else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) - { - exp = decl_constant_value_for_broken_optimization (exp); - type = TREE_TYPE (exp); - } - - /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as - an lvalue. - - 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))) - exp = TREE_OPERAND (exp, 0); - - if (TREE_NO_WARNING (orig_exp)) - TREE_NO_WARNING (exp) = 1; + gcc_assert (INTEGRAL_TYPE_P (type)); /* Normally convert enums to int, but convert wide enums to something wider. */ @@ -1361,6 +1379,8 @@ default_conversion (tree exp) return convert (type, exp); } + /* ??? This should no longer be needed now bit-fields have their + proper types. */ if (TREE_CODE (exp) == COMPONENT_REF && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)) /* If it's thinner than an int, promote it like a @@ -1379,6 +1399,48 @@ default_conversion (tree exp) return convert (integer_type_node, exp); } + return 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. + In addition, manifest constants symbols are replaced by their values. */ + +tree +default_conversion (tree exp) +{ + tree orig_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); + + /* Constants can be used directly unless they're not loadable. */ + if (TREE_CODE (exp) == CONST_DECL) + exp = DECL_INITIAL (exp); + + /* Replace a nonvolatile const static variable with its value unless + it is an array, in which case we must be sure that taking the + address of the array produces consistent results. */ + else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) + { + exp = decl_constant_value_for_broken_optimization (exp); + type = TREE_TYPE (exp); + } + + /* Strip no-op conversions. */ + orig_exp = exp; + STRIP_TYPE_NOPS (exp); + + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp) = 1; + + if (INTEGRAL_TYPE_P (type)) + return perform_integral_promotions (exp); + if (code == VOID_TYPE) { error ("void value not ignored as it ought to be"); @@ -1510,8 +1572,7 @@ build_component_ref (tree datum, tree component) if (!field) { - error ("%qT has no member named %qs", type, - IDENTIFIER_POINTER (component)); + error ("%qT has no member named %qE", type, component); return error_mark_node; } @@ -1546,8 +1607,8 @@ build_component_ref (tree datum, tree component) return ref; } else if (code != ERROR_MARK) - error ("request for member %qs in something not a structure or union", - IDENTIFIER_POINTER (component)); + error ("request for member %qE in something not a structure or union", + component); return error_mark_node; } @@ -1741,9 +1802,10 @@ build_array_ref (tree array, tree index) } /* Build an external reference to identifier ID. FUN indicates - whether this will be used for a function call. */ + whether this will be used for a function call. LOC is the source + location of the identifier. */ tree -build_external_ref (tree id, int fun) +build_external_ref (tree id, int fun, location_t loc) { tree ref; tree decl = lookup_name (id); @@ -1763,7 +1825,7 @@ build_external_ref (tree id, int fun) return error_mark_node; else { - undeclared_variable (id); + undeclared_variable (id, loc); return error_mark_node; } @@ -2075,6 +2137,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) tree val = TREE_VALUE (valtail); tree rname = function; int argnum = parmnum + 1; + const char *invalid_func_diag; if (type == void_type_node) { @@ -2088,11 +2151,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) argnum -= 2; } - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here! We do not want an enumerator with value 0 - to convert automatically to a pointer. */ - if (TREE_CODE (val) == NON_LVALUE_EXPR) - val = TREE_OPERAND (val, 0); + STRIP_TYPE_NOPS (val); val = default_function_array_conversion (val); @@ -2189,11 +2248,6 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) /* Change in signedness doesn't matter if a constant value is unaffected. */ ; - /* Likewise for a constant in a NOP_EXPR. */ - else if (TREE_CODE (val) == NOP_EXPR - && TREE_CODE (TREE_OPERAND (val, 0)) == INTEGER_CST - && int_fits_type_p (TREE_OPERAND (val, 0), type)) - ; /* If the value is extended from a narrower unsigned type, it doesn't matter whether we pass it as signed or unsigned; the value @@ -2226,6 +2280,12 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) < TYPE_PRECISION (double_type_node))) /* Convert `float' to `double'. */ result = tree_cons (NULL_TREE, convert (double_type_node, val), result); + else if ((invalid_func_diag = + targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val))) + { + error (invalid_func_diag); + return error_mark_node; + } else /* Convert `short' and `char' to full-size `int'. */ result = tree_cons (NULL_TREE, default_conversion (val), result); @@ -2503,6 +2563,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) 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 @@ -2512,7 +2574,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) error ("wrong type argument to unary exclamation mark"); return error_mark_node; } - arg = lang_hooks.truthvalue_conversion (arg); + arg = c_objc_common_truthvalue_conversion (arg); return invert_truthvalue (arg); case NOP_EXPR: @@ -2707,7 +2769,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) Lvalues can be assigned, unless their type has TYPE_READONLY. Lvalues can have their address taken, unless they have C_DECL_REGISTER. */ -int +static int lvalue_p (tree ref) { enum tree_code code = TREE_CODE (ref); @@ -2757,21 +2819,37 @@ readonly_error (tree arg, enum lvalue_use use) if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) readonly_error (TREE_OPERAND (arg, 0), use); else - error (READONLY_MSG (N_("assignment of read-only member %qs"), - N_("increment of read-only member %qs"), - N_("decrement of read-only member %qs")), - IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1)))); + error (READONLY_MSG (N_("assignment of read-only member %qD"), + N_("increment of read-only member %qD"), + N_("decrement of read-only member %qD")), + TREE_OPERAND (arg, 1)); } else if (TREE_CODE (arg) == VAR_DECL) - error (READONLY_MSG (N_("assignment of read-only variable %qs"), - N_("increment of read-only variable %qs"), - N_("decrement of read-only variable %qs")), - IDENTIFIER_POINTER (DECL_NAME (arg))); + error (READONLY_MSG (N_("assignment of read-only variable %qD"), + N_("increment of read-only variable %qD"), + N_("decrement of read-only variable %qD")), + arg); else error (READONLY_MSG (N_("assignment of read-only location"), N_("increment of read-only location"), N_("decrement of read-only location"))); } + + +/* Return nonzero if REF is an lvalue valid for this language; + otherwise, print an error message and return zero. USE says + how the lvalue is being used and so selects the error message. */ + +static int +lvalue_or_else (tree ref, enum lvalue_use use) +{ + int win = lvalue_p (ref); + + if (!win) + lvalue_error (use); + + return win; +} /* Mark EXP saying that we need to be able to take the address of it; it should not be allocated in a register. @@ -2852,8 +2930,6 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) tree result_type = NULL; tree orig_op1 = op1, orig_op2 = op2; - ifexp = lang_hooks.truthvalue_conversion (default_conversion (ifexp)); - /* Promote both alternatives. */ if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE) @@ -2893,7 +2969,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) && (code2 == INTEGER_TYPE || code2 == REAL_TYPE || code2 == COMPLEX_TYPE)) { - result_type = common_type (type1, type2); + result_type = c_common_type (type1, type2); /* If -Wsign-compare, warn here if type1 and type2 have different signedness. We'll promote the signed to unsigned @@ -3303,11 +3379,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) return error_mark_node; - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (rhs) == NON_LVALUE_EXPR) - rhs = TREE_OPERAND (rhs, 0); + STRIP_TYPE_NOPS (rhs); newrhs = rhs; @@ -3441,11 +3513,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, } \ } while (0) - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (rhs) == NON_LVALUE_EXPR) - rhs = TREE_OPERAND (rhs, 0); + STRIP_TYPE_NOPS (rhs); if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE) @@ -3887,8 +3955,7 @@ store_init_value (tree decl, tree init) { tree inside_init = init; - if (TREE_CODE (init) == NON_LVALUE_EXPR) - inside_init = TREE_OPERAND (init, 0); + STRIP_TYPE_NOPS (inside_init); inside_init = fold (inside_init); if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR) @@ -4108,11 +4175,7 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) || TREE_TYPE (init) == error_mark_node) return error_mark_node; - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (init) == NON_LVALUE_EXPR) - inside_init = TREE_OPERAND (init, 0); + STRIP_TYPE_NOPS (inside_init); inside_init = fold (inside_init); @@ -4458,7 +4521,7 @@ struct constructor_stack char designated; }; -struct constructor_stack *constructor_stack; +static struct constructor_stack *constructor_stack; /* This stack represents designators from some range designator up to the last designator in the list. */ @@ -4473,7 +4536,7 @@ struct constructor_range_stack tree fields; }; -struct constructor_range_stack *constructor_range_stack; +static struct constructor_range_stack *constructor_range_stack; /* This stack records separate initializers that are nested. Nested initializers can't happen in ANSI C, but GNU C allows them @@ -4494,7 +4557,7 @@ struct initializer_stack char require_constant_elements; }; -struct initializer_stack *initializer_stack; +static struct initializer_stack *initializer_stack; /* Prepare to parse and output the initializer for variable DECL. */ @@ -4674,7 +4737,10 @@ really_start_incremental_init (tree type) TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); } else - constructor_index = bitsize_zero_node; + { + constructor_index = bitsize_zero_node; + constructor_max_index = NULL_TREE; + } constructor_unfilled_index = constructor_index; } @@ -4878,7 +4944,8 @@ push_init_level (int implicit) } else { - warning_init ("braces around scalar initializer"); + if (constructor_type != error_mark_node) + warning_init ("braces around scalar initializer"); constructor_fields = constructor_type; constructor_unfilled_fields = constructor_type; } @@ -5150,21 +5217,6 @@ set_init_index (tree first, tree last) return; } - while ((TREE_CODE (first) == NOP_EXPR - || TREE_CODE (first) == CONVERT_EXPR - || TREE_CODE (first) == NON_LVALUE_EXPR) - && (TYPE_MODE (TREE_TYPE (first)) - == TYPE_MODE (TREE_TYPE (TREE_OPERAND (first, 0))))) - first = TREE_OPERAND (first, 0); - - if (last) - while ((TREE_CODE (last) == NOP_EXPR - || TREE_CODE (last) == CONVERT_EXPR - || TREE_CODE (last) == NON_LVALUE_EXPR) - && (TYPE_MODE (TREE_TYPE (last)) - == TYPE_MODE (TREE_TYPE (TREE_OPERAND (last, 0))))) - last = TREE_OPERAND (last, 0); - if (TREE_CODE (first) != INTEGER_CST) error_init ("nonconstant array index in initializer"); else if (last != 0 && TREE_CODE (last) != INTEGER_CST) @@ -5235,8 +5287,7 @@ set_init_label (tree fieldname) } if (tail == 0) - error ("unknown field %qs specified in initializer", - IDENTIFIER_POINTER (fieldname)); + error ("unknown field %qE specified in initializer", fieldname); else { constructor_fields = tail; @@ -6240,7 +6291,8 @@ process_init_element (struct c_expr value) /* Handle the sole element allowed in a braced initializer for a scalar variable. */ - else if (constructor_fields == 0) + else if (constructor_type != error_mark_node + && constructor_fields == 0) { pedwarn_init ("excess elements in scalar initializer"); break; @@ -6428,6 +6480,23 @@ c_finish_goto_label (tree label) if (!decl) return NULL_TREE; + if (C_DECL_UNJUMPABLE_STMT_EXPR (decl)) + { + error ("jump into statement expression"); + return NULL_TREE; + } + + if (!C_DECL_UNDEFINABLE_STMT_EXPR (decl)) + { + /* No jump from outside this statement expression context, so + record that there is a jump from within this context. */ + struct c_label_list *nlist; + nlist = XOBNEW (&parser_obstack, struct c_label_list); + nlist->next = label_context_stack->labels_used; + nlist->label = decl; + label_context_stack->labels_used = nlist; + } + TREE_USED (decl) = 1; return add_stmt (build1 (GOTO_EXPR, void_type_node, decl)); } @@ -6554,6 +6623,11 @@ struct c_switch { of the GNU case range extension. */ splay_tree cases; + /* Number of nested statement expressions within this switch + statement; if nonzero, case and default labels may not + appear. */ + unsigned int blocked_stmt_expr; + /* The next node on the stack. */ struct c_switch *next; }; @@ -6608,6 +6682,7 @@ c_start_case (tree exp) cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, orig_type); cs->orig_type = orig_type; cs->cases = splay_tree_new (case_compare, NULL, NULL); + cs->blocked_stmt_expr = 0; cs->next = c_switch_stack; c_switch_stack = cs; @@ -6621,7 +6696,7 @@ do_case (tree low_value, tree high_value) { tree label = NULL_TREE; - if (c_switch_stack) + if (c_switch_stack && !c_switch_stack->blocked_stmt_expr) { label = c_add_case_label (c_switch_stack->cases, SWITCH_STMT_COND (c_switch_stack->switch_stmt), @@ -6630,6 +6705,15 @@ do_case (tree low_value, tree high_value) if (label == error_mark_node) label = NULL_TREE; } + else if (c_switch_stack && c_switch_stack->blocked_stmt_expr) + { + if (low_value) + error ("case label in statement expression not containing " + "enclosing switch statement"); + else + error ("% label in statement expression not containing " + "enclosing switch statement"); + } else if (low_value) error ("case label not within a switch statement"); else @@ -6647,6 +6731,8 @@ c_finish_case (tree body) SWITCH_STMT_BODY (cs->switch_stmt) = body; + gcc_assert (!cs->blocked_stmt_expr); + /* Emit warnings as needed. */ c_do_switch_warnings (cs->cases, cs->switch_stmt); @@ -6913,12 +6999,30 @@ tree c_begin_stmt_expr (void) { tree ret; + struct c_label_context *nstack; + struct c_label_list *glist; /* We must force a BLOCK for this level so that, if it is not expanded later, there is a way to turn off the entire subtree of blocks that are contained in it. */ keep_next_level (); ret = c_begin_compound_stmt (true); + if (c_switch_stack) + { + c_switch_stack->blocked_stmt_expr++; + gcc_assert (c_switch_stack->blocked_stmt_expr != 0); + } + for (glist = label_context_stack->labels_used; + glist != NULL; + glist = glist->next) + { + C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 1; + } + nstack = XOBNEW (&parser_obstack, struct c_label_context); + nstack->labels_def = NULL; + nstack->labels_used = NULL; + nstack->next = label_context_stack; + label_context_stack = nstack; /* Mark the current statement list as belonging to a statement list. */ STATEMENT_LIST_STMT_EXPR (ret) = 1; @@ -6931,8 +7035,36 @@ c_finish_stmt_expr (tree body) { tree last, type, tmp, val; tree *last_p; + struct c_label_list *dlist, *glist, *glist_prev = NULL; body = c_end_compound_stmt (body, true); + if (c_switch_stack) + { + gcc_assert (c_switch_stack->blocked_stmt_expr != 0); + c_switch_stack->blocked_stmt_expr--; + } + /* It is no longer possible to jump to labels defined within this + statement expression. */ + for (dlist = label_context_stack->labels_def; + dlist != NULL; + dlist = dlist->next) + { + C_DECL_UNJUMPABLE_STMT_EXPR (dlist->label) = 1; + } + /* It is again possible to define labels with a goto just outside + this statement expression. */ + for (glist = label_context_stack->next->labels_used; + glist != NULL; + glist = glist->next) + { + C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 0; + glist_prev = glist; + } + if (glist_prev != NULL) + glist_prev->next = label_context_stack->labels_used; + else + label_context_stack->next->labels_used = label_context_stack->labels_used; + label_context_stack = label_context_stack->next; /* Locate the last statement in BODY. See c_end_compound_stmt about always returning a BIND_EXPR. */ @@ -7266,8 +7398,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, but that does not mean the operands should be converted to ints! */ result_type = integer_type_node; - op0 = lang_hooks.truthvalue_conversion (op0); - op1 = lang_hooks.truthvalue_conversion (op1); + op0 = c_common_truthvalue_conversion (op0); + op1 = c_common_truthvalue_conversion (op1); converted = 1; } break; @@ -7456,7 +7588,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE); if (shorten || common || short_compare) - result_type = common_type (type0, type1); + result_type = c_common_type (type0, type1); /* For certain operations (which identify themselves by shorten != 0) if both args were extended from the same smaller type, @@ -7514,7 +7646,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, && (unsigned0 || !uns)) result_type = c_common_signed_or_unsigned_type - (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1))); + (unsigned0, c_common_type (TREE_TYPE (arg0), TREE_TYPE (arg1))); else if (TREE_CODE (arg0) == INTEGER_CST && (unsigned1 || !uns) && (TYPE_PRECISION (TREE_TYPE (arg1)) @@ -7747,3 +7879,34 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, return result; } } + + +/* Convert EXPR to be a truth-value, validating its type for this + purpose. Passes EXPR to default_function_array_conversion. */ + +tree +c_objc_common_truthvalue_conversion (tree expr) +{ + expr = default_function_array_conversion (expr); + switch (TREE_CODE (TREE_TYPE (expr))) + { + case ARRAY_TYPE: + error ("used array that cannot be converted to pointer where scalar is required"); + return error_mark_node; + + case RECORD_TYPE: + error ("used struct type value where scalar is required"); + return error_mark_node; + + case UNION_TYPE: + error ("used union type value where scalar is required"); + return error_mark_node; + + default: + break; + } + + /* ??? Should we also give an error for void and vectors rather than + leaving those to give errors later? */ + return c_common_truthvalue_conversion (expr); +}