diff options
Diffstat (limited to 'gcc/c/c-typeck.c')
-rw-r--r-- | gcc/c/c-typeck.c | 227 |
1 files changed, 121 insertions, 106 deletions
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 11825a9218e..7d2df6b1d12 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -101,14 +101,15 @@ static void push_string (const char *); static void push_member_name (tree); static int spelling_length (void); static char *print_spelling (char *); -static void warning_init (int, const char *); +static void warning_init (location_t, int, const char *); static tree digest_init (location_t, tree, tree, tree, bool, bool, int); static void output_init_element (location_t, tree, tree, bool, tree, tree, int, bool, struct obstack *); static void output_pending_init_elements (int, struct obstack *); static int set_designator (int, struct obstack *); static void push_range_stack (tree, struct obstack *); -static void add_pending_init (tree, tree, tree, bool, struct obstack *); +static void add_pending_init (location_t, tree, tree, tree, bool, + struct obstack *); static void set_nonincremental_init (struct obstack *); static void set_nonincremental_init_from_string (tree, struct obstack *); static tree find_init_member (tree, struct obstack *); @@ -1754,22 +1755,20 @@ type_lists_compatible_p (const_tree args1, const_tree args2, } } -/* Compute the size to increment a pointer by. */ +/* Compute the size to increment a pointer by. When a function type or void + type or incomplete type is passed, size_one_node is returned. + This function does not emit any diagnostics; the caller is responsible + for that. */ static tree c_size_in_bytes (const_tree type) { enum tree_code code = TREE_CODE (type); - if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK) + if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK + || !COMPLETE_TYPE_P (type)) return size_one_node; - if (!COMPLETE_OR_VOID_TYPE_P (type)) - { - error ("arithmetic on pointer to an incomplete type"); - return size_one_node; - } - /* Convert in case a char is more than one unit. */ return size_binop_loc (input_location, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type), size_int (TYPE_PRECISION (char_type_node) @@ -2108,7 +2107,8 @@ default_conversion (tree exp) if (code == VOID_TYPE) { - error ("void value not ignored as it ought to be"); + error_at (EXPR_LOC_OR_LOC (exp, input_location), + "void value not ignored as it ought to be"); return error_mark_node; } @@ -3529,7 +3529,6 @@ pointer_diff (location_t loc, tree op0, tree op1) if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1)))) error_at (loc, "arithmetic on pointer to an incomplete type"); - /* This generates an error if op0 is pointer to incomplete type. */ op1 = c_size_in_bytes (target_type); if (pointer_to_zero_sized_aggr_p (TREE_TYPE (orig_op1))) @@ -4003,16 +4002,18 @@ build_unary_op (location_t location, if (typecode == POINTER_TYPE) { - /* If pointer target is an undefined struct, + /* If pointer target is an incomplete type, we just cannot know how to do the arithmetic. */ if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype))) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) error_at (location, - "increment of pointer to unknown structure"); + "increment of pointer to an incomplete type %qT", + TREE_TYPE (argtype)); else error_at (location, - "decrement of pointer to unknown structure"); + "decrement of pointer to an incomplete type %qT", + TREE_TYPE (argtype)); } else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE) @@ -5539,6 +5540,72 @@ convert_to_anonymous_field (location_t location, tree type, tree rhs) return ret; } +/* Issue an error message for a bad initializer component. + GMSGID identifies the message. + The component name is taken from the spelling stack. */ + +static void +error_init (const char *gmsgid) +{ + char *ofwhat; + + /* The gmsgid may be a format string with %< and %>. */ + error (gmsgid); + ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); + if (*ofwhat) + error ("(near initialization for %qs)", ofwhat); +} + +/* Issue a pedantic warning for a bad initializer component. OPT is + the option OPT_* (from options.h) controlling this warning or 0 if + it is unconditionally given. GMSGID identifies the message. The + component name is taken from the spelling stack. */ + +static void +pedwarn_init (location_t location, int opt, const char *gmsgid) +{ + char *ofwhat; + + /* The gmsgid may be a format string with %< and %>. */ + pedwarn (location, opt, gmsgid); + ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); + if (*ofwhat) + pedwarn (location, opt, "(near initialization for %qs)", ofwhat); +} + +/* Issue a warning for a bad initializer component. + + OPT is the OPT_W* value corresponding to the warning option that + controls this warning. GMSGID identifies the message. The + component name is taken from the spelling stack. */ + +static void +warning_init (location_t loc, int opt, const char *gmsgid) +{ + char *ofwhat; + + /* The gmsgid may be a format string with %< and %>. */ + warning_at (loc, opt, gmsgid); + ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); + if (*ofwhat) + warning_at (loc, opt, "(near initialization for %qs)", ofwhat); +} + +/* If TYPE is an array type and EXPR is a parenthesized string + constant, warn if pedantic that EXPR is being used to initialize an + object of type TYPE. */ + +void +maybe_warn_string_init (tree type, struct c_expr expr) +{ + if (pedantic + && TREE_CODE (type) == ARRAY_TYPE + && TREE_CODE (expr.value) == STRING_CST + && expr.original_code != STRING_CST) + pedwarn_init (input_location, OPT_Wpedantic, + "array initialized from parenthesized string constant"); +} + /* Convert value RHS to type TYPE as preparation for an assignment to an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the original type of RHS; this differs from TREE_TYPE (RHS) for enum @@ -5850,7 +5917,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, vice-versa. */ if (TYPE_QUALS_NO_ADDR_SPACE (ttl) & ~TYPE_QUALS_NO_ADDR_SPACE (ttr)) - WARN_FOR_QUALIFIERS (location, 0, + WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers, G_("passing argument %d of %qE " "makes %q#v qualified function " "pointer from unqualified"), @@ -5866,7 +5933,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, } else if (TYPE_QUALS_NO_ADDR_SPACE (ttr) & ~TYPE_QUALS_NO_ADDR_SPACE (ttl)) - WARN_FOR_QUALIFIERS (location, 0, + WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers, G_("passing argument %d of %qE discards " "%qv qualifier from pointer target type"), G_("assignment discards %qv qualifier " @@ -6047,7 +6114,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr) & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl)) { - WARN_FOR_QUALIFIERS (location, 0, + WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers, G_("passing argument %d of %qE discards " "%qv qualifier from pointer target type"), G_("assignment discards %qv qualifier " @@ -6084,7 +6151,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, where an ordinary one is wanted, but not vice-versa. */ if (TYPE_QUALS_NO_ADDR_SPACE (ttl) & ~TYPE_QUALS_NO_ADDR_SPACE (ttr)) - WARN_FOR_QUALIFIERS (location, 0, + WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers, G_("passing argument %d of %qE makes " "%q#v qualified function pointer " "from unqualified"), @@ -6404,72 +6471,6 @@ print_spelling (char *buffer) return buffer; } -/* Issue an error message for a bad initializer component. - GMSGID identifies the message. - The component name is taken from the spelling stack. */ - -void -error_init (const char *gmsgid) -{ - char *ofwhat; - - /* The gmsgid may be a format string with %< and %>. */ - error (gmsgid); - ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); - if (*ofwhat) - error ("(near initialization for %qs)", ofwhat); -} - -/* Issue a pedantic warning for a bad initializer component. OPT is - the option OPT_* (from options.h) controlling this warning or 0 if - it is unconditionally given. GMSGID identifies the message. The - component name is taken from the spelling stack. */ - -void -pedwarn_init (location_t location, int opt, const char *gmsgid) -{ - char *ofwhat; - - /* The gmsgid may be a format string with %< and %>. */ - pedwarn (location, opt, gmsgid); - ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); - if (*ofwhat) - pedwarn (location, opt, "(near initialization for %qs)", ofwhat); -} - -/* Issue a warning for a bad initializer component. - - OPT is the OPT_W* value corresponding to the warning option that - controls this warning. GMSGID identifies the message. The - component name is taken from the spelling stack. */ - -static void -warning_init (int opt, const char *gmsgid) -{ - char *ofwhat; - - /* The gmsgid may be a format string with %< and %>. */ - warning (opt, gmsgid); - ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); - if (*ofwhat) - warning (opt, "(near initialization for %qs)", ofwhat); -} - -/* If TYPE is an array type and EXPR is a parenthesized string - constant, warn if pedantic that EXPR is being used to initialize an - object of type TYPE. */ - -void -maybe_warn_string_init (tree type, struct c_expr expr) -{ - if (pedantic - && TREE_CODE (type) == ARRAY_TYPE - && TREE_CODE (expr.value) == STRING_CST - && expr.original_code != STRING_CST) - pedwarn_init (input_location, OPT_Wpedantic, - "array initialized from parenthesized string constant"); -} - /* Digest the parser output INIT as an initializer for type TYPE. Return a C expression of type TYPE to represent the initial value. @@ -7267,6 +7268,9 @@ push_init_level (int implicit, struct obstack * braced_init_obstack) push_member_name (constructor_fields); constructor_depth++; } + /* If upper initializer is designated, then mark this as + designated too to prevent bogus warnings. */ + constructor_designated = p->designated; } else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { @@ -7298,7 +7302,8 @@ push_init_level (int implicit, struct obstack * braced_init_obstack) if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned) { missing_braces_mentioned = 1; - warning_init (OPT_Wmissing_braces, "missing braces around initializer"); + warning_init (input_location, OPT_Wmissing_braces, + "missing braces around initializer"); } if (TREE_CODE (constructor_type) == RECORD_TYPE @@ -7359,7 +7364,7 @@ push_init_level (int implicit, struct obstack * braced_init_obstack) else { if (constructor_type != error_mark_node) - warning_init (0, "braces around scalar initializer"); + warning_init (input_location, 0, "braces around scalar initializer"); constructor_fields = constructor_type; constructor_unfilled_fields = constructor_type; } @@ -7774,8 +7779,8 @@ set_init_label (tree fieldname, struct obstack * braced_init_obstack) existing initializer. */ static void -add_pending_init (tree purpose, tree value, tree origtype, bool implicit, - struct obstack * braced_init_obstack) +add_pending_init (location_t loc, tree purpose, tree value, tree origtype, + bool implicit, struct obstack *braced_init_obstack) { struct init_node *p, **q, *r; @@ -7796,9 +7801,12 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit, if (!implicit) { if (TREE_SIDE_EFFECTS (p->value)) - warning_init (0, "initialized field with side-effects overwritten"); + warning_init (loc, 0, + "initialized field with side-effects " + "overwritten"); else if (warn_override_init) - warning_init (OPT_Woverride_init, "initialized field overwritten"); + warning_init (loc, OPT_Woverride_init, + "initialized field overwritten"); } p->value = value; p->origtype = origtype; @@ -7823,9 +7831,12 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit, if (!implicit) { if (TREE_SIDE_EFFECTS (p->value)) - warning_init (0, "initialized field with side-effects overwritten"); + warning_init (loc, 0, + "initialized field with side-effects " + "overwritten"); else if (warn_override_init) - warning_init (OPT_Woverride_init, "initialized field overwritten"); + warning_init (loc, OPT_Woverride_init, + "initialized field overwritten"); } p->value = value; p->origtype = origtype; @@ -8014,10 +8025,8 @@ set_nonincremental_init (struct obstack * braced_init_obstack) return; FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value) - { - add_pending_init (index, value, NULL_TREE, true, - braced_init_obstack); - } + add_pending_init (input_location, index, value, NULL_TREE, true, + braced_init_obstack); constructor_elements = NULL; if (TREE_CODE (constructor_type) == RECORD_TYPE) { @@ -8112,7 +8121,7 @@ set_nonincremental_init_from_string (tree str, value = wide_int_to_tree (type, wide_int::from_array (val, 2, HOST_BITS_PER_WIDE_INT * 2)); - add_pending_init (purpose, value, NULL_TREE, true, + add_pending_init (input_location, purpose, value, NULL_TREE, true, braced_init_obstack); } @@ -8278,7 +8287,7 @@ output_init_element (location_t loc, tree value, tree origtype, if (checktype != error_mark_node && (TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (DECL_BIT_FIELD_TYPE (field)))) - warning_init (OPT_Wc___compat, + warning_init (loc, OPT_Wc___compat, "enum conversion in initialization is invalid in C++"); } @@ -8314,7 +8323,7 @@ output_init_element (location_t loc, tree value, tree origtype, && tree_int_cst_lt (field, constructor_unfilled_index)) set_nonincremental_init (braced_init_obstack); - add_pending_init (field, value, origtype, implicit, + add_pending_init (loc, field, value, origtype, implicit, braced_init_obstack); return; } @@ -8341,7 +8350,7 @@ output_init_element (location_t loc, tree value, tree origtype, } } - add_pending_init (field, value, origtype, implicit, + add_pending_init (loc, field, value, origtype, implicit, braced_init_obstack); return; } @@ -8351,10 +8360,11 @@ output_init_element (location_t loc, tree value, tree origtype, if (!implicit) { if (TREE_SIDE_EFFECTS (constructor_elements->last ().value)) - warning_init (0, + warning_init (loc, 0, "initialized field with side-effects overwritten"); else if (warn_override_init) - warning_init (OPT_Woverride_init, "initialized field overwritten"); + warning_init (loc, OPT_Woverride_init, + "initialized field overwritten"); } /* We can have just one union field set. */ @@ -9263,9 +9273,14 @@ c_finish_return (location_t loc, tree retval, tree origtype) && !DECL_EXTERNAL (inner) && !TREE_STATIC (inner) && DECL_CONTEXT (inner) == current_function_decl) - warning_at (loc, - OPT_Wreturn_local_addr, "function returns address " - "of local variable"); + { + if (TREE_CODE (inner) == LABEL_DECL) + warning_at (loc, OPT_Wreturn_local_addr, + "function returns address of label"); + else + warning_at (loc, OPT_Wreturn_local_addr, + "function returns address of local variable"); + } break; default: |