📄 c-decl.c
字号:
error ("an empty parameter name list declaration."); break; } if (TYPE_MAIN_VARIANT (type) == float_type_node || C_PROMOTING_INTEGER_TYPE_P (type)) { error ("An argument type that has a default promotion"); error ("can't match an empty parameter name list declaration."); break; } } } error_with_decl (olddecl, "previous declaration of `%s'"); } else { errmsg = redeclaration_error_message (newdecl, olddecl); if (errmsg) { error_with_decl (newdecl, errmsg); error_with_decl (olddecl, ((DECL_INITIAL (olddecl) && current_binding_level == global_binding_level) ? "`%s' previously defined here" : "`%s' previously declared here")); } else if (TREE_CODE (newdecl) == TYPE_DECL && (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))) { warning_with_decl (newdecl, "redefinition of `%s'"); warning_with_decl (olddecl, ((DECL_INITIAL (olddecl) && current_binding_level == global_binding_level) ? "`%s' previously defined here" : "`%s' previously declared here")); } else if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl) != 0 && TYPE_ARG_TYPES (oldtype) == 0 && TYPE_ARG_TYPES (newtype) != 0 && TYPE_ACTUAL_ARG_TYPES (oldtype) != 0) { register tree type, parm; register int nargs; /* Prototype decl follows defn w/o prototype. */ for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype), type = TYPE_ARG_TYPES (newtype), nargs = 1; (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) != void_type_node || TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node); parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++) { if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) { errmsg = "prototype for `%s' follows and number of arguments"; break; } /* Type for passing arg must be consistent with that declared for the arg. */ if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type)) /* If -traditional, allow `unsigned int' instead of `int' in the prototype. */ && (! (flag_traditional && TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node))) { errmsg = "prototype for `%s' follows and argument %d"; break; } } if (errmsg) { error_with_decl (newdecl, errmsg, nargs); error_with_decl (olddecl, "doesn't match non-prototype definition here"); } else { warning_with_decl (newdecl, "prototype for `%s' follows"); warning_with_decl (olddecl, "non-prototype definition here"); } } /* Warn about mismatches in various flags. */ else { /* Warn if function is now inline but was previously declared not inline and has been called. */ if (TREE_CODE (olddecl) == FUNCTION_DECL && ! DECL_INLINE (olddecl) && DECL_INLINE (newdecl) && TREE_USED (olddecl)) warning_with_decl (newdecl, "`%s' declared inline after being called"); if (TREE_CODE (olddecl) == FUNCTION_DECL && ! DECL_INLINE (olddecl) && DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) != 0) warning_with_decl (newdecl, "`%s' declared inline after its definition"); /* If pedantic, warn when static declaration follows a non-static declaration. Otherwise, do so only for functions. */ if ((pedantic || TREE_CODE (olddecl) == FUNCTION_DECL) && TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl)) warning_with_decl (newdecl, "static declaration for `%s' follows non-static"); /* Warn when const declaration follows a non-const declaration, but not for functions. */ if (TREE_CODE (olddecl) != FUNCTION_DECL && !TREE_READONLY (olddecl) && TREE_READONLY (newdecl)) warning_with_decl (newdecl, "const declaration for `%s' follows non-const"); /* These bits are logically part of the type, for variables. But not for functions (where qualifiers are not valid ANSI anyway). */ else if (pedantic && TREE_CODE (olddecl) != FUNCTION_DECL && (TREE_READONLY (newdecl) != TREE_READONLY (olddecl) || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))) pedwarn_with_decl (newdecl, "type qualifiers for `%s' conflict with previous decl"); } } /* Optionally warn about more than one declaration for the same name. */ if (errmsg == 0 && warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0 /* Don't warn about a function declaration followed by a definition. */ && !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0 && DECL_INITIAL (olddecl) == 0) /* Don't warn about extern decl followed by (tentative) definition. */ && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))) { warning_with_decl (newdecl, "redundant redeclaration of `%s' in same scope"); warning_with_decl (olddecl, "previous declaration of `%s'"); } /* Copy all the DECL_... slots specified in the new decl except for any that we copy here from the old type. Past this point, we don't change OLDTYPE and NEWTYPE even if we change the types of NEWDECL and OLDDECL. */ if (types_match) { /* When copying info to olddecl, we store into write_olddecl instead. This allows us to avoid modifying olddecl when different_binding_level is true. */ tree write_olddecl = different_binding_level ? newdecl : olddecl; /* Make sure we put the new type in the same obstack as the old ones. If the old types are not both in the same obstack, use the permanent one. */ if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype)) push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype)); else { push_obstacks_nochange (); end_temporary_allocation (); } /* Merge the data types specified in the two decls. */ if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl)) { if (different_binding_level) TREE_TYPE (newdecl) = build_type_attribute_variant (newtype, merge_attributes (TYPE_ATTRIBUTES (newtype), TYPE_ATTRIBUTES (oldtype))); else TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = common_type (newtype, oldtype); } /* Lay the type out, unless already done. */ if (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); if (TREE_CODE (olddecl) != FUNCTION_DECL) if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl)) DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl); } /* Keep the old rtl since we can safely use it. */ DECL_RTL (newdecl) = DECL_RTL (olddecl); /* Merge the type qualifiers. */ if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl) && !TREE_THIS_VOLATILE (newdecl)) TREE_THIS_VOLATILE (write_olddecl) = 0; if (TREE_READONLY (newdecl)) TREE_READONLY (write_olddecl) = 1; if (TREE_THIS_VOLATILE (newdecl)) { TREE_THIS_VOLATILE (write_olddecl) = 1; if (TREE_CODE (newdecl) == VAR_DECL) make_var_volatile (newdecl); } /* Keep source location of definition rather than declaration. */ /* When called with different_binding_level set, keep the old information so that meaningful diagnostics can be given. */ if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0 && ! different_binding_level) { DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl); DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl); } /* Merge the unused-warning information. */ if (DECL_IN_SYSTEM_HEADER (olddecl)) DECL_IN_SYSTEM_HEADER (newdecl) = 1; else if (DECL_IN_SYSTEM_HEADER (newdecl)) DECL_IN_SYSTEM_HEADER (write_olddecl) = 1; /* Merge the initialization information. */ /* When called with different_binding_level set, don't copy over DECL_INITIAL, so that we don't accidentally change function declarations into function definitions. */ if (DECL_INITIAL (newdecl) == 0 && ! different_binding_level) DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); /* Merge the section attribute. We want to issue an error if the sections conflict but that must be done later in decl_attributes since we are called before attributes are assigned. */ if (DECL_SECTION_NAME (newdecl) == NULL_TREE) DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl); if (TREE_CODE (newdecl) == FUNCTION_DECL) { DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl); DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); } pop_obstacks (); } /* If cannot merge, then use the new type and qualifiers, and don't preserve the old rtl. */ else if (! different_binding_level) { TREE_TYPE (olddecl) = TREE_TYPE (newdecl); TREE_READONLY (olddecl) = TREE_READONLY (newdecl); TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl); TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl); } /* Merge the storage class information. */ DECL_WEAK (newdecl) |= DECL_WEAK (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. */ /* No need to worry about different_binding_level here because then TREE_PUBLIC (newdecl) was true. */ 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; } 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); } else { TREE_STATIC (olddecl) = TREE_STATIC (newdecl); TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); } /* If either decl says `inline', this fn is inline, unless its definition was passed already. */ if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0) DECL_INLINE (olddecl) = 1; DECL_INLINE (newdecl) = DECL_INLINE (olddecl); if (TREE_CODE (newdecl) == FUNCTION_DECL) { if (DECL_BUILT_IN (olddecl)) { /* Get rid of any built-in function if new arg types don't match it or if we have a function definition. */ if (! types_match || new_is_definition) { if (! different_binding_level) { TREE_TYPE (olddecl) = TREE_TYPE (newdecl); DECL_BUILT_IN (olddecl) = 0; } } else { /* If redeclaring a builtin function, and not a definition, it stays built in. */ DECL_BUILT_IN (newdecl) = 1; DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); } } /* Also preserve various other info from the definition. */ else if (! new_is_definition) DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl); if (! new_is_definition) { DECL_RESULT (newdecl) = DECL_RESULT (olddecl); /* When called with different_binding_level set, don't copy over DECL_INITIAL, so that we don't accidentally change function declarations into function definitions. */ if (! different_binding_level) DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl); DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); if (DECL_INLINE (newdecl)) DECL_ABSTRACT_ORIGIN (newdecl) = olddecl; } } if (different_binding_level) { /* Don't output a duplicate symbol for this declaration. */ TREE_ASM_WRITTEN (newdecl) = 1; return 0; } /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. But preserve OLDdECL's DECL_UID. */ { register unsigned olddecl_uid = DECL_UID (olddecl); bcopy ((char *) newdecl + sizeof (struct tree_common), (char *) olddecl + sizeof (struct tree_common), sizeof (struct tree_decl) - sizeof (struct tree_common)); DECL_UID (olddecl) = olddecl_uid; } return 1;}/* 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. */treepushdecl (x) tree x;{ register tree t; register tree name = DECL_NAME (x); register struct binding_level *b = current_binding_level; DECL_CONTEXT (x) = current_function_decl; /* A local extern declaration for a function doesn't constitute nesting. A local auto declaration does, since it's a forward decl for a nested function coming later. */ if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x)) DECL_CONTEXT (x) = 0; if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level && x != IDENTIFIER_IMPLICIT_DECL (name) /* Don't print error messages for __FUNCTION__ and __PRETTY_FUNCTION__ */ && !DECL_IN_SYSTEM_HEADER (x)) warning ("nested extern declaration of `%s'", IDENTIFIER_POINTER (name)); if (name) { char *file; int line; int different_binding_level = 0; t = lookup_name_current_level (name); /* Don't type check externs here when -traditional. This is so that code with conflicting declarations inside blocks will get warnings not errors. X11 for instance depends on this. */ if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional) { t = IDENTIFIER_GLOBAL_VALUE (name); /* Type decls at global scope don't conflict with externs declared inside lexical blocks. */ if (t && TREE_CODE (t) == TYPE_DECL) t = 0; different_binding_level = 1; } if (t != 0 && t == error_mark_node) /* error_mark_node is 0 for a while during initializ
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -