⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c-decl.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* 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 + -