📄 c-decl.c
字号:
/* 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_SET_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 declaration for a function doesn't constitute nesting. */ if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0) DECL_CONTEXT (x) = 0; if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level && x != IDENTIFIER_IMPLICIT_DECL (name)) warning ("nested extern declaration of `%s'", IDENTIFIER_POINTER (name)); if (name) { char *file; int line; 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); } 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) && ! 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)); } 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 { 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 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 (DECL_EXTERNAL (x) && ! DECL_INLINE (x)) { tree decl; if (IDENTIFIER_GLOBAL_VALUE (name) != 0 && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name)) || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name)))) decl = IDENTIFIER_GLOBAL_VALUE (name); else if (IDENTIFIER_LIMBO_VALUE (name) != 0) /* Decls in limbo are always extern, so no need to check that. */ decl = IDENTIFIER_LIMBO_VALUE (name); else decl = 0; if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl))) { pedwarn_with_decl (x, "type mismatch with previous external decl"); pedwarn_with_decl (decl, "previous external decl of `%s'"); } } /* If a function has had an implicit declaration, and then is defined, make sure they are compatible. */ if (IDENTIFIER_IMPLICIT_DECL (name) != 0 && IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_CODE (x) == FUNCTION_DECL && ! comptypes (TREE_TYPE (x), TREE_TYPE (IDENTIFIER_IMPLICIT_DECL (name)))) { warning_with_decl (x, "type mismatch with previous implicit declaration"); warning_with_decl (IDENTIFIER_IMPLICIT_DECL (name), "previous implicit declaration of `%s'"); } /* In PCC-compatibility mode, extern decls of vars with no current decl take effect at top level no matter where they are. */ if (flag_traditional && DECL_EXTERNAL (x) && lookup_name (name) == 0) { tree type = TREE_TYPE (x); /* But don't do this if the type contains temporary nodes. */ while (type) { if (type == error_mark_node) break; if (! TREE_PERMANENT (type)) { warning_with_decl (x, "type of external `%s' is not global"); /* By exiting the loop early, we leave TYPE nonzero, and thus prevent globalization of the decl. */ break; } else if (TREE_CODE (type) == FUNCTION_TYPE && TYPE_ARG_TYPES (type) != 0) /* The types might not be truly local, but the list of arg types certainly is temporary. Since prototypes are nontraditional, ok not to do the traditional thing. */ break; type = TREE_TYPE (type); } if (type == 0) b = global_binding_level; } /* This name is new in its binding level. Install the new declaration and return it. */ if (b == global_binding_level) { /* Install a global value. */ /* If the first global decl has external linkage, warn if we later see static one. */ if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x)) TREE_PUBLIC (name) = 1; IDENTIFIER_GLOBAL_VALUE (name) = x; /* We no longer care about any previous block level declarations. */ IDENTIFIER_LIMBO_VALUE (name) = 0; /* Don't forget if the function was used via an implicit decl. */ if (IDENTIFIER_IMPLICIT_DECL (name) && TREE_USED (IDENTIFIER_IMPLICIT_DECL (name))) TREE_USED (x) = 1, TREE_USED (name) = 1; /* Don't forget if its address was taken in that way. */ if (IDENTIFIER_IMPLICIT_DECL (name) && TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name))) TREE_ADDRESSABLE (x) = 1; /* Warn about mismatches against previous implicit decl. */ if (IDENTIFIER_IMPLICIT_DECL (name) != 0 /* If this real decl matches the implicit, don't complain. */ && ! (TREE_CODE (x) == FUNCTION_DECL && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (x))) == integer_type_node))) pedwarn ("`%s' was previously implicitly declared to return `int'", IDENTIFIER_POINTER (name)); /* If this decl is `static' and an `extern' was seen previously, that is erroneous. */ if (TREE_PUBLIC (name) && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x)) { /* Okay to redeclare an ANSI built-in as static. */ if (t != 0 && DECL_BUILT_IN (t)) ; /* Okay to declare a non-ANSI built-in as anything. */ else if (t != 0 && DECL_BUILT_IN_NONANSI (t)) ; else if (IDENTIFIER_IMPLICIT_DECL (name)) pedwarn ("`%s' was declared implicitly `extern' and later `static'", IDENTIFIER_POINTER (name)); else pedwarn ("`%s' was declared `extern' and later `static'", IDENTIFIER_POINTER (name)); } } else { /* Here to install a non-global value. */ tree oldlocal = IDENTIFIER_LOCAL_VALUE (name); tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name); IDENTIFIER_LOCAL_VALUE (name) = x; /* If this is an extern function declaration, see if we have a global definition or declaration for the function. */ if (oldlocal == 0 && DECL_EXTERNAL (x) && !DECL_INLINE (x) && oldglobal != 0 && TREE_CODE (x) == FUNCTION_DECL && TREE_CODE (oldglobal) == FUNCTION_DECL) { /* We have one. Their types must agree. */ if (! comptypes (TREE_TYPE (x), TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)))) pedwarn_with_decl (x, "extern declaration of `%s' doesn't match global one"); else { /* Inner extern decl is inline if global one is. Copy enough to really inline it. */ if (DECL_INLINE (oldglobal)) { DECL_INLINE (x) = DECL_INLINE (oldglobal); DECL_INITIAL (x) = (current_function_decl == oldglobal ? 0 : DECL_INITIAL (oldglobal)); DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal); DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal); DECL_RESULT (x) = DECL_RESULT (oldglobal); TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal); DECL_ABSTRACT_ORIGIN (x) = oldglobal; } /* Inner extern decl is built-in if global one is. */ if (DECL_BUILT_IN (oldglobal)) { DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal); DECL_SET_FUNCTION_CODE (x, DECL_FUNCTION_CODE (oldglobal)); } /* Keep the arg types from a file-scope fcn defn. */ if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0 && DECL_INITIAL (oldglobal) && TYPE_ARG_TYPES (TREE_TYPE (x)) == 0) TREE_TYPE (x) = TREE_TYPE (oldglobal); } }#if 0 /* This case is probably sometimes the right thing to do. */ /* If we have a local external declaration, then any file-scope declaration should not have been static. */ if (oldlocal == 0 && oldglobal != 0 && !TREE_PUBLIC (oldglobal) && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) warning ("`%s' locally external but globally static", IDENTIFIER_POINTER (name));#endif /* If we have a local external declaration, and no file-scope declaration has yet been seen, then if we later have a file-scope decl it must not be static. */ if (oldlocal == 0 && oldglobal == 0 && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) { TREE_PUBLIC (name) = 1; /* Save this decl, so that we can do type checking against other decls after it falls out of scope. Only save it once. This prevents temporary decls created in expand_inline_function from being used here, since this will have been set when the inline function was parsed. It also helps give slightly better warnings. */ if (IDENTIFIER_LIMBO_VALUE (name) == 0) IDENTIFIER_LIMBO_VALUE (name) = x; } /* Warn if shadowing an argument at the top level of the body. */ if (oldlocal != 0 && !DECL_EXTERNAL (x) /* This warning doesn't apply to the parms of a nested fcn. */ && ! current_binding_level->parm_flag /* Check that this is one level down from the parms. */ && current_binding_level->level_chain->parm_flag /* Check that the decl being shadowed comes from the parm level, one level up. */ && chain_member (oldlocal, current_binding_level->level_chain->names)) { if (TREE_CODE (oldlocal) == PARM_DECL) pedwarn ("declaration of `%s' shadows a parameter", IDENTIFIER_POINTER (name)); else pedwarn ("declaration of `%s' shadows a symbol from the parameter list", IDENTIFIER_POINTER (name)); } /* Maybe warn if shadowing something else. */ else if (warn_shadow && !DECL_EXTERNAL (x) /* No shadow warnings for internally generated vars. */ && DECL_SOURCE_LINE (x) != 0 /* No shadow warnings for vars made for inlining. */ && ! DECL_FROM_INLINE (x)) { char *warnstring = 0; if (TREE_CODE (x) == PARM_DECL && current_binding_level->parm_flag == 1) /* Don't warn about the parm names in a declaration. */ ; else if (oldlocal != 0 && TREE_CODE (oldlocal) ==
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -