Mercurial > hg > CbC > CbC_gcc
diff gcc/c-decl.c @ 69:1b10fe6932e1
merge 69
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 21 Aug 2011 07:53:12 +0900 |
parents | 326d9e06c2e3 f6334be47118 |
children | b81903832de2 |
line wrap: on
line diff
--- a/gcc/c-decl.c Tue Dec 14 03:58:33 2010 +0900 +++ b/gcc/c-decl.c Sun Aug 21 07:53:12 2011 +0900 @@ -1,6 +1,6 @@ /* Process declarations and variables for C compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -34,33 +34,28 @@ #include "intl.h" #include "tree.h" #include "tree-inline.h" -#include "rtl.h" #include "flags.h" #include "function.h" #include "output.h" -#include "expr.h" #include "c-tree.h" #include "toplev.h" -#include "ggc.h" #include "tm_p.h" #include "cpplib.h" #include "target.h" #include "debug.h" #include "opts.h" #include "timevar.h" -#include "c-common.h" -#include "c-pragma.h" +#include "c-family/c-common.h" +#include "c-family/c-objc.h" +#include "c-family/c-pragma.h" #include "c-lang.h" #include "langhooks.h" #include "tree-mudflap.h" -#include "gimple.h" #include "tree-iterator.h" -#include "diagnostic.h" +#include "diagnostic-core.h" #include "tree-dump.h" #include "cgraph.h" #include "hashtab.h" -#include "libfuncs.h" -#include "except.h" #include "langhooks-def.h" #include "pointer-set.h" #include "gimple.h" @@ -70,8 +65,8 @@ tree cbc_return_f; location_t cbc_return; #endif - #include "plugin.h" +#include "c-family/c-ada-spec.h" /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -131,12 +126,6 @@ tree c_break_label; tree c_cont_label; -/* Linked list of TRANSLATION_UNIT_DECLS for the translation units - included in this invocation. Note that the current translation - unit is not included in this list. */ - -static GTY(()) tree all_translation_units; - /* A list of decls to be made automatically visible in each file scope. */ static GTY(()) tree visible_builtins; @@ -422,6 +411,13 @@ up searching for labels when popping scopes, particularly since labels are normally only found at function scope. */ BOOL_BITFIELD has_label_bindings : 1; + + /* True if we should issue a warning if a goto statement crosses any + of the bindings. We still need to check the list of bindings to + find the specific ones we need to warn about. This is true if + decl_jump_unsafe would return true for any of the bindings. This + is used to avoid looping over all the bindings unnecessarily. */ + BOOL_BITFIELD has_jump_unsafe_decl : 1; }; /* The scope currently in effect. */ @@ -572,6 +568,31 @@ return t; } +/* Return true if we will want to say something if a goto statement + crosses DECL. */ + +static bool +decl_jump_unsafe (tree decl) +{ + if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node) + return false; + + /* Always warn about crossing variably modified types. */ + if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL) + && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE)) + return true; + + /* Otherwise, only warn if -Wgoto-misses-init and this is an + initialized automatic decl. */ + if (warn_jump_misses_init + && TREE_CODE (decl) == VAR_DECL + && !TREE_STATIC (decl) + && DECL_INITIAL (decl) != NULL_TREE) + return true; + + return false; +} + void c_print_identifier (FILE *file, tree node, int indent) @@ -603,7 +624,7 @@ binding_freelist = b->prev; } else - b = GGC_NEW (struct c_binding); + b = ggc_alloc_c_binding (); b->shadowed = 0; b->decl = decl; @@ -620,6 +641,9 @@ b->prev = scope->bindings; scope->bindings = b; + if (decl_jump_unsafe (decl)) + scope->has_jump_unsafe_decl = 1; + if (!name) return; @@ -717,7 +741,7 @@ record_inline_static (location_t loc, tree func, tree decl, enum c_inline_static_type type) { - struct c_inline_static *csi = GGC_NEW (struct c_inline_static); + struct c_inline_static *csi = ggc_alloc_c_inline_static (); csi->location = loc; csi->function = func; csi->static_decl = decl; @@ -776,31 +800,6 @@ p->left_stmt_expr = false; } -/* Return true if we will want to say something if a goto statement - crosses DECL. */ - -static bool -decl_jump_unsafe (tree decl) -{ - if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node) - return false; - - /* Always warn about crossing variably modified types. */ - if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL) - && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE)) - return true; - - /* Otherwise, only warn if -Wgoto-misses-init and this is an - initialized automatic decl. */ - if (warn_jump_misses_init - && TREE_CODE (decl) == VAR_DECL - && !TREE_STATIC (decl) - && DECL_INITIAL (decl) != NULL_TREE) - return true; - - return false; -} - /* Update spot bindings P as we pop out of SCOPE. Return true if we should push decls for a label. */ @@ -941,7 +940,7 @@ scope_freelist = scope->outer; } else - scope = GGC_CNEW (struct c_scope); + scope = ggc_alloc_cleared_c_scope (); /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes. */ if (current_scope) @@ -980,44 +979,51 @@ while (s != NULL) { if (s->has_label_bindings) - { - struct c_binding *b; - - for (b = s->bindings; b != NULL; b = b->prev) - { - struct c_label_vars *label_vars; - struct c_binding *b1; - unsigned int ix; - struct c_goto_bindings *g; - - if (TREE_CODE (b->decl) != LABEL_DECL) - continue; - label_vars = b->u.label; - - b1 = label_vars->label_bindings.bindings_in_scope; - if (update_spot_bindings (scope, &label_vars->label_bindings)) - { - /* This label is defined in this scope. */ - for (; b1 != NULL; b1 = b1->prev) - { - /* A goto from later in the function to this - label will never see the initialization of - B1, if any. Save it to issue a warning if - needed. */ - if (decl_jump_unsafe (b1->decl)) - VEC_safe_push (tree, gc, label_vars->decls_in_scope, - b1->decl); - } - } - - /* Update the bindings of any goto statements associated - with this label. */ - for (ix = 0; - VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g); - ++ix) - update_spot_bindings (scope, &g->goto_bindings); - } - } + { + struct c_binding *b; + + for (b = s->bindings; b != NULL; b = b->prev) + { + struct c_label_vars *label_vars; + struct c_binding *b1; + bool hjud; + unsigned int ix; + struct c_goto_bindings *g; + + if (TREE_CODE (b->decl) != LABEL_DECL) + continue; + label_vars = b->u.label; + + b1 = label_vars->label_bindings.bindings_in_scope; + if (label_vars->label_bindings.scope == NULL) + hjud = false; + else + hjud = label_vars->label_bindings.scope->has_jump_unsafe_decl; + if (update_spot_bindings (scope, &label_vars->label_bindings)) + { + /* This label is defined in this scope. */ + if (hjud) + { + for (; b1 != NULL; b1 = b1->prev) + { + /* A goto from later in the function to this + label will never see the initialization + of B1, if any. Save it to issue a + warning if needed. */ + if (decl_jump_unsafe (b1->decl)) + VEC_safe_push (tree, gc, + label_vars->decls_in_scope, + b1->decl); + } + } + } + + /* Update the bindings of any goto statements associated + with this label. */ + FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g) + update_spot_bindings (scope, &g->goto_bindings); + } + } /* Don't search beyond the current function. */ if (s == current_function_scope) @@ -1087,10 +1093,7 @@ context = current_function_decl; else if (scope == file_scope) { - tree file_decl = build_decl (UNKNOWN_LOCATION, - TRANSLATION_UNIT_DECL, 0, 0); - TREE_CHAIN (file_decl) = all_translation_units; - all_translation_units = file_decl; + tree file_decl = build_translation_unit_decl (NULL_TREE); context = file_decl; } else @@ -1101,159 +1104,166 @@ { p = b->decl; switch (TREE_CODE (p)) - { - case LABEL_DECL: - /* Warnings for unused labels, errors for undefined labels. */ - if (TREE_USED (p) && !DECL_INITIAL (p)) - { - error ("label %q+D used but not defined", p); - DECL_INITIAL (p) = error_mark_node; - } - else - warn_for_unused_label (p); - - /* Labels go in BLOCK_VARS. */ - TREE_CHAIN (p) = BLOCK_VARS (block); - BLOCK_VARS (block) = p; - gcc_assert (I_LABEL_BINDING (b->id) == b); - I_LABEL_BINDING (b->id) = b->shadowed; - - /* Also pop back to the shadowed label_vars. */ - release_tree_vector (b->u.label->decls_in_scope); - b->u.label = b->u.label->shadowed; - break; - - case ENUMERAL_TYPE: - case UNION_TYPE: - case RECORD_TYPE: - set_type_context (p, context); - - /* Types may not have tag-names, in which case the type - appears in the bindings list with b->id NULL. */ - if (b->id) - { - gcc_assert (I_TAG_BINDING (b->id) == b); - I_TAG_BINDING (b->id) = b->shadowed; - } - break; - - case FUNCTION_DECL: - /* Propagate TREE_ADDRESSABLE from nested functions to their - containing functions. */ - if (!TREE_ASM_WRITTEN (p) - && DECL_INITIAL (p) != 0 - && TREE_ADDRESSABLE (p) - && DECL_ABSTRACT_ORIGIN (p) != 0 - && DECL_ABSTRACT_ORIGIN (p) != p) - TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1; - if (!DECL_EXTERNAL (p) - && !DECL_INITIAL (p) - && scope != file_scope - && scope != external_scope) - { - error ("nested function %q+D declared but never defined", p); - undef_nested_function = true; - } - else if (DECL_DECLARED_INLINE_P (p) - && TREE_PUBLIC (p) - && !DECL_INITIAL (p)) - { - /* C99 6.7.4p6: "a function with external linkage... declared - with an inline function specifier ... shall also be defined - in the same translation unit." */ - if (!flag_gnu89_inline) - pedwarn (input_location, 0, - "inline function %q+D declared but never defined", p); - DECL_EXTERNAL (p) = 1; - } - - goto common_symbol; - - case VAR_DECL: - /* Warnings for unused variables. */ - if (!TREE_USED (p) - && !TREE_NO_WARNING (p) - && !DECL_IN_SYSTEM_HEADER (p) - && DECL_NAME (p) - && !DECL_ARTIFICIAL (p) - && scope != file_scope - && scope != external_scope) - warning (OPT_Wunused_variable, "unused variable %q+D", p); - - if (b->inner_comp) - { - error ("type of array %q+D completed incompatibly with" - " implicit initialization", p); - } - - /* Fall through. */ - case TYPE_DECL: - case CONST_DECL: - common_symbol: - /* All of these go in BLOCK_VARS, but only if this is the - binding in the home scope. */ - if (!b->nested) - { - TREE_CHAIN (p) = BLOCK_VARS (block); - BLOCK_VARS (block) = p; - } - else if (VAR_OR_FUNCTION_DECL_P (p)) - { - /* For block local externs add a special - DECL_EXTERNAL decl for debug info generation. */ - tree extp = copy_node (p); - - DECL_EXTERNAL (extp) = 1; - TREE_STATIC (extp) = 0; - TREE_PUBLIC (extp) = 1; - DECL_INITIAL (extp) = NULL_TREE; - DECL_LANG_SPECIFIC (extp) = NULL; - DECL_CONTEXT (extp) = current_function_decl; - if (TREE_CODE (p) == FUNCTION_DECL) - { - DECL_RESULT (extp) = NULL_TREE; - DECL_SAVED_TREE (extp) = NULL_TREE; - DECL_STRUCT_FUNCTION (extp) = NULL; - } - if (b->locus != UNKNOWN_LOCATION) - DECL_SOURCE_LOCATION (extp) = b->locus; - TREE_CHAIN (extp) = BLOCK_VARS (block); - BLOCK_VARS (block) = extp; - } - /* If this is the file scope, and we are processing more - than one translation unit in this compilation, set - DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL. - This makes same_translation_unit_p work, and causes - static declarations to be given disambiguating suffixes. */ - if (scope == file_scope && num_in_fnames > 1) - { - DECL_CONTEXT (p) = context; - if (TREE_CODE (p) == TYPE_DECL) - set_type_context (TREE_TYPE (p), context); - } - - /* Fall through. */ - /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have - already been put there by store_parm_decls. Unused- - parameter warnings are handled by function.c. - error_mark_node obviously does not go in BLOCK_VARS and - does not get unused-variable warnings. */ - case PARM_DECL: - case ERROR_MARK: - /* It is possible for a decl not to have a name. We get - here with b->id NULL in this case. */ - if (b->id) - { - gcc_assert (I_SYMBOL_BINDING (b->id) == b); - I_SYMBOL_BINDING (b->id) = b->shadowed; - if (b->shadowed && b->shadowed->u.type) - TREE_TYPE (b->shadowed->decl) = b->shadowed->u.type; - } - break; - - default: - gcc_unreachable (); - } + { + case LABEL_DECL: + /* Warnings for unused labels, errors for undefined labels. */ + if (TREE_USED (p) && !DECL_INITIAL (p)) + { + error ("label %q+D used but not defined", p); + DECL_INITIAL (p) = error_mark_node; + } + else + warn_for_unused_label (p); + /* Labels go in BLOCK_VARS. */ + DECL_CHAIN (p) = BLOCK_VARS (block); + BLOCK_VARS (block) = p; + gcc_assert (I_LABEL_BINDING (b->id) == b); + I_LABEL_BINDING (b->id) = b->shadowed; + + /* Also pop back to the shadowed label_vars. */ + release_tree_vector (b->u.label->decls_in_scope); + b->u.label = b->u.label->shadowed; + break; + + case ENUMERAL_TYPE: + case UNION_TYPE: + case RECORD_TYPE: + set_type_context (p, context); + + /* Types may not have tag-names, in which case the type + appears in the bindings list with b->id NULL. */ + if (b->id) + { + gcc_assert (I_TAG_BINDING (b->id) == b); + I_TAG_BINDING (b->id) = b->shadowed; + } + break; + + case FUNCTION_DECL: + /* Propagate TREE_ADDRESSABLE from nested functions to their + containing functions. */ + if (!TREE_ASM_WRITTEN (p) + && DECL_INITIAL (p) != 0 + && TREE_ADDRESSABLE (p) + && DECL_ABSTRACT_ORIGIN (p) != 0 + && DECL_ABSTRACT_ORIGIN (p) != p) + TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1; + if (!DECL_EXTERNAL (p) + && !DECL_INITIAL (p) + && scope != file_scope + && scope != external_scope) + { + error ("nested function %q+D declared but never defined", p); + undef_nested_function = true; + } + else if (DECL_DECLARED_INLINE_P (p) + && TREE_PUBLIC (p) + && !DECL_INITIAL (p)) + { + /* C99 6.7.4p6: "a function with external linkage... declared + with an inline function specifier ... shall also be defined + in the same translation unit." */ + if (!flag_gnu89_inline) + pedwarn (input_location, 0, + "inline function %q+D declared but never defined", p); + DECL_EXTERNAL (p) = 1; + } + + goto common_symbol; + + case VAR_DECL: + /* Warnings for unused variables. */ + if ((!TREE_USED (p) || !DECL_READ_P (p)) + && !TREE_NO_WARNING (p) + && !DECL_IN_SYSTEM_HEADER (p) + && DECL_NAME (p) + && !DECL_ARTIFICIAL (p) + && scope != file_scope + && scope != external_scope) + { + if (!TREE_USED (p)) + warning (OPT_Wunused_variable, "unused variable %q+D", p); + else if (DECL_CONTEXT (p) == current_function_decl) + warning_at (DECL_SOURCE_LOCATION (p), + OPT_Wunused_but_set_variable, + "variable %qD set but not used", p); + } + + if (b->inner_comp) + { + error ("type of array %q+D completed incompatibly with" + " implicit initialization", p); + } + + /* Fall through. */ + case TYPE_DECL: + case CONST_DECL: + common_symbol: + /* All of these go in BLOCK_VARS, but only if this is the + binding in the home scope. */ + if (!b->nested) + { + DECL_CHAIN (p) = BLOCK_VARS (block); + BLOCK_VARS (block) = p; + } + else if (VAR_OR_FUNCTION_DECL_P (p)) + { + /* For block local externs add a special + DECL_EXTERNAL decl for debug info generation. */ + tree extp = copy_node (p); + + + DECL_EXTERNAL (extp) = 1; + TREE_STATIC (extp) = 0; + TREE_PUBLIC (extp) = 1; + DECL_INITIAL (extp) = NULL_TREE; + DECL_LANG_SPECIFIC (extp) = NULL; + DECL_CONTEXT (extp) = current_function_decl; + if (TREE_CODE (p) == FUNCTION_DECL) + { + DECL_RESULT (extp) = NULL_TREE; + DECL_SAVED_TREE (extp) = NULL_TREE; + DECL_STRUCT_FUNCTION (extp) = NULL; + } + if (b->locus != UNKNOWN_LOCATION) + DECL_SOURCE_LOCATION (extp) = b->locus; + DECL_CHAIN (extp) = BLOCK_VARS (block); + BLOCK_VARS (block) = extp; + } + /* If this is the file scope set DECL_CONTEXT of each decl to + the TRANSLATION_UNIT_DECL. This makes same_translation_unit_p + work. */ + if (scope == file_scope) + { + DECL_CONTEXT (p) = context; + if (TREE_CODE (p) == TYPE_DECL + && TREE_TYPE (p) != error_mark_node) + set_type_context (TREE_TYPE (p), context); + } + + + /* Fall through. */ + /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have + already been put there by store_parm_decls. Unused- + parameter warnings are handled by function.c. + error_mark_node obviously does not go in BLOCK_VARS and + does not get unused-variable warnings. */ + case PARM_DECL: + case ERROR_MARK: + /* It is possible for a decl not to have a name. We get + here with b->id NULL in this case. */ + if (b->id) + { + gcc_assert (I_SYMBOL_BINDING (b->id) == b); + I_SYMBOL_BINDING (b->id) = b->shadowed; + if (b->shadowed && b->shadowed->u.type) + TREE_TYPE (b->shadowed->decl) = b->shadowed->u.type; + } + break; + + default: + gcc_unreachable (); + } } @@ -1299,7 +1309,7 @@ start_fname_decls (); - for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl)) + for (decl = visible_builtins; decl; decl = DECL_CHAIN (decl)) bind (DECL_NAME (decl), decl, file_scope, /*invisible=*/false, /*nested=*/true, DECL_SOURCE_LOCATION (decl)); } @@ -1349,20 +1359,18 @@ continue; for (b = scope->bindings; b != NULL; b = b->prev) - { - struct c_label_vars *label_vars; - unsigned int ix; - struct c_goto_bindings *g; - - if (TREE_CODE (b->decl) != LABEL_DECL) - continue; - label_vars = b->u.label; - ++label_vars->label_bindings.stmt_exprs; - for (ix = 0; - VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g); - ++ix) - ++g->goto_bindings.stmt_exprs; - } + { + struct c_label_vars *label_vars; + unsigned int ix; + struct c_goto_bindings *g; + + if (TREE_CODE (b->decl) != LABEL_DECL) + continue; + label_vars = b->u.label; + ++label_vars->label_bindings.stmt_exprs; + FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g) + ++g->goto_bindings.stmt_exprs; + } } if (switch_bindings != NULL) @@ -1384,32 +1392,30 @@ continue; for (b = scope->bindings; b != NULL; b = b->prev) - { - struct c_label_vars *label_vars; - unsigned int ix; - struct c_goto_bindings *g; - - if (TREE_CODE (b->decl) != LABEL_DECL) - continue; - label_vars = b->u.label; - --label_vars->label_bindings.stmt_exprs; - if (label_vars->label_bindings.stmt_exprs < 0) - { - label_vars->label_bindings.left_stmt_expr = true; - label_vars->label_bindings.stmt_exprs = 0; - } - for (ix = 0; - VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g); - ++ix) - { - --g->goto_bindings.stmt_exprs; - if (g->goto_bindings.stmt_exprs < 0) - { - g->goto_bindings.left_stmt_expr = true; - g->goto_bindings.stmt_exprs = 0; - } - } - } + { + struct c_label_vars *label_vars; + unsigned int ix; + struct c_goto_bindings *g; + + if (TREE_CODE (b->decl) != LABEL_DECL) + continue; + label_vars = b->u.label; + --label_vars->label_bindings.stmt_exprs; + if (label_vars->label_bindings.stmt_exprs < 0) + { + label_vars->label_bindings.left_stmt_expr = true; + label_vars->label_bindings.stmt_exprs = 0; + } + FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g) + { + --g->goto_bindings.stmt_exprs; + if (g->goto_bindings.stmt_exprs < 0) + { + g->goto_bindings.left_stmt_expr = true; + g->goto_bindings.stmt_exprs = 0; + } + } + } } if (switch_bindings != NULL) @@ -1522,9 +1528,8 @@ if (TREE_CODE (olddecl) != FUNCTION_DECL || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype)) - || !((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0) - || - (TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0))) + || !((!prototype_p (oldtype) && DECL_INITIAL (olddecl) == 0) + || (!prototype_p (newtype) && DECL_INITIAL (newdecl) == 0))) return; t = TYPE_ARG_TYPES (oldtype); @@ -1792,18 +1797,48 @@ /* Redeclaration of a type is a constraint violation (6.7.2.3p1), but silently ignore the redeclaration if either is in a system - header. (Conflicting redeclarations were handled above.) */ + header. (Conflicting redeclarations were handled above.) This + is allowed for C1X if the types are the same, not just + compatible. */ if (TREE_CODE (newdecl) == TYPE_DECL) { + bool types_different = false; + int comptypes_result; + + comptypes_result + = comptypes_check_different_types (oldtype, newtype, &types_different); + + if (comptypes_result != 1 || types_different) + { + error ("redefinition of typedef %q+D with different type", newdecl); + locate_old_decl (olddecl); + return false; + } + if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl) || TREE_NO_WARNING (newdecl) || TREE_NO_WARNING (olddecl)) return true; /* Allow OLDDECL to continue in use. */ - error ("redefinition of typedef %q+D", newdecl); - locate_old_decl (olddecl); - return false; + if (pedantic && !flag_isoc1x) + { + pedwarn (input_location, OPT_pedantic, + "redefinition of typedef %q+D", newdecl); + locate_old_decl (olddecl); + } + else if (variably_modified_type_p (newtype, NULL)) + { + /* Whether there is a constraint violation for the types not + being the same cannot be determined at compile time; a + warning that there may be one at runtime is considered + appropriate (WG14 reflector message 11743, 8 May 2009). */ + warning (0, "redefinition of typedef %q+D may be a constraint " + "violation at runtime", newdecl); + locate_old_decl (olddecl); + } + + return true; } /* Function declarations can either be 'static' or 'extern' (no @@ -1821,16 +1856,16 @@ can't validate the argument list) the built-in definition is overridden, but optionally warn this was a bad choice of name. */ if (DECL_BUILT_IN (olddecl) - && !C_DECL_DECLARED_BUILTIN (olddecl) - && (!TREE_PUBLIC (newdecl) - || (DECL_INITIAL (newdecl) - && !TYPE_ARG_TYPES (TREE_TYPE (newdecl))))) - { - warning (OPT_Wshadow, "declaration of %q+D shadows " - "a built-in function", newdecl); - /* Discard the old built-in function. */ - return false; - } + && !C_DECL_DECLARED_BUILTIN (olddecl) + && (!TREE_PUBLIC (newdecl) + || (DECL_INITIAL (newdecl) + && !prototype_p (TREE_TYPE (newdecl))))) + { + warning (OPT_Wshadow, "declaration of %q+D shadows " + "a built-in function", newdecl); + /* Discard the old built-in function. */ + return false; + } if (DECL_INITIAL (newdecl)) { @@ -1861,13 +1896,13 @@ /* If we have a prototype after an old-style function definition, the argument types must be checked specially. */ else if (DECL_INITIAL (olddecl) - && !TYPE_ARG_TYPES (oldtype) && TYPE_ARG_TYPES (newtype) - && TYPE_ACTUAL_ARG_TYPES (oldtype) - && !validate_proto_after_old_defn (newdecl, newtype, oldtype)) - { - locate_old_decl (olddecl); - return false; - } + && !prototype_p (oldtype) && prototype_p (newtype) + && TYPE_ACTUAL_ARG_TYPES (oldtype) + && !validate_proto_after_old_defn (newdecl, newtype, oldtype)) + { + locate_old_decl (olddecl); + return false; + } /* A non-static declaration (even an "extern") followed by a static declaration is undefined behavior per C99 6.2.2p3-5,7. The same is true for a static forward declaration at block @@ -2130,9 +2165,9 @@ bool new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0); bool new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL - && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0); + && prototype_p (TREE_TYPE (newdecl))); bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL - && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0); + && prototype_p (TREE_TYPE (olddecl))); bool extern_changed = false; /* For real parm decl following a forward decl, rechain the old decl @@ -2369,22 +2404,21 @@ /* Also preserve various other info from the definition. */ if (!new_is_definition) - { - tree t; - DECL_RESULT (newdecl) = DECL_RESULT (olddecl); - DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); - DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl); - DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl); - gimple_set_body (newdecl, gimple_body (olddecl)); - DECL_ARGUMENTS (newdecl) = copy_list (DECL_ARGUMENTS (olddecl)); - for (t = DECL_ARGUMENTS (newdecl); t ; t = TREE_CHAIN (t)) - DECL_CONTEXT (t) = newdecl; - - /* See if we've got a function to instantiate from. */ - if (DECL_SAVED_TREE (olddecl)) - DECL_ABSTRACT_ORIGIN (newdecl) - = DECL_ABSTRACT_ORIGIN (olddecl); - } + { + tree t; + DECL_RESULT (newdecl) = DECL_RESULT (olddecl); + DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); + DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl); + DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl); + DECL_ARGUMENTS (newdecl) = copy_list (DECL_ARGUMENTS (olddecl)); + for (t = DECL_ARGUMENTS (newdecl); t ; t = DECL_CHAIN (t)) + DECL_CONTEXT (t) = newdecl; + + /* See if we've got a function to instantiate from. */ + if (DECL_SAVED_TREE (olddecl)) + DECL_ABSTRACT_ORIGIN (newdecl) + = DECL_ABSTRACT_ORIGIN (olddecl); + } } extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl); @@ -2394,6 +2428,12 @@ TREE_USED (newdecl) = 1; else if (TREE_USED (newdecl)) TREE_USED (olddecl) = 1; + if (TREE_CODE (olddecl) == VAR_DECL || TREE_CODE (olddecl) == PARM_DECL) + DECL_READ_P (newdecl) |= DECL_READ_P (olddecl); + if (DECL_PRESERVE_P (olddecl)) + DECL_PRESERVE_P (newdecl) = 1; + else if (DECL_PRESERVE_P (newdecl)) + DECL_PRESERVE_P (olddecl) = 1; /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. But preserve OLDDECL's DECL_UID, DECL_CONTEXT and @@ -2411,9 +2451,6 @@ switch (TREE_CODE (olddecl)) { case FUNCTION_DECL: - gimple_set_body (olddecl, gimple_body (newdecl)); - /* fall through */ - case FIELD_DECL: case VAR_DECL: case PARM_DECL: @@ -2961,14 +2998,14 @@ } else { - error_at (loc, "%qE undeclared (first use in this function)", id); - + if (!objc_diagnose_private_ivar (id)) + error_at (loc, "%qE undeclared (first use in this function)", id); if (!already) - { - error_at (loc, "(Each undeclared identifier is reported only once"); - error_at (loc, "for each function it appears in.)"); - already = true; - } + { + inform (loc, "each undeclared identifier is reported only" + " once for each function it appears in"); + already = true; + } /* If we are parsing old-style parameter decls, current_function_decl will be nonnull but current_function_scope will be null. */ @@ -2992,7 +3029,7 @@ DECL_CONTEXT (label) = current_function_decl; DECL_MODE (label) = VOIDmode; - label_vars = GGC_NEW (struct c_label_vars); + label_vars = ggc_alloc_c_label_vars (); label_vars->shadowed = NULL; set_spot_bindings (&label_vars->label_bindings, defining); label_vars->decls_in_scope = make_tree_vector (); @@ -3013,7 +3050,7 @@ tree label; struct c_label_vars *label_vars; - if (current_function_decl == 0) + if (current_function_scope == 0) { error ("label %qE referenced outside of any function", name); return 0; @@ -3090,7 +3127,7 @@ { struct c_goto_bindings *g; - g = GGC_NEW (struct c_goto_bindings); + g = ggc_alloc_c_goto_bindings (); g->loc = loc; set_spot_bindings (&g->goto_bindings, true); VEC_safe_push (c_goto_bindings_p, gc, label_vars->gotos, g); @@ -3105,7 +3142,7 @@ ... goto lab; Issue a warning or error. */ - for (ix = 0; VEC_iterate (tree, label_vars->decls_in_scope, ix, decl); ++ix) + FOR_EACH_VEC_ELT (tree, label_vars->decls_in_scope, ix, decl) warn_about_goto (loc, label, decl); if (label_vars->label_bindings.left_stmt_expr) @@ -3157,41 +3194,45 @@ unsigned int ix; struct c_goto_bindings *g; - for (ix = 0; - VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g); - ++ix) + FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g) { struct c_binding *b; struct c_scope *scope; /* We have a goto to this label. The goto is going forward. In - g->scope, the goto is going to skip any binding which was - defined after g->bindings_in_scope. */ - for (b = g->goto_bindings.scope->bindings; - b != g->goto_bindings.bindings_in_scope; - b = b->prev) - { - if (decl_jump_unsafe (b->decl)) - warn_about_goto (g->loc, label, b->decl); - } + g->scope, the goto is going to skip any binding which was + defined after g->bindings_in_scope. */ + if (g->goto_bindings.scope->has_jump_unsafe_decl) + { + for (b = g->goto_bindings.scope->bindings; + b != g->goto_bindings.bindings_in_scope; + b = b->prev) + { + if (decl_jump_unsafe (b->decl)) + warn_about_goto (g->loc, label, b->decl); + } + } /* We also need to warn about decls defined in any scopes between the scope of the label and the scope of the goto. */ for (scope = label_vars->label_bindings.scope; - scope != g->goto_bindings.scope; - scope = scope->outer) - { - gcc_assert (scope != NULL); - if (scope == label_vars->label_bindings.scope) - b = label_vars->label_bindings.bindings_in_scope; - else - b = scope->bindings; - for (; b != NULL; b = b->prev) - { - if (decl_jump_unsafe (b->decl)) - warn_about_goto (g->loc, label, b->decl); - } - } + scope != g->goto_bindings.scope; + scope = scope->outer) + { + gcc_assert (scope != NULL); + if (scope->has_jump_unsafe_decl) + { + if (scope == label_vars->label_bindings.scope) + b = label_vars->label_bindings.bindings_in_scope; + else + b = scope->bindings; + for (; b != NULL; b = b->prev) + { + if (decl_jump_unsafe (b->decl)) + warn_about_goto (g->loc, label, b->decl); + } + } + } if (g->goto_bindings.stmt_exprs > 0) { @@ -3305,6 +3346,10 @@ struct c_binding *b; gcc_assert (scope != NULL); + + if (!scope->has_jump_unsafe_decl) + continue; + for (b = scope->bindings; b != NULL; b = b->prev) { if (decl_jump_unsafe (b->decl)) @@ -3459,7 +3504,7 @@ using preprocessed headers. */ input_location = BUILTINS_LOCATION; - build_common_tree_nodes (flag_signed_char, false); + build_common_tree_nodes (flag_signed_char); c_common_nodes_and_builtins (); @@ -3518,10 +3563,10 @@ void foo() const char* p = __FUNCTION__; - the __FUNCTION__ is believed to appear in K&R style function - parameter declarator. In that case we still don't have - function_scope. */ - && (!errorcount || current_function_scope)) + the __FUNCTION__ is believed to appear in K&R style function + parameter declarator. In that case we still don't have + function_scope. */ + && (!seen_error () || current_function_scope)) { DECL_CONTEXT (decl) = current_function_decl; bind (id, decl, current_function_scope, @@ -3540,7 +3585,7 @@ tree id = DECL_NAME (decl); const char *name = IDENTIFIER_POINTER (id); - C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0); + C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type); /* Should never be called on a symbol with a preexisting meaning. */ gcc_assert (!I_SYMBOL_BINDING (id)); @@ -3552,7 +3597,7 @@ needing to be explicitly declared. See push_file_scope. */ if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1]))) { - TREE_CHAIN (decl) = visible_builtins; + DECL_CHAIN (decl) = visible_builtins; visible_builtins = decl; } @@ -3566,7 +3611,7 @@ tree id = DECL_NAME (decl); const char *name = IDENTIFIER_POINTER (id); - C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0); + C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type); /* Should never be called on a symbol with a preexisting meaning. */ gcc_assert (!I_SYMBOL_BINDING (id)); @@ -3578,7 +3623,7 @@ needing to be explicitly declared. See push_file_scope. */ if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1]))) { - TREE_CHAIN (decl) = visible_builtins; + DECL_CHAIN (decl) = visible_builtins; visible_builtins = decl; } @@ -3612,53 +3657,67 @@ enum tree_code code = TREE_CODE (value); if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE) - /* Used to test also that TYPE_SIZE (value) != 0. - That caused warning for `struct foo;' at top level in the file. */ - { - tree name = TYPE_NAME (value); - tree t; - - found_tag = true; - - if (declspecs->restrict_p) - { - error ("invalid use of %<restrict%>"); - warned = 1; - } - - if (name == 0) - { - if (warned != 1 && code != ENUMERAL_TYPE) - /* Empty unnamed enum OK */ - { - pedwarn (input_location, 0, - "unnamed struct/union that defines no instances"); - warned = 1; - } - } - else if (!declspecs->tag_defined_p - && declspecs->storage_class != csc_none) - { - if (warned != 1) - pedwarn (input_location, 0, - "empty declaration with storage class specifier " - "does not redeclare tag"); - warned = 1; - pending_xref_error (); - } - else if (!declspecs->tag_defined_p - && (declspecs->const_p - || declspecs->volatile_p - || declspecs->restrict_p - || declspecs->address_space)) - { - if (warned != 1) - pedwarn (input_location, 0, - "empty declaration with type qualifier " - "does not redeclare tag"); - warned = 1; - pending_xref_error (); - } + /* Used to test also that TYPE_SIZE (value) != 0. + That caused warning for `struct foo;' at top level in the file. */ + { + tree name = TYPE_NAME (value); + tree t; + + found_tag = true; + + if (declspecs->restrict_p) + { + error ("invalid use of %<restrict%>"); + warned = 1; + } + + if (name == 0) + { + if (warned != 1 && code != ENUMERAL_TYPE) + /* Empty unnamed enum OK */ + { + pedwarn (input_location, 0, + "unnamed struct/union that defines no instances"); + warned = 1; + } + } + else if (declspecs->typespec_kind != ctsk_tagdef + && declspecs->typespec_kind != ctsk_tagfirstref + && declspecs->storage_class != csc_none) + { + if (warned != 1) + pedwarn (input_location, 0, + "empty declaration with storage class specifier " + "does not redeclare tag"); + warned = 1; + pending_xref_error (); + } + else if (declspecs->typespec_kind != ctsk_tagdef + && declspecs->typespec_kind != ctsk_tagfirstref + && (declspecs->const_p + || declspecs->volatile_p + || declspecs->restrict_p + || declspecs->address_space)) + { + if (warned != 1) + pedwarn (input_location, 0, + "empty declaration with type qualifier " + "does not redeclare tag"); + warned = 1; + pending_xref_error (); + } + else + { + pending_invalid_xref = 0; + t = lookup_tag (code, name, 1, NULL); + + if (t == 0) + { + t = make_node (code); + pushtag (input_location, name, t); + } + } + } else { pending_invalid_xref = 0; @@ -4000,7 +4059,7 @@ prototypes file (if requested). */ if (TREE_CODE (decl) == FUNCTION_DECL) - gen_aux_info_record (decl, 0, 0, TYPE_ARG_TYPES (TREE_TYPE (decl)) != 0); + gen_aux_info_record (decl, 0, 0, prototype_p (TREE_TYPE (decl))); /* ANSI specifies that a tentative definition which is not merged with a non-tentative definition behaves exactly like a definition with an @@ -4044,16 +4103,16 @@ if (ce->kind == cdk_pointer) ce = declarator->declarator; if (ce->kind == cdk_function) - { - tree args = ce->u.arg_info->parms; - for (; args; args = TREE_CHAIN (args)) - { - tree type = TREE_TYPE (args); - if (type && INTEGRAL_TYPE_P (type) - && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) - DECL_ARG_TYPE (args) = integer_type_node; - } - } + { + tree args = ce->u.arg_info->parms; + for (; args; args = DECL_CHAIN (args)) + { + tree type = TREE_TYPE (args); + if (type && INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) + DECL_ARG_TYPE (args) = integer_type_node; + } + } } if (TREE_CODE (decl) == FUNCTION_DECL @@ -4075,6 +4134,11 @@ record_inline_static (input_location, current_function_decl, decl, csi_modifiable); + if (c_dialect_objc () + && (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL)) + objc_check_global_decl (decl); + /* Add this decl to the current scope. TEM may equal DECL or it may be a previous decl of the same name. */ tem = pushdecl (decl); @@ -4088,6 +4152,35 @@ return tem; } +/* Subroutine of finish_decl. TYPE is the type of an uninitialized object + DECL or the non-array element type if DECL is an uninitialized array. + If that type has a const member, diagnose this. */ + +static void +diagnose_uninitialized_cst_member (tree decl, tree type) +{ + tree field; + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + tree field_type; + if (TREE_CODE (field) != FIELD_DECL) + continue; + field_type = strip_array_types (TREE_TYPE (field)); + + if (TYPE_QUALS (field_type) & TYPE_QUAL_CONST) + { + warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat, + "uninitialized const member in %qT is invalid in C++", + strip_array_types (TREE_TYPE (decl))); + inform (DECL_SOURCE_LOCATION (field), "%qD should be initialized", field); + } + + if (TREE_CODE (field_type) == RECORD_TYPE + || TREE_CODE (field_type) == UNION_TYPE) + diagnose_uninitialized_cst_member (decl, field_type); + } +} + /* Finish processing of a declaration; install its initial value. If ORIGTYPE is not NULL_TREE, it is the original type of INIT. @@ -4246,7 +4339,10 @@ } if (TREE_USED (type)) - TREE_USED (decl) = 1; + { + TREE_USED (decl) = 1; + DECL_READ_P (decl) = 1; + } } /* If this is a function and an assembler name is specified, reset DECL_RTL @@ -4377,35 +4473,43 @@ { tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl)); if (attr) - { - tree cleanup_id = TREE_VALUE (TREE_VALUE (attr)); - tree cleanup_decl = lookup_name (cleanup_id); - tree cleanup; - VEC(tree,gc) *vec; - - /* Build "cleanup(&decl)" for the destructor. */ - cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0); - vec = VEC_alloc (tree, gc, 1); - VEC_quick_push (tree, vec, cleanup); - cleanup = build_function_call_vec (DECL_SOURCE_LOCATION (decl), - cleanup_decl, vec, NULL); - VEC_free (tree, gc, vec); - - /* Don't warn about decl unused; the cleanup uses it. */ - TREE_USED (decl) = 1; - TREE_USED (cleanup_decl) = 1; - - push_cleanup (decl, cleanup, false); - } + { + tree cleanup_id = TREE_VALUE (TREE_VALUE (attr)); + tree cleanup_decl = lookup_name (cleanup_id); + tree cleanup; + VEC(tree,gc) *vec; + + /* Build "cleanup(&decl)" for the destructor. */ + cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0); + vec = VEC_alloc (tree, gc, 1); + VEC_quick_push (tree, vec, cleanup); + cleanup = build_function_call_vec (DECL_SOURCE_LOCATION (decl), + cleanup_decl, vec, NULL); + VEC_free (tree, gc, vec); + + /* Don't warn about decl unused; the cleanup uses it. */ + TREE_USED (decl) = 1; + TREE_USED (cleanup_decl) = 1; + DECL_READ_P (decl) = 1; + + push_cleanup (decl, cleanup, false); + } } if (warn_cxx_compat && TREE_CODE (decl) == VAR_DECL - && TREE_READONLY (decl) && !DECL_EXTERNAL (decl) && DECL_INITIAL (decl) == NULL_TREE) - warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat, - "uninitialized const %qD is invalid in C++", decl); + { + type = strip_array_types (type); + if (TREE_READONLY (decl)) + warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat, + "uninitialized const %qD is invalid in C++", decl); + else if ((TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE) + && C_TYPE_FIELDS_READONLY (type)) + diagnose_uninitialized_cst_member (decl, type); + } } /* Given a parsed parameter declaration, decode it into a PARM_DECL. */ @@ -4476,7 +4580,8 @@ tree complit; tree stmt; - if (type == error_mark_node) + if (type == error_mark_node + || init == error_mark_node) return error_mark_node; decl = build_decl (loc, VAR_DECL, NULL_TREE, type); @@ -4485,6 +4590,7 @@ TREE_STATIC (decl) = (current_scope == file_scope); DECL_CONTEXT (decl) = current_function_decl; TREE_USED (decl) = 1; + DECL_READ_P (decl) = 1; TREE_TYPE (decl) = type; TREE_READONLY (decl) = TYPE_READONLY (type); store_init_value (loc, decl, init, NULL_TREE); @@ -4535,7 +4641,9 @@ void check_compound_literal_type (location_t loc, struct c_type_name *type_name) { - if (warn_cxx_compat && type_name->specs->tag_defined_p) + if (warn_cxx_compat + && (type_name->specs->typespec_kind == ctsk_tagdef + || type_name->specs->typespec_kind == ctsk_tagfirstref)) warning_at (loc, OPT_Wc___compat, "defining a type in a compound literal is invalid in C++"); } @@ -4552,9 +4660,9 @@ case RECORD_TYPE: x = TYPE_FIELDS (type); if (x == NULL_TREE) - return false; - while (TREE_CHAIN (x) != NULL_TREE) - x = TREE_CHAIN (x); + return false; + while (DECL_CHAIN (x) != NULL_TREE) + x = DECL_CHAIN (x); if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE @@ -4562,11 +4670,11 @@ return true; return false; case UNION_TYPE: - for (x = TYPE_FIELDS (type); x != NULL_TREE; x = TREE_CHAIN (x)) - { - if (flexible_array_type_p (TREE_TYPE (x))) - return true; - } + for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x)) + { + if (flexible_array_type_p (TREE_TYPE (x))) + return true; + } return false; default: return false; @@ -4815,6 +4923,8 @@ tree expr_dummy; bool expr_const_operands_dummy; + if (TREE_CODE (type) == ERROR_MARK) + return error_mark_node; if (expr == NULL) expr = &expr_dummy; if (expr_const_operands == NULL) @@ -5105,411 +5215,415 @@ } switch (declarator->kind) - { - case cdk_attrs: - { - /* A declarator with embedded attributes. */ - tree attrs = declarator->u.attrs; - const struct c_declarator *inner_decl; - int attr_flags = 0; - declarator = declarator->declarator; - inner_decl = declarator; - while (inner_decl->kind == cdk_attrs) - inner_decl = inner_decl->declarator; - if (inner_decl->kind == cdk_id) - attr_flags |= (int) ATTR_FLAG_DECL_NEXT; - else if (inner_decl->kind == cdk_function) - attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT; - else if (inner_decl->kind == cdk_array) - attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT; - returned_attrs = decl_attributes (&type, - chainon (returned_attrs, attrs), - attr_flags); - break; - } - case cdk_array: - { - tree itype = NULL_TREE; - tree size = declarator->u.array.dimen; - /* The index is a signed object `sizetype' bits wide. */ - tree index_type = c_common_signed_type (sizetype); - - array_ptr_quals = declarator->u.array.quals; - array_ptr_attrs = declarator->u.array.attrs; - array_parm_static = declarator->u.array.static_p; - array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p; - - declarator = declarator->declarator; - - /* Check for some types that there cannot be arrays of. */ - - if (VOID_TYPE_P (type)) - { - if (name) - error_at (loc, "declaration of %qE as array of voids", name); - else - error_at (loc, "declaration of type name as array of voids"); - type = error_mark_node; - } - - if (TREE_CODE (type) == FUNCTION_TYPE) - { - if (name) - error_at (loc, "declaration of %qE as array of functions", - name); - else - error_at (loc, "declaration of type name as array of " - "functions"); - type = error_mark_node; - } - - if (pedantic && !in_system_header && flexible_array_type_p (type)) - pedwarn (loc, OPT_pedantic, - "invalid use of structure with flexible array member"); - - if (size == error_mark_node) - type = error_mark_node; - - if (type == error_mark_node) - continue; - - /* If size was specified, set ITYPE to a range-type for - that size. Otherwise, ITYPE remains null. finish_decl - may figure it out from an initial value. */ - - if (size) - { - bool size_maybe_const = true; - bool size_int_const = (TREE_CODE (size) == INTEGER_CST - && !TREE_OVERFLOW (size)); - bool this_size_varies = false; - - /* Strip NON_LVALUE_EXPRs since we aren't using as an - lvalue. */ - STRIP_TYPE_NOPS (size); - - if (!INTEGRAL_TYPE_P (TREE_TYPE (size))) - { - if (name) - error_at (loc, "size of array %qE has non-integer type", - name); - else - error_at (loc, - "size of unnamed array has non-integer type"); - size = integer_one_node; - } - - size = c_fully_fold (size, false, &size_maybe_const); - - if (pedantic && size_maybe_const && integer_zerop (size)) - { - if (name) - pedwarn (loc, OPT_pedantic, - "ISO C forbids zero-size array %qE", name); - else - pedwarn (loc, OPT_pedantic, - "ISO C forbids zero-size array"); - } - - if (TREE_CODE (size) == INTEGER_CST && size_maybe_const) - { - constant_expression_warning (size); - if (tree_int_cst_sgn (size) < 0) - { - if (name) - error_at (loc, "size of array %qE is negative", name); - else - error_at (loc, "size of unnamed array is negative"); - size = integer_one_node; - } - /* Handle a size folded to an integer constant but - not an integer constant expression. */ - if (!size_int_const) - { - /* If this is a file scope declaration of an - ordinary identifier, this is invalid code; - diagnosing it here and not subsequently - treating the type as variable-length avoids - more confusing diagnostics later. */ - if ((decl_context == NORMAL || decl_context == FIELD) - && current_scope == file_scope) - pedwarn (input_location, 0, - "variably modified %qE at file scope", - name); - else - this_size_varies = size_varies = true; - warn_variable_length_array (name, size); - } - } - else if ((decl_context == NORMAL || decl_context == FIELD) - && current_scope == file_scope) - { - error_at (loc, "variably modified %qE at file scope", name); - size = integer_one_node; - } - else - { - /* Make sure the array size remains visibly - nonconstant even if it is (eg) a const variable - with known value. */ - this_size_varies = size_varies = true; - warn_variable_length_array (name, size); - } - - if (integer_zerop (size) && !this_size_varies) - { - /* A zero-length array cannot be represented with - an unsigned index type, which is what we'll - get with build_index_type. Create an - open-ended range instead. */ - itype = build_range_type (sizetype, size, NULL_TREE); - } - else - { - /* Arrange for the SAVE_EXPR on the inside of the - MINUS_EXPR, which allows the -1 to get folded - with the +1 that happens when building TYPE_SIZE. */ - if (size_varies) - size = c_variable_size (size); - if (this_size_varies && TREE_CODE (size) == INTEGER_CST) - size = build2 (COMPOUND_EXPR, TREE_TYPE (size), - integer_zero_node, size); - - /* Compute the maximum valid index, that is, size - - 1. Do the calculation in index_type, so that - if it is a variable the computations will be - done in the proper mode. */ - itype = fold_build2_loc (loc, MINUS_EXPR, index_type, - convert (index_type, size), - convert (index_type, - size_one_node)); - - /* If that overflowed, the array is too big. ??? - While a size of INT_MAX+1 technically shouldn't - cause an overflow (because we subtract 1), the - overflow is recorded during the conversion to - index_type, before the subtraction. Handling - this case seems like an unnecessary - complication. */ - if (TREE_CODE (itype) == INTEGER_CST - && TREE_OVERFLOW (itype)) - { - if (name) - error_at (loc, "size of array %qE is too large", - name); - else - error_at (loc, "size of unnamed array is too large"); - type = error_mark_node; - continue; - } - - itype = build_index_type (itype); - } - if (this_size_varies) - { - if (*expr) - *expr = build2 (COMPOUND_EXPR, TREE_TYPE (size), - *expr, size); - else - *expr = size; - *expr_const_operands &= size_maybe_const; - } - } - else if (decl_context == FIELD) - { - bool flexible_array_member = false; - if (array_parm_vla_unspec_p) - /* Field names can in fact have function prototype - scope so [*] is disallowed here through making - the field variably modified, not through being - something other than a declaration with function - prototype scope. */ - size_varies = true; - else - { - const struct c_declarator *t = declarator; - while (t->kind == cdk_attrs) - t = t->declarator; - flexible_array_member = (t->kind == cdk_id); - } - if (flexible_array_member - && pedantic && !flag_isoc99 && !in_system_header) - pedwarn (loc, OPT_pedantic, - "ISO C90 does not support flexible array members"); - - /* ISO C99 Flexible array members are effectively - identical to GCC's zero-length array extension. */ - if (flexible_array_member || array_parm_vla_unspec_p) - itype = build_range_type (sizetype, size_zero_node, - NULL_TREE); - } - else if (decl_context == PARM) - { - if (array_parm_vla_unspec_p) - { - itype = build_range_type (sizetype, size_zero_node, NULL_TREE); - size_varies = true; - } - } - else if (decl_context == TYPENAME) - { - if (array_parm_vla_unspec_p) - { - /* C99 6.7.5.2p4 */ - warning (0, "%<[*]%> not in a declaration"); - /* We use this to avoid messing up with incomplete - array types of the same type, that would - otherwise be modified below. */ - itype = build_range_type (sizetype, size_zero_node, - NULL_TREE); - size_varies = true; - } - } - - /* Complain about arrays of incomplete types. */ - if (!COMPLETE_TYPE_P (type)) - { - error_at (loc, "array type has incomplete element type"); - type = error_mark_node; - } - else - /* When itype is NULL, a shared incomplete array type is - returned for all array of a given type. Elsewhere we - make sure we don't complete that type before copying - it, but here we want to make sure we don't ever - modify the shared type, so we gcc_assert (itype) - below. */ - { - addr_space_t as = DECODE_QUAL_ADDR_SPACE (type_quals); - if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type)) - type = build_qualified_type (type, - ENCODE_QUAL_ADDR_SPACE (as)); - - type = build_array_type (type, itype); - } - - if (type != error_mark_node) - { - if (size_varies) - { - /* It is ok to modify type here even if itype is - NULL: if size_varies, we're in a - multi-dimensional array and the inner type has - variable size, so the enclosing shared array type - must too. */ - if (size && TREE_CODE (size) == INTEGER_CST) - type - = build_distinct_type_copy (TYPE_MAIN_VARIANT (type)); - C_TYPE_VARIABLE_SIZE (type) = 1; - } - - /* The GCC extension for zero-length arrays differs from - ISO flexible array members in that sizeof yields - zero. */ - if (size && integer_zerop (size)) - { - gcc_assert (itype); - TYPE_SIZE (type) = bitsize_zero_node; - TYPE_SIZE_UNIT (type) = size_zero_node; - } - if (array_parm_vla_unspec_p) - { - gcc_assert (itype); - /* The type is complete. C99 6.7.5.2p4 */ - TYPE_SIZE (type) = bitsize_zero_node; - TYPE_SIZE_UNIT (type) = size_zero_node; - } - } - - if (decl_context != PARM - && (array_ptr_quals != TYPE_UNQUALIFIED - || array_ptr_attrs != NULL_TREE - || array_parm_static)) - { - error_at (loc, "static or type qualifiers in non-parameter array declarator"); - array_ptr_quals = TYPE_UNQUALIFIED; - array_ptr_attrs = NULL_TREE; - array_parm_static = 0; - } - break; - } - case cdk_function: - { - /* Say it's a definition only for the declarator closest - to the identifier, apart possibly from some - attributes. */ - bool really_funcdef = false; - tree arg_types; - if (funcdef_flag) - { - const struct c_declarator *t = declarator->declarator; - while (t->kind == cdk_attrs) - t = t->declarator; - really_funcdef = (t->kind == cdk_id); - } - - /* Declaring a function type. Make sure we have a valid - type for the function to return. */ - if (type == error_mark_node) - continue; - - size_varies = false; - - /* Warn about some types functions can't return. */ - if (TREE_CODE (type) == FUNCTION_TYPE) - { - if (name) - error_at (loc, "%qE declared as function returning a " - "function", name); - else - error_at (loc, "type name declared as function " - "returning a function"); - type = integer_type_node; - } - if (TREE_CODE (type) == ARRAY_TYPE) - { - if (name) - error_at (loc, "%qE declared as function returning an array", - name); - else - error_at (loc, "type name declared as function returning " - "an array"); - type = integer_type_node; - } - errmsg = targetm.invalid_return_type (type); - if (errmsg) - { - error (errmsg); - type = integer_type_node; - } - - /* Construct the function type and go to the next - inner layer of declarator. */ - arg_info = declarator->u.arg_info; - arg_types = grokparms (arg_info, really_funcdef); - if (really_funcdef) - put_pending_sizes (arg_info->pending_sizes); - - /* Type qualifiers before the return type of the function - qualify the return type, not the function type. */ - if (type_quals) - { - /* Type qualifiers on a function return type are - normally permitted by the standard but have no - effect, so give a warning at -Wreturn-type. - Qualifiers on a void return type are banned on - function definitions in ISO C; GCC used to used - them for noreturn functions. */ - if (VOID_TYPE_P (type) && really_funcdef) - pedwarn (loc, 0, - "function definition has qualified void return type"); - else - warning_at (loc, OPT_Wignored_qualifiers, - "type qualifiers ignored on function return type"); - - type = c_build_qualified_type (type, type_quals); - } - type_quals = TYPE_UNQUALIFIED; + { + case cdk_attrs: + { + /* A declarator with embedded attributes. */ + tree attrs = declarator->u.attrs; + const struct c_declarator *inner_decl; + int attr_flags = 0; + declarator = declarator->declarator; + inner_decl = declarator; + while (inner_decl->kind == cdk_attrs) + inner_decl = inner_decl->declarator; + if (inner_decl->kind == cdk_id) + attr_flags |= (int) ATTR_FLAG_DECL_NEXT; + else if (inner_decl->kind == cdk_function) + attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT; + else if (inner_decl->kind == cdk_array) + attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT; + returned_attrs = decl_attributes (&type, + chainon (returned_attrs, attrs), + attr_flags); + break; + } + case cdk_array: + { + tree itype = NULL_TREE; + tree size = declarator->u.array.dimen; + /* The index is a signed object `sizetype' bits wide. */ + tree index_type = c_common_signed_type (sizetype); + + array_ptr_quals = declarator->u.array.quals; + array_ptr_attrs = declarator->u.array.attrs; + array_parm_static = declarator->u.array.static_p; + array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p; + + declarator = declarator->declarator; + + /* Check for some types that there cannot be arrays of. */ + + if (VOID_TYPE_P (type)) + { + if (name) + error_at (loc, "declaration of %qE as array of voids", name); + else + error_at (loc, "declaration of type name as array of voids"); + type = error_mark_node; + } + + if (TREE_CODE (type) == FUNCTION_TYPE) + { + if (name) + error_at (loc, "declaration of %qE as array of functions", + name); + else + error_at (loc, "declaration of type name as array of " + "functions"); + type = error_mark_node; + } + if (pedantic && !in_system_header && flexible_array_type_p (type)) + pedwarn (loc, OPT_pedantic, + "invalid use of structure with flexible array member"); + + if (size == error_mark_node) + type = error_mark_node; + + if (type == error_mark_node) + continue; + + /* If size was specified, set ITYPE to a range-type for + that size. Otherwise, ITYPE remains null. finish_decl + may figure it out from an initial value. */ + + if (size) + { + bool size_maybe_const = true; + bool size_int_const = (TREE_CODE (size) == INTEGER_CST + && !TREE_OVERFLOW (size)); + bool this_size_varies = false; + + /* Strip NON_LVALUE_EXPRs since we aren't using as an + lvalue. */ + STRIP_TYPE_NOPS (size); + + if (!INTEGRAL_TYPE_P (TREE_TYPE (size))) + { + if (name) + error_at (loc, "size of array %qE has non-integer type", + name); + else + error_at (loc, + "size of unnamed array has non-integer type"); + size = integer_one_node; + } + + size = c_fully_fold (size, false, &size_maybe_const); + + if (pedantic && size_maybe_const && integer_zerop (size)) + { + if (name) + pedwarn (loc, OPT_pedantic, + "ISO C forbids zero-size array %qE", name); + else + pedwarn (loc, OPT_pedantic, + "ISO C forbids zero-size array"); + } + + if (TREE_CODE (size) == INTEGER_CST && size_maybe_const) + { + constant_expression_warning (size); + if (tree_int_cst_sgn (size) < 0) + { + if (name) + error_at (loc, "size of array %qE is negative", name); + else + error_at (loc, "size of unnamed array is negative"); + size = integer_one_node; + } + /* Handle a size folded to an integer constant but + not an integer constant expression. */ + if (!size_int_const) + { + /* If this is a file scope declaration of an + ordinary identifier, this is invalid code; + diagnosing it here and not subsequently + treating the type as variable-length avoids + more confusing diagnostics later. */ + if ((decl_context == NORMAL || decl_context == FIELD) + && current_scope == file_scope) + pedwarn (input_location, 0, + "variably modified %qE at file scope", + name); + else + this_size_varies = size_varies = true; + warn_variable_length_array (name, size); + } + } + else if ((decl_context == NORMAL || decl_context == FIELD) + && current_scope == file_scope) + { + error_at (loc, "variably modified %qE at file scope", name); + size = integer_one_node; + } + else + { + /* Make sure the array size remains visibly + nonconstant even if it is (eg) a const variable + with known value. */ + this_size_varies = size_varies = true; + warn_variable_length_array (name, size); + } + + if (integer_zerop (size) && !this_size_varies) + { + /* A zero-length array cannot be represented with + an unsigned index type, which is what we'll + get with build_index_type. Create an + open-ended range instead. */ + itype = build_range_type (sizetype, size, NULL_TREE); + } + else + { + /* Arrange for the SAVE_EXPR on the inside of the + MINUS_EXPR, which allows the -1 to get folded + with the +1 that happens when building TYPE_SIZE. */ + if (size_varies) + size = c_variable_size (size); + if (this_size_varies && TREE_CODE (size) == INTEGER_CST) + size = build2 (COMPOUND_EXPR, TREE_TYPE (size), + integer_zero_node, size); + + /* Compute the maximum valid index, that is, size + - 1. Do the calculation in index_type, so that + if it is a variable the computations will be + done in the proper mode. */ + itype = fold_build2_loc (loc, MINUS_EXPR, index_type, + convert (index_type, size), + convert (index_type, + size_one_node)); + + /* If that overflowed, the array is too big. ??? + While a size of INT_MAX+1 technically shouldn't + cause an overflow (because we subtract 1), the + overflow is recorded during the conversion to + index_type, before the subtraction. Handling + this case seems like an unnecessary + complication. */ + if (TREE_CODE (itype) == INTEGER_CST + && TREE_OVERFLOW (itype)) + { + if (name) + error_at (loc, "size of array %qE is too large", + name); + else + error_at (loc, "size of unnamed array is too large"); + type = error_mark_node; + continue; + } + + itype = build_index_type (itype); + } + if (this_size_varies) + { + if (*expr) + *expr = build2 (COMPOUND_EXPR, TREE_TYPE (size), + *expr, size); + else + *expr = size; + *expr_const_operands &= size_maybe_const; + } + } + else if (decl_context == FIELD) + { + bool flexible_array_member = false; + if (array_parm_vla_unspec_p) + /* Field names can in fact have function prototype + scope so [*] is disallowed here through making + the field variably modified, not through being + something other than a declaration with function + prototype scope. */ + size_varies = true; + else + { + const struct c_declarator *t = declarator; + while (t->kind == cdk_attrs) + t = t->declarator; + flexible_array_member = (t->kind == cdk_id); + } + if (flexible_array_member + && pedantic && !flag_isoc99 && !in_system_header) + pedwarn (loc, OPT_pedantic, + "ISO C90 does not support flexible array members"); + + /* ISO C99 Flexible array members are effectively + identical to GCC's zero-length array extension. */ + if (flexible_array_member || array_parm_vla_unspec_p) + itype = build_range_type (sizetype, size_zero_node, + NULL_TREE); + } + else if (decl_context == PARM) + { + if (array_parm_vla_unspec_p) + { + itype = build_range_type (sizetype, size_zero_node, NULL_TREE); + size_varies = true; + } + } + else if (decl_context == TYPENAME) + { + if (array_parm_vla_unspec_p) + { + /* C99 6.7.5.2p4 */ + warning (0, "%<[*]%> not in a declaration"); + /* We use this to avoid messing up with incomplete + array types of the same type, that would + otherwise be modified below. */ + itype = build_range_type (sizetype, size_zero_node, + NULL_TREE); + size_varies = true; + } + } + + /* Complain about arrays of incomplete types. */ + if (!COMPLETE_TYPE_P (type)) + { + error_at (loc, "array type has incomplete element type"); + type = error_mark_node; + } + else + /* When itype is NULL, a shared incomplete array type is + returned for all array of a given type. Elsewhere we + make sure we don't complete that type before copying + it, but here we want to make sure we don't ever + modify the shared type, so we gcc_assert (itype) + below. */ + { + addr_space_t as = DECODE_QUAL_ADDR_SPACE (type_quals); + if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type)) + type = build_qualified_type (type, + ENCODE_QUAL_ADDR_SPACE (as)); + + type = build_array_type (type, itype); + } + + if (type != error_mark_node) + { + if (size_varies) + { + /* It is ok to modify type here even if itype is + NULL: if size_varies, we're in a + multi-dimensional array and the inner type has + variable size, so the enclosing shared array type + must too. */ + if (size && TREE_CODE (size) == INTEGER_CST) + type + = build_distinct_type_copy (TYPE_MAIN_VARIANT (type)); + C_TYPE_VARIABLE_SIZE (type) = 1; + } + + /* The GCC extension for zero-length arrays differs from + ISO flexible array members in that sizeof yields + zero. */ + if (size && integer_zerop (size)) + { + gcc_assert (itype); + type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type)); + TYPE_SIZE (type) = bitsize_zero_node; + TYPE_SIZE_UNIT (type) = size_zero_node; + SET_TYPE_STRUCTURAL_EQUALITY (type); + } + if (array_parm_vla_unspec_p) + { + gcc_assert (itype); + /* The type is complete. C99 6.7.5.2p4 */ + type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type)); + TYPE_SIZE (type) = bitsize_zero_node; + TYPE_SIZE_UNIT (type) = size_zero_node; + SET_TYPE_STRUCTURAL_EQUALITY (type); + } + } + + if (decl_context != PARM + && (array_ptr_quals != TYPE_UNQUALIFIED + || array_ptr_attrs != NULL_TREE + || array_parm_static)) + { + error_at (loc, "static or type qualifiers in non-parameter array declarator"); + array_ptr_quals = TYPE_UNQUALIFIED; + array_ptr_attrs = NULL_TREE; + array_parm_static = 0; + } + break; + } + case cdk_function: + { + /* Say it's a definition only for the declarator closest + to the identifier, apart possibly from some + attributes. */ + bool really_funcdef = false; + tree arg_types; + if (funcdef_flag) + { + const struct c_declarator *t = declarator->declarator; + while (t->kind == cdk_attrs) + t = t->declarator; + really_funcdef = (t->kind == cdk_id); + } + + + /* Declaring a function type. Make sure we have a valid + type for the function to return. */ + if (type == error_mark_node) + continue; + + size_varies = false; + + /* Warn about some types functions can't return. */ + if (TREE_CODE (type) == FUNCTION_TYPE) + { + if (name) + error_at (loc, "%qE declared as function returning a " + "function", name); + else + error_at (loc, "type name declared as function " + "returning a function"); + type = integer_type_node; + } + if (TREE_CODE (type) == ARRAY_TYPE) + { + if (name) + error_at (loc, "%qE declared as function returning an array", + name); + else + error_at (loc, "type name declared as function returning " + "an array"); + type = integer_type_node; + } + errmsg = targetm.invalid_return_type (type); + if (errmsg) + { + error (errmsg); + type = integer_type_node; + } + + /* Construct the function type and go to the next + inner layer of declarator. */ + arg_info = declarator->u.arg_info; + arg_types = grokparms (arg_info, really_funcdef); + if (really_funcdef) + put_pending_sizes (arg_info->pending_sizes); + + /* Type qualifiers before the return type of the function + qualify the return type, not the function type. */ + if (type_quals) + { + /* Type qualifiers on a function return type are + normally permitted by the standard but have no + effect, so give a warning at -Wreturn-type. + Qualifiers on a void return type are banned on + function definitions in ISO C; GCC used to used + them for noreturn functions. */ + if (VOID_TYPE_P (type) && really_funcdef) + pedwarn (loc, 0, + "function definition has qualified void return type"); + else + warning_at (loc, OPT_Wignored_qualifiers, + "type qualifiers ignored on function return type"); + + type = c_build_qualified_type (type, type_quals); + } + type_quals = TYPE_UNQUALIFIED; #ifndef noCbC if ( declspecs->typespec_word == cts_CbC_code ) @@ -5521,81 +5635,76 @@ { type = build_function_type (type, arg_types); } - - declarator = declarator->declarator; - - /* Set the TYPE_CONTEXTs for each tagged type which is local to - the formal parameter list of this FUNCTION_TYPE to point to - the FUNCTION_TYPE node itself. */ - { - tree link; - - for (link = arg_info->tags; - link; - link = TREE_CHAIN (link)) - TYPE_CONTEXT (TREE_VALUE (link)) = type; - } - break; - } - case cdk_pointer: - { - /* Merge any constancy or volatility into the target type - for the pointer. */ - - if (pedantic && TREE_CODE (type) == FUNCTION_TYPE - && type_quals) - pedwarn (loc, OPT_pedantic, - "ISO C forbids qualified function types"); - if (type_quals) - type = c_build_qualified_type (type, type_quals); - size_varies = false; - - /* When the pointed-to type involves components of variable size, - care must be taken to ensure that the size evaluation code is - emitted early enough to dominate all the possible later uses - and late enough for the variables on which it depends to have - been assigned. - - This is expected to happen automatically when the pointed-to - type has a name/declaration of it's own, but special attention - is required if the type is anonymous. - - We handle the NORMAL and FIELD contexts here by attaching an - artificial TYPE_DECL to such pointed-to type. This forces the - sizes evaluation at a safe point and ensures it is not deferred - until e.g. within a deeper conditional context. - - We expect nothing to be needed here for PARM or TYPENAME. - Pushing a TYPE_DECL at this point for TYPENAME would actually - be incorrect, as we might be in the middle of an expression - with side effects on the pointed-to type size "arguments" prior - to the pointer declaration point and the fake TYPE_DECL in the - enclosing context would force the size evaluation prior to the - side effects. */ - - if (!TYPE_NAME (type) - && (decl_context == NORMAL || decl_context == FIELD) - && variably_modified_type_p (type, NULL_TREE)) - { - tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type); - DECL_ARTIFICIAL (decl) = 1; - pushdecl (decl); - finish_decl (decl, loc, NULL_TREE, NULL_TREE, NULL_TREE); - TYPE_NAME (type) = decl; - } - - type = build_pointer_type (type); - - /* Process type qualifiers (such as const or volatile) - that were given inside the `*'. */ - type_quals = declarator->u.pointer_quals; - - declarator = declarator->declarator; - break; - } - default: - gcc_unreachable (); - } + declarator = declarator->declarator; + + /* Set the TYPE_CONTEXTs for each tagged type which is local to + the formal parameter list of this FUNCTION_TYPE to point to + the FUNCTION_TYPE node itself. */ + { + c_arg_tag *tag; + unsigned ix; + + FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag) + TYPE_CONTEXT (tag->type) = type; + } + break; + } + case cdk_pointer: + { + /* Merge any constancy or volatility into the target type + for the pointer. */ + if (pedantic && TREE_CODE (type) == FUNCTION_TYPE + && type_quals) + pedwarn (loc, OPT_pedantic, + "ISO C forbids qualified function types"); + if (type_quals) + type = c_build_qualified_type (type, type_quals); + size_varies = false; + + /* When the pointed-to type involves components of variable size, + care must be taken to ensure that the size evaluation code is + emitted early enough to dominate all the possible later uses + and late enough for the variables on which it depends to have + been assigned. + This is expected to happen automatically when the pointed-to + type has a name/declaration of it's own, but special attention + is required if the type is anonymous. + We handle the NORMAL and FIELD contexts here by attaching an + artificial TYPE_DECL to such pointed-to type. This forces the + sizes evaluation at a safe point and ensures it is not deferred + until e.g. within a deeper conditional context. + We expect nothing to be needed here for PARM or TYPENAME. + Pushing a TYPE_DECL at this point for TYPENAME would actually + be incorrect, as we might be in the middle of an expression + with side effects on the pointed-to type size "arguments" prior + to the pointer declaration point and the fake TYPE_DECL in the + enclosing context would force the size evaluation prior to the + side effects. */ + + if (!TYPE_NAME (type) + && (decl_context == NORMAL || decl_context == FIELD) + && variably_modified_type_p (type, NULL_TREE)) + { + tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type); + DECL_ARTIFICIAL (decl) = 1; + pushdecl (decl); + finish_decl (decl, loc, NULL_TREE, NULL_TREE, NULL_TREE); + TYPE_NAME (type) = decl; + } + + type = build_pointer_type (type); + + /* Process type qualifiers (such as const or volatile) + that were given inside the `*'. */ + type_quals = declarator->u.pointer_quals; + + + declarator = declarator->declarator; + break; + } + default: + gcc_unreachable (); + } } *decl_attrs = chainon (returned_attrs, *decl_attrs); @@ -5856,83 +5965,78 @@ } else if (TREE_CODE (type) == FUNCTION_TYPE) { - if (storage_class == csc_register || threadp) - { - error_at (loc, "invalid storage class for function %qE", name); - } - else if (current_scope != file_scope) - { - /* Function declaration not at file scope. Storage - classes other than `extern' are not allowed, C99 - 6.7.1p5, and `extern' makes no difference. However, - GCC allows 'auto', perhaps with 'inline', to support - nested functions. */ - if (storage_class == csc_auto) - pedwarn (loc, OPT_pedantic, - "invalid storage class for function %qE", name); - else if (storage_class == csc_static) - { - error_at (loc, "invalid storage class for function %qE", name); - if (funcdef_flag) - storage_class = declspecs->storage_class = csc_none; - else - return 0; - } - } - - decl = build_decl (declarator->id_loc, - FUNCTION_DECL, declarator->u.id, type); - decl = build_decl_attribute_variant (decl, decl_attr); - - if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl)) - pedwarn (loc, OPT_pedantic, - "ISO C forbids qualified function types"); - - /* GNU C interprets a volatile-qualified function type to indicate - that the function does not return. */ - if ((type_quals & TYPE_QUAL_VOLATILE) - && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) - warning_at (loc, 0, "%<noreturn%> function returns non-void value"); - - /* Every function declaration is an external reference - (DECL_EXTERNAL) except for those which are not at file - scope and are explicitly declared "auto". This is - forbidden by standard C (C99 6.7.1p5) and is interpreted by - GCC to signify a forward declaration of a nested function. */ - if (storage_class == csc_auto && current_scope != file_scope) - DECL_EXTERNAL (decl) = 0; - /* In C99, a function which is declared 'inline' with 'extern' - is not an external reference (which is confusing). It - means that the later definition of the function must be output - in this file, C99 6.7.4p6. In GNU C89, a function declared - 'extern inline' is an external reference. */ - else if (declspecs->inline_p && storage_class != csc_static) - DECL_EXTERNAL (decl) = ((storage_class == csc_extern) - == flag_gnu89_inline); - else - DECL_EXTERNAL (decl) = !initialized; - - /* Record absence of global scope for `static' or `auto'. */ - TREE_PUBLIC (decl) - = !(storage_class == csc_static || storage_class == csc_auto); - - /* For a function definition, record the argument information - block where store_parm_decls will look for it. */ - if (funcdef_flag) - current_function_arg_info = arg_info; - - if (declspecs->default_int_p) - C_FUNCTION_IMPLICIT_INT (decl) = 1; - - /* Record presence of `inline', if it is reasonable. */ - if (flag_hosted && MAIN_NAME_P (declarator->u.id)) - { - if (declspecs->inline_p) - pedwarn (loc, 0, "cannot inline function %<main%>"); - } - else if (declspecs->inline_p) - /* Record that the function is declared `inline'. */ - DECL_DECLARED_INLINE_P (decl) = 1; + if (storage_class == csc_register || threadp) + { + error_at (loc, "invalid storage class for function %qE", name); + } + else if (current_scope != file_scope) + { + /* Function declaration not at file scope. Storage + classes other than `extern' are not allowed, C99 + 6.7.1p5, and `extern' makes no difference. However, + GCC allows 'auto', perhaps with 'inline', to support + nested functions. */ + if (storage_class == csc_auto) + pedwarn (loc, OPT_pedantic, + "invalid storage class for function %qE", name); + else if (storage_class == csc_static) + { + error_at (loc, "invalid storage class for function %qE", name); + if (funcdef_flag) + storage_class = declspecs->storage_class = csc_none; + else + return 0; + } + } + + + decl = build_decl (declarator->id_loc, + FUNCTION_DECL, declarator->u.id, type); + decl = build_decl_attribute_variant (decl, decl_attr); + + if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl)) + pedwarn (loc, OPT_pedantic, + "ISO C forbids qualified function types"); + + /* Every function declaration is an external reference + (DECL_EXTERNAL) except for those which are not at file + scope and are explicitly declared "auto". This is + forbidden by standard C (C99 6.7.1p5) and is interpreted by + GCC to signify a forward declaration of a nested function. */ + if (storage_class == csc_auto && current_scope != file_scope) + DECL_EXTERNAL (decl) = 0; + /* In C99, a function which is declared 'inline' with 'extern' + is not an external reference (which is confusing). It + means that the later definition of the function must be output + in this file, C99 6.7.4p6. In GNU C89, a function declared + 'extern inline' is an external reference. */ + else if (declspecs->inline_p && storage_class != csc_static) + DECL_EXTERNAL (decl) = ((storage_class == csc_extern) + == flag_gnu89_inline); + else + DECL_EXTERNAL (decl) = !initialized; + + /* Record absence of global scope for `static' or `auto'. */ + TREE_PUBLIC (decl) + = !(storage_class == csc_static || storage_class == csc_auto); + + /* For a function definition, record the argument information + block where store_parm_decls will look for it. */ + if (funcdef_flag) + current_function_arg_info = arg_info; + + if (declspecs->default_int_p) + C_FUNCTION_IMPLICIT_INT (decl) = 1; + + /* Record presence of `inline', if it is reasonable. */ + if (flag_hosted && MAIN_NAME_P (declarator->u.id)) + { + if (declspecs->inline_p) + pedwarn (loc, 0, "cannot inline function %<main%>"); + } + else if (declspecs->inline_p) + /* Record that the function is declared `inline'. */ + DECL_DECLARED_INLINE_P (decl) = 1; } else { @@ -6095,9 +6199,12 @@ else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE) { if (!funcdef_flag) - pedwarn (input_location, 0, "parameter names (without types) in function declaration"); - - arg_info->parms = arg_info->types; + { + pedwarn (input_location, 0, "parameter names (without types) in function declaration"); + arg_info->parms = NULL_TREE; + } + else + arg_info->parms = arg_info->types; arg_info->types = 0; return 0; } @@ -6117,57 +6224,75 @@ warn. */ for (parm = arg_info->parms, typelt = arg_types, parmno = 1; - parm; - parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++) - { - type = TREE_VALUE (typelt); - if (type == error_mark_node) - continue; - - if (!COMPLETE_TYPE_P (type)) - { - if (funcdef_flag) - { - if (DECL_NAME (parm)) - error_at (input_location, - "parameter %u (%q+D) has incomplete type", - parmno, parm); - else - error_at (DECL_SOURCE_LOCATION (parm), - "parameter %u has incomplete type", - parmno); - - TREE_VALUE (typelt) = error_mark_node; - TREE_TYPE (parm) = error_mark_node; - } - else if (VOID_TYPE_P (type)) - { - if (DECL_NAME (parm)) - warning_at (input_location, 0, - "parameter %u (%q+D) has void type", - parmno, parm); - else - warning_at (DECL_SOURCE_LOCATION (parm), 0, - "parameter %u has void type", - parmno); - } - } - - errmsg = targetm.invalid_parameter_type (type); - if (errmsg) - { - error (errmsg); - TREE_VALUE (typelt) = error_mark_node; - TREE_TYPE (parm) = error_mark_node; - } - - if (DECL_NAME (parm) && TREE_USED (parm)) - warn_if_shadowing (parm); - } + parm; + parm = DECL_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++) + { + type = TREE_VALUE (typelt); + if (type == error_mark_node) + continue; + + if (!COMPLETE_TYPE_P (type)) + { + if (funcdef_flag) + { + if (DECL_NAME (parm)) + error_at (input_location, + "parameter %u (%q+D) has incomplete type", + parmno, parm); + else + error_at (DECL_SOURCE_LOCATION (parm), + "parameter %u has incomplete type", + parmno); + + TREE_VALUE (typelt) = error_mark_node; + TREE_TYPE (parm) = error_mark_node; + arg_types = NULL_TREE; + } + else if (VOID_TYPE_P (type)) + { + if (DECL_NAME (parm)) + warning_at (input_location, 0, + "parameter %u (%q+D) has void type", + parmno, parm); + else + warning_at (DECL_SOURCE_LOCATION (parm), 0, + "parameter %u has void type", + parmno); + } + } + + errmsg = targetm.invalid_parameter_type (type); + if (errmsg) + { + error (errmsg); + TREE_VALUE (typelt) = error_mark_node; + TREE_TYPE (parm) = error_mark_node; + arg_types = NULL_TREE; + } + + if (DECL_NAME (parm) && TREE_USED (parm)) + warn_if_shadowing (parm); + } return arg_types; } } +/* Allocate and initialize a c_arg_info structure from the parser's + obstack. */ + +struct c_arg_info * +build_arg_info (void) +{ + struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info); + ret->parms = NULL_TREE; + ret->tags = NULL; + ret->types = NULL_TREE; + ret->others = NULL_TREE; + ret->pending_sizes = NULL; + ret->had_vla_unspec = 0; + return ret; +} + /* Take apart the current scope and return a c_arg_info structure with info on a parameter list just parsed. @@ -6180,21 +6305,16 @@ get_parm_info (bool ellipsis) { struct c_binding *b = current_scope->bindings; - struct c_arg_info *arg_info = XOBNEW (&parser_obstack, - struct c_arg_info); + struct c_arg_info *arg_info = build_arg_info (); + tree parms = 0; - tree tags = 0; + VEC(c_arg_tag,gc) *tags = NULL; tree types = 0; tree others = 0; static bool explained_incomplete_types = false; bool gave_void_only_once_err = false; - arg_info->parms = 0; - arg_info->tags = 0; - arg_info->types = 0; - arg_info->others = 0; - arg_info->pending_sizes = 0; arg_info->had_vla_unspec = current_scope->had_vla_unspec; /* The bindings in this scope must not get put into a block. @@ -6237,111 +6357,119 @@ { tree decl = b->decl; tree type = TREE_TYPE (decl); + c_arg_tag *tag; const char *keyword; switch (TREE_CODE (decl)) - { - case PARM_DECL: - if (b->id) - { - gcc_assert (I_SYMBOL_BINDING (b->id) == b); - I_SYMBOL_BINDING (b->id) = b->shadowed; - } - - /* Check for forward decls that never got their actual decl. */ - if (TREE_ASM_WRITTEN (decl)) - error ("parameter %q+D has just a forward declaration", decl); - /* Check for (..., void, ...) and issue an error. */ - else if (VOID_TYPE_P (type) && !DECL_NAME (decl)) - { - if (!gave_void_only_once_err) - { - error ("%<void%> must be the only parameter"); - gave_void_only_once_err = true; - } - } - else - { - /* Valid parameter, add it to the list. */ - TREE_CHAIN (decl) = parms; - parms = decl; - - /* Since there is a prototype, args are passed in their - declared types. The back end may override this later. */ - DECL_ARG_TYPE (decl) = type; - types = tree_cons (0, type, types); - } - break; - - case ENUMERAL_TYPE: keyword = "enum"; goto tag; - case UNION_TYPE: keyword = "union"; goto tag; - case RECORD_TYPE: keyword = "struct"; goto tag; - tag: - /* Types may not have tag-names, in which case the type - appears in the bindings list with b->id NULL. */ - if (b->id) - { - gcc_assert (I_TAG_BINDING (b->id) == b); - I_TAG_BINDING (b->id) = b->shadowed; - } - - /* Warn about any struct, union or enum tags defined in a - parameter list. The scope of such types is limited to - the parameter list, which is rarely if ever desirable - (it's impossible to call such a function with type- - correct arguments). An anonymous union parm type is - meaningful as a GNU extension, so don't warn for that. */ - if (TREE_CODE (decl) != UNION_TYPE || b->id != 0) - { - if (b->id) - /* The %s will be one of 'struct', 'union', or 'enum'. */ - warning (0, "%<%s %E%> declared inside parameter list", - keyword, b->id); - else - /* The %s will be one of 'struct', 'union', or 'enum'. */ - warning (0, "anonymous %s declared inside parameter list", - keyword); - - if (!explained_incomplete_types) - { - warning (0, "its scope is only this definition or declaration," - " which is probably not what you want"); - explained_incomplete_types = true; - } - } - - tags = tree_cons (b->id, decl, tags); - break; - - case CONST_DECL: - case TYPE_DECL: - case FUNCTION_DECL: - /* CONST_DECLs appear here when we have an embedded enum, - and TYPE_DECLs appear here when we have an embedded struct - or union. No warnings for this - we already warned about the - type itself. FUNCTION_DECLs appear when there is an implicit - function declaration in the parameter list. */ - - TREE_CHAIN (decl) = others; - others = decl; - /* fall through */ - - case ERROR_MARK: - /* error_mark_node appears here when we have an undeclared - variable. Just throw it away. */ - if (b->id) - { - gcc_assert (I_SYMBOL_BINDING (b->id) == b); - I_SYMBOL_BINDING (b->id) = b->shadowed; - } - break; - - /* Other things that might be encountered. */ - case LABEL_DECL: - case VAR_DECL: - default: - gcc_unreachable (); - } + { + case PARM_DECL: + if (b->id) + { + gcc_assert (I_SYMBOL_BINDING (b->id) == b); + I_SYMBOL_BINDING (b->id) = b->shadowed; + } + + /* Check for forward decls that never got their actual decl. */ + if (TREE_ASM_WRITTEN (decl)) + error ("parameter %q+D has just a forward declaration", decl); + /* Check for (..., void, ...) and issue an error. */ + else if (VOID_TYPE_P (type) && !DECL_NAME (decl)) + { + if (!gave_void_only_once_err) + { + error ("%<void%> must be the only parameter"); + gave_void_only_once_err = true; + } + } + else + { + /* Valid parameter, add it to the list. */ + DECL_CHAIN (decl) = parms; + parms = decl; + + /* Since there is a prototype, args are passed in their + declared types. The back end may override this later. */ + DECL_ARG_TYPE (decl) = type; + types = tree_cons (0, type, types); + } + break; + + case ENUMERAL_TYPE: keyword = "enum"; goto tag; + case UNION_TYPE: keyword = "union"; goto tag; + case RECORD_TYPE: keyword = "struct"; goto tag; + tag: + /* Types may not have tag-names, in which case the type + appears in the bindings list with b->id NULL. */ + if (b->id) + { + gcc_assert (I_TAG_BINDING (b->id) == b); + I_TAG_BINDING (b->id) = b->shadowed; + } + + /* Warn about any struct, union or enum tags defined in a + parameter list. The scope of such types is limited to + the parameter list, which is rarely if ever desirable + (it's impossible to call such a function with type- + correct arguments). An anonymous union parm type is + meaningful as a GNU extension, so don't warn for that. */ + if (TREE_CODE (decl) != UNION_TYPE || b->id != 0) + { + if (b->id) + /* The %s will be one of 'struct', 'union', or 'enum'. */ + warning (0, "%<%s %E%> declared inside parameter list", + keyword, b->id); + else + /* The %s will be one of 'struct', 'union', or 'enum'. */ + warning (0, "anonymous %s declared inside parameter list", + keyword); + + if (!explained_incomplete_types) + { + warning (0, "its scope is only this definition or declaration," + " which is probably not what you want"); + explained_incomplete_types = true; + } + } + + tag = VEC_safe_push (c_arg_tag, gc, tags, NULL); + tag->id = b->id; + tag->type = decl; + break; + + case CONST_DECL: + case TYPE_DECL: + case FUNCTION_DECL: + /* CONST_DECLs appear here when we have an embedded enum, + and TYPE_DECLs appear here when we have an embedded struct + or union. No warnings for this - we already warned about the + type itself. FUNCTION_DECLs appear when there is an implicit + function declaration in the parameter list. */ + + /* When we reinsert this decl in the function body, we need + to reconstruct whether it was marked as nested. */ + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL + ? b->nested + : !b->nested); + DECL_CHAIN (decl) = others; + others = decl; + /* fall through */ + + case ERROR_MARK: + /* error_mark_node appears here when we have an undeclared + variable. Just throw it away. */ + if (b->id) + { + gcc_assert (I_SYMBOL_BINDING (b->id) == b); + I_SYMBOL_BINDING (b->id) = b->shadowed; + } + break; + + /* Other things that might be encountered. */ + case LABEL_DECL: + case VAR_DECL: + default: + gcc_unreachable (); + } b = free_binding_and_advance (b); } @@ -6558,46 +6686,55 @@ { /* This is an unnamed decl. - If we have something of the form "union { list } ;" then this - is the anonymous union extension. Similarly for struct. - - If this is something of the form "struct foo;", then - If MS extensions are enabled, this is handled as an - anonymous struct. - Otherwise this is a forward declaration of a structure tag. - - If this is something of the form "foo;" and foo is a TYPE_DECL, then - If MS extensions are enabled and foo names a structure, then - again this is an anonymous struct. - Otherwise this is an error. - - Oh what a horrid tangled web we weave. I wonder if MS consciously - took this from Plan 9 or if it was an accident of implementation - that took root before someone noticed the bug... */ + If we have something of the form "union { list } ;" then this + is the anonymous union extension. Similarly for struct. + + If this is something of the form "struct foo;", then + If MS or Plan 9 extensions are enabled, this is handled as + an anonymous struct. + Otherwise this is a forward declaration of a structure tag. + + If this is something of the form "foo;" and foo is a TYPE_DECL, then + If foo names a structure or union without a tag, then this + is an anonymous struct (this is permitted by C1X). + If MS or Plan 9 extensions are enabled and foo names a + structure, then again this is an anonymous struct. + Otherwise this is an error. + + Oh what a horrid tangled web we weave. I wonder if MS consciously + took this from Plan 9 or if it was an accident of implementation + that took root before someone noticed the bug... */ tree type = declspecs->type; bool type_ok = (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE); bool ok = false; - if (type_ok - && (flag_ms_extensions || !declspecs->typedef_p)) - { - if (flag_ms_extensions) - ok = true; - else if (flag_iso) - ok = false; - else if (TYPE_NAME (type) == NULL) - ok = true; - else - ok = false; - } + if (type_ok) + { + if (flag_ms_extensions || flag_plan9_extensions) + ok = true; + else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL) + ok = true; + else + ok = false; + } + + if (!ok) - { - pedwarn (loc, 0, "declaration does not declare anything"); - return NULL_TREE; - } - pedwarn (loc, OPT_pedantic, "ISO C doesn%'t support unnamed structs/unions"); + { + pedwarn (loc, 0, "declaration does not declare anything"); + return NULL_TREE; + } + if (!flag_isoc1x) + { + if (flag_isoc99) + pedwarn (loc, OPT_pedantic, + "ISO C99 doesn%'t support unnamed structs/unions"); + else + pedwarn (loc, OPT_pedantic, + "ISO C90 doesn%'t support unnamed structs/unions"); + } } value = grokdeclarator (declarator, declspecs, FIELD, false, @@ -6629,6 +6766,90 @@ return value; } +/* Subroutine of detect_field_duplicates: return whether X and Y, + which are both fields in the same struct, have duplicate field + names. */ + +static bool +is_duplicate_field (tree x, tree y) +{ + if (DECL_NAME (x) != NULL_TREE && DECL_NAME (x) == DECL_NAME (y)) + return true; + + /* When using -fplan9-extensions, an anonymous field whose name is a + typedef can duplicate a field name. */ + if (flag_plan9_extensions + && (DECL_NAME (x) == NULL_TREE || DECL_NAME (y) == NULL_TREE)) + { + tree xt, xn, yt, yn; + + xt = TREE_TYPE (x); + if (DECL_NAME (x) != NULL_TREE) + xn = DECL_NAME (x); + else if ((TREE_CODE (xt) == RECORD_TYPE || TREE_CODE (xt) == UNION_TYPE) + && TYPE_NAME (xt) != NULL_TREE + && TREE_CODE (TYPE_NAME (xt)) == TYPE_DECL) + xn = DECL_NAME (TYPE_NAME (xt)); + else + xn = NULL_TREE; + + yt = TREE_TYPE (y); + if (DECL_NAME (y) != NULL_TREE) + yn = DECL_NAME (y); + else if ((TREE_CODE (yt) == RECORD_TYPE || TREE_CODE (yt) == UNION_TYPE) + && TYPE_NAME (yt) != NULL_TREE + && TREE_CODE (TYPE_NAME (yt)) == TYPE_DECL) + yn = DECL_NAME (TYPE_NAME (yt)); + else + yn = NULL_TREE; + + if (xn != NULL_TREE && xn == yn) + return true; + } + + return false; +} + +/* Subroutine of detect_field_duplicates: add the fields of FIELDLIST + to HTAB, giving errors for any duplicates. */ + +static void +detect_field_duplicates_hash (tree fieldlist, htab_t htab) +{ + tree x, y; + void **slot; + + for (x = fieldlist; x ; x = DECL_CHAIN (x)) + if ((y = DECL_NAME (x)) != 0) + { + slot = htab_find_slot (htab, y, INSERT); + if (*slot) + { + error ("duplicate member %q+D", x); + DECL_NAME (x) = NULL_TREE; + } + *slot = y; + } + else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE) + { + detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab); + + /* When using -fplan9-extensions, an anonymous field whose + name is a typedef can duplicate a field name. */ + if (flag_plan9_extensions + && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE + && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL) + { + tree xn = DECL_NAME (TYPE_NAME (TREE_TYPE (x))); + slot = htab_find_slot (htab, xn, INSERT); + if (*slot) + error ("duplicate member %q+D", TYPE_NAME (TREE_TYPE (x))); + *slot = xn; + } + } +} + /* Generate an error for any duplicate field names in FIELDLIST. Munge the list such that this does not present a problem later. */ @@ -6638,50 +6859,60 @@ tree x, y; int timeout = 10; + /* If the struct is the list of instance variables of an Objective-C + class, then we need to add all the instance variables of + superclasses before checking for duplicates (since you can't have + an instance variable in a subclass with the same name as an + instance variable in a superclass). objc_get_interface_ivars() + leaves fieldlist unchanged if we are not in this case, so in that + case nothing changes compared to C. + */ + if (c_dialect_objc ()) + fieldlist = objc_get_interface_ivars (fieldlist); + /* First, see if there are more than "a few" fields. This is trivially true if there are zero or one fields. */ - if (!fieldlist) + if (!fieldlist || !DECL_CHAIN (fieldlist)) return; - x = TREE_CHAIN (fieldlist); - if (!x) - return; + x = fieldlist; do { timeout--; - x = TREE_CHAIN (x); + if (DECL_NAME (x) == NULL_TREE + && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)) + timeout = 0; + x = DECL_CHAIN (x); } while (timeout > 0 && x); - /* If there were "few" fields, avoid the overhead of allocating - a hash table. Instead just do the nested traversal thing. */ + /* If there were "few" fields and no anonymous structures or unions, + avoid the overhead of allocating a hash table. Instead just do + the nested traversal thing. */ if (timeout > 0) { - for (x = TREE_CHAIN (fieldlist); x ; x = TREE_CHAIN (x)) - if (DECL_NAME (x)) - { - for (y = fieldlist; y != x; y = TREE_CHAIN (y)) - if (DECL_NAME (y) == DECL_NAME (x)) - { - error ("duplicate member %q+D", x); - DECL_NAME (x) = NULL_TREE; - } - } + for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x)) + /* When using -fplan9-extensions, we can have duplicates + between typedef names and fields. */ + if (DECL_NAME (x) + || (flag_plan9_extensions + && DECL_NAME (x) == NULL_TREE + && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE) + && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE + && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL)) + { + for (y = fieldlist; y != x; y = TREE_CHAIN (y)) + if (is_duplicate_field (y, x)) + { + error ("duplicate member %q+D", x); + DECL_NAME (x) = NULL_TREE; + } + } } else { htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL); - void **slot; - - for (x = fieldlist; x ; x = TREE_CHAIN (x)) - if ((y = DECL_NAME (x)) != 0) - { - slot = htab_find_slot (htab, y, INSERT); - if (*slot) - { - error ("duplicate member %q+D", x); - DECL_NAME (x) = NULL_TREE; - } - *slot = y; - } - + + detect_field_duplicates_hash (fieldlist, htab); htab_delete (htab); } } @@ -6700,7 +6931,7 @@ because the flag is used to issue visibility warnings, and we only want to issue those warnings if the type is referenced outside of the struct declaration. */ - for (ix = 0; VEC_iterate (tree, struct_parse_info->struct_types, ix, x); ++ix) + FOR_EACH_VEC_ELT (tree, struct_parse_info->struct_types, ix, x) C_TYPE_DEFINED_IN_STRUCT (x) = 1; /* The TYPEDEFS_SEEN field of STRUCT_PARSE_INFO is a list of @@ -6716,32 +6947,28 @@ a pointer_set because identifiers are interned. */ struct pointer_set_t *tset = pointer_set_create (); - for (ix = 0; - VEC_iterate (tree, struct_parse_info->typedefs_seen, ix, x); - ++ix) - pointer_set_insert (tset, DECL_NAME (x)); - - for (x = fieldlist; x != NULL_TREE; x = TREE_CHAIN (x)) - { - if (pointer_set_contains (tset, DECL_NAME (x))) - { - warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat, - ("using %qD as both field and typedef name is " - "invalid in C++"), - x); - /* FIXME: It would be nice to report the location where - the typedef name is used. */ - } - } - + FOR_EACH_VEC_ELT (tree, struct_parse_info->typedefs_seen, ix, x) + pointer_set_insert (tset, DECL_NAME (x)); + + for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x)) + { + if (DECL_NAME (x) != NULL_TREE + && pointer_set_contains (tset, DECL_NAME (x))) + { + warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat, + ("using %qD as both field and typedef name is " + "invalid in C++"), + x); + /* FIXME: It would be nice to report the location where + the typedef name is used. */ + } + } pointer_set_destroy (tset); } /* For each field which has a binding and which was not defined in an enclosing struct, clear the in_struct field. */ - for (ix = 0; - VEC_iterate (c_binding_ptr, struct_parse_info->fields, ix, b); - ++ix) + FOR_EACH_VEC_ELT (c_binding_ptr, struct_parse_info->fields, ix, b) b->in_struct = 0; } @@ -6770,9 +6997,15 @@ if (pedantic) { - for (x = fieldlist; x; x = TREE_CHAIN (x)) - if (DECL_NAME (x) != 0) - break; + for (x = fieldlist; x; x = DECL_CHAIN (x)) + { + if (DECL_NAME (x) != 0) + break; + if (flag_isoc1x + && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)) + break; + } if (x == 0) { @@ -6801,7 +7034,7 @@ until now.) */ saw_named_field = 0; - for (x = fieldlist; x; x = TREE_CHAIN (x)) + for (x = fieldlist; x; x = DECL_CHAIN (x)) { if (TREE_TYPE (x) == error_mark_node) continue; @@ -6812,15 +7045,13 @@ if (TREE_READONLY (x)) C_TYPE_FIELDS_READONLY (t) = 1; else - { - /* A field that is pseudo-const makes the structure likewise. */ - tree t1 = TREE_TYPE (x); - while (TREE_CODE (t1) == ARRAY_TYPE) - t1 = TREE_TYPE (t1); - if ((TREE_CODE (t1) == RECORD_TYPE || TREE_CODE (t1) == UNION_TYPE) - && C_TYPE_FIELDS_READONLY (t1)) - C_TYPE_FIELDS_READONLY (t) = 1; - } + { + /* A field that is pseudo-const makes the structure likewise. */ + tree t1 = strip_array_types (TREE_TYPE (x)); + if ((TREE_CODE (t1) == RECORD_TYPE || TREE_CODE (t1) == UNION_TYPE) + && C_TYPE_FIELDS_READONLY (t1)) + C_TYPE_FIELDS_READONLY (t) = 1; + } /* Any field that is volatile means variables of this type must be treated in some ways as volatile. */ @@ -6846,37 +7077,39 @@ /* Detect flexible array member in an invalid context. */ if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE - && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE - && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE - && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE) - { - if (TREE_CODE (t) == UNION_TYPE) - { - error_at (DECL_SOURCE_LOCATION (x), - "flexible array member in union"); - TREE_TYPE (x) = error_mark_node; - } - else if (TREE_CHAIN (x) != NULL_TREE) - { - error_at (DECL_SOURCE_LOCATION (x), - "flexible array member not at end of struct"); - TREE_TYPE (x) = error_mark_node; - } - else if (!saw_named_field) - { - error_at (DECL_SOURCE_LOCATION (x), - "flexible array member in otherwise empty struct"); - TREE_TYPE (x) = error_mark_node; - } - } + && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE + && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE) + { + if (TREE_CODE (t) == UNION_TYPE) + { + error_at (DECL_SOURCE_LOCATION (x), + "flexible array member in union"); + TREE_TYPE (x) = error_mark_node; + } + else if (DECL_CHAIN (x) != NULL_TREE) + { + error_at (DECL_SOURCE_LOCATION (x), + "flexible array member not at end of struct"); + TREE_TYPE (x) = error_mark_node; + } + else if (!saw_named_field) + { + error_at (DECL_SOURCE_LOCATION (x), + "flexible array member in otherwise empty struct"); + TREE_TYPE (x) = error_mark_node; + } + } if (pedantic && TREE_CODE (t) == RECORD_TYPE && flexible_array_type_p (TREE_TYPE (x))) pedwarn (DECL_SOURCE_LOCATION (x), OPT_pedantic, "invalid use of structure with flexible array member"); - if (DECL_NAME (x)) - saw_named_field = 1; + if (DECL_NAME (x) + || TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE) + saw_named_field = 1; } detect_field_duplicates (fieldlist); @@ -6907,7 +7140,7 @@ DECL_INITIAL (*fieldlistp) = 0; } else - fieldlistp = &TREE_CHAIN (*fieldlistp); + fieldlistp = &DECL_CHAIN (*fieldlistp); } /* Now we have the truly final field list. @@ -6921,7 +7154,7 @@ { int len = 0; - for (x = fieldlist; x; x = TREE_CHAIN (x)) + for (x = fieldlist; x; x = DECL_CHAIN (x)) { if (len > 15 || DECL_NAME (x) == NULL) break; @@ -6930,39 +7163,39 @@ if (len > 15) { - tree *field_array; - struct lang_type *space; - struct sorted_fields_type *space2; - - len += list_length (x); - - /* Use the same allocation policy here that make_node uses, to - ensure that this lives as long as the rest of the struct decl. - All decls in an inline function need to be saved. */ - - space = GGC_CNEW (struct lang_type); - space2 = GGC_NEWVAR (struct sorted_fields_type, - sizeof (struct sorted_fields_type) + len * sizeof (tree)); - - len = 0; - space->s = space2; - field_array = &space2->elts[0]; - for (x = fieldlist; x; x = TREE_CHAIN (x)) - { - field_array[len++] = x; - - /* If there is anonymous struct or union, break out of the loop. */ - if (DECL_NAME (x) == NULL) - break; - } - /* Found no anonymous struct/union. Add the TYPE_LANG_SPECIFIC. */ - if (x == NULL) - { - TYPE_LANG_SPECIFIC (t) = space; - TYPE_LANG_SPECIFIC (t)->s->len = len; - field_array = TYPE_LANG_SPECIFIC (t)->s->elts; - qsort (field_array, len, sizeof (tree), field_decl_cmp); - } + tree *field_array; + struct lang_type *space; + struct sorted_fields_type *space2; + + len += list_length (x); + + /* Use the same allocation policy here that make_node uses, to + ensure that this lives as long as the rest of the struct decl. + All decls in an inline function need to be saved. */ + + space = ggc_alloc_cleared_lang_type (sizeof (struct lang_type)); + space2 = ggc_alloc_sorted_fields_type + (sizeof (struct sorted_fields_type) + len * sizeof (tree)); + + len = 0; + space->s = space2; + field_array = &space2->elts[0]; + for (x = fieldlist; x; x = DECL_CHAIN (x)) + { + field_array[len++] = x; + + /* If there is anonymous struct or union, break out of the loop. */ + if (DECL_NAME (x) == NULL) + break; + } + /* Found no anonymous struct/union. Add the TYPE_LANG_SPECIFIC. */ + if (x == NULL) + { + TYPE_LANG_SPECIFIC (t) = space; + TYPE_LANG_SPECIFIC (t)->s->len = len; + field_array = TYPE_LANG_SPECIFIC (t)->s->elts; + qsort (field_array, len, sizeof (tree), field_decl_cmp); + } } } @@ -6978,10 +7211,10 @@ /* If this was supposed to be a transparent union, but we can't make it one, warn and turn off the flag. */ if (TREE_CODE (t) == UNION_TYPE - && TYPE_TRANSPARENT_UNION (t) + && TYPE_TRANSPARENT_AGGR (t) && (!TYPE_FIELDS (t) || TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t)))) { - TYPE_TRANSPARENT_UNION (t) = 0; + TYPE_TRANSPARENT_AGGR (t) = 0; warning_at (loc, 0, "union cannot be made transparent"); } @@ -7223,7 +7456,7 @@ /* Record the min/max values so that we can warn about bit-field enumerations that are too small for the values. */ - lt = GGC_CNEW (struct lang_type); + lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type)); lt->enum_min = minnode; lt->enum_max = maxnode; TYPE_LANG_SPECIFIC (enumtype) = lt; @@ -7261,13 +7494,14 @@ /* Build and install a CONST_DECL for one value of the current enumeration type (one that was begun with start_enum). - LOC is the location of the enumerator. + DECL_LOC is the location of the enumerator. + LOC is the location of the '=' operator if any, DECL_LOC otherwise. Return a tree-list containing the CONST_DECL and its value. Assignment of sequential values by default is handled here. */ tree -build_enumerator (location_t loc, - struct c_enum_contents *the_enum, tree name, tree value) +build_enumerator (location_t decl_loc, location_t loc, + struct c_enum_contents *the_enum, tree name, tree value) { tree decl, type; @@ -7340,9 +7574,8 @@ /* Set basis for default for next value. */ the_enum->enum_next_value - = build_binary_op - (EXPR_HAS_LOCATION (value) ? EXPR_LOCATION (value) : input_location, - PLUS_EXPR, value, integer_one_node, 0); + = build_binary_op (EXPR_LOC_OR_HERE (value), + PLUS_EXPR, value, integer_one_node, 0); the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value); /* Now create a declaration for the enum value name. */ @@ -7354,7 +7587,7 @@ >= TYPE_PRECISION (integer_type_node) && TYPE_UNSIGNED (type))); - decl = build_decl (loc, CONST_DECL, name, type); + decl = build_decl (decl_loc, CONST_DECL, name, type); DECL_INITIAL (decl) = convert (type, value); pushdecl (decl); @@ -7515,6 +7748,10 @@ error_mark_node is replaced below (in pop_scope) with the BLOCK. */ DECL_INITIAL (decl1) = error_mark_node; + /* A nested function is not global. */ + if (current_function_decl != 0) + TREE_PUBLIC (decl1) = 0; + /* If this definition isn't a prototype and we had a prototype declaration before, copy the arg type info from that prototype. */ old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope); @@ -7523,7 +7760,7 @@ current_function_prototype_locus = UNKNOWN_LOCATION; current_function_prototype_built_in = false; current_function_prototype_arg_types = NULL_TREE; - if (TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0) + if (!prototype_p (TREE_TYPE (decl1))) { if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE && comptypes (TREE_TYPE (TREE_TYPE (decl1)), @@ -7572,7 +7809,7 @@ /* Optionally warn of old-fashioned def with no previous prototype. */ if (warn_strict_prototypes && old_decl != error_mark_node - && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0 + && !prototype_p (TREE_TYPE (decl1)) && C_DECL_ISNT_PROTOTYPE (old_decl)) warning_at (loc, OPT_Wstrict_prototypes, "function declaration isn%'t a prototype"); @@ -7587,10 +7824,10 @@ /* Optionally warn of any def with no previous prototype if the function has already been used. */ else if (warn_missing_prototypes - && old_decl != 0 - && old_decl != error_mark_node - && TREE_USED (old_decl) - && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0) + && old_decl != 0 + && old_decl != error_mark_node + && TREE_USED (old_decl) + && !prototype_p (TREE_TYPE (old_decl))) warning_at (loc, OPT_Wmissing_prototypes, "%qD was used with no prototype before its definition", decl1); /* Optionally warn of any global def with no previous declaration. */ @@ -7615,10 +7852,6 @@ (This does not mean `static' in the C sense!) */ TREE_STATIC (decl1) = 1; - /* A nested function is not global. */ - if (current_function_decl != 0) - TREE_PUBLIC (decl1) = 0; - /* This is the earliest point at which we might know the assembler name of the function. Thus, if it's set before this, die horribly. */ gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1)); @@ -7669,6 +7902,8 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info) { tree decl; + c_arg_tag *tag; + unsigned ix; if (current_scope->bindings) { @@ -7691,7 +7926,7 @@ /* Now make all the parameter declarations visible in the function body. We can bypass most of the grunt work of pushdecl. */ - for (decl = arg_info->parms; decl; decl = TREE_CHAIN (decl)) + for (decl = arg_info->parms; decl; decl = DECL_CHAIN (decl)) { DECL_CONTEXT (decl) = current_function_decl; if (DECL_NAME (decl)) @@ -7710,19 +7945,21 @@ DECL_ARGUMENTS (fndecl) = arg_info->parms; /* Now make all the ancillary declarations visible, likewise. */ - for (decl = arg_info->others; decl; decl = TREE_CHAIN (decl)) + for (decl = arg_info->others; decl; decl = DECL_CHAIN (decl)) { DECL_CONTEXT (decl) = current_function_decl; if (DECL_NAME (decl)) - bind (DECL_NAME (decl), decl, current_scope, - /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION); + bind (DECL_NAME (decl), decl, current_scope, + /*invisible=*/false, + /*nested=*/(TREE_CODE (decl) == FUNCTION_DECL), + UNKNOWN_LOCATION); } /* And all the tag declarations. */ - for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl)) - if (TREE_PURPOSE (decl)) - bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope, - /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION); + FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag) + if (tag->id) + bind (tag->id, tag->type, current_scope, + /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION); } /* Subroutine of store_parm_decls which handles old-style function @@ -7754,33 +7991,36 @@ b = I_SYMBOL_BINDING (TREE_VALUE (parm)); if (b && B_IN_CURRENT_SCOPE (b)) - { - decl = b->decl; - /* If we got something other than a PARM_DECL it is an error. */ - if (TREE_CODE (decl) != PARM_DECL) - error_at (DECL_SOURCE_LOCATION (decl), - "%qD declared as a non-parameter", decl); - /* If the declaration is already marked, we have a duplicate - name. Complain and ignore the duplicate. */ - else if (pointer_set_contains (seen_args, decl)) - { - error_at (DECL_SOURCE_LOCATION (decl), - "multiple parameters named %qD", decl); - TREE_PURPOSE (parm) = 0; - continue; - } - /* If the declaration says "void", complain and turn it into - an int. */ - else if (VOID_TYPE_P (TREE_TYPE (decl))) - { - error_at (DECL_SOURCE_LOCATION (decl), - "parameter %qD declared with void type", decl); - TREE_TYPE (decl) = integer_type_node; - DECL_ARG_TYPE (decl) = integer_type_node; - layout_decl (decl, 0); - } - warn_if_shadowing (decl); - } + { + decl = b->decl; + /* Skip erroneous parameters. */ + if (decl == error_mark_node) + continue; + /* If we got something other than a PARM_DECL it is an error. */ + if (TREE_CODE (decl) != PARM_DECL) + error_at (DECL_SOURCE_LOCATION (decl), + "%qD declared as a non-parameter", decl); + /* If the declaration is already marked, we have a duplicate + name. Complain and ignore the duplicate. */ + else if (pointer_set_contains (seen_args, decl)) + { + error_at (DECL_SOURCE_LOCATION (decl), + "multiple parameters named %qD", decl); + TREE_PURPOSE (parm) = 0; + continue; + } + /* If the declaration says "void", complain and turn it into + an int. */ + else if (VOID_TYPE_P (TREE_TYPE (decl))) + { + error_at (DECL_SOURCE_LOCATION (decl), + "parameter %qD declared with void type", decl); + TREE_TYPE (decl) = integer_type_node; + DECL_ARG_TYPE (decl) = integer_type_node; + layout_decl (decl, 0); + } + warn_if_shadowing (decl); + } /* If no declaration found, default to int. */ else { @@ -7858,12 +8098,12 @@ DECL_ARGUMENTS (fndecl) = last; for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm)) - if (TREE_PURPOSE (parm)) - { - TREE_CHAIN (last) = TREE_PURPOSE (parm); - last = TREE_PURPOSE (parm); - } - TREE_CHAIN (last) = 0; + if (TREE_PURPOSE (parm)) + { + DECL_CHAIN (last) = TREE_PURPOSE (parm); + last = TREE_PURPOSE (parm); + } + DECL_CHAIN (last) = 0; } pointer_set_destroy (seen_args); @@ -7879,88 +8119,88 @@ type = current_function_prototype_arg_types; parm || (type && TREE_VALUE (type) != error_mark_node && (TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node)); - parm = TREE_CHAIN (parm), type = TREE_CHAIN (type)) - { - if (parm == 0 || type == 0 - || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) - { - if (current_function_prototype_built_in) - warning_at (DECL_SOURCE_LOCATION (fndecl), - 0, "number of arguments doesn%'t match " - "built-in prototype"); - else - { - /* FIXME diagnostics: This should be the location of - FNDECL, but there is bug when a prototype is - declared inside function context, but defined - outside of it (e.g., gcc.dg/pr15698-2.c). In - which case FNDECL gets the location of the - prototype, not the definition. */ - error_at (input_location, - "number of arguments doesn%'t match prototype"); - - error_at (current_function_prototype_locus, - "prototype declaration"); - } - break; - } - /* Type for passing arg must be consistent with that - declared for the arg. ISO C says we take the unqualified - type for parameters declared with qualified type. */ - if (TREE_TYPE (parm) != error_mark_node - && TREE_TYPE (type) != error_mark_node - && !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)), - TYPE_MAIN_VARIANT (TREE_VALUE (type)))) - { - if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) - == TYPE_MAIN_VARIANT (TREE_VALUE (type))) - { - /* Adjust argument to match prototype. E.g. a previous - `int foo(float);' prototype causes - `int foo(x) float x; {...}' to be treated like - `int foo(float x) {...}'. This is particularly - useful for argument types like uid_t. */ - DECL_ARG_TYPE (parm) = TREE_TYPE (parm); - - if (targetm.calls.promote_prototypes (TREE_TYPE (current_function_decl)) - && INTEGRAL_TYPE_P (TREE_TYPE (parm)) - && TYPE_PRECISION (TREE_TYPE (parm)) - < TYPE_PRECISION (integer_type_node)) - DECL_ARG_TYPE (parm) = integer_type_node; - - /* ??? Is it possible to get here with a - built-in prototype or will it always have - been diagnosed as conflicting with an - old-style definition and discarded? */ - if (current_function_prototype_built_in) - warning_at (DECL_SOURCE_LOCATION (parm), - OPT_pedantic, "promoted argument %qD " - "doesn%'t match built-in prototype", parm); - else - { - pedwarn (DECL_SOURCE_LOCATION (parm), - OPT_pedantic, "promoted argument %qD " - "doesn%'t match prototype", parm); - pedwarn (current_function_prototype_locus, OPT_pedantic, - "prototype declaration"); - } - } - else - { - if (current_function_prototype_built_in) - warning_at (DECL_SOURCE_LOCATION (parm), - 0, "argument %qD doesn%'t match " - "built-in prototype", parm); - else - { - error_at (DECL_SOURCE_LOCATION (parm), - "argument %qD doesn%'t match prototype", parm); - error_at (current_function_prototype_locus, - "prototype declaration"); - } - } - } - } + parm = DECL_CHAIN (parm), type = TREE_CHAIN (type)) + { + if (parm == 0 || type == 0 + || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) + { + if (current_function_prototype_built_in) + warning_at (DECL_SOURCE_LOCATION (fndecl), + 0, "number of arguments doesn%'t match " + "built-in prototype"); + else + { + /* FIXME diagnostics: This should be the location of + FNDECL, but there is bug when a prototype is + declared inside function context, but defined + outside of it (e.g., gcc.dg/pr15698-2.c). In + which case FNDECL gets the location of the + prototype, not the definition. */ + error_at (input_location, + "number of arguments doesn%'t match prototype"); + + error_at (current_function_prototype_locus, + "prototype declaration"); + } + break; + } + /* Type for passing arg must be consistent with that + declared for the arg. ISO C says we take the unqualified + type for parameters declared with qualified type. */ + if (TREE_TYPE (parm) != error_mark_node + && TREE_TYPE (type) != error_mark_node + && !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)), + TYPE_MAIN_VARIANT (TREE_VALUE (type)))) + { + if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) + == TYPE_MAIN_VARIANT (TREE_VALUE (type))) + { + /* Adjust argument to match prototype. E.g. a previous + `int foo(float);' prototype causes + `int foo(x) float x; {...}' to be treated like + `int foo(float x) {...}'. This is particularly + useful for argument types like uid_t. */ + DECL_ARG_TYPE (parm) = TREE_TYPE (parm); + + if (targetm.calls.promote_prototypes (TREE_TYPE (current_function_decl)) + && INTEGRAL_TYPE_P (TREE_TYPE (parm)) + && TYPE_PRECISION (TREE_TYPE (parm)) + < TYPE_PRECISION (integer_type_node)) + DECL_ARG_TYPE (parm) = integer_type_node; + + /* ??? Is it possible to get here with a + built-in prototype or will it always have + been diagnosed as conflicting with an + old-style definition and discarded? */ + if (current_function_prototype_built_in) + warning_at (DECL_SOURCE_LOCATION (parm), + OPT_pedantic, "promoted argument %qD " + "doesn%'t match built-in prototype", parm); + else + { + pedwarn (DECL_SOURCE_LOCATION (parm), + OPT_pedantic, "promoted argument %qD " + "doesn%'t match prototype", parm); + pedwarn (current_function_prototype_locus, OPT_pedantic, + "prototype declaration"); + } + } + else + { + if (current_function_prototype_built_in) + warning_at (DECL_SOURCE_LOCATION (parm), + 0, "argument %qD doesn%'t match " + "built-in prototype", parm); + else + { + error_at (DECL_SOURCE_LOCATION (parm), + "argument %qD doesn%'t match prototype", parm); + error_at (current_function_prototype_locus, + "prototype declaration"); + } + } + } + } TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0; } @@ -7970,15 +8210,15 @@ { tree actual = 0, last = 0, type; - for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm)) - { - type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE); - if (last) - TREE_CHAIN (last) = type; - else - actual = type; - last = type; - } + for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm)) + { + type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE); + if (last) + TREE_CHAIN (last) = type; + else + actual = type; + last = type; + } type = tree_cons (NULL_TREE, void_type_node, NULL_TREE); if (last) TREE_CHAIN (last) = type; @@ -8060,9 +8300,12 @@ thus won't naturally see the SAVE_EXPR containing the increment. All other pending sizes would be handled by gimplify_parameters. */ { + VEC(tree,gc) *pending_sizes = get_pending_sizes (); tree t; - for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t)) - add_stmt (TREE_VALUE (t)); + int i; + + FOR_EACH_VEC_ELT (tree, pending_sizes, i, t) + add_stmt (t); } /* Even though we're inside a function body, we still don't want to @@ -8074,7 +8317,7 @@ /* Finish up a function declaration and compile that function - all the way to assembler language output. The free the storage + all the way to assembler language output. Then free the storage for the function definition. This is called after parsing the body of the function definition. */ @@ -8083,18 +8326,21 @@ finish_function (void) { tree fndecl = current_function_decl; + + if (c_dialect_objc ()) + objc_finish_function (); if (TREE_CODE (fndecl) == FUNCTION_DECL && targetm.calls.promote_prototypes (TREE_TYPE (fndecl))) { tree args = DECL_ARGUMENTS (fndecl); - for (; args; args = TREE_CHAIN (args)) - { - tree type = TREE_TYPE (args); - if (INTEGRAL_TYPE_P (type) - && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) - DECL_ARG_TYPE (args) = integer_type_node; - } + for (; args; args = DECL_CHAIN (args)) + { + tree type = TREE_TYPE (args); + if (INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) + DECL_ARG_TYPE (args) = integer_type_node; + } } if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node) @@ -8129,6 +8375,8 @@ && !current_function_returns_value && !current_function_returns_null /* Don't complain if we are no-return. */ && !current_function_returns_abnormally + /* Don't complain if we are declared noreturn. */ + && !TREE_THIS_VOLATILE (fndecl) /* Don't warn for main(). */ && !MAIN_NAME_P (DECL_NAME (fndecl)) /* Or if they didn't actually specify a return type. */ @@ -8142,6 +8390,25 @@ TREE_NO_WARNING (fndecl) = 1; } + /* Complain about parameters that are only set, but never otherwise used. */ + if (warn_unused_but_set_parameter) + { + tree decl; + + for (decl = DECL_ARGUMENTS (fndecl); + decl; + decl = DECL_CHAIN (decl)) + if (TREE_USED (decl) + && TREE_CODE (decl) == PARM_DECL + && !DECL_READ_P (decl) + && DECL_NAME (decl) + && !DECL_ARTIFICIAL (decl) + && !TREE_NO_WARNING (decl)) + warning_at (DECL_SOURCE_LOCATION (decl), + OPT_Wunused_but_set_parameter, + "parameter %qD set but not used", decl); + } + /* Store the end of the function, so that we get good line number info for the epilogue. */ cfun->function_end_locus = input_location; @@ -8196,16 +8463,23 @@ /* Check the declarations given in a for-loop for satisfying the C99 constraints. If exactly one such decl is found, return it. LOC is - the location of the opening parenthesis of the for loop. */ + the location of the opening parenthesis of the for loop. The last + parameter allows you to control the "for loop initial declarations + are only allowed in C99 mode". Normally, you should pass + flag_isoc99 as that parameter. But in some cases (Objective-C + foreach loop, for example) we want to run the checks in this + function even if not in C99 mode, so we allow the caller to turn + off the error about not being in C99 mode. +*/ tree -check_for_loop_decls (location_t loc) +check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error) { struct c_binding *b; tree one_decl = NULL_TREE; int n_decls = 0; - if (!flag_isoc99) + if (!turn_off_iso_c99_error) { static bool hint = true; /* If we get here, declarations have been used in a for loop without @@ -8292,7 +8566,7 @@ c_push_function_context (void) { struct language_function *p; - p = GGC_NEW (struct language_function); + p = ggc_alloc_language_function (); cfun->language = p; p->base.x_stmt_tree = c_stmt_tree; @@ -8491,10 +8765,9 @@ ret->storage_class = csc_none; ret->expr_const_operands = true; ret->declspecs_seen_p = false; - ret->type_seen_p = false; + ret->typespec_kind = ctsk_none; ret->non_sc_seen_p = false; ret->typedef_p = false; - ret->tag_defined_p = false; ret->explicit_signed_p = false; ret->deprecated_p = false; ret->default_int_p = false; @@ -8578,7 +8851,7 @@ tree type = spec.spec; specs->non_sc_seen_p = true; specs->declspecs_seen_p = true; - specs->type_seen_p = true; + specs->typespec_kind = spec.kind; if (TREE_DEPRECATED (type)) specs->deprecated_p = true; @@ -8594,105 +8867,114 @@ return specs; } if ((int) i <= (int) RID_LAST_MODIFIER) - { - /* "long", "short", "signed", "unsigned", "_Complex" or "_Sat". */ - bool dupe = false; - switch (i) - { - case RID_LONG: - if (specs->long_long_p) - { - error_at (loc, "%<long long long%> is too long for GCC"); - break; - } - if (specs->long_p) - { - if (specs->typespec_word == cts_double) - { - error_at (loc, - ("both %<long long%> and %<double%> in " - "declaration specifiers")); - break; - } - pedwarn_c90 (loc, OPT_Wlong_long, - "ISO C90 does not support %<long long%>"); - specs->long_long_p = 1; - break; - } - if (specs->short_p) - error_at (loc, - ("both %<long%> and %<short%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_void) - error_at (loc, - ("both %<long%> and %<void%> in " - "declaration specifiers")); + { + /* "long", "short", "signed", "unsigned", "_Complex" or "_Sat". */ + bool dupe = false; + switch (i) + { + case RID_LONG: + if (specs->long_long_p) + { + error_at (loc, "%<long long long%> is too long for GCC"); + break; + } + if (specs->long_p) + { + if (specs->typespec_word == cts_double) + { + error_at (loc, + ("both %<long long%> and %<double%> in " + "declaration specifiers")); + break; + } + pedwarn_c90 (loc, OPT_Wlong_long, + "ISO C90 does not support %<long long%>"); + specs->long_long_p = 1; + break; + } + if (specs->short_p) + error_at (loc, + ("both %<long%> and %<short%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_void) + error_at (loc, + ("both %<long%> and %<void%> in " + "declaration specifiers")); #ifndef noCbC - else if (specs->typespec_word == cts_CbC_code) - error_at (loc, - ("both %<long%> and %<void%> in " - "declaration specifiers")); + else if (specs->typespec_word == cts_CbC_code) + error_at (loc, + ("both %<long%> and %<void%> in " + "declaration specifiers")); #endif - else if (specs->typespec_word == cts_bool) - error_at (loc, - ("both %<long%> and %<_Bool%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_char) - error_at (loc, - ("both %<long%> and %<char%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_float) - error_at (loc, - ("both %<long%> and %<float%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_dfloat32) - error_at (loc, - ("both %<long%> and %<_Decimal32%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_dfloat64) - error_at (loc, - ("both %<long%> and %<_Decimal64%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_dfloat128) - error_at (loc, - ("both %<long%> and %<_Decimal128%> in " - "declaration specifiers")); - else - specs->long_p = true; - break; - case RID_SHORT: - dupe = specs->short_p; - if (specs->long_p) - error_at (loc, - ("both %<long%> and %<short%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_void) - error_at (loc, - ("both %<short%> and %<void%> in " - "declaration specifiers")); + else if (specs->typespec_word == cts_int128) + error_at (loc, + ("both %<long%> and %<__int128%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_bool) + error_at (loc, + ("both %<long%> and %<_Bool%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_char) + error_at (loc, + ("both %<long%> and %<char%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_float) + error_at (loc, + ("both %<long%> and %<float%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat32) + error_at (loc, + ("both %<long%> and %<_Decimal32%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat64) + error_at (loc, + ("both %<long%> and %<_Decimal64%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat128) + error_at (loc, + ("both %<long%> and %<_Decimal128%> in " + "declaration specifiers")); + else + specs->long_p = true; + break; + case RID_SHORT: + dupe = specs->short_p; + if (specs->long_p) + error_at (loc, + ("both %<long%> and %<short%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_void) + error_at (loc, + ("both %<short%> and %<void%> in " + "declaration specifiers")); #ifndef noCbC - else if (specs->typespec_word == cts_CbC_code) - error_at (loc, - ("both %<short%> and %<void%> in " - "declaration specifiers")); + else if (specs->typespec_word == cts_CbC_code) + error_at (loc, + ("both %<short%> and %<void%> in " + "declaration specifiers")); #endif - else if (specs->typespec_word == cts_bool) - error_at (loc, - ("both %<short%> and %<_Bool%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_char) - error_at (loc, - ("both %<short%> and %<char%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_float) - error_at (loc, - ("both %<short%> and %<float%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_double) - error_at (loc, - ("both %<short%> and %<double%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_dfloat32) + else if (specs->typespec_word == cts_int128) + error_at (loc, + ("both %<short%> and %<__int128%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_bool) + error_at (loc, + ("both %<short%> and %<_Bool%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_char) + error_at (loc, + ("both %<short%> and %<char%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_float) + error_at (loc, + ("both %<short%> and %<float%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_double) + error_at (loc, + ("both %<short%> and %<double%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat32) +>>>>>>> other error_at (loc, ("both %<short%> and %<_Decimal32%> in " "declaration specifiers")); @@ -8813,60 +9095,66 @@ ("both %<complex%> and %<_Bool%> in " "declaration specifiers")); else if (specs->typespec_word == cts_dfloat32) - error_at (loc, - ("both %<complex%> and %<_Decimal32%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_dfloat64) - error_at (loc, - ("both %<complex%> and %<_Decimal64%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_dfloat128) - error_at (loc, - ("both %<complex%> and %<_Decimal128%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_fract) - error_at (loc, - ("both %<complex%> and %<_Fract%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_accum) - error_at (loc, - ("both %<complex%> and %<_Accum%> in " - "declaration specifiers")); - else if (specs->saturating_p) - error_at (loc, - ("both %<complex%> and %<_Sat%> in " - "declaration specifiers")); - else - specs->complex_p = true; - break; - case RID_SAT: - dupe = specs->saturating_p; - pedwarn (loc, OPT_pedantic, - "ISO C does not support saturating types"); - if (specs->typespec_word == cts_void) - error_at (loc, - ("both %<_Sat%> and %<void%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_bool) - error_at (loc, - ("both %<_Sat%> and %<_Bool%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_char) - error_at (loc, - ("both %<_Sat%> and %<char%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_int) - error_at (loc, - ("both %<_Sat%> and %<int%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_float) - error_at (loc, - ("both %<_Sat%> and %<float%> in " - "declaration specifiers")); - else if (specs->typespec_word == cts_double) - error_at (loc, - ("both %<_Sat%> and %<double%> in " - "declaration specifiers")); + error_at (loc, + ("both %<complex%> and %<_Decimal32%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat64) + error_at (loc, + ("both %<complex%> and %<_Decimal64%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat128) + error_at (loc, + ("both %<complex%> and %<_Decimal128%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_fract) + error_at (loc, + ("both %<complex%> and %<_Fract%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_accum) + error_at (loc, + ("both %<complex%> and %<_Accum%> in " + "declaration specifiers")); + else if (specs->saturating_p) + error_at (loc, + ("both %<complex%> and %<_Sat%> in " + "declaration specifiers")); + else + specs->complex_p = true; + break; + case RID_SAT: + dupe = specs->saturating_p; + pedwarn (loc, OPT_pedantic, + "ISO C does not support saturating types"); + if (specs->typespec_word == cts_int128) + { + error_at (loc, + ("both %<_Sat%> and %<__int128%> in " + "declaration specifiers")); + } + else if (specs->typespec_word == cts_void) + error_at (loc, + ("both %<_Sat%> and %<void%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_bool) + error_at (loc, + ("both %<_Sat%> and %<_Bool%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_char) + error_at (loc, + ("both %<_Sat%> and %<char%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_int) + error_at (loc, + ("both %<_Sat%> and %<int%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_float) + error_at (loc, + ("both %<_Sat%> and %<float%> in " + "declaration specifiers")); + else if (specs->typespec_word == cts_double) + error_at (loc, + ("both %<_Sat%> and %<double%> in " + "declaration specifiers")); else if (specs->typespec_word == cts_dfloat32) error_at (loc, ("both %<_Sat%> and %<_Decimal32%> in " @@ -8896,202 +9184,227 @@ return specs; } else - { - /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32", - "_Decimal64", "_Decimal128", "_Fract" or "_Accum". */ - if (specs->typespec_word != cts_none) - { - error_at (loc, - "two or more data types in declaration specifiers"); - return specs; - } - switch (i) - { - case RID_VOID: - if (specs->long_p) - error_at (loc, - ("both %<long%> and %<void%> in " - "declaration specifiers")); - else if (specs->short_p) - error_at (loc, - ("both %<short%> and %<void%> in " - "declaration specifiers")); - else if (specs->signed_p) - error_at (loc, - ("both %<signed%> and %<void%> in " - "declaration specifiers")); - else if (specs->unsigned_p) - error_at (loc, - ("both %<unsigned%> and %<void%> in " - "declaration specifiers")); - else if (specs->complex_p) - error_at (loc, - ("both %<complex%> and %<void%> in " - "declaration specifiers")); - else if (specs->saturating_p) - error_at (loc, - ("both %<_Sat%> and %<void%> in " - "declaration specifiers")); - else - specs->typespec_word = cts_void; - return specs; + { + /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32", + "__int128", "_Decimal64", "_Decimal128", "_Fract" or "_Accum". */ + if (specs->typespec_word != cts_none) + { + error_at (loc, + "two or more data types in declaration specifiers"); + return specs; + } + switch (i) + { + case RID_INT128: + if (int128_integer_type_node == NULL_TREE) + { + error_at (loc, "%<__int128%> is not supported for this target"); + return specs; + } + if (!in_system_header) + pedwarn (loc, OPT_pedantic, + "ISO C does not support %<__int128%> type"); + + if (specs->long_p) + error_at (loc, + ("both %<__int128%> and %<long%> in " + "declaration specifiers")); + else if (specs->saturating_p) + error_at (loc, + ("both %<_Sat%> and %<__int128%> in " + "declaration specifiers")); + else if (specs->short_p) + error_at (loc, + ("both %<__int128%> and %<short%> in " + "declaration specifiers")); + else + specs->typespec_word = cts_int128; + return specs; + case RID_VOID: + if (specs->long_p) + error_at (loc, + ("both %<long%> and %<void%> in " + "declaration specifiers")); + else if (specs->short_p) + error_at (loc, + ("both %<short%> and %<void%> in " + "declaration specifiers")); + else if (specs->signed_p) + error_at (loc, + ("both %<signed%> and %<void%> in " + "declaration specifiers")); + else if (specs->unsigned_p) + error_at (loc, + ("both %<unsigned%> and %<void%> in " + "declaration specifiers")); + else if (specs->complex_p) + error_at (loc, + ("both %<complex%> and %<void%> in " + "declaration specifiers")); + else if (specs->saturating_p) + error_at (loc, + ("both %<_Sat%> and %<void%> in " + "declaration specifiers")); + else + specs->typespec_word = cts_void; + return specs; #ifndef noCbC - case RID_CbC_CODE: - if (specs->long_p) - error ("both %<long%> and %<void%> in " - "declaration specifiers"); - else if (specs->short_p) - error ("both %<short%> and %<void%> in " - "declaration specifiers"); - else if (specs->signed_p) - error ("both %<signed%> and %<void%> in " - "declaration specifiers"); - else if (specs->unsigned_p) - error ("both %<unsigned%> and %<void%> in " - "declaration specifiers"); - else if (specs->complex_p) - error ("both %<complex%> and %<void%> in " - "declaration specifiers"); - else - specs->typespec_word = cts_CbC_code; - return specs; + case RID_CbC_CODE: + if (specs->long_p) + error ("both %<long%> and %<void%> in " + "declaration specifiers"); + else if (specs->short_p) + error ("both %<short%> and %<void%> in " + "declaration specifiers"); + else if (specs->signed_p) + error ("both %<signed%> and %<void%> in " + "declaration specifiers"); + else if (specs->unsigned_p) + error ("both %<unsigned%> and %<void%> in " + "declaration specifiers"); + else if (specs->complex_p) + error ("both %<complex%> and %<void%> in " + "declaration specifiers"); + else + specs->typespec_word = cts_CbC_code; + return specs; #endif - case RID_BOOL: - if (specs->long_p) - error_at (loc, - ("both %<long%> and %<_Bool%> in " - "declaration specifiers")); - else if (specs->short_p) - error_at (loc, - ("both %<short%> and %<_Bool%> in " - "declaration specifiers")); - else if (specs->signed_p) - error_at (loc, - ("both %<signed%> and %<_Bool%> in " - "declaration specifiers")); - else if (specs->unsigned_p) - error_at (loc, - ("both %<unsigned%> and %<_Bool%> in " - "declaration specifiers")); - else if (specs->complex_p) - error_at (loc, - ("both %<complex%> and %<_Bool%> in " - "declaration specifiers")); - else if (specs->saturating_p) - error_at (loc, - ("both %<_Sat%> and %<_Bool%> in " - "declaration specifiers")); - else - specs->typespec_word = cts_bool; - return specs; - case RID_CHAR: - if (specs->long_p) - error_at (loc, - ("both %<long%> and %<char%> in " - "declaration specifiers")); - else if (specs->short_p) - error_at (loc, - ("both %<short%> and %<char%> in " - "declaration specifiers")); - else if (specs->saturating_p) - error_at (loc, - ("both %<_Sat%> and %<char%> in " - "declaration specifiers")); - else - specs->typespec_word = cts_char; - return specs; - case RID_INT: - if (specs->saturating_p) - error_at (loc, - ("both %<_Sat%> and %<int%> in " - "declaration specifiers")); - else - specs->typespec_word = cts_int; - return specs; - case RID_FLOAT: - if (specs->long_p) - error_at (loc, - ("both %<long%> and %<float%> in " - "declaration specifiers")); - else if (specs->short_p) - error_at (loc, - ("both %<short%> and %<float%> in " - "declaration specifiers")); - else if (specs->signed_p) - error_at (loc, - ("both %<signed%> and %<float%> in " - "declaration specifiers")); - else if (specs->unsigned_p) - error_at (loc, - ("both %<unsigned%> and %<float%> in " - "declaration specifiers")); - else if (specs->saturating_p) - error_at (loc, - ("both %<_Sat%> and %<float%> in " - "declaration specifiers")); - else - specs->typespec_word = cts_float; - return specs; - case RID_DOUBLE: - if (specs->long_long_p) - error_at (loc, - ("both %<long long%> and %<double%> in " - "declaration specifiers")); - else if (specs->short_p) - error_at (loc, - ("both %<short%> and %<double%> in " - "declaration specifiers")); - else if (specs->signed_p) - error_at (loc, - ("both %<signed%> and %<double%> in " - "declaration specifiers")); - else if (specs->unsigned_p) - error_at (loc, - ("both %<unsigned%> and %<double%> in " - "declaration specifiers")); - else if (specs->saturating_p) - error_at (loc, - ("both %<_Sat%> and %<double%> in " - "declaration specifiers")); - else - specs->typespec_word = cts_double; - return specs; - case RID_DFLOAT32: - case RID_DFLOAT64: - case RID_DFLOAT128: - { - const char *str; - if (i == RID_DFLOAT32) - str = "_Decimal32"; - else if (i == RID_DFLOAT64) - str = "_Decimal64"; - else - str = "_Decimal128"; - if (specs->long_long_p) - error_at (loc, - ("both %<long long%> and %<%s%> in " - "declaration specifiers"), - str); - if (specs->long_p) - error_at (loc, - ("both %<long%> and %<%s%> in " - "declaration specifiers"), - str); - else if (specs->short_p) - error_at (loc, - ("both %<short%> and %<%s%> in " - "declaration specifiers"), - str); - else if (specs->signed_p) - error_at (loc, - ("both %<signed%> and %<%s%> in " - "declaration specifiers"), - str); - else if (specs->unsigned_p) - error_at (loc, - ("both %<unsigned%> and %<%s%> in " - "declaration specifiers"), - str); + case RID_BOOL: + if (specs->long_p) + error_at (loc, + ("both %<long%> and %<_Bool%> in " + "declaration specifiers")); + else if (specs->short_p) + error_at (loc, + ("both %<short%> and %<_Bool%> in " + "declaration specifiers")); + else if (specs->signed_p) + error_at (loc, + ("both %<signed%> and %<_Bool%> in " + "declaration specifiers")); + else if (specs->unsigned_p) + error_at (loc, + ("both %<unsigned%> and %<_Bool%> in " + "declaration specifiers")); + else if (specs->complex_p) + error_at (loc, + ("both %<complex%> and %<_Bool%> in " + "declaration specifiers")); + else if (specs->saturating_p) + error_at (loc, + ("both %<_Sat%> and %<_Bool%> in " + "declaration specifiers")); + else + specs->typespec_word = cts_bool; + return specs; + case RID_CHAR: + if (specs->long_p) + error_at (loc, + ("both %<long%> and %<char%> in " + "declaration specifiers")); + else if (specs->short_p) + error_at (loc, + ("both %<short%> and %<char%> in " + "declaration specifiers")); + else if (specs->saturating_p) + error_at (loc, + ("both %<_Sat%> and %<char%> in " + "declaration specifiers")); + else + specs->typespec_word = cts_char; + return specs; + case RID_INT: + if (specs->saturating_p) + error_at (loc, + ("both %<_Sat%> and %<int%> in " + "declaration specifiers")); + else + specs->typespec_word = cts_int; + return specs; + case RID_FLOAT: + if (specs->long_p) + error_at (loc, + ("both %<long%> and %<float%> in " + "declaration specifiers")); + else if (specs->short_p) + error_at (loc, + ("both %<short%> and %<float%> in " + "declaration specifiers")); + else if (specs->signed_p) + error_at (loc, + ("both %<signed%> and %<float%> in " + "declaration specifiers")); + else if (specs->unsigned_p) + error_at (loc, + ("both %<unsigned%> and %<float%> in " + "declaration specifiers")); + else if (specs->saturating_p) + error_at (loc, + ("both %<_Sat%> and %<float%> in " + "declaration specifiers")); + else + specs->typespec_word = cts_float; + return specs; + case RID_DOUBLE: + if (specs->long_long_p) + error_at (loc, + ("both %<long long%> and %<double%> in " + "declaration specifiers")); + else if (specs->short_p) + error_at (loc, + ("both %<short%> and %<double%> in " + "declaration specifiers")); + else if (specs->signed_p) + error_at (loc, + ("both %<signed%> and %<double%> in " + "declaration specifiers")); + else if (specs->unsigned_p) + error_at (loc, + ("both %<unsigned%> and %<double%> in " + "declaration specifiers")); + else if (specs->saturating_p) + error_at (loc, + ("both %<_Sat%> and %<double%> in " + "declaration specifiers")); + else + specs->typespec_word = cts_double; + return specs; + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: + { + const char *str; + if (i == RID_DFLOAT32) + str = "_Decimal32"; + else if (i == RID_DFLOAT64) + str = "_Decimal64"; + else + str = "_Decimal128"; + if (specs->long_long_p) + error_at (loc, + ("both %<long long%> and %<%s%> in " + "declaration specifiers"), + str); + if (specs->long_p) + error_at (loc, + ("both %<long%> and %<%s%> in " + "declaration specifiers"), + str); + else if (specs->short_p) + error_at (loc, + ("both %<short%> and %<%s%> in " + "declaration specifiers"), + str); + else if (specs->signed_p) + error_at (loc, + ("both %<signed%> and %<%s%> in " + "declaration specifiers"), + str); + else if (specs->unsigned_p) + error_at (loc, + ("both %<unsigned%> and %<%s%> in " + "declaration specifiers"), + str); else if (specs->complex_p) error_at (loc, ("both %<complex%> and %<%s%> in " @@ -9191,23 +9504,21 @@ else specs->type = TREE_TYPE (t); } - else if (TREE_CODE (type) != ERROR_MARK) - { - if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref) - specs->tag_defined_p = true; - if (spec.kind == ctsk_typeof) - { - specs->typedef_p = true; - if (spec.expr) - { - if (specs->expr) - specs->expr = build2 (COMPOUND_EXPR, TREE_TYPE (spec.expr), - specs->expr, spec.expr); - else - specs->expr = spec.expr; - specs->expr_const_operands &= spec.expr_const_operands; - } - } + else + { + if (TREE_CODE (type) != ERROR_MARK && spec.kind == ctsk_typeof) + { + specs->typedef_p = true; + if (spec.expr) + { + if (specs->expr) + specs->expr = build2 (COMPOUND_EXPR, TREE_TYPE (spec.expr), + specs->expr, spec.expr); + else + specs->expr = spec.expr; + specs->expr_const_operands &= spec.expr_const_operands; + } + } specs->type = type; } @@ -9323,8 +9634,12 @@ if (specs->type != NULL_TREE) { gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p - && !specs->signed_p && !specs->unsigned_p - && !specs->complex_p); + && !specs->signed_p && !specs->unsigned_p + && !specs->complex_p); + + /* Set a dummy type. */ + if (TREE_CODE (specs->type) == ERROR_MARK) + specs->type = integer_type_node; return specs; } @@ -9403,6 +9718,19 @@ specs->type = build_complex_type (specs->type); } break; + case cts_int128: + gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p); + gcc_assert (!(specs->signed_p && specs->unsigned_p)); + specs->type = (specs->unsigned_p + ? int128_unsigned_type_node + : int128_integer_type_node); + if (specs->complex_p) + { + pedwarn (input_location, OPT_pedantic, + "ISO C does not support complex integer types"); + specs->type = build_complex_type (specs->type); + } + break; case cts_int: gcc_assert (!(specs->long_p && specs->short_p)); gcc_assert (!(specs->signed_p && specs->unsigned_p)); @@ -9568,7 +9896,7 @@ bool reconsider; /* Process the decls in the order they were written. */ - for (decl = globals; decl; decl = TREE_CHAIN (decl)) + for (decl = globals; decl; decl = DECL_CHAIN (decl)) { /* Check for used but undefined static functions using the C standard's definition of "used", and set TREE_NO_WARNING so @@ -9589,12 +9917,12 @@ do { reconsider = false; - for (decl = globals; decl; decl = TREE_CHAIN (decl)) - reconsider |= wrapup_global_declaration_2 (decl); + for (decl = globals; decl; decl = DECL_CHAIN (decl)) + reconsider |= wrapup_global_declaration_2 (decl); } while (reconsider); - for (decl = globals; decl; decl = TREE_CHAIN (decl)) + for (decl = globals; decl; decl = DECL_CHAIN (decl)) check_global_declaration_1 (decl); } @@ -9606,10 +9934,49 @@ { tree decl; - for (decl = globals; decl ; decl = TREE_CHAIN (decl)) + for (decl = globals; decl ; decl = DECL_CHAIN (decl)) debug_hooks->global_decl (decl); } +/* Callback to collect a source_ref from a DECL. */ + +static void +collect_source_ref_cb (tree decl) +{ + if (!DECL_IS_BUILTIN (decl)) + collect_source_ref (LOCATION_FILE (decl_sloc (decl, false))); +} + +/* Collect all references relevant to SOURCE_FILE. */ + +static void +collect_all_refs (const char *source_file) +{ + tree t; + unsigned i; + + FOR_EACH_VEC_ELT (tree, all_translation_units, i, t) + collect_ada_nodes (BLOCK_VARS (DECL_INITIAL (t)), source_file); +} + +/* Iterate over all global declarations and call CALLBACK. */ + +static void +for_each_global_decl (void (*callback) (tree decl)) +{ + tree t; + tree decls; + tree decl; + unsigned i; + + FOR_EACH_VEC_ELT (tree, all_translation_units, i, t) + { + decls = DECL_INITIAL (t); + for (decl = BLOCK_VARS (decls); decl; decl = TREE_CHAIN (decl)) + callback (decl); + } +} + /* Preserve the external declarations scope across a garbage collect. */ static GTY(()) tree ext_block; @@ -9617,21 +9984,35 @@ c_write_global_declarations (void) { tree t; + unsigned i; /* We don't want to do this if generating a PCH. */ if (pch_file) return; - /* Don't waste time on further processing if -fsyntax-only. - Continue for warning and errors issued during lowering though. */ - if (flag_syntax_only) - return; + /* Do the Objective-C stuff. This is where all the Objective-C + module stuff gets generated (symtab, class/protocol/selector + lists etc). */ + if (c_dialect_objc ()) + objc_write_global_declarations (); /* Close the external scope. */ ext_block = pop_scope (); external_scope = 0; gcc_assert (!current_scope); + /* Handle -fdump-ada-spec[-slim]. */ + if (dump_enabled_p (TDI_ada)) + { + /* Build a table of files to generate specs for */ + if (get_dump_file_info (TDI_ada)->flags & TDF_SLIM) + collect_source_ref (main_input_filename); + else + for_each_global_decl (collect_source_ref_cb); + + dump_ada_specs (collect_all_refs, NULL); + } + if (ext_block) { tree tmp = BLOCK_VARS (ext_block); @@ -9646,7 +10027,7 @@ /* Process all file scopes in this compilation, and the external_scope, through wrapup_global_declarations and check_global_declarations. */ - for (t = all_translation_units; t; t = TREE_CHAIN (t)) + FOR_EACH_VEC_ELT (tree, all_translation_units, i, t) c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t))); c_write_global_declarations_1 (BLOCK_VARS (ext_block)); @@ -9656,11 +10037,11 @@ /* After cgraph has had a chance to emit everything that's going to be emitted, output debug information for globals. */ - if (errorcount == 0 && sorrycount == 0) + if (!seen_error ()) { timevar_push (TV_SYMOUT); - for (t = all_translation_units; t; t = TREE_CHAIN (t)) - c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t))); + FOR_EACH_VEC_ELT (tree, all_translation_units, i, t) + c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t))); c_write_global_declarations_2 (BLOCK_VARS (ext_block)); timevar_pop (TV_SYMOUT); } @@ -9668,4 +10049,23 @@ ext_block = NULL; } +/* Register reserved keyword WORD as qualifier for address space AS. */ + +void +c_register_addr_space (const char *word, addr_space_t as) +{ + int rid = RID_FIRST_ADDR_SPACE + as; + tree id; + + /* Address space qualifiers are only supported + in C with GNU extensions enabled. */ + if (c_dialect_objc () || flag_no_asm) + return; + + id = get_identifier (word); + C_SET_RID_CODE (id, rid); + C_IS_RESERVED_WORD (id) = 1; + ridpointers [rid] = id; +} + #include "gt-c-decl.h"