📄 c-decl.c
字号:
} /* 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 /* Dont 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) { /* 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)) 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 (olddecl) = 0; if (TREE_READONLY (newdecl)) TREE_READONLY (olddecl) = 1; if (TREE_THIS_VOLATILE (newdecl)) { TREE_THIS_VOLATILE (olddecl) = 1; if (TREE_CODE (newdecl) == VAR_DECL) make_var_volatile (newdecl); } /* Keep source location of definition rather than declaration. Likewise, keep decl at outer scope. */ if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0) || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0)) { DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl); DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl); if (DECL_CONTEXT (olddecl) == 0 && TREE_CODE (newdecl) != FUNCTION_DECL) DECL_CONTEXT (newdecl) = 0; } /* 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 (olddecl) = 1; /* Merge the initialization information. */ if (DECL_INITIAL (newdecl) == 0) 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 { 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. */ 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); } 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); /* Get rid of any built-in function if new arg types don't match it or if we have a function definition. */ if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl) && (!types_match || new_is_definition)) { TREE_TYPE (olddecl) = TREE_TYPE (newdecl); DECL_BUILT_IN (olddecl) = 0; } /* If redeclaring a builtin function, and not a definition, it stays built in. Also preserve various other info from the definition. */ if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition) { if (DECL_BUILT_IN (olddecl)) { DECL_BUILT_IN (newdecl) = 1; DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); } else DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl); DECL_RESULT (newdecl) = DECL_RESULT (olddecl); DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl); DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); } /* 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 declared_global; /* 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 (DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional) t = lookup_name_current_level_global (name); else t = lookup_name_current_level (name); if (t != 0 && t == error_mark_node) /* error_mark_node is 0 for a while during initialization! */ { t = 0; error_with_decl (x, "`%s' used prior to declaration"); } if (t != 0) { file = DECL_SOURCE_FILE (t); line = DECL_SOURCE_LINE (t); } /* duplicate_decls might write to TREE_PUBLIC (x) and DECL_EXTERNAL (x) to make it identical to the initial declaration. */ declared_global = TREE_PUBLIC (x) || DECL_EXTERNAL (x); if (t != 0 && duplicate_decls (x, t)) { if (TREE_CODE (t) == PARM_DECL) { /* Don't allow more than one "real" duplicate of a forward parm decl. */ TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x); return t; } /* If this decl is `static' and an implicit decl was seen previously, warn. But don't complain if -traditional, since traditional compilers don't complain. */ if (!flag_traditional && TREE_PUBLIC (name) /* should this be '&& ! declared_global' ? */ && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x) /* We used to warn also for explicit extern followed by static, but sometimes you need to do it that way. */ && IDENTIFIER_IMPLICIT_DECL (name) != 0) { pedwarn ("`%s' was declared implicitly `extern' and later `static'", IDENTIFIER_POINTER (name)); pedwarn_with_file_and_line (file, line, "previous declaration of `%s'", IDENTIFIER_POINTER (name)); } /* If this is a global decl, and there exists a conflicting local decl in a parent block, then we can't return as yet, because we need to register this decl in the current binding block. */ /* A test for TREE_PUBLIC (x) will fail for variables that have been declared static first, and extern now. */ if (! declared_global || lookup_name (name) == t) return t; } /* If we are processing a typedef statement, generate a whole new ..._TYPE node (which will be just an variant of the existing ..._TYPE node with identical properties) and then install the TYPE_DECL node generated to represent the typedef name as the TYPE_NAME of this brand new (duplicate) ..._TYPE node. The whole point here is to end up with a situation where each and every ..._TYPE node the compiler creates will be uniquely associated with AT MOST one node representing a typedef name. This way, even though the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very early on, later parts of the compiler can always do the reverse translation and get back the corresponding typedef name. For example, given: typedef struct S MY_TYPE; MY_TYPE object; Later parts of the compiler might only know that `object' was of type `struct S' if if were not for code just below. With this code however, later parts of the compiler see something like: struct S' == struct S typedef struct S' MY_TYPE; struct S' object; And they can then deduce (from the node for type struct S') that the original object declaration was: MY_TYPE object; Being able to do this is important for proper support of protoize, and also for generating precise symbolic debugging information which takes full account of the programmer's (typedef) vocabulary. Obviously, we don't want to generate a duplicate ..._TYPE node if the TYPE_DECL node that we are now processing really represents a standard built-in type. Since all standard types are effectively declared at line zero in the source file, we can easily check to see if we are working on a standard type by checking the current value of lineno. */ if (TREE_CODE (x) == TYPE_DECL) { if (DECL_SOURCE_LINE (x) == 0) { if (TYPE_NAME (TREE_TYPE (x)) == 0) TYPE_NAME (TREE_TYPE (x)) = x; } else if (TREE_TYPE (x) != error_mark_node) { tree tt = TREE_TYPE (x); tt = build_type_copy (tt); TYPE_NAME (tt) = x; TREE_TYPE (x) = tt; } } /* Multiple external decls of the same identifier ought to match. Check against both global declarations (when traditional) and out of scope (limbo) block level declarations. We get warnings about inline functions where they are defined. Avoid duplicate warnings where they are used. */ if (TREE_PUBLIC (x) && ! DECL_INLINE (x)) { tree decl; if (flag_traditional && IDENTIFIER_GLOBAL_VALUE (name) != 0 && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name)) || TREE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -