| /* Process declarations and variables for C compiler. |
| Copyright (C) 1988-2022 Free Software Foundation, Inc. |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify it under |
| the terms of the GNU General Public License as published by the Free |
| Software Foundation; either version 3, or (at your option) any later |
| version. |
| |
| GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
| WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| /* Process declarations and symbol lookup for C front end. |
| Also constructs types; the standard scalar types at initialization, |
| and structure, union, array and enum types when they are declared. */ |
| |
| /* ??? not all decl nodes are given the most useful possible |
| line numbers. For example, the CONST_DECLs for enum values. */ |
| |
| #include "config.h" |
| #define INCLUDE_STRING |
| #define INCLUDE_MEMORY |
| #include "system.h" |
| #include "coretypes.h" |
| #include "target.h" |
| #include "function.h" |
| #include "c-tree.h" |
| #include "timevar.h" |
| #include "stringpool.h" |
| #include "cgraph.h" |
| #include "intl.h" |
| #include "print-tree.h" |
| #include "stor-layout.h" |
| #include "varasm.h" |
| #include "attribs.h" |
| #include "toplev.h" |
| #include "debug.h" |
| #include "c-family/c-objc.h" |
| #include "c-family/c-pragma.h" |
| #include "c-family/c-ubsan.h" |
| #include "c-lang.h" |
| #include "langhooks.h" |
| #include "tree-iterator.h" |
| #include "dumpfile.h" |
| #include "plugin.h" |
| #include "c-family/c-ada-spec.h" |
| #include "builtins.h" |
| #include "spellcheck-tree.h" |
| #include "gcc-rich-location.h" |
| #include "asan.h" |
| #include "c-family/name-hint.h" |
| #include "c-family/known-headers.h" |
| #include "c-family/c-spellcheck.h" |
| #include "context.h" /* For 'g'. */ |
| #include "omp-general.h" |
| #include "omp-offload.h" /* For offload_vars. */ |
| |
| #include "tree-pretty-print.h" |
| |
| /* In grokdeclarator, distinguish syntactic contexts of declarators. */ |
| enum decl_context |
| { NORMAL, /* Ordinary declaration */ |
| FUNCDEF, /* Function definition */ |
| PARM, /* Declaration of parm before function body */ |
| FIELD, /* Declaration inside struct or union */ |
| TYPENAME}; /* Typename (inside cast or sizeof) */ |
| |
| /* States indicating how grokdeclarator() should handle declspecs marked |
| with __attribute__((deprecated)) or __attribute__((unavailable)). |
| An object declared as __attribute__((unavailable)) should suppress |
| any reports of being declared with unavailable or deprecated items. |
| An object declared as __attribute__((deprecated)) should suppress |
| warnings of uses of other deprecated items. */ |
| |
| enum deprecated_states { |
| DEPRECATED_NORMAL, |
| DEPRECATED_SUPPRESS, |
| UNAVAILABLE_DEPRECATED_SUPPRESS |
| }; |
| |
| |
| /* Nonzero if we have seen an invalid cross reference |
| to a struct, union, or enum, but not yet printed the message. */ |
| tree pending_invalid_xref; |
| |
| /* File and line to appear in the eventual error message. */ |
| location_t pending_invalid_xref_location; |
| |
| /* The file and line that the prototype came from if this is an |
| old-style definition; used for diagnostics in |
| store_parm_decls_oldstyle. */ |
| |
| static location_t current_function_prototype_locus; |
| |
| /* Whether this prototype was built-in. */ |
| |
| static bool current_function_prototype_built_in; |
| |
| /* The argument type information of this prototype. */ |
| |
| static tree current_function_prototype_arg_types; |
| |
| /* The argument information structure for the function currently being |
| defined. */ |
| |
| static struct c_arg_info *current_function_arg_info; |
| |
| /* The obstack on which parser and related data structures, which are |
| not live beyond their top-level declaration or definition, are |
| allocated. */ |
| struct obstack parser_obstack; |
| |
| /* The current statement tree. */ |
| |
| static GTY(()) struct stmt_tree_s c_stmt_tree; |
| |
| /* Zero if we are not in an iteration or switch statement, otherwise |
| a bitmask. See bitmask definitions in c-tree.h. */ |
| unsigned char in_statement; |
| |
| /* A list of decls to be made automatically visible in each file scope. */ |
| static GTY(()) tree visible_builtins; |
| |
| /* Set to 0 at beginning of a function definition, set to 1 if |
| a return statement that specifies a return value is seen. */ |
| |
| int current_function_returns_value; |
| |
| /* Set to 0 at beginning of a function definition, set to 1 if |
| a return statement with no argument is seen. */ |
| |
| int current_function_returns_null; |
| |
| /* Set to 0 at beginning of a function definition, set to 1 if |
| a call to a noreturn function is seen. */ |
| |
| int current_function_returns_abnormally; |
| |
| /* Set to nonzero by `grokdeclarator' for a function |
| whose return type is defaulted, if warnings for this are desired. */ |
| |
| static int warn_about_return_type; |
| |
| /* Nonzero when the current toplevel function contains a declaration |
| of a nested function which is never defined. */ |
| |
| static bool undef_nested_function; |
| |
| /* If non-zero, implicit "omp declare target" attribute is added into the |
| attribute lists. */ |
| int current_omp_declare_target_attribute; |
| |
| /* Each c_binding structure describes one binding of an identifier to |
| a decl. All the decls in a scope - irrespective of namespace - are |
| chained together by the ->prev field, which (as the name implies) |
| runs in reverse order. All the decls in a given namespace bound to |
| a given identifier are chained by the ->shadowed field, which runs |
| from inner to outer scopes. |
| |
| The ->decl field usually points to a DECL node, but there are two |
| exceptions. In the namespace of type tags, the bound entity is a |
| RECORD_TYPE, UNION_TYPE, or ENUMERAL_TYPE node. If an undeclared |
| identifier is encountered, it is bound to error_mark_node to |
| suppress further errors about that identifier in the current |
| function. |
| |
| The ->u.type field stores the type of the declaration in this scope; |
| if NULL, the type is the type of the ->decl field. This is only of |
| relevance for objects with external or internal linkage which may |
| be redeclared in inner scopes, forming composite types that only |
| persist for the duration of those scopes. In the external scope, |
| this stores the composite of all the types declared for this |
| object, visible or not. The ->inner_comp field (used only at file |
| scope) stores whether an incomplete array type at file scope was |
| completed at an inner scope to an array size other than 1. |
| |
| The ->u.label field is used for labels. It points to a structure |
| which stores additional information used for warnings. |
| |
| The depth field is copied from the scope structure that holds this |
| decl. It is used to preserve the proper ordering of the ->shadowed |
| field (see bind()) and also for a handful of special-case checks. |
| Finally, the invisible bit is true for a decl which should be |
| ignored for purposes of normal name lookup, and the nested bit is |
| true for a decl that's been bound a second time in an inner scope; |
| in all such cases, the binding in the outer scope will have its |
| invisible bit true. */ |
| |
| struct GTY((chain_next ("%h.prev"))) c_binding { |
| union GTY(()) { /* first so GTY desc can use decl */ |
| tree GTY((tag ("0"))) type; /* the type in this scope */ |
| struct c_label_vars * GTY((tag ("1"))) label; /* for warnings */ |
| } GTY((desc ("TREE_CODE (%0.decl) == LABEL_DECL"))) u; |
| tree decl; /* the decl bound */ |
| tree id; /* the identifier it's bound to */ |
| struct c_binding *prev; /* the previous decl in this scope */ |
| struct c_binding *shadowed; /* the innermost decl shadowed by this one */ |
| unsigned int depth : 28; /* depth of this scope */ |
| BOOL_BITFIELD invisible : 1; /* normal lookup should ignore this binding */ |
| BOOL_BITFIELD nested : 1; /* do not set DECL_CONTEXT when popping */ |
| BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */ |
| BOOL_BITFIELD in_struct : 1; /* currently defined as struct field */ |
| location_t locus; /* location for nested bindings */ |
| }; |
| #define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth) |
| #define B_IN_CURRENT_SCOPE(b) ((b)->depth == current_scope->depth) |
| #define B_IN_FILE_SCOPE(b) ((b)->depth == 1 /*file_scope->depth*/) |
| #define B_IN_EXTERNAL_SCOPE(b) ((b)->depth == 0 /*external_scope->depth*/) |
| |
| /* Each C symbol points to three linked lists of c_binding structures. |
| These describe the values of the identifier in the three different |
| namespaces defined by the language. */ |
| |
| struct GTY(()) lang_identifier { |
| struct c_common_identifier common_id; |
| struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */ |
| struct c_binding *tag_binding; /* struct/union/enum tags */ |
| struct c_binding *label_binding; /* labels */ |
| }; |
| |
| /* Validate c-lang.cc's assumptions. */ |
| extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate |
| [(sizeof(struct lang_identifier) == C_SIZEOF_STRUCT_LANG_IDENTIFIER) ? 1 : -1]; |
| |
| /* The binding oracle; see c-tree.h. */ |
| void (*c_binding_oracle) (enum c_oracle_request, tree identifier); |
| |
| /* This flag is set on an identifier if we have previously asked the |
| binding oracle for this identifier's symbol binding. */ |
| #define I_SYMBOL_CHECKED(node) \ |
| (TREE_LANG_FLAG_4 (IDENTIFIER_NODE_CHECK (node))) |
| |
| static inline struct c_binding* * |
| i_symbol_binding (tree node) |
| { |
| struct lang_identifier *lid |
| = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node); |
| |
| if (lid->symbol_binding == NULL |
| && c_binding_oracle != NULL |
| && !I_SYMBOL_CHECKED (node)) |
| { |
| /* Set the "checked" flag first, to avoid infinite recursion |
| when the binding oracle calls back into gcc. */ |
| I_SYMBOL_CHECKED (node) = 1; |
| c_binding_oracle (C_ORACLE_SYMBOL, node); |
| } |
| |
| return &lid->symbol_binding; |
| } |
| |
| #define I_SYMBOL_BINDING(node) (*i_symbol_binding (node)) |
| |
| #define I_SYMBOL_DECL(node) \ |
| (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0) |
| |
| /* This flag is set on an identifier if we have previously asked the |
| binding oracle for this identifier's tag binding. */ |
| #define I_TAG_CHECKED(node) \ |
| (TREE_LANG_FLAG_5 (IDENTIFIER_NODE_CHECK (node))) |
| |
| static inline struct c_binding ** |
| i_tag_binding (tree node) |
| { |
| struct lang_identifier *lid |
| = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node); |
| |
| if (lid->tag_binding == NULL |
| && c_binding_oracle != NULL |
| && !I_TAG_CHECKED (node)) |
| { |
| /* Set the "checked" flag first, to avoid infinite recursion |
| when the binding oracle calls back into gcc. */ |
| I_TAG_CHECKED (node) = 1; |
| c_binding_oracle (C_ORACLE_TAG, node); |
| } |
| |
| return &lid->tag_binding; |
| } |
| |
| #define I_TAG_BINDING(node) (*i_tag_binding (node)) |
| |
| #define I_TAG_DECL(node) \ |
| (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0) |
| |
| /* This flag is set on an identifier if we have previously asked the |
| binding oracle for this identifier's label binding. */ |
| #define I_LABEL_CHECKED(node) \ |
| (TREE_LANG_FLAG_6 (IDENTIFIER_NODE_CHECK (node))) |
| |
| static inline struct c_binding ** |
| i_label_binding (tree node) |
| { |
| struct lang_identifier *lid |
| = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node); |
| |
| if (lid->label_binding == NULL |
| && c_binding_oracle != NULL |
| && !I_LABEL_CHECKED (node)) |
| { |
| /* Set the "checked" flag first, to avoid infinite recursion |
| when the binding oracle calls back into gcc. */ |
| I_LABEL_CHECKED (node) = 1; |
| c_binding_oracle (C_ORACLE_LABEL, node); |
| } |
| |
| return &lid->label_binding; |
| } |
| |
| #define I_LABEL_BINDING(node) (*i_label_binding (node)) |
| |
| #define I_LABEL_DECL(node) \ |
| (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0) |
| |
| /* The resulting tree type. */ |
| |
| union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), |
| chain_next ("(union lang_tree_node *) c_tree_chain_next (&%h.generic)"))) lang_tree_node |
| { |
| union tree_node GTY ((tag ("0"), |
| desc ("tree_node_structure (&%h)"))) |
| generic; |
| struct lang_identifier GTY ((tag ("1"))) identifier; |
| }; |
| |
| /* Track bindings and other things that matter for goto warnings. For |
| efficiency, we do not gather all the decls at the point of |
| definition. Instead, we point into the bindings structure. As |
| scopes are popped, we update these structures and gather the decls |
| that matter at that time. */ |
| |
| struct GTY(()) c_spot_bindings { |
| /* The currently open scope which holds bindings defined when the |
| label was defined or the goto statement was found. */ |
| struct c_scope *scope; |
| /* The bindings in the scope field which were defined at the point |
| of the label or goto. This lets us look at older or newer |
| bindings in the scope, as appropriate. */ |
| struct c_binding *bindings_in_scope; |
| /* The number of statement expressions that have started since this |
| label or goto statement was defined. This is zero if we are at |
| the same statement expression level. It is positive if we are in |
| a statement expression started since this spot. It is negative |
| if this spot was in a statement expression and we have left |
| it. */ |
| int stmt_exprs; |
| /* Whether we started in a statement expression but are no longer in |
| it. This is set to true if stmt_exprs ever goes negative. */ |
| bool left_stmt_expr; |
| }; |
| |
| /* This structure is used to keep track of bindings seen when a goto |
| statement is defined. This is only used if we see the goto |
| statement before we see the label. */ |
| |
| struct GTY(()) c_goto_bindings { |
| /* The location of the goto statement. */ |
| location_t loc; |
| /* The bindings of the goto statement. */ |
| struct c_spot_bindings goto_bindings; |
| }; |
| |
| typedef struct c_goto_bindings *c_goto_bindings_p; |
| |
| /* The additional information we keep track of for a label binding. |
| These fields are updated as scopes are popped. */ |
| |
| struct GTY(()) c_label_vars { |
| /* The shadowed c_label_vars, when one label shadows another (which |
| can only happen using a __label__ declaration). */ |
| struct c_label_vars *shadowed; |
| /* The bindings when the label was defined. */ |
| struct c_spot_bindings label_bindings; |
| /* A list of decls that we care about: decls about which we should |
| warn if a goto branches to this label from later in the function. |
| Decls are added to this list as scopes are popped. We only add |
| the decls that matter. */ |
| vec<tree, va_gc> *decls_in_scope; |
| /* A list of goto statements to this label. This is only used for |
| goto statements seen before the label was defined, so that we can |
| issue appropriate warnings for them. */ |
| vec<c_goto_bindings_p, va_gc> *gotos; |
| }; |
| |
| /* Each c_scope structure describes the complete contents of one |
| scope. Four scopes are distinguished specially: the innermost or |
| current scope, the innermost function scope, the file scope (always |
| the second to outermost) and the outermost or external scope. |
| |
| Most declarations are recorded in the current scope. |
| |
| All normal label declarations are recorded in the innermost |
| function scope, as are bindings of undeclared identifiers to |
| error_mark_node. (GCC permits nested functions as an extension, |
| hence the 'innermost' qualifier.) Explicitly declared labels |
| (using the __label__ extension) appear in the current scope. |
| |
| Being in the file scope (current_scope == file_scope) causes |
| special behavior in several places below. Also, under some |
| conditions the Objective-C front end records declarations in the |
| file scope even though that isn't the current scope. |
| |
| All declarations with external linkage are recorded in the external |
| scope, even if they aren't visible there; this models the fact that |
| such declarations are visible to the entire program, and (with a |
| bit of cleverness, see pushdecl) allows diagnosis of some violations |
| of C99 6.2.2p7 and 6.2.7p2: |
| |
| If, within the same translation unit, the same identifier appears |
| with both internal and external linkage, the behavior is |
| undefined. |
| |
| All declarations that refer to the same object or function shall |
| have compatible type; otherwise, the behavior is undefined. |
| |
| Initially only the built-in declarations, which describe compiler |
| intrinsic functions plus a subset of the standard library, are in |
| this scope. |
| |
| The order of the blocks list matters, and it is frequently appended |
| to. To avoid having to walk all the way to the end of the list on |
| each insertion, or reverse the list later, we maintain a pointer to |
| the last list entry. (FIXME: It should be feasible to use a reversed |
| list here.) |
| |
| The bindings list is strictly in reverse order of declarations; |
| pop_scope relies on this. */ |
| |
| |
| struct GTY((chain_next ("%h.outer"))) c_scope { |
| /* The scope containing this one. */ |
| struct c_scope *outer; |
| |
| /* The next outermost function scope. */ |
| struct c_scope *outer_function; |
| |
| /* All bindings in this scope. */ |
| struct c_binding *bindings; |
| |
| /* For each scope (except the global one), a chain of BLOCK nodes |
| for all the scopes that were entered and exited one level down. */ |
| tree blocks; |
| tree blocks_last; |
| |
| /* The depth of this scope. Used to keep the ->shadowed chain of |
| bindings sorted innermost to outermost. */ |
| unsigned int depth : 28; |
| |
| /* True if we are currently filling this scope with parameter |
| declarations. */ |
| BOOL_BITFIELD parm_flag : 1; |
| |
| /* True if we saw [*] in this scope. Used to give an error messages |
| if these appears in a function definition. */ |
| BOOL_BITFIELD had_vla_unspec : 1; |
| |
| /* True if we already complained about forward parameter decls |
| in this scope. This prevents double warnings on |
| foo (int a; int b; ...) */ |
| BOOL_BITFIELD warned_forward_parm_decls : 1; |
| |
| /* True if this is the outermost block scope of a function body. |
| This scope contains the parameters, the local variables declared |
| in the outermost block, and all the labels (except those in |
| nested functions, or declared at block scope with __label__). */ |
| BOOL_BITFIELD function_body : 1; |
| |
| /* True means make a BLOCK for this scope no matter what. */ |
| BOOL_BITFIELD keep : 1; |
| |
| /* True means that an unsuffixed float constant is _Decimal64. */ |
| BOOL_BITFIELD float_const_decimal64 : 1; |
| |
| /* True if this scope has any label bindings. This is used to speed |
| 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. */ |
| |
| static GTY(()) struct c_scope *current_scope; |
| |
| /* The innermost function scope. Ordinary (not explicitly declared) |
| labels, bindings to error_mark_node, and the lazily-created |
| bindings of __func__ and its friends get this scope. */ |
| |
| static GTY(()) struct c_scope *current_function_scope; |
| |
| /* The C file scope. This is reset for each input translation unit. */ |
| |
| static GTY(()) struct c_scope *file_scope; |
| |
| /* The outermost scope. This is used for all declarations with |
| external linkage, and only these, hence the name. */ |
| |
| static GTY(()) struct c_scope *external_scope; |
| |
| /* A chain of c_scope structures awaiting reuse. */ |
| |
| static GTY((deletable)) struct c_scope *scope_freelist; |
| |
| /* A chain of c_binding structures awaiting reuse. */ |
| |
| static GTY((deletable)) struct c_binding *binding_freelist; |
| |
| /* Append VAR to LIST in scope SCOPE. */ |
| #define SCOPE_LIST_APPEND(scope, list, decl) do { \ |
| struct c_scope *s_ = (scope); \ |
| tree d_ = (decl); \ |
| if (s_->list##_last) \ |
| BLOCK_CHAIN (s_->list##_last) = d_; \ |
| else \ |
| s_->list = d_; \ |
| s_->list##_last = d_; \ |
| } while (0) |
| |
| /* Concatenate FROM in scope FSCOPE onto TO in scope TSCOPE. */ |
| #define SCOPE_LIST_CONCAT(tscope, to, fscope, from) do { \ |
| struct c_scope *t_ = (tscope); \ |
| struct c_scope *f_ = (fscope); \ |
| if (t_->to##_last) \ |
| BLOCK_CHAIN (t_->to##_last) = f_->from; \ |
| else \ |
| t_->to = f_->from; \ |
| t_->to##_last = f_->from##_last; \ |
| } while (0) |
| |
| /* A c_inline_static structure stores details of a static identifier |
| referenced in a definition of a function that may be an inline |
| definition if no subsequent declaration of that function uses |
| "extern" or does not use "inline". */ |
| |
| struct GTY((chain_next ("%h.next"))) c_inline_static { |
| /* The location for a diagnostic. */ |
| location_t location; |
| |
| /* The function that may be an inline definition. */ |
| tree function; |
| |
| /* The object or function referenced. */ |
| tree static_decl; |
| |
| /* What sort of reference this is. */ |
| enum c_inline_static_type type; |
| |
| /* The next such structure or NULL. */ |
| struct c_inline_static *next; |
| }; |
| |
| /* List of static identifiers used or referenced in functions that may |
| be inline definitions. */ |
| static GTY(()) struct c_inline_static *c_inline_statics; |
| |
| /* True means unconditionally make a BLOCK for the next scope pushed. */ |
| |
| static bool keep_next_level_flag; |
| |
| /* True means the next call to push_scope will be the outermost scope |
| of a function body, so do not push a new scope, merely cease |
| expecting parameter decls. */ |
| |
| static bool next_is_function_body; |
| |
| /* A vector of pointers to c_binding structures. */ |
| |
| typedef struct c_binding *c_binding_ptr; |
| |
| /* Information that we keep for a struct or union while it is being |
| parsed. */ |
| |
| class c_struct_parse_info |
| { |
| public: |
| /* If warn_cxx_compat, a list of types defined within this |
| struct. */ |
| auto_vec<tree> struct_types; |
| /* If warn_cxx_compat, a list of field names which have bindings, |
| and which are defined in this struct, but which are not defined |
| in any enclosing struct. This is used to clear the in_struct |
| field of the c_bindings structure. */ |
| auto_vec<c_binding_ptr> fields; |
| /* If warn_cxx_compat, a list of typedef names used when defining |
| fields in this struct. */ |
| auto_vec<tree> typedefs_seen; |
| }; |
| |
| /* Information for the struct or union currently being parsed, or |
| NULL if not parsing a struct or union. */ |
| static class c_struct_parse_info *struct_parse_info; |
| |
| /* Forward declarations. */ |
| static tree lookup_name_in_scope (tree, struct c_scope *); |
| static tree c_make_fname_decl (location_t, tree, int); |
| static tree grokdeclarator (const struct c_declarator *, |
| struct c_declspecs *, |
| enum decl_context, bool, tree *, tree *, tree *, |
| bool *, enum deprecated_states); |
| static tree grokparms (struct c_arg_info *, bool); |
| static void layout_array_type (tree); |
| static void warn_defaults_to (location_t, int, const char *, ...) |
| ATTRIBUTE_GCC_DIAG(3,4); |
| static const char *header_for_builtin_fn (tree); |
| |
| /* T is a statement. Add it to the statement-tree. This is the |
| C/ObjC version--C++ has a slightly different version of this |
| function. */ |
| |
| tree |
| add_stmt (tree t) |
| { |
| enum tree_code code = TREE_CODE (t); |
| |
| if (CAN_HAVE_LOCATION_P (t) && code != LABEL_EXPR) |
| { |
| if (!EXPR_HAS_LOCATION (t)) |
| SET_EXPR_LOCATION (t, input_location); |
| } |
| |
| if (code == LABEL_EXPR || code == CASE_LABEL_EXPR) |
| STATEMENT_LIST_HAS_LABEL (cur_stmt_list) = 1; |
| |
| /* Add T to the statement-tree. Non-side-effect statements need to be |
| recorded during statement expressions. */ |
| if (!building_stmt_list_p ()) |
| push_stmt_list (); |
| append_to_statement_list_force (t, &cur_stmt_list); |
| |
| return t; |
| } |
| |
| /* Build a pointer type using the default pointer mode. */ |
| |
| static tree |
| c_build_pointer_type (tree to_type) |
| { |
| addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC |
| : TYPE_ADDR_SPACE (to_type); |
| machine_mode pointer_mode; |
| |
| if (as != ADDR_SPACE_GENERIC || c_default_pointer_mode == VOIDmode) |
| pointer_mode = targetm.addr_space.pointer_mode (as); |
| else |
| pointer_mode = c_default_pointer_mode; |
| return build_pointer_type_for_mode (to_type, pointer_mode, false); |
| } |
| |
| |
| /* Return true if we will want to say something if a goto statement |
| crosses DECL. */ |
| |
| static bool |
| decl_jump_unsafe (tree decl) |
| { |
| if (error_operand_p (decl)) |
| return false; |
| |
| /* Don't warn for compound literals. If a goto statement crosses |
| their initialization, it should cross also all the places where |
| the complit is used or where the complit address might be saved |
| into some variable, so code after the label to which goto jumps |
| should not be able to refer to the compound literal. */ |
| if (VAR_P (decl) && C_DECL_COMPOUND_LITERAL_P (decl)) |
| return false; |
| |
| /* Always warn about crossing variably modified types. */ |
| if ((VAR_P (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 |
| && VAR_P (decl) |
| && !TREE_STATIC (decl) |
| && DECL_INITIAL (decl) != NULL_TREE) |
| return true; |
| |
| return false; |
| } |
| |
| |
| void |
| c_print_identifier (FILE *file, tree node, int indent) |
| { |
| void (*save) (enum c_oracle_request, tree identifier); |
| |
| /* Temporarily hide any binding oracle. Without this, calls to |
| debug_tree from the debugger will end up calling into the oracle, |
| making for a confusing debug session. As the oracle isn't needed |
| here for normal operation, it's simplest to suppress it. */ |
| save = c_binding_oracle; |
| c_binding_oracle = NULL; |
| |
| print_node (file, "symbol", I_SYMBOL_DECL (node), indent + 4); |
| print_node (file, "tag", I_TAG_DECL (node), indent + 4); |
| print_node (file, "label", I_LABEL_DECL (node), indent + 4); |
| if (C_IS_RESERVED_WORD (node) && C_RID_CODE (node) != RID_CXX_COMPAT_WARN) |
| { |
| tree rid = ridpointers[C_RID_CODE (node)]; |
| indent_to (file, indent + 4); |
| fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"", |
| (void *) rid, IDENTIFIER_POINTER (rid)); |
| } |
| |
| c_binding_oracle = save; |
| } |
| |
| /* Establish a binding between NAME, an IDENTIFIER_NODE, and DECL, |
| which may be any of several kinds of DECL or TYPE or error_mark_node, |
| in the scope SCOPE. */ |
| static void |
| bind (tree name, tree decl, struct c_scope *scope, bool invisible, |
| bool nested, location_t locus) |
| { |
| struct c_binding *b, **here; |
| |
| if (binding_freelist) |
| { |
| b = binding_freelist; |
| binding_freelist = b->prev; |
| } |
| else |
| b = ggc_alloc<c_binding> (); |
| |
| b->shadowed = 0; |
| b->decl = decl; |
| b->id = name; |
| b->depth = scope->depth; |
| b->invisible = invisible; |
| b->nested = nested; |
| b->inner_comp = 0; |
| b->in_struct = 0; |
| b->locus = locus; |
| |
| b->u.type = NULL; |
| |
| b->prev = scope->bindings; |
| scope->bindings = b; |
| |
| if (decl_jump_unsafe (decl)) |
| scope->has_jump_unsafe_decl = 1; |
| |
| if (!name) |
| return; |
| |
| switch (TREE_CODE (decl)) |
| { |
| case LABEL_DECL: here = &I_LABEL_BINDING (name); break; |
| case ENUMERAL_TYPE: |
| case UNION_TYPE: |
| case RECORD_TYPE: here = &I_TAG_BINDING (name); break; |
| case VAR_DECL: |
| case FUNCTION_DECL: |
| case TYPE_DECL: |
| case CONST_DECL: |
| case PARM_DECL: |
| case ERROR_MARK: here = &I_SYMBOL_BINDING (name); break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| /* Locate the appropriate place in the chain of shadowed decls |
| to insert this binding. Normally, scope == current_scope and |
| this does nothing. */ |
| while (*here && (*here)->depth > scope->depth) |
| here = &(*here)->shadowed; |
| |
| b->shadowed = *here; |
| *here = b; |
| } |
| |
| /* Clear the binding structure B, stick it on the binding_freelist, |
| and return the former value of b->prev. This is used by pop_scope |
| and get_parm_info to iterate destructively over all the bindings |
| from a given scope. */ |
| static struct c_binding * |
| free_binding_and_advance (struct c_binding *b) |
| { |
| struct c_binding *prev = b->prev; |
| |
| memset (b, 0, sizeof (struct c_binding)); |
| b->prev = binding_freelist; |
| binding_freelist = b; |
| |
| return prev; |
| } |
| |
| /* Bind a label. Like bind, but skip fields which aren't used for |
| labels, and add the LABEL_VARS value. */ |
| static void |
| bind_label (tree name, tree label, struct c_scope *scope, |
| struct c_label_vars *label_vars) |
| { |
| struct c_binding *b; |
| |
| bind (name, label, scope, /*invisible=*/false, /*nested=*/false, |
| UNKNOWN_LOCATION); |
| |
| scope->has_label_bindings = true; |
| |
| b = scope->bindings; |
| gcc_assert (b->decl == label); |
| label_vars->shadowed = b->u.label; |
| b->u.label = label_vars; |
| } |
| |
| /* Hook called at end of compilation to assume 1 elt |
| for a file-scope tentative array defn that wasn't complete before. */ |
| |
| void |
| c_finish_incomplete_decl (tree decl) |
| { |
| if (VAR_P (decl)) |
| { |
| tree type = TREE_TYPE (decl); |
| if (type != error_mark_node |
| && TREE_CODE (type) == ARRAY_TYPE |
| && !DECL_EXTERNAL (decl) |
| && TYPE_DOMAIN (type) == NULL_TREE) |
| { |
| warning_at (DECL_SOURCE_LOCATION (decl), |
| 0, "array %q+D assumed to have one element", decl); |
| |
| complete_array_type (&TREE_TYPE (decl), NULL_TREE, true); |
| |
| relayout_decl (decl); |
| } |
| } |
| } |
| |
| /* Record that inline function FUNC contains a reference (location |
| LOC) to static DECL (file-scope or function-local according to |
| TYPE). */ |
| |
| void |
| record_inline_static (location_t loc, tree func, tree decl, |
| enum c_inline_static_type type) |
| { |
| c_inline_static *csi = ggc_alloc<c_inline_static> (); |
| csi->location = loc; |
| csi->function = func; |
| csi->static_decl = decl; |
| csi->type = type; |
| csi->next = c_inline_statics; |
| c_inline_statics = csi; |
| } |
| |
| /* Check for references to static declarations in inline functions at |
| the end of the translation unit and diagnose them if the functions |
| are still inline definitions. */ |
| |
| static void |
| check_inline_statics (void) |
| { |
| struct c_inline_static *csi; |
| for (csi = c_inline_statics; csi; csi = csi->next) |
| { |
| if (DECL_EXTERNAL (csi->function)) |
| switch (csi->type) |
| { |
| case csi_internal: |
| pedwarn (csi->location, 0, |
| "%qD is static but used in inline function %qD " |
| "which is not static", csi->static_decl, csi->function); |
| break; |
| case csi_modifiable: |
| pedwarn (csi->location, 0, |
| "%q+D is static but declared in inline function %qD " |
| "which is not static", csi->static_decl, csi->function); |
| break; |
| default: |
| gcc_unreachable (); |
| } |
| } |
| c_inline_statics = NULL; |
| } |
| |
| /* Fill in a c_spot_bindings structure. If DEFINING is true, set it |
| for the current state, otherwise set it to uninitialized. */ |
| |
| static void |
| set_spot_bindings (struct c_spot_bindings *p, bool defining) |
| { |
| if (defining) |
| { |
| p->scope = current_scope; |
| p->bindings_in_scope = current_scope->bindings; |
| } |
| else |
| { |
| p->scope = NULL; |
| p->bindings_in_scope = NULL; |
| } |
| p->stmt_exprs = 0; |
| p->left_stmt_expr = false; |
| } |
| |
| /* Update spot bindings P as we pop out of SCOPE. Return true if we |
| should push decls for a label. */ |
| |
| static bool |
| update_spot_bindings (struct c_scope *scope, struct c_spot_bindings *p) |
| { |
| if (p->scope != scope) |
| { |
| /* This label or goto is defined in some other scope, or it is a |
| label which is not yet defined. There is nothing to |
| update. */ |
| return false; |
| } |
| |
| /* Adjust the spot bindings to refer to the bindings already defined |
| in the enclosing scope. */ |
| p->scope = scope->outer; |
| p->bindings_in_scope = p->scope->bindings; |
| |
| return true; |
| } |
| |
| /* The Objective-C front-end often needs to determine the current scope. */ |
| |
| void * |
| objc_get_current_scope (void) |
| { |
| return current_scope; |
| } |
| |
| /* The following function is used only by Objective-C. It needs to live here |
| because it accesses the innards of c_scope. */ |
| |
| void |
| objc_mark_locals_volatile (void *enclosing_blk) |
| { |
| struct c_scope *scope; |
| struct c_binding *b; |
| |
| for (scope = current_scope; |
| scope && scope != enclosing_blk; |
| scope = scope->outer) |
| { |
| for (b = scope->bindings; b; b = b->prev) |
| objc_volatilize_decl (b->decl); |
| |
| /* Do not climb up past the current function. */ |
| if (scope->function_body) |
| break; |
| } |
| } |
| |
| /* Return true if we are in the global binding level. */ |
| |
| bool |
| global_bindings_p (void) |
| { |
| return current_scope == file_scope; |
| } |
| |
| /* Return true if we're declaring parameters in an old-style function |
| declaration. */ |
| |
| bool |
| old_style_parameter_scope (void) |
| { |
| /* If processing parameters and there is no function statement list, we |
| * have an old-style function declaration. */ |
| return (current_scope->parm_flag && !DECL_SAVED_TREE (current_function_decl)); |
| } |
| |
| void |
| keep_next_level (void) |
| { |
| keep_next_level_flag = true; |
| } |
| |
| /* Set the flag for the FLOAT_CONST_DECIMAL64 pragma being ON. */ |
| |
| void |
| set_float_const_decimal64 (void) |
| { |
| current_scope->float_const_decimal64 = true; |
| } |
| |
| /* Clear the flag for the FLOAT_CONST_DECIMAL64 pragma. */ |
| |
| void |
| clear_float_const_decimal64 (void) |
| { |
| current_scope->float_const_decimal64 = false; |
| } |
| |
| /* Return nonzero if an unsuffixed float constant is _Decimal64. */ |
| |
| bool |
| float_const_decimal64_p (void) |
| { |
| return current_scope->float_const_decimal64; |
| } |
| |
| /* Identify this scope as currently being filled with parameters. */ |
| |
| void |
| declare_parm_level (void) |
| { |
| current_scope->parm_flag = true; |
| } |
| |
| void |
| push_scope (void) |
| { |
| if (next_is_function_body) |
| { |
| /* This is the transition from the parameters to the top level |
| of the function body. These are the same scope |
| (C99 6.2.1p4,6) so we do not push another scope structure. |
| next_is_function_body is set only by store_parm_decls, which |
| in turn is called when and only when we are about to |
| encounter the opening curly brace for the function body. |
| |
| The outermost block of a function always gets a BLOCK node, |
| because the debugging output routines expect that each |
| function has at least one BLOCK. */ |
| current_scope->parm_flag = false; |
| current_scope->function_body = true; |
| current_scope->keep = true; |
| current_scope->outer_function = current_function_scope; |
| current_function_scope = current_scope; |
| |
| keep_next_level_flag = false; |
| next_is_function_body = false; |
| |
| /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes. */ |
| if (current_scope->outer) |
| current_scope->float_const_decimal64 |
| = current_scope->outer->float_const_decimal64; |
| else |
| current_scope->float_const_decimal64 = false; |
| } |
| else |
| { |
| struct c_scope *scope; |
| if (scope_freelist) |
| { |
| scope = scope_freelist; |
| scope_freelist = scope->outer; |
| } |
| else |
| scope = ggc_cleared_alloc<c_scope> (); |
| |
| /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes. */ |
| if (current_scope) |
| scope->float_const_decimal64 = current_scope->float_const_decimal64; |
| else |
| scope->float_const_decimal64 = false; |
| |
| scope->keep = keep_next_level_flag; |
| scope->outer = current_scope; |
| scope->depth = current_scope ? (current_scope->depth + 1) : 0; |
| |
| /* Check for scope depth overflow. Unlikely (2^28 == 268,435,456) but |
| possible. */ |
| if (current_scope && scope->depth == 0) |
| { |
| scope->depth--; |
| sorry ("GCC supports only %u nested scopes", scope->depth); |
| } |
| |
| current_scope = scope; |
| keep_next_level_flag = false; |
| } |
| } |
| |
| /* This is called when we are leaving SCOPE. For each label defined |
| in SCOPE, add any appropriate decls to its decls_in_scope fields. |
| These are the decls whose initialization will be skipped by a goto |
| later in the function. */ |
| |
| static void |
| update_label_decls (struct c_scope *scope) |
| { |
| struct c_scope *s; |
| |
| s = scope; |
| 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; |
| 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(label_vars->decls_in_scope, b1->decl); |
| } |
| } |
| } |
| |
| /* Update the bindings of any goto statements associated |
| with this label. */ |
| FOR_EACH_VEC_SAFE_ELT (label_vars->gotos, ix, g) |
| update_spot_bindings (scope, &g->goto_bindings); |
| } |
| } |
| |
| /* Don't search beyond the current function. */ |
| if (s == current_function_scope) |
| break; |
| |
| s = s->outer; |
| } |
| } |
| |
| /* Set the TYPE_CONTEXT of all of TYPE's variants to CONTEXT. */ |
| |
| static void |
| set_type_context (tree type, tree context) |
| { |
| for (type = TYPE_MAIN_VARIANT (type); type; |
| type = TYPE_NEXT_VARIANT (type)) |
| TYPE_CONTEXT (type) = context; |
| } |
| |
| /* Exit a scope. Restore the state of the identifier-decl mappings |
| that were in effect when this scope was entered. Return a BLOCK |
| node containing all the DECLs in this scope that are of interest |
| to debug info generation. */ |
| |
| tree |
| pop_scope (void) |
| { |
| struct c_scope *scope = current_scope; |
| tree block, context, p; |
| struct c_binding *b; |
| |
| bool functionbody = scope->function_body; |
| bool keep = functionbody || scope->keep || scope->bindings; |
| |
| update_label_decls (scope); |
| |
| /* If appropriate, create a BLOCK to record the decls for the life |
| of this function. */ |
| block = NULL_TREE; |
| if (keep) |
| { |
| block = make_node (BLOCK); |
| BLOCK_SUBBLOCKS (block) = scope->blocks; |
| TREE_USED (block) = 1; |
| |
| /* In each subblock, record that this is its superior. */ |
| for (p = scope->blocks; p; p = BLOCK_CHAIN (p)) |
| BLOCK_SUPERCONTEXT (p) = block; |
| |
| BLOCK_VARS (block) = NULL_TREE; |
| } |
| |
| /* The TYPE_CONTEXTs for all of the tagged types belonging to this |
| scope must be set so that they point to the appropriate |
| construct, i.e. either to the current FUNCTION_DECL node, or |
| else to the BLOCK node we just constructed. |
| |
| Note that for tagged types whose scope is just the formal |
| parameter list for some function type specification, we can't |
| properly set their TYPE_CONTEXTs here, because we don't have a |
| pointer to the appropriate FUNCTION_TYPE node readily available |
| to us. For those cases, the TYPE_CONTEXTs of the relevant tagged |
| type nodes get set in `grokdeclarator' as soon as we have created |
| the FUNCTION_TYPE node which will represent the "scope" for these |
| "parameter list local" tagged types. */ |
| if (scope->function_body) |
| context = current_function_decl; |
| else if (scope == file_scope) |
| { |
| tree file_decl |
| = build_translation_unit_decl (get_identifier (main_input_filename)); |
| context = file_decl; |
| debug_hooks->register_main_translation_unit (file_decl); |
| } |
| else |
| context = block; |
| |
| /* Clear all bindings in this scope. */ |
| for (b = scope->bindings; b; b = free_binding_and_advance (b)) |
| { |
| 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. */ |
| 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) != NULL_TREE |
| && TREE_ADDRESSABLE (p) |
| && DECL_ABSTRACT_ORIGIN (p) != NULL_TREE |
| && DECL_ABSTRACT_ORIGIN (p) != p) |
| TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1; |
| if (!TREE_PUBLIC (p) |
| && !DECL_INITIAL (p) |
| && !b->nested |
| && 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 |
| && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (p)) |
| && scope == external_scope) |
| 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)) |
| && !warning_suppressed_p (p, OPT_Wunused_but_set_variable) |
| && !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) && scope != file_scope) |
| { |
| /* 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); |
| } |
| |
| gcc_fallthrough (); |
| /* 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.cc. |
| 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 (); |
| } |
| } |
| |
| |
| /* Dispose of the block that we just made inside some higher level. */ |
| if ((scope->function_body || scope == file_scope) && context) |
| { |
| DECL_INITIAL (context) = block; |
| BLOCK_SUPERCONTEXT (block) = context; |
| } |
| else if (scope->outer) |
| { |
| if (block) |
| SCOPE_LIST_APPEND (scope->outer, blocks, block); |
| /* If we did not make a block for the scope just exited, any |
| blocks made for inner scopes must be carried forward so they |
| will later become subblocks of something else. */ |
| else if (scope->blocks) |
| SCOPE_LIST_CONCAT (scope->outer, blocks, scope, blocks); |
| } |
| |
| /* Pop the current scope, and free the structure for reuse. */ |
| current_scope = scope->outer; |
| if (scope->function_body) |
| current_function_scope = scope->outer_function; |
| |
| memset (scope, 0, sizeof (struct c_scope)); |
| scope->outer = scope_freelist; |
| scope_freelist = scope; |
| |
| return block; |
| } |
| |
| void |
| push_file_scope (void) |
| { |
| tree decl; |
| |
| if (file_scope) |
| return; |
| |
| push_scope (); |
| file_scope = current_scope; |
| |
| start_fname_decls (); |
| |
| for (decl = visible_builtins; decl; decl = DECL_CHAIN (decl)) |
| bind (DECL_NAME (decl), decl, file_scope, |
| /*invisible=*/false, /*nested=*/true, DECL_SOURCE_LOCATION (decl)); |
| } |
| |
| void |
| pop_file_scope (void) |
| { |
| /* In case there were missing closebraces, get us back to the global |
| binding level. */ |
| while (current_scope != file_scope) |
| pop_scope (); |
| |
| /* __FUNCTION__ is defined at file scope (""). This |
| call may not be necessary as my tests indicate it |
| still works without it. */ |
| finish_fname_decls (); |
| |
| check_inline_statics (); |
| |
| /* This is the point to write out a PCH if we're doing that. |
| In that case we do not want to do anything else. */ |
| if (pch_file) |
| { |
| c_common_write_pch (); |
| /* Ensure even the callers don't try to finalize the CU. */ |
| flag_syntax_only = 1; |
| return; |
| } |
| |
| /* Pop off the file scope and close this translation unit. */ |
| pop_scope (); |
| file_scope = 0; |
| |
| maybe_apply_pending_pragma_weaks (); |
| } |
| |
| /* Adjust the bindings for the start of a statement expression. */ |
| |
| void |
| c_bindings_start_stmt_expr (struct c_spot_bindings* switch_bindings) |
| { |
| struct c_scope *scope; |
| |
| for (scope = current_scope; scope != NULL; scope = scope->outer) |
| { |
| struct c_binding *b; |
| |
| if (!scope->has_label_bindings) |
| 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_EACH_VEC_SAFE_ELT (label_vars->gotos, ix, g) |
| ++g->goto_bindings.stmt_exprs; |
| } |
| } |
| |
| if (switch_bindings != NULL) |
| ++switch_bindings->stmt_exprs; |
| } |
| |
| /* Adjust the bindings for the end of a statement expression. */ |
| |
| void |
| c_bindings_end_stmt_expr (struct c_spot_bindings *switch_bindings) |
| { |
| struct c_scope *scope; |
| |
| for (scope = current_scope; scope != NULL; scope = scope->outer) |
| { |
| struct c_binding *b; |
| |
| if (!scope->has_label_bindings) |
| 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_EACH_VEC_SAFE_ELT (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) |
| { |
| --switch_bindings->stmt_exprs; |
| gcc_assert (switch_bindings->stmt_exprs >= 0); |
| } |
| } |
| |
| /* Push a definition or a declaration of struct, union or enum tag "name". |
| "type" should be the type node. |
| We assume that the tag "name" is not already defined, and has a location |
| of LOC. |
| |
| Note that the definition may really be just a forward reference. |
| In that case, the TYPE_SIZE will be zero. */ |
| |
| static void |
| pushtag (location_t loc, tree name, tree type) |
| { |
| /* Record the identifier as the type's name if it has none. */ |
| if (name && !TYPE_NAME (type)) |
| TYPE_NAME (type) = name; |
| bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false, loc); |
| |
| /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the |
| tagged type we just added to the current scope. This fake |
| NULL-named TYPE_DECL node helps dwarfout.c to know when it needs |
| to output a representation of a tagged type, and it also gives |
| us a convenient place to record the "scope start" address for the |
| tagged type. */ |
| |
| TYPE_STUB_DECL (type) = pushdecl (build_decl (loc, |
| TYPE_DECL, NULL_TREE, type)); |
| |
| /* An approximation for now, so we can tell this is a function-scope tag. |
| This will be updated in pop_scope. */ |
| TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type)); |
| |
| if (warn_cxx_compat && name != NULL_TREE) |
| { |
| struct c_binding *b = I_SYMBOL_BINDING (name); |
| |
| if (b != NULL |
| && b->decl != NULL_TREE |
| && TREE_CODE (b->decl) == TYPE_DECL |
| && (B_IN_CURRENT_SCOPE (b) |
| || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b))) |
| && (TYPE_MAIN_VARIANT (TREE_TYPE (b->decl)) |
| != TYPE_MAIN_VARIANT (type))) |
| { |
| auto_diagnostic_group d; |
| if (warning_at (loc, OPT_Wc___compat, |
| ("using %qD as both a typedef and a tag is " |
| "invalid in C++"), b->decl) |
| && b->locus != UNKNOWN_LOCATION) |
| inform (b->locus, "originally defined here"); |
| } |
| } |
| } |
| |
| /* An exported interface to pushtag. This is used by the gdb plugin's |
| binding oracle to introduce a new tag binding. */ |
| |
| void |
| c_pushtag (location_t loc, tree name, tree type) |
| { |
| pushtag (loc, name, type); |
| } |
| |
| /* An exported interface to bind a declaration. LOC is the location |
| to use. DECL is the declaration to bind. The decl's name is used |
| to determine how it is bound. If DECL is a VAR_DECL, then |
| IS_GLOBAL determines whether the decl is put into the global (file |
| and external) scope or the current function's scope; if DECL is not |
| a VAR_DECL then it is always put into the file scope. */ |
| |
| void |
| c_bind (location_t loc, tree decl, bool is_global) |
| { |
| struct c_scope *scope; |
| bool nested = false; |
| |
| if (!VAR_P (decl) || current_function_scope == NULL) |
| { |
| /* Types and functions are always considered to be global. */ |
| scope = file_scope; |
| DECL_EXTERNAL (decl) = 1; |
| TREE_PUBLIC (decl) = 1; |
| } |
| else if (is_global) |
| { |
| /* Also bind it into the external scope. */ |
| bind (DECL_NAME (decl), decl, external_scope, true, false, loc); |
| nested = true; |
| scope = file_scope; |
| DECL_EXTERNAL (decl) = 1; |
| TREE_PUBLIC (decl) = 1; |
| } |
| else |
| { |
| DECL_CONTEXT (decl) = current_function_decl; |
| TREE_PUBLIC (decl) = 0; |
| scope = current_function_scope; |
| } |
| |
| bind (DECL_NAME (decl), decl, scope, false, nested, loc); |
| } |
| |
| |
| /* Stores the first FILE*, const struct tm* etc. argument type (whatever |
| it is) seen in a declaration of a file I/O etc. built-in, corresponding |
| to the builtin_structptr_types array. Subsequent declarations of such |
| built-ins are expected to refer to it rather than to fileptr_type_node, |
| etc. which is just void* (or to any other type). |
| Used only by match_builtin_function_types. */ |
| |
| static const unsigned builtin_structptr_type_count |
| = sizeof builtin_structptr_types / sizeof builtin_structptr_types[0]; |
| |
| static GTY(()) tree last_structptr_types[builtin_structptr_type_count]; |
| |
| /* Returns true if types T1 and T2 representing return types or types |
| of function arguments are close enough to be considered interchangeable |
| in redeclarations of built-in functions. */ |
| |
| static bool |
| types_close_enough_to_match (tree t1, tree t2) |
| { |
| return (TYPE_MODE (t1) == TYPE_MODE (t2) |
| && POINTER_TYPE_P (t1) == POINTER_TYPE_P (t2) |
| && FUNCTION_POINTER_TYPE_P (t1) == FUNCTION_POINTER_TYPE_P (t2)); |
| } |
| |
| /* Subroutine of compare_decls. Allow harmless mismatches in return |
| and argument types provided that the type modes match. Set *STRICT |
| and *ARGNO to the expected argument type and number in case of |
| an argument type mismatch or null and zero otherwise. Return |
| a unified type given a suitable match, and 0 otherwise. */ |
| |
| static tree |
| match_builtin_function_types (tree newtype, tree oldtype, |
| tree *strict, unsigned *argno) |
| { |
| *argno = 0; |
| *strict = NULL_TREE; |
| |
| /* Accept the return type of the new declaration if it has the same |
| mode and if they're both pointers or if neither is. */ |
| tree oldrettype = TREE_TYPE (oldtype); |
| tree newrettype = TREE_TYPE (newtype); |
| |
| if (!types_close_enough_to_match (oldrettype, newrettype)) |
| return NULL_TREE; |
| |
| /* Check that the return types are compatible but don't fail if they |
| are not (e.g., int vs long in ILP32) and just let the caller know. */ |
| if (!comptypes (TYPE_MAIN_VARIANT (oldrettype), |
| TYPE_MAIN_VARIANT (newrettype))) |
| *strict = oldrettype; |
| |
| tree oldargs = TYPE_ARG_TYPES (oldtype); |
| tree newargs = TYPE_ARG_TYPES (newtype); |
| tree tryargs = newargs; |
| |
| const unsigned nlst |
| = sizeof last_structptr_types / sizeof last_structptr_types[0]; |
| const unsigned nbst |
| = sizeof builtin_structptr_types / sizeof builtin_structptr_types[0]; |
| |
| gcc_checking_assert (nlst == nbst); |
| |
| for (unsigned i = 1; oldargs || newargs; ++i) |
| { |
| if (!oldargs |
| || !newargs |
| || !TREE_VALUE (oldargs) |
| || !TREE_VALUE (newargs)) |
| return NULL_TREE; |
| |
| tree oldtype = TYPE_MAIN_VARIANT (TREE_VALUE (oldargs)); |
| tree newtype = TREE_VALUE (newargs); |
| if (newtype == error_mark_node) |
| return NULL_TREE; |
| newtype = TYPE_MAIN_VARIANT (newtype); |
| |
| if (!types_close_enough_to_match (oldtype, newtype)) |
| return NULL_TREE; |
| |
| unsigned j = nbst; |
| if (POINTER_TYPE_P (oldtype)) |
| /* Iterate over well-known struct types like FILE (whose types |
| aren't known to us) and compare the pointer to each to |
| the pointer argument. */ |
| for (j = 0; j < nbst; ++j) |
| { |
| if (TREE_VALUE (oldargs) != builtin_structptr_types[j].node) |
| continue; |
| /* Store the first FILE* etc. argument type (whatever it is), and |
| expect any subsequent declarations of file I/O etc. built-ins |
| to refer to it rather than to fileptr_type_node etc. which is |
| just void* (or const void*). */ |
| if (last_structptr_types[j]) |
| { |
| if (!comptypes (last_structptr_types[j], newtype)) |
| { |
| *argno = i; |
| *strict = last_structptr_types[j]; |
| } |
| } |
| else |
| last_structptr_types[j] = newtype; |
| break; |
| } |
| |
| if (j == nbst && !comptypes (oldtype, newtype)) |
| { |
| if (POINTER_TYPE_P (oldtype)) |
| { |
| /* For incompatible pointers, only reject differences in |
| the unqualified variants of the referenced types but |
| consider differences in qualifiers as benign (report |
| those to caller via *STRICT below). */ |
| tree oldref = TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)); |
| tree newref = TYPE_MAIN_VARIANT (TREE_TYPE (newtype)); |
| if (!comptypes (oldref, newref)) |
| return NULL_TREE; |
| } |
| |
| if (!*strict) |
| { |
| *argno = i; |
| *strict = oldtype; |
| } |
| } |
| |
| oldargs = TREE_CHAIN (oldargs); |
| newargs = TREE_CHAIN (newargs); |
| } |
| |
| tree trytype = build_function_type (newrettype, tryargs); |
| |
| /* Allow declaration to change transaction_safe attribute. */ |
| tree oldattrs = TYPE_ATTRIBUTES (oldtype); |
| tree oldtsafe = lookup_attribute ("transaction_safe", oldattrs); |
| tree newattrs = TYPE_ATTRIBUTES (newtype); |
| tree newtsafe = lookup_attribute ("transaction_safe", newattrs); |
| if (oldtsafe && !newtsafe) |
| oldattrs = remove_attribute ("transaction_safe", oldattrs); |
| else if (newtsafe && !oldtsafe) |
| oldattrs = tree_cons (get_identifier ("transaction_safe"), |
| NULL_TREE, oldattrs); |
| |
| return build_type_attribute_variant (trytype, oldattrs); |
| } |
| |
| /* Subroutine of diagnose_mismatched_decls. Check for function type |
| mismatch involving an empty arglist vs a nonempty one and give clearer |
| diagnostics. */ |
| static void |
| diagnose_arglist_conflict (tree newdecl, tree olddecl, |
| tree newtype, tree oldtype) |
| { |
| tree t; |
| |
| if (TREE_CODE (olddecl) != FUNCTION_DECL |
| || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype)) |
| || !((!prototype_p (oldtype) && DECL_INITIAL (olddecl) == NULL_TREE) |
| || (!prototype_p (newtype) && DECL_INITIAL (newdecl) == NULL_TREE))) |
| return; |
| |
| t = TYPE_ARG_TYPES (oldtype); |
| if (t == NULL_TREE) |
| t = TYPE_ARG_TYPES (newtype); |
| for (; t; t = TREE_CHAIN (t)) |
| { |
| tree type = TREE_VALUE (t); |
| |
| if (TREE_CHAIN (t) == NULL_TREE |
| && TYPE_MAIN_VARIANT (type) != void_type_node) |
| { |
| inform (input_location, "a parameter list with an ellipsis " |
| "cannot match an empty parameter name list declaration"); |
| break; |
| } |
| |
| if (c_type_promotes_to (type) != type) |
| { |
| inform (input_location, "an argument type that has a default " |
| "promotion cannot match an empty parameter name list " |
| "declaration"); |
| break; |
| } |
| } |
| } |
| |
| /* Another subroutine of diagnose_mismatched_decls. OLDDECL is an |
| old-style function definition, NEWDECL is a prototype declaration. |
| Diagnose inconsistencies in the argument list. Returns TRUE if |
| the prototype is compatible, FALSE if not. */ |
| static bool |
| validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype) |
| { |
| tree newargs, oldargs; |
| int i; |
| |
| #define END_OF_ARGLIST(t) ((t) == void_type_node) |
| |
| oldargs = TYPE_ACTUAL_ARG_TYPES (oldtype); |
| newargs = TYPE_ARG_TYPES (newtype); |
| i = 1; |
| |
| for (;;) |
| { |
| tree oldargtype = TREE_VALUE (oldargs); |
| tree newargtype = TREE_VALUE (newargs); |
| |
| if (oldargtype == error_mark_node || newargtype == error_mark_node) |
| return false; |
| |
| oldargtype = (TYPE_ATOMIC (oldargtype) |
| ? c_build_qualified_type (TYPE_MAIN_VARIANT (oldargtype), |
| TYPE_QUAL_ATOMIC) |
| : TYPE_MAIN_VARIANT (oldargtype)); |
| newargtype = (TYPE_ATOMIC (newargtype) |
| ? c_build_qualified_type (TYPE_MAIN_VARIANT (newargtype), |
| TYPE_QUAL_ATOMIC) |
| : TYPE_MAIN_VARIANT (newargtype)); |
| |
| if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype)) |
| break; |
| |
| /* Reaching the end of just one list means the two decls don't |
| agree on the number of arguments. */ |
| if (END_OF_ARGLIST (oldargtype)) |
| { |
| error ("prototype for %q+D declares more arguments " |
| "than previous old-style definition", newdecl); |
| return false; |
| } |
| else if (END_OF_ARGLIST (newargtype)) |
| { |
| error ("prototype for %q+D declares fewer arguments " |
| "than previous old-style definition", newdecl); |
| return false; |
| } |
| |
| /* Type for passing arg must be consistent with that declared |
| for the arg. */ |
| else if (!comptypes (oldargtype, newargtype)) |
| { |
| error ("prototype for %q+D declares argument %d" |
| " with incompatible type", |
| newdecl, i); |
| return false; |
| } |
| |
| oldargs = TREE_CHAIN (oldargs); |
| newargs = TREE_CHAIN (newargs); |
| i++; |
| } |
| |
| /* If we get here, no errors were found, but do issue a warning |
| for this poor-style construct. */ |
| warning (0, "prototype for %q+D follows non-prototype definition", |
| newdecl); |
| return true; |
| #undef END_OF_ARGLIST |
| } |
| |
| /* Subroutine of diagnose_mismatched_decls. Report the location of DECL, |
| first in a pair of mismatched declarations, using the diagnostic |
| function DIAG. */ |
| static void |
| locate_old_decl (tree decl) |
| { |
| if (TREE_CODE (decl) == FUNCTION_DECL |
| && fndecl_built_in_p (decl) |
| && !C_DECL_DECLARED_BUILTIN (decl)) |
| ; |
| else if (DECL_INITIAL (decl)) |
| inform (input_location, |
| "previous definition of %q+D with type %qT", |
| decl, TREE_TYPE (decl)); |
| else if (C_DECL_IMPLICIT (decl)) |
| inform (input_location, |
| "previous implicit declaration of %q+D with type %qT", |
| decl, TREE_TYPE (decl)); |
| else |
| inform (input_location, |
| "previous declaration of %q+D with type %qT", |
| decl, TREE_TYPE (decl)); |
| } |
| |
| /* Subroutine of duplicate_decls. Compare NEWDECL to OLDDECL. |
| Returns true if the caller should proceed to merge the two, false |
| if OLDDECL should simply be discarded. As a side effect, issues |
| all necessary diagnostics for invalid or poor-style combinations. |
| If it returns true, writes the types of NEWDECL and OLDDECL to |
| *NEWTYPEP and *OLDTYPEP - these may have been adjusted from |
| TREE_TYPE (NEWDECL, OLDDECL) respectively. */ |
| |
| static bool |
| diagnose_mismatched_decls (tree newdecl, tree olddecl, |
| tree *newtypep, tree *oldtypep) |
| { |
| tree newtype, oldtype; |
| bool retval = true; |
| |
| #define DECL_EXTERN_INLINE(DECL) (DECL_DECLARED_INLINE_P (DECL) \ |
| && DECL_EXTERNAL (DECL)) |
| |
| /* If we have error_mark_node for either decl or type, just discard |
| the previous decl - we're in an error cascade already. */ |
| if (olddecl == error_mark_node || newdecl == error_mark_node) |
| return false; |
| *oldtypep = oldtype = TREE_TYPE (olddecl); |
| *newtypep = newtype = TREE_TYPE (newdecl); |
| if (oldtype == error_mark_node || newtype == error_mark_node) |
| return false; |
| |
| /* Two different categories of symbol altogether. This is an error |
| unless OLDDECL is a builtin. OLDDECL will be discarded in any case. */ |
| if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) |
| { |
| if (!(TREE_CODE (olddecl) == FUNCTION_DECL |
| && fndecl_built_in_p (olddecl) |
| && !C_DECL_DECLARED_BUILTIN (olddecl))) |
| { |
| auto_diagnostic_group d; |
| error ("%q+D redeclared as different kind of symbol", newdecl); |
| locate_old_decl (olddecl); |
| } |
| else if (TREE_PUBLIC (newdecl)) |
| warning (OPT_Wbuiltin_declaration_mismatch, |
| "built-in function %q+D declared as non-function", |
| newdecl); |
| else |
| warning (OPT_Wshadow, "declaration of %q+D shadows " |
| "a built-in function", newdecl); |
| return false; |
| } |
| |
| /* Enumerators have no linkage, so may only be declared once in a |
| given scope. */ |
| if (TREE_CODE (olddecl) == CONST_DECL) |
| { |
| auto_diagnostic_group d; |
| error ("redeclaration of enumerator %q+D", newdecl); |
| locate_old_decl (olddecl); |
| return false; |
| } |
| |
| bool pedwarned = false; |
| bool warned = false; |
| auto_diagnostic_group d; |
| |
| if (!comptypes (oldtype, newtype)) |
| { |
| if (TREE_CODE (olddecl) == FUNCTION_DECL |
| && fndecl_built_in_p (olddecl, BUILT_IN_NORMAL) |
| && !C_DECL_DECLARED_BUILTIN (olddecl)) |
| { |
| /* Accept "harmless" mismatches in function types such |
| as missing qualifiers or int vs long when they're the same |
| size. However, diagnose return and argument types that are |
| incompatible according to language rules. */ |
| tree mismatch_expect; |
| unsigned mismatch_argno; |
| |
| tree trytype = match_builtin_function_types (newtype, oldtype, |
| &mismatch_expect, |
| &mismatch_argno); |
| |
| if (trytype && comptypes (newtype, trytype)) |
| *oldtypep = oldtype = trytype; |
| else |
| { |
| /* If types don't match for a built-in, throw away the |
| built-in. No point in calling locate_old_decl here, it |
| won't print anything. */ |
| const char *header = header_for_builtin_fn (olddecl); |
| location_t loc = DECL_SOURCE_LOCATION (newdecl); |
| if (warning_at (loc, OPT_Wbuiltin_declaration_mismatch, |
| "conflicting types for built-in function %q+D; " |
| "expected %qT", |
| newdecl, oldtype) |
| && header) |
| { |
| /* Suggest the right header to include as the preferred |
| solution rather than the spelling of the declaration. */ |
| rich_location richloc (line_table, loc); |
| maybe_add_include_fixit (&richloc, header, true); |
| inform (&richloc, |
| "%qD is declared in header %qs", olddecl, header); |
| } |
| return false; |
| } |
| |
| if (mismatch_expect && extra_warnings) |
| { |
| location_t newloc = DECL_SOURCE_LOCATION (newdecl); |
| bool warned = false; |
| if (mismatch_argno) |
| warned = warning_at (newloc, OPT_Wbuiltin_declaration_mismatch, |
| "mismatch in argument %u type of built-in " |
| "function %qD; expected %qT", |
| mismatch_argno, newdecl, mismatch_expect); |
| else |
| warned = warning_at (newloc, OPT_Wbuiltin_declaration_mismatch, |
| "mismatch in return type of built-in " |
| "function %qD; expected %qT", |
| newdecl, mismatch_expect); |
| const char *header = header_for_builtin_fn (olddecl); |
| if (warned && header) |
| { |
| rich_location richloc (line_table, newloc); |
| maybe_add_include_fixit (&richloc, header, true); |
| inform (&richloc, |
| "%qD is declared in header %qs", olddecl, header); |
| } |
| } |
| } |
| else if (TREE_CODE (olddecl) == FUNCTION_DECL |
| && DECL_IS_UNDECLARED_BUILTIN (olddecl)) |
| { |
| /* A conflicting function declaration for a predeclared |
| function that isn't actually built in. Objective C uses |
| these. The new declaration silently overrides everything |
| but the volatility (i.e. noreturn) indication. See also |
| below. FIXME: Make Objective C use normal builtins. */ |
| TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); |
| return false; |
| } |
| /* Permit void foo (...) to match int foo (...) if the latter is |
| the definition and implicit int was used. See |
| c-torture/compile/920625-2.c. */ |
| else if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) |
| && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node |
| && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node |
| && C_FUNCTION_IMPLICIT_INT (newdecl) && !DECL_INITIAL (olddecl)) |
| { |
| pedwarned = pedwarn (input_location, 0, |
| "conflicting types for %q+D", newdecl); |
| /* Make sure we keep void as the return type. */ |
| TREE_TYPE (newdecl) = *newtypep = newtype = oldtype; |
| C_FUNCTION_IMPLICIT_INT (newdecl) = 0; |
| } |
| /* Permit void foo (...) to match an earlier call to foo (...) with |
| no declared type (thus, implicitly int). */ |
| else if (TREE_CODE (newdecl) == FUNCTION_DECL |
| && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == void_type_node |
| && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == integer_type_node |
| && C_DECL_IMPLICIT (olddecl) && !DECL_INITIAL (olddecl)) |
| { |
| pedwarned = pedwarn (input_location, 0, |
| "conflicting types for %q+D; have %qT", |
| newdecl, newtype); |
| /* Make sure we keep void as the return type. */ |
| TREE_TYPE (olddecl) = *oldtypep = oldtype = newtype; |
| } |
| else |
| { |
| int new_quals = TYPE_QUALS (newtype); |
| int old_quals = TYPE_QUALS (oldtype); |
| |
| if (new_quals != old_quals) |
| { |
| addr_space_t new_addr = DECODE_QUAL_ADDR_SPACE (new_quals); |
| addr_space_t old_addr = DECODE_QUAL_ADDR_SPACE (old_quals); |
| if (new_addr != old_addr) |
| { |
| if (ADDR_SPACE_GENERIC_P (new_addr)) |
| error ("conflicting named address spaces (generic vs %s) " |
| "for %q+D", |
| c_addr_space_name (old_addr), newdecl); |
| else if (ADDR_SPACE_GENERIC_P (old_addr)) |
| error ("conflicting named address spaces (%s vs generic) " |
| "for %q+D", |
| c_addr_space_name (new_addr), newdecl); |
| else |
| error ("conflicting named address spaces (%s vs %s) " |
| "for %q+D", |
| c_addr_space_name (new_addr), |
| c_addr_space_name (old_addr), |
| newdecl); |
| } |
| |
| if (CLEAR_QUAL_ADDR_SPACE (new_quals) |
| != CLEAR_QUAL_ADDR_SPACE (old_quals)) |
| error ("conflicting type qualifiers for %q+D", newdecl); |
| } |
| else |
| error ("conflicting types for %q+D; have %qT", newdecl, newtype); |
| diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype); |
| locate_old_decl (olddecl); |
| return false; |
| } |
| } |
| |
| /* 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.) This |
| is allowed for C11 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) |
| || warning_suppressed_p (newdecl, OPT_Wpedantic) |
| || warning_suppressed_p (olddecl, OPT_Wpedantic)) |
| return true; /* Allow OLDDECL to continue in use. */ |
| |
| if (variably_modified_type_p (newtype, NULL)) |
| { |
| error ("redefinition of typedef %q+D with variably modified type", |
| newdecl); |
| locate_old_decl (olddecl); |
| } |
| else if (pedwarn_c99 (input_location, OPT_Wpedantic, |
| "redefinition of typedef %q+D", newdecl)) |
| locate_old_decl (olddecl); |
| |
| return true; |
| } |
| |
| /* Function declarations can either be 'static' or 'extern' (no |
| qualifier is equivalent to 'extern' - C99 6.2.2p5) and therefore |
| can never conflict with each other on account of linkage |
| (6.2.2p4). Multiple definitions are not allowed (6.9p3,5) but |
| gnu89 mode permits two definitions if one is 'extern inline' and |
| one is not. The non- extern-inline definition supersedes the |
| extern-inline definition. */ |
| |
| else if (TREE_CODE (newdecl) == FUNCTION_DECL) |
| { |
| /* If you declare a built-in function name as static, or |
| define the built-in with an old-style definition (so we |
| can't validate the argument list) the built-in definition is |
| overridden, but optionally warn this was a bad choice of name. */ |
| if (fndecl_built_in_p (olddecl) |
| && !C_DECL_DECLARED_BUILTIN (olddecl)) |
| { |
| if (!TREE_PUBLIC (newdecl) |
| || (DECL_INITIAL (newdecl) |
| && !prototype_p (TREE_TYPE (newdecl)))) |
| { |
| warning_at (DECL_SOURCE_LOCATION (newdecl), |
| OPT_Wshadow, "declaration of %qD shadows " |
| "a built-in function", newdecl); |
| /* Discard the old built-in function. */ |
| return false; |
| } |
| |
| if (!prototype_p (TREE_TYPE (newdecl))) |
| { |
| /* Set for built-ins that take no arguments. */ |
| bool func_void_args = false; |
| if (tree at = TYPE_ARG_TYPES (oldtype)) |
| func_void_args = VOID_TYPE_P (TREE_VALUE (at)); |
| |
| if (extra_warnings && !func_void_args) |
| warning_at (DECL_SOURCE_LOCATION (newdecl), |
| OPT_Wbuiltin_declaration_mismatch, |
| "declaration of built-in function %qD without " |
| "a prototype; expected %qT", |
| newdecl, TREE_TYPE (olddecl)); |
| } |
| } |
| |
| if (DECL_INITIAL (newdecl)) |
| { |
| if (DECL_INITIAL (olddecl)) |
| { |
| /* If both decls are in the same TU and the new declaration |
| isn't overriding an extern inline reject the new decl. |
| In c99, no overriding is allowed in the same translation |
| unit. */ |
| if ((!DECL_EXTERN_INLINE (olddecl) |
| || DECL_EXTERN_INLINE (newdecl) |
| || (!flag_gnu89_inline |
| && (!DECL_DECLARED_INLINE_P (olddecl) |
| || !lookup_attribute ("gnu_inline", |
| DECL_ATTRIBUTES (olddecl))) |
| && (!DECL_DECLARED_INLINE_P (newdecl) |
| || !lookup_attribute ("gnu_inline", |
| DECL_ATTRIBUTES (newdecl)))) |
| ) |
| && same_translation_unit_p (newdecl, olddecl)) |
| { |
| auto_diagnostic_group d; |
| error ("redefinition of %q+D", newdecl); |
| locate_old_decl (olddecl); |
| return false; |
| } |
| } |
| } |
| /* If we have a prototype after an old-style function definition, |
| the argument types must be checked specially. */ |
| else if (DECL_INITIAL (olddecl) |
| && !prototype_p (oldtype) && prototype_p (newtype) |
| && TYPE_ACTUAL_ARG_TYPES (oldtype)) |
| { |
| auto_diagnostic_group d; |
| if (!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 |
| scope followed by a non-static declaration/definition at file |
| scope. Static followed by non-static at the same scope is |
| not undefined behavior, and is the most convenient way to get |
| some effects (see e.g. what unwind-dw2-fde-glibc.c does to |
| the definition of _Unwind_Find_FDE in unwind-dw2-fde.c), but |
| we do diagnose it if -Wtraditional. */ |
| if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl)) |
| { |
| /* Two exceptions to the rule. If olddecl is an extern |
| inline, or a predeclared function that isn't actually |
| built in, newdecl silently overrides olddecl. The latter |
| occur only in Objective C; see also above. (FIXME: Make |
| Objective C use normal builtins.) */ |
| if (!DECL_IS_UNDECLARED_BUILTIN (olddecl) |
| && !DECL_EXTERN_INLINE (olddecl)) |
| { |
| auto_diagnostic_group d; |
| error ("static declaration of %q+D follows " |
| "non-static declaration", newdecl); |
| locate_old_decl (olddecl); |
| } |
| return false; |
| } |
| else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl)) |
| { |
| if (DECL_CONTEXT (olddecl)) |
| { |
| auto_diagnostic_group d; |
| error ("non-static declaration of %q+D follows " |
| "static declaration", newdecl); |
| locate_old_decl (olddecl); |
| return false; |
| } |
| else if (warn_traditional) |
| { |
| warned |= warning (OPT_Wtraditional, |
| "non-static declaration of %q+D " |
| "follows static declaration", newdecl); |
| } |
| } |
| |
| /* Make sure gnu_inline attribute is either not present, or |
| present on all inline decls. */ |
| if (DECL_DECLARED_INLINE_P (olddecl) |
| && DECL_DECLARED_INLINE_P (newdecl)) |
| { |
| bool newa = lookup_attribute ("gnu_inline", |
| DECL_ATTRIBUTES (newdecl)) != NULL; |
| bool olda = lookup_attribute ("gnu_inline", |
| DECL_ATTRIBUTES (olddecl)) != NULL; |
| if (newa != olda) |
| { |
| auto_diagnostic_group d; |
| error_at (input_location, "%<gnu_inline%> attribute present on %q+D", |
| newa ? newdecl : olddecl); |
| error_at (DECL_SOURCE_LOCATION (newa ? olddecl : newdecl), |
| "but not here"); |
| } |
| } |
| } |
| else if (VAR_P (newdecl)) |
| { |
| /* Only variables can be thread-local, and all declarations must |
| agree on this property. */ |
| if (C_DECL_THREADPRIVATE_P (olddecl) && !DECL_THREAD_LOCAL_P (newdecl)) |
| { |
| /* Nothing to check. Since OLDDECL is marked threadprivate |
| and NEWDECL does not have a thread-local attribute, we |
| will merge the threadprivate attribute into NEWDECL. */ |
| ; |
| } |
| else if (DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)) |
| { |
| auto_diagnostic_group d; |
| if (DECL_THREAD_LOCAL_P (newdecl)) |
| error ("thread-local declaration of %q+D follows " |
| "non-thread-local declaration", newdecl); |
| else |
| error ("non-thread-local declaration of %q+D follows " |
| "thread-local declaration", newdecl); |
| |
| locate_old_decl (olddecl); |
| return false; |
| } |
| |
| /* Multiple initialized definitions are not allowed (6.9p3,5). */ |
| if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl)) |
| { |
| auto_diagnostic_group d; |
| error ("redefinition of %q+D", newdecl); |
| locate_old_decl (olddecl); |
| return false; |
| } |
| |
| /* Objects declared at file scope: if the first declaration had |
| external linkage (even if it was an external reference) the |
| second must have external linkage as well, or the behavior is |
| undefined. If the first declaration had internal linkage, then |
| the second must too, or else be an external reference (in which |
| case the composite declaration still has internal linkage). |
| As for function declarations, we warn about the static-then- |
| extern case only for -Wtraditional. See generally 6.2.2p3-5,7. */ |
| if (DECL_FILE_SCOPE_P (newdecl) |
| && TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl)) |
| { |
| if (DECL_EXTERNAL (newdecl)) |
| { |
| if (!DECL_FILE_SCOPE_P (olddecl)) |
| { |
| auto_diagnostic_group d; |
| error ("extern declaration of %q+D follows " |
| "declaration with no linkage", newdecl); |
| locate_old_decl (olddecl); |
| return false; |
| } |
| else if (warn_traditional) |
| { |
| warned |= warning (OPT_Wtraditional, |
| "non-static declaration of %q+D " |
| "follows static declaration", newdecl); |
| } |
| } |
| else |
| { |
| auto_diagnostic_group d; |
| if (TREE_PUBLIC (newdecl)) |
| error ("non-static declaration of %q+D follows " |
| "static declaration", newdecl); |
| else |
| error ("static declaration of %q+D follows " |
| "non-static declaration", newdecl); |
| |
| locate_old_decl (olddecl); |
| return false; |
| } |
| } |
| /* Two objects with the same name declared at the same block |
| scope must both be external references (6.7p3). */ |
| else if (!DECL_FILE_SCOPE_P (newdecl)) |
| { |
| if (DECL_EXTERNAL (newdecl)) |
| { |
| /* Extern with initializer at block scope, which will |
| already have received an error. */ |
| } |
| else if (DECL_EXTERNAL (olddecl)) |
| { |
| auto_diagnostic_group d; |
| error ("declaration of %q+D with no linkage follows " |
| "extern declaration", newdecl); |
| locate_old_decl (olddecl); |
| } |
| else |
| { |
| auto_diagnostic_group d; |
| error ("redeclaration of %q+D with no linkage", newdecl); |
| locate_old_decl (olddecl); |
| } |
| |
| return false; |
| } |
| |
| /* C++ does not permit a decl to appear multiple times at file |
| scope. */ |
| if (warn_cxx_compat |
| && DECL_FILE_SCOPE_P (newdecl) |
| && !DECL_EXTERNAL (newdecl) |
| && !DECL_EXTERNAL (olddecl)) |
| warned |= warning_at (DECL_SOURCE_LOCATION (newdecl), |
| OPT_Wc___compat, |
| ("duplicate declaration of %qD is " |
| "invalid in C++"), |
| newdecl); |
| } |
| |
| /* warnings */ |
| /* All decls must agree on a visibility. */ |
| if (CODE_CONTAINS_STRUCT (TREE_CODE (newdecl), TS_DECL_WITH_VIS) |
| && DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl) |
| && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl)) |
| { |
| warned |= warning (0, "redeclaration of %q+D with different visibility " |
| "(old visibility preserved)", newdecl); |
| } |
| |
| if (TREE_CODE (newdecl) == FUNCTION_DECL) |
| warned |= diagnose_mismatched_attributes (olddecl, newdecl); |
| else /* PARM_DECL, VAR_DECL */ |
| { |
| /* Redeclaration of a parameter is a constraint violation (this is |
| not explicitly stated, but follows from C99 6.7p3 [no more than |
| one declaration of the same identifier with no linkage in the |
| same scope, except type tags] and 6.2.2p6 [parameters have no |
| linkage]). We must check for a forward parameter declaration, |
| indicated by TREE_ASM_WRITTEN on the old declaration - this is |
| an extension, the mandatory diagnostic for which is handled by |
| mark_forward_parm_decls. */ |
| |
| if (TREE_CODE (newdecl) == PARM_DECL |
| && (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl))) |
| { |
| auto_diagnostic_group d; |
| error ("redefinition of parameter %q+D", newdecl); |
| locate_old_decl (olddecl); |
| return false; |
| } |
| } |
| |
| /* Optional warning for completely redundant decls. */ |
| if (!warned && !pedwarned |
| && warn_redundant_decls |
| /* Don't warn about a function declaration followed by a |
| definition. */ |
| && !(TREE_CODE (newdecl) == FUNCTION_DECL |
| && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl)) |
| /* Don't warn about redundant redeclarations of builtins. */ |
| && !(TREE_CODE (newdecl) == FUNCTION_DECL |
| && !fndecl_built_in_p (newdecl) |
| && fndecl_built_in_p (olddecl) |
| && !C_DECL_DECLARED_BUILTIN (olddecl)) |
| /* Don't warn about an extern followed by a definition. */ |
| && !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl)) |
| /* Don't warn about forward parameter decls. */ |
| && !(TREE_CODE (newdecl) == PARM_DECL |
| && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl)) |
| /* Don't warn about a variable definition following a declaration. */ |
| && !(VAR_P (newdecl) |
| && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))) |
| { |
| warned = warning (OPT_Wredundant_decls, "redundant redeclaration of %q+D", |
| newdecl); |
| } |
| |
| /* Report location of previous decl/defn. */ |
| if (warned || pedwarned) |
| locate_old_decl (olddecl); |
| |
| #undef DECL_EXTERN_INLINE |
| |
| return retval; |
| } |
| |
| /* Subroutine of duplicate_decls. NEWDECL has been found to be |
| consistent with OLDDECL, but carries new information. Merge the |
| new information into OLDDECL. This function issues no |
| diagnostics. */ |
| |
| static void |
| merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) |
| { |
| bool new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL |
| && DECL_INITIAL (newdecl) != NULL_TREE); |
| bool new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL |
| && prototype_p (TREE_TYPE (newdecl))); |
| bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL |
| && prototype_p (TREE_TYPE (olddecl))); |
| |
| /* For real parm decl following a forward decl, rechain the old decl |
| in its new location and clear TREE_ASM_WRITTEN (it's not a |
| forward decl anymore). */ |
| if (TREE_CODE (newdecl) == PARM_DECL |
| && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl)) |
| { |
| struct c_binding *b, **here; |
| |
| for (here = ¤t_scope->bindings; *here; here = &(*here)->prev) |
| if ((*here)->decl == olddecl) |
| goto found; |
| gcc_unreachable (); |
| |
| found: |
| b = *here; |
| *here = b->prev; |
| b->prev = current_scope->bindings; |
| current_scope->bindings = b; |
| |
| TREE_ASM_WRITTEN (olddecl) = 0; |
| } |
| |
| DECL_ATTRIBUTES (newdecl) |
| = targetm.merge_decl_attributes (olddecl, newdecl); |
| |
| /* For typedefs use the old type, as the new type's DECL_NAME points |
| at newdecl, which will be ggc_freed. */ |
| if (TREE_CODE (newdecl) == TYPE_DECL) |
| { |
| /* But NEWTYPE might have an attribute, honor that. */ |
| tree tem = newtype; |
| newtype = oldtype; |
| |
| if (TYPE_USER_ALIGN (tem)) |
| { |
| if (TYPE_ALIGN (tem) > TYPE_ALIGN (newtype)) |
| SET_TYPE_ALIGN (newtype, TYPE_ALIGN (tem)); |
| TYPE_USER_ALIGN (newtype) = true; |
| } |
| |
| /* And remove the new type from the variants list. */ |
| if (TYPE_NAME (TREE_TYPE (newdecl)) == newdecl) |
| { |
| tree remove = TREE_TYPE (newdecl); |
| if (TYPE_MAIN_VARIANT (remove) == remove) |
| { |
| gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE); |
| /* If remove is the main variant, no need to remove that |
| from the list. One of the DECL_ORIGINAL_TYPE |
| variants, e.g. created for aligned attribute, might still |
| refer to the newdecl TYPE_DECL though, so remove that one |
| in that case. */ |
| if (DECL_ORIGINAL_TYPE (newdecl) |
| && DECL_ORIGINAL_TYPE (newdecl) != remove) |
| for (tree t = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (newdecl)); |
| t; t = TYPE_MAIN_VARIANT (t)) |
| if (TYPE_NAME (TYPE_NEXT_VARIANT (t)) == newdecl) |
| { |
| TYPE_NEXT_VARIANT (t) |
| = TYPE_NEXT_VARIANT (TYPE_NEXT_VARIANT (t)); |
| break; |
| } |
| } |
| else |
| for (tree t = TYPE_MAIN_VARIANT (remove); ; |
| t = TYPE_NEXT_VARIANT (t)) |
| if (TYPE_NEXT_VARIANT (t) == remove) |
| { |
| TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove); |
| break; |
| } |
| } |
| } |
| |
| /* Merge the data types specified in the two decls. */ |
| TREE_TYPE (newdecl) |
| = TREE_TYPE (olddecl) |
| = composite_type (newtype, oldtype); |
| |
| /* Lay the type out, unless already done. */ |
| if (!comptypes (oldtype, TREE_TYPE (newdecl))) |
| { |
| if (TREE_TYPE (newdecl) != error_mark_node) |
| layout_type (TREE_TYPE (newdecl)); |
| if (TREE_CODE (newdecl) != FUNCTION_DECL |
| && TREE_CODE (newdecl) != TYPE_DECL |
| && TREE_CODE (newdecl) != CONST_DECL) |
| layout_decl (newdecl, 0); |
| } |
| else |
| { |
| /* Since the type is OLDDECL's, make OLDDECL's size go with. */ |
| DECL_SIZE (newdecl) = DECL_SIZE (olddecl); |
| DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl); |
| SET_DECL_MODE (newdecl, DECL_MODE (olddecl)); |
| if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl)) |
| { |
| SET_DECL_ALIGN (newdecl, DECL_ALIGN (olddecl)); |
| DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl); |
| } |
| else if (DECL_ALIGN (olddecl) == DECL_ALIGN (newdecl) |
| && DECL_USER_ALIGN (olddecl) != DECL_USER_ALIGN (newdecl)) |
| DECL_USER_ALIGN (newdecl) = 1; |
| if (DECL_WARN_IF_NOT_ALIGN (olddecl) |
| > DECL_WARN_IF_NOT_ALIGN (newdecl)) |
| SET_DECL_WARN_IF_NOT_ALIGN (newdecl, |
| DECL_WARN_IF_NOT_ALIGN (olddecl)); |
| } |
| |
| /* Keep the old rtl since we can safely use it. */ |
| if (HAS_RTL_P (olddecl)) |
| COPY_DECL_RTL (olddecl, newdecl); |
| |
| /* Merge the type qualifiers. */ |
| if (TREE_READONLY (newdecl)) |
| TREE_READONLY (olddecl) = 1; |
| |
| if (TREE_THIS_VOLATILE (newdecl)) |
| TREE_THIS_VOLATILE (olddecl) = 1; |
| |
| /* Merge deprecatedness. */ |
| if (TREE_DEPRECATED (newdecl)) |
| TREE_DEPRECATED (olddecl) = 1; |
| |
| /* Merge unavailability. */ |
| if (TREE_UNAVAILABLE (newdecl)) |
| TREE_UNAVAILABLE (olddecl) = 1; |
| |
| /* If a decl is in a system header and the other isn't, keep the one on the |
| system header. Otherwise, keep source location of definition rather than |
| declaration and of prototype rather than non-prototype unless that |
| prototype is built-in. */ |
| if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS) |
| && DECL_IN_SYSTEM_HEADER (olddecl) |
| && !DECL_IN_SYSTEM_HEADER (newdecl) ) |
| DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl); |
| else if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS) |
| && DECL_IN_SYSTEM_HEADER (newdecl) |
| && !DECL_IN_SYSTEM_HEADER (olddecl)) |
| DECL_SOURCE_LOCATION (olddecl) = DECL_SOURCE_LOCATION (newdecl); |
| else if ((DECL_INITIAL (newdecl) == NULL_TREE |
| && DECL_INITIAL (olddecl) != NULL_TREE) |
| || (old_is_prototype && !new_is_prototype |
| && !C_DECL_BUILTIN_PROTOTYPE (olddecl))) |
| DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl); |
| |
| /* Merge the initialization information. */ |
| if (DECL_INITIAL (newdecl) == NULL_TREE) |
| DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); |
| |
| /* Merge the threadprivate attribute. */ |
| if (VAR_P (olddecl) && C_DECL_THREADPRIVATE_P (olddecl)) |
| C_DECL_THREADPRIVATE_P (newdecl) = 1; |
| |
| if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS)) |
| { |
| /* Copy the assembler name. |
| Currently, it can only be defined in the prototype. */ |
| COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); |
| |
| /* Use visibility of whichever declaration had it specified */ |
| if (DECL_VISIBILITY_SPECIFIED (olddecl)) |
| { |
| DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl); |
| DECL_VISIBILITY_SPECIFIED (newdecl) = 1; |
| } |
| |
| if (TREE_CODE (newdecl) == FUNCTION_DECL) |
| { |
| DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl); |
| DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); |
| DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl); |
| DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl) |
| |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl); |
| TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); |
| DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl); |
| if (DECL_IS_OPERATOR_NEW_P (olddecl)) |
| DECL_SET_IS_OPERATOR_NEW (newdecl, true); |
| if (DECL_IS_OPERATOR_DELETE_P (olddecl)) |
| DECL_SET_IS_OPERATOR_DELETE (newdecl, true); |
| TREE_READONLY (newdecl) |= TREE_READONLY (olddecl); |
| DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl); |
| DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl); |
| } |
| |
| /* Merge the storage class information. */ |
| merge_weak (newdecl, olddecl); |
| |
| /* For functions, static overrides non-static. */ |
| if (TREE_CODE (newdecl) == FUNCTION_DECL) |
| { |
| TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl); |
| /* This is since we don't automatically |
| copy the attributes of NEWDECL into OLDDECL. */ |
| TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); |
| /* If this clears `static', clear it in the identifier too. */ |
| if (!TREE_PUBLIC (olddecl)) |
| TREE_PUBLIC (DECL_NAME (olddecl)) = 0; |
| } |
| } |
| |
| /* In c99, 'extern' declaration before (or after) 'inline' means this |
| function is not DECL_EXTERNAL, unless 'gnu_inline' attribute |
| is present. */ |
| if (TREE_CODE (newdecl) == FUNCTION_DECL |
| && !flag_gnu89_inline |
| && (DECL_DECLARED_INLINE_P (newdecl) |
| || DECL_DECLARED_INLINE_P (olddecl)) |
| && (!DECL_DECLARED_INLINE_P (newdecl) |
| || !DECL_DECLARED_INLINE_P (olddecl) |
| || !DECL_EXTERNAL (olddecl)) |
| && DECL_EXTERNAL (newdecl) |
| && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (newdecl)) |
| && !current_function_decl) |
| DECL_EXTERNAL (newdecl) = 0; |
| |
| /* An inline definition following a static declaration is not |
| DECL_EXTERNAL. */ |
| if (new_is_definition |
| && (DECL_DECLARED_INLINE_P (newdecl) |
| || DECL_DECLARED_INLINE_P (olddecl)) |
| && !TREE_PUBLIC (olddecl)) |
| DECL_EXTERNAL (newdecl) = 0; |
| |
| if (DECL_EXTERNAL (newdecl)) |
| { |
| TREE_STATIC (newdecl) = TREE_STATIC (olddecl); |
| DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl); |
| |
| /* An extern decl does not override previous storage class. */ |
| TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); |
| if (!DECL_EXTERNAL (newdecl)) |
| { |
| DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl); |
| DECL_COMMON (newdecl) = DECL_COMMON (olddecl); |
| } |
| } |
| else |
| { |
| TREE_STATIC (olddecl) = TREE_STATIC (newdecl); |
| TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); |
| } |
| |
| if (TREE_CODE (newdecl) == FUNCTION_DECL) |
| { |
| /* If we're redefining a function previously defined as extern |
| inline, make sure we emit debug info for the inline before we |
| throw it away, in case it was inlined into a function that |
| hasn't been written out yet. */ |
| if (new_is_definition && DECL_INITIAL (olddecl)) |
| /* The new defn must not be inline. */ |
| DECL_UNINLINABLE (newdecl) = 1; |
| else |
| { |
| /* If either decl says `inline', this fn is inline, unless |
| its definition was passed already. */ |
| if (DECL_DECLARED_INLINE_P (newdecl) |
| || DECL_DECLARED_INLINE_P (olddecl)) |
| DECL_DECLARED_INLINE_P (newdecl) = 1; |
| |
| DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl) |
| = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)); |
| |
| DECL_DISREGARD_INLINE_LIMITS (newdecl) |
| = DECL_DISREGARD_INLINE_LIMITS (olddecl) |
| = (DECL_DISREGARD_INLINE_LIMITS (newdecl) |
| || DECL_DISREGARD_INLINE_LIMITS (olddecl)); |
| } |
| |
| if (fndecl_built_in_p (olddecl)) |
| { |
| /* If redeclaring a builtin function, it stays built in. |
| But it gets tagged as having been declared. */ |
| copy_decl_built_in_function (newdecl, olddecl); |
| C_DECL_DECLARED_BUILTIN (newdecl) = 1; |
| if (new_is_prototype) |
| { |
| C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0; |
| if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL) |
| { |
| enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl); |
| switch (fncode) |
| { |
| /* If a compatible prototype of these builtin functions |
| is seen, assume the runtime implements it with the |
| expected semantics. */ |
| case BUILT_IN_STPCPY: |
| if (builtin_decl_explicit_p (fncode)) |
| set_builtin_decl_implicit_p (fncode, true); |
| break; |
| default: |
| if (builtin_decl_explicit_p (fncode)) |
| set_builtin_decl_declared_p (fncode, true); |
| break; |
| } |
| |
| copy_attributes_to_builtin (newdecl); |
| } |
| } |
| else |
| C_DECL_BUILTIN_PROTOTYPE (newdecl) |
| = C_DECL_BUILTIN_PROTOTYPE (olddecl); |
| } |
| |
| /* Preserve function specific target and optimization options */ |
| if (DECL_FUNCTION_SPECIFIC_TARGET (olddecl) |
| && !DECL_FUNCTION_SPECIFIC_TARGET (newdecl)) |
| DECL_FUNCTION_SPECIFIC_TARGET (newdecl) |
| = DECL_FUNCTION_SPECIFIC_TARGET (olddecl); |
| |
| if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl) |
| && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl)) |
| DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl) |
| = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl); |
| |
| /* 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); |
| 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); |
| } |
| } |
| |
| /* Merge the USED information. */ |
| if (TREE_USED (olddecl)) |
| TREE_USED (newdecl) = 1; |
| else if (TREE_USED (newdecl)) |
| TREE_USED (olddecl) = 1; |
| if (VAR_P (olddecl) || 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; |
| |
| /* Merge DECL_COMMON */ |
| if (VAR_P (olddecl) && VAR_P (newdecl) |
| && !lookup_attribute ("common", DECL_ATTRIBUTES (newdecl)) |
| && !lookup_attribute ("nocommon", DECL_ATTRIBUTES (newdecl))) |
| DECL_COMMON (newdecl) = DECL_COMMON (newdecl) && DECL_COMMON (olddecl); |
| |
| /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. |
| But preserve OLDDECL's DECL_UID, DECL_CONTEXT and |
| DECL_ARGUMENTS (if appropriate). */ |
| { |
| unsigned olddecl_uid = DECL_UID (olddecl); |
| tree olddecl_context = DECL_CONTEXT (olddecl); |
| tree olddecl_arguments = NULL; |
| if (TREE_CODE (olddecl) == FUNCTION_DECL) |
| olddecl_arguments = DECL_ARGUMENTS (olddecl); |
| |
| memcpy ((char *) olddecl + sizeof (struct tree_common), |
| (char *) newdecl + sizeof (struct tree_common), |
| sizeof (struct tree_decl_common) - sizeof (struct tree_common)); |
| DECL_USER_ALIGN (olddecl) = DECL_USER_ALIGN (newdecl); |
| switch (TREE_CODE (olddecl)) |
| { |
| case FUNCTION_DECL: |
| case VAR_DECL: |
| { |
| struct symtab_node *snode = olddecl->decl_with_vis.symtab_node; |
| |
| memcpy ((char *) olddecl + sizeof (struct tree_decl_common), |
| (char *) newdecl + sizeof (struct tree_decl_common), |
| tree_code_size (TREE_CODE (olddecl)) - sizeof (struct tree_decl_common)); |
| olddecl->decl_with_vis.symtab_node = snode; |
| |
| if ((DECL_EXTERNAL (olddecl) |
| || TREE_PUBLIC (olddecl) |
| || TREE_STATIC (olddecl)) |
| && DECL_SECTION_NAME (newdecl) != NULL) |
| set_decl_section_name (olddecl, newdecl); |
| |
| /* This isn't quite correct for something like |
| int __thread x attribute ((tls_model ("local-exec"))); |
| extern int __thread x; |
| as we'll lose the "local-exec" model. */ |
| if (VAR_P (olddecl) && DECL_THREAD_LOCAL_P (newdecl)) |
| set_decl_tls_model (olddecl, DECL_TLS_MODEL (newdecl)); |
| break; |
| } |
| |
| case FIELD_DECL: |
| case PARM_DECL: |
| case LABEL_DECL: |
| case RESULT_DECL: |
| case CONST_DECL: |
| case TYPE_DECL: |
| memcpy ((char *) olddecl + sizeof (struct tree_decl_common), |
| (char *) newdecl + sizeof (struct tree_decl_common), |
| tree_code_size (TREE_CODE (olddecl)) - sizeof (struct tree_decl_common)); |
| break; |
| |
| default: |
| |
| memcpy ((char *) olddecl + sizeof (struct tree_decl_common), |
| (char *) newdecl + sizeof (struct tree_decl_common), |
| sizeof (struct tree_decl_non_common) - sizeof (struct tree_decl_common)); |
| } |
| DECL_UID (olddecl) = olddecl_uid; |
| DECL_CONTEXT (olddecl) = olddecl_context; |
| if (TREE_CODE (olddecl) == FUNCTION_DECL) |
| DECL_ARGUMENTS (olddecl) = olddecl_arguments; |
| } |
| |
| /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl |
| so that encode_section_info has a chance to look at the new decl |
| flags and attributes. */ |
| if (DECL_RTL_SET_P (olddecl) |
| && (TREE_CODE (olddecl) == FUNCTION_DECL |
| || (VAR_P (olddecl) && TREE_STATIC (olddecl)))) |
| make_decl_rtl (olddecl); |
| } |
| |
| /* Handle when a new declaration NEWDECL has the same name as an old |
| one OLDDECL in the same binding contour. Prints an error message |
| if appropriate. |
| |
| If safely possible, alter OLDDECL to look like NEWDECL, and return |
| true. Otherwise, return false. */ |
| |
| static bool |
| duplicate_decls (tree newdecl, tree olddecl) |
| { |
| tree newtype = NULL, oldtype = NULL; |
| |
| if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype)) |
| { |
| /* Avoid `unused variable' and other warnings for OLDDECL. */ |
| suppress_warning (olddecl, OPT_Wunused); |
| /* If the types are completely different, poison them both with |
| error_mark_node. */ |
| if (TREE_CODE (TREE_TYPE (newdecl)) != TREE_CODE (TREE_TYPE (olddecl)) |
| && olddecl != error_mark_node |
| && seen_error ()) |
| { |
| if (TREE_CODE (olddecl) != FUNCTION_DECL) |
| TREE_TYPE (olddecl) = error_mark_node; |
| if (TREE_CODE (newdecl) != FUNCTION_DECL) |
| TREE_TYPE (newdecl) = error_mark_node; |
| } |
| return false; |
| } |
| |
| merge_decls (newdecl, olddecl, newtype, oldtype); |
| |
| /* The NEWDECL will no longer be needed. |
| |
| Before releasing the node, be sure to remove function from symbol |
| table that might have been inserted there to record comdat group. |
| Be sure to however do not free DECL_STRUCT_FUNCTION because this |
| structure is shared in between NEWDECL and OLDECL. */ |
| if (TREE_CODE (newdecl) == FUNCTION_DECL) |
| DECL_STRUCT_FUNCTION (newdecl) = NULL; |
| if (VAR_OR_FUNCTION_DECL_P (newdecl)) |
| { |
| struct symtab_node *snode = symtab_node::get (newdecl); |
| if (snode) |
| snode->remove (); |
| } |
| ggc_free (newdecl); |
| return true; |
| } |
| |
| |
| /* Check whether decl-node NEW_DECL shadows an existing declaration. */ |
| static void |
| warn_if_shadowing (tree new_decl) |
| { |
| struct c_binding *b; |
| |
| /* Shadow warnings wanted? */ |
| if (!(warn_shadow |
| || warn_shadow_local |
| || warn_shadow_compatible_local) |
| /* No shadow warnings for internally generated vars. */ |
| || DECL_IS_UNDECLARED_BUILTIN (new_decl)) |
| return; |
| |
| /* Is anything being shadowed? Invisible decls do not count. */ |
| for (b = I_SYMBOL_BINDING (DECL_NAME (new_decl)); b; b = b->shadowed) |
| if (b->decl && b->decl != new_decl && !b->invisible |
| && (b->decl == error_mark_node |
| || diagnostic_report_warnings_p (global_dc, |
| DECL_SOURCE_LOCATION (b->decl)))) |
| { |
| tree old_decl = b->decl; |
| |
| if (old_decl == error_mark_node) |
| { |
| warning (OPT_Wshadow, "declaration of %q+D shadows previous " |
| "non-variable", new_decl); |
| break; |
| } |
| |
| bool warned = false; |
| auto_diagnostic_group d; |
| if (TREE_CODE (old_decl) == PARM_DECL) |
| { |
| enum opt_code warning_code; |
| |
| /* If '-Wshadow=compatible-local' is specified without other |
| -Wshadow= flags, we will warn only when the types of the |
| shadowing variable (i.e. new_decl) and the shadowed variable |
| (old_decl) are compatible. */ |
| if (warn_shadow) |
| warning_code = OPT_Wshadow; |
| else if (comptypes (TREE_TYPE (old_decl), TREE_TYPE (new_decl))) |
| warning_code = OPT_Wshadow_compatible_local; |
| else |
| warning_code = OPT_Wshadow_local; |
| warned = warning_at (DECL_SOURCE_LOCATION (new_decl), warning_code, |
| "declaration of %qD shadows a parameter", |
| new_decl); |
| } |
| else if (DECL_FILE_SCOPE_P (old_decl)) |
| { |
| /* Do not warn if a variable shadows a function, unless |
| the variable is a function or a pointer-to-function. */ |
| if (TREE_CODE (old_decl) == FUNCTION_DECL |
| && TREE_CODE (new_decl) != FUNCTION_DECL |
| && !FUNCTION_POINTER_TYPE_P (TREE_TYPE (new_decl))) |
| continue; |
| |
| warned = warning_at (DECL_SOURCE_LOCATION (new_decl), OPT_Wshadow, |
| "declaration of %qD shadows a global " |
| "declaration", |
| new_decl); |
| } |
| else if (TREE_CODE (old_decl) == FUNCTION_DECL |
| && fndecl_built_in_p (old_decl)) |
| { |
| warning (OPT_Wshadow, "declaration of %q+D shadows " |
| "a built-in function", new_decl); |
| break; |
| } |
| else |
| { |
| enum opt_code warning_code; |
| |
| /* If '-Wshadow=compatible-local' is specified without other |
| -Wshadow= flags, we will warn only when the types of the |
| shadowing variable (i.e. new_decl) and the shadowed variable |
| (old_decl) are compatible. */ |
| if (warn_shadow) |
| warning_code = OPT_Wshadow; |
| else if (comptypes (TREE_TYPE (old_decl), TREE_TYPE (new_decl))) |
| warning_code = OPT_Wshadow_compatible_local; |
| else |
| warning_code = OPT_Wshadow_local; |
| warned = warning_at (DECL_SOURCE_LOCATION (new_decl), warning_code, |
| "declaration of %qD shadows a previous local", |
| new_decl); |
| } |
| |
| if (warned) |
| inform (DECL_SOURCE_LOCATION (old_decl), |
| "shadowed declaration is here"); |
| |
| break; |
| } |
| } |
| |
| /* Record a decl-node X as belonging to the current lexical scope. |
| Check for errors (such as an incompatible declaration for the same |
| name already seen in the same scope). |
| |
| Returns either X or an old decl for the same name. |
| If an old decl is returned, it may have been smashed |
| to agree with what X says. */ |
| |
| tree |
| pushdecl (tree x) |
| { |
| tree name = DECL_NAME (x); |
| struct c_scope *scope = current_scope; |
| struct c_binding *b; |
| bool nested = false; |
| location_t locus = DECL_SOURCE_LOCATION (x); |
| |
| /* Must set DECL_CONTEXT for everything not at file scope or |
| DECL_FILE_SCOPE_P won't work. Local externs don't count |
| unless they have initializers (which generate code). */ |
| if (current_function_decl |
| && (!VAR_OR_FUNCTION_DECL_P (x) |
| || DECL_INITIAL (x) || !TREE_PUBLIC (x))) |
| DECL_CONTEXT (x) = current_function_decl; |
| |
| /* Anonymous decls are just inserted in the scope. */ |
| if (!name) |
| { |
| bind (name, x, scope, /*invisible=*/false, /*nested=*/false, |
| locus); |
| return x; |
| } |
| |
| /* First, see if there is another declaration with the same name in |
| the current scope. If there is, duplicate_decls may do all the |
| work for us. If duplicate_decls returns false, that indicates |
| two incompatible decls in the same scope; we are to silently |
| replace the old one (duplicate_decls has issued all appropriate |
| diagnostics). In particular, we should not consider possible |
| duplicates in the external scope, or shadowing. */ |
| b = I_SYMBOL_BINDING (name); |
| if (b && B_IN_SCOPE (b, scope)) |
| { |
| struct c_binding *b_ext, *b_use; |
| tree type = TREE_TYPE (x); |
| tree visdecl = b->decl; |
| tree vistype = TREE_TYPE (visdecl); |
| if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE |
| && COMPLETE_TYPE_P (TREE_TYPE (x))) |
| b->inner_comp = false; |
| b_use = b; |
| b_ext = b; |
| /* If this is an external linkage declaration, we should check |
| for compatibility with the type in the external scope before |
| setting the type at this scope based on the visible |
| information only. */ |
| if (TREE_PUBLIC (x) && TREE_PUBLIC (visdecl)) |
| { |
| while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext)) |
| b_ext = b_ext->shadowed; |
| if (b_ext) |
| { |
| b_use = b_ext; |
| if (b_use->u.type) |
| TREE_TYPE (b_use->decl) = b_use->u.type; |
| } |
| } |
| if (duplicate_decls (x, b_use->decl)) |
| { |
| if (b_use != b) |
| { |
| /* Save the updated type in the external scope and |
| restore the proper type for this scope. */ |
| tree thistype; |
| if (comptypes (vistype, type)) |
| thistype = composite_type (vistype, type); |
| else |
| thistype = TREE_TYPE (b_use->decl); |
| b_use->u.type = TREE_TYPE (b_use->decl); |
| if (TREE_CODE (b_use->decl) == FUNCTION_DECL |
| && fndecl_built_in_p (b_use->decl)) |
| thistype |
| = build_type_attribute_variant (thistype, |
| TYPE_ATTRIBUTES |
| (b_use->u.type)); |
| TREE_TYPE (b_use->decl) = thistype; |
| } |
| return b_use->decl; |
| } |
| else |
| goto skip_external_and_shadow_checks; |
| } |
| |
| /* All declarations with external linkage, and all external |
| references, go in the external scope, no matter what scope is |
| current. However, the binding in that scope is ignored for |
| purposes of normal name lookup. A separate binding structure is |
| created in the requested scope; this governs the normal |
| visibility of the symbol. |
| |
| The binding in the externals scope is used exclusively for |
| detecting duplicate declarations of the same object, no matter |
| what scope they are in; this is what we do here. (C99 6.2.7p2: |
| All declarations that refer to the same object or function shall |
| have compatible type; otherwise, the behavior is undefined.) |
| However, in Objective-C, we also want to detect declarations |
| conflicting with those of the basic types. */ |
| if ((DECL_EXTERNAL (x) || scope == file_scope) |
| && (VAR_OR_FUNCTION_DECL_P (x) || c_dialect_objc ())) |
| { |
| tree type = TREE_TYPE (x); |
| tree vistype = NULL_TREE; |
| tree visdecl = NULL_TREE; |
| bool type_saved = false; |
| if (b && !B_IN_EXTERNAL_SCOPE (b) |
| && VAR_OR_FUNCTION_DECL_P (b->decl) |
| && DECL_FILE_SCOPE_P (b->decl)) |
| { |
| visdecl = b->decl;
|