c-common.c

来自「GCC编译器源代码」· C语言 代码 · 共 2,225 行 · 第 1/5 页

C
2,225
字号
		   || TREE_CODE (decl) == VAR_DECL		   || TREE_CODE (decl) == FUNCTION_DECL)	    TREE_USED (decl) = 1;	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_CONST:	  if (TREE_CODE (decl) == FUNCTION_DECL)	    TREE_READONLY (decl) = 1;	  else if (TREE_CODE (type) == POINTER_TYPE		   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)	    TREE_TYPE (decl) = type	      = build_pointer_type		(build_type_variant (TREE_TYPE (type), 1,				     TREE_THIS_VOLATILE (TREE_TYPE (type))));	  else	    warning ( "`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_T_UNION:	  if (is_type	      && TREE_CODE (type) == UNION_TYPE	      && (decl == 0		  || (TYPE_FIELDS (type) != 0		      && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))))	    TYPE_TRANSPARENT_UNION (type) = 1;	  else if (decl != 0 && TREE_CODE (decl) == PARM_DECL		   && TREE_CODE (type) == UNION_TYPE		   && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))	    DECL_TRANSPARENT_UNION (decl) = 1;	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_CONSTRUCTOR:	  if (TREE_CODE (decl) == FUNCTION_DECL	      && TREE_CODE (type) == FUNCTION_TYPE	      && decl_function_context (decl) == 0)	    {	      DECL_STATIC_CONSTRUCTOR (decl) = 1;	      TREE_USED (decl) = 1;	    }	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_DESTRUCTOR:	  if (TREE_CODE (decl) == FUNCTION_DECL	      && TREE_CODE (type) == FUNCTION_TYPE	      && decl_function_context (decl) == 0)	    {	      DECL_STATIC_DESTRUCTOR (decl) = 1;	      TREE_USED (decl) = 1;	    }	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_MODE:	  if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  else	    {	      int j;	      char *p = IDENTIFIER_POINTER (TREE_VALUE (args));	      int len = strlen (p);	      enum machine_mode mode = VOIDmode;	      tree typefm;	      if (len > 4 && p[0] == '_' && p[1] == '_'		  && p[len - 1] == '_' && p[len - 2] == '_')		{		  char *newp = (char *) alloca (len - 1);		  strcpy (newp, &p[2]);		  newp[len - 4] = '\0';		  p = newp;		}	      /* Give this decl a type with the specified mode.		 First check for the special modes.  */	      if (! strcmp (p, "byte"))		mode = byte_mode;	      else if (!strcmp (p, "word"))		mode = word_mode;	      else if (! strcmp (p, "pointer"))		mode = ptr_mode;	      else		for (j = 0; j < NUM_MACHINE_MODES; j++)		  if (!strcmp (p, GET_MODE_NAME (j)))		    mode = (enum machine_mode) j;	      if (mode == VOIDmode)		error ("unknown machine mode `%s'", p);	      else if (0 == (typefm = type_for_mode (mode,						     TREE_UNSIGNED (type))))		error ("no data type for mode `%s'", p);	      else		{		  TREE_TYPE (decl) = type = typefm;		  DECL_SIZE (decl) = 0;		  layout_decl (decl, 0);		}	    }	  break;	case A_SECTION:#ifdef ASM_OUTPUT_SECTION_NAME	  if ((TREE_CODE (decl) == FUNCTION_DECL	       || TREE_CODE (decl) == VAR_DECL)	      && TREE_CODE (TREE_VALUE (args)) == STRING_CST)	    {	      if (TREE_CODE (decl) == VAR_DECL 		  && current_function_decl != NULL_TREE		  && ! TREE_STATIC (decl))		error_with_decl (decl,		  "section attribute cannot be specified for local variables");	      /* The decl may have already been given a section attribute from		 a previous declaration.  Ensure they match.  */	      else if (DECL_SECTION_NAME (decl) != NULL_TREE		       && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),				  TREE_STRING_POINTER (TREE_VALUE (args))) != 0)		error_with_decl (node,				 "section of `%s' conflicts with previous declaration");	      else		DECL_SECTION_NAME (decl) = TREE_VALUE (args);	    }	  else	    error_with_decl (node,			   "section attribute not allowed for `%s'");#else	  error_with_decl (node,		  "section attributes are not supported for this target");#endif	  break;	case A_ALIGNED:	  {	    tree align_expr	      = (args ? TREE_VALUE (args)		 : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));	    int align;	    /* Strip any NOPs of any kind.  */	    while (TREE_CODE (align_expr) == NOP_EXPR		   || TREE_CODE (align_expr) == CONVERT_EXPR		   || TREE_CODE (align_expr) == NON_LVALUE_EXPR)	      align_expr = TREE_OPERAND (align_expr, 0);	  	    if (TREE_CODE (align_expr) != INTEGER_CST)	      {		error ("requested alignment is not a constant");		continue;	      }	    align = TREE_INT_CST_LOW (align_expr) * BITS_PER_UNIT;	    if (exact_log2 (align) == -1)	      error ("requested alignment is not a power of 2");	    else if (is_type)	      TYPE_ALIGN (type) = align;	    else if (TREE_CODE (decl) != VAR_DECL		     && TREE_CODE (decl) != FIELD_DECL)	      error_with_decl (decl,			       "alignment may not be specified for `%s'");	    else	      DECL_ALIGN (decl) = align;	  }	  break;	case A_FORMAT:	  {	    tree format_type = TREE_VALUE (args);	    tree format_num_expr = TREE_VALUE (TREE_CHAIN (args));	    tree first_arg_num_expr	      = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));	    int format_num;	    int first_arg_num;	    int is_scan;	    tree argument;	    int arg_num;		    if (TREE_CODE (decl) != FUNCTION_DECL)	      {		error_with_decl (decl,			 "argument format specified for non-function `%s'");		continue;	      }		    if (TREE_CODE (format_type) == IDENTIFIER_NODE		&& (!strcmp (IDENTIFIER_POINTER (format_type), "printf")		    || !strcmp (IDENTIFIER_POINTER (format_type),				"__printf__")))	      is_scan = 0;	    else if (TREE_CODE (format_type) == IDENTIFIER_NODE		     && (!strcmp (IDENTIFIER_POINTER (format_type), "scanf")			 || !strcmp (IDENTIFIER_POINTER (format_type),				     "__scanf__")))	      is_scan = 1;	    else if (TREE_CODE (format_type) == IDENTIFIER_NODE)	      {		error ("`%s' is an unrecognized format function type",		       IDENTIFIER_POINTER (format_type));		continue;	      }	    else	      {		error ("unrecognized format specifier");		continue;	      }	    /* Strip any conversions from the string index and first arg number	       and verify they are constants.  */	    while (TREE_CODE (format_num_expr) == NOP_EXPR		   || TREE_CODE (format_num_expr) == CONVERT_EXPR		   || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)	      format_num_expr = TREE_OPERAND (format_num_expr, 0);	    while (TREE_CODE (first_arg_num_expr) == NOP_EXPR		   || TREE_CODE (first_arg_num_expr) == CONVERT_EXPR		   || TREE_CODE (first_arg_num_expr) == NON_LVALUE_EXPR)	      first_arg_num_expr = TREE_OPERAND (first_arg_num_expr, 0);	    if (TREE_CODE (format_num_expr) != INTEGER_CST		|| TREE_CODE (first_arg_num_expr) != INTEGER_CST)	      {		error ("format string has non-constant operand number");		continue;	      }	    format_num = TREE_INT_CST_LOW (format_num_expr);	    first_arg_num = TREE_INT_CST_LOW (first_arg_num_expr);	    if (first_arg_num != 0 && first_arg_num <= format_num)	      {		error ("format string arg follows the args to be formatted");		continue;	      }	    /* If a parameter list is specified, verify that the format_num	       argument is actually a string, in case the format attribute	       is in error.  */	    argument = TYPE_ARG_TYPES (type);	    if (argument)	      {		for (arg_num = 1; ; ++arg_num)		  {		    if (argument == 0 || arg_num == format_num)		      break;		    argument = TREE_CHAIN (argument);		  }		if (! argument		    || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE		  || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))		      != char_type_node))		  {		    error ("format string arg not a string type");		    continue;		  }		if (first_arg_num != 0)		  {		    /* Verify that first_arg_num points to the last arg,		       the ...  */		    while (argument)		      arg_num++, argument = TREE_CHAIN (argument);		  if (arg_num != first_arg_num)		    {		      error ("args to be formatted is not ...");		      continue;		    }		  }	      }	    record_function_format (DECL_NAME (decl),				    DECL_ASSEMBLER_NAME (decl),				    is_scan, format_num, first_arg_num);	    break;	  }	case A_FORMAT_ARG:	  {	    tree format_num_expr = TREE_VALUE (args);	    int format_num, arg_num;	    tree argument;		    if (TREE_CODE (decl) != FUNCTION_DECL)	      {		error_with_decl (decl,			 "argument format specified for non-function `%s'");		continue;	      }		    /* Strip any conversions from the first arg number and verify it	       is a constant.  */	    while (TREE_CODE (format_num_expr) == NOP_EXPR		   || TREE_CODE (format_num_expr) == CONVERT_EXPR		   || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)	      format_num_expr = TREE_OPERAND (format_num_expr, 0);	    if (TREE_CODE (format_num_expr) != INTEGER_CST)	      {		error ("format string has non-constant operand number");		continue;	      }	    format_num = TREE_INT_CST_LOW (format_num_expr);	    /* If a parameter list is specified, verify that the format_num	       argument is actually a string, in case the format attribute	       is in error.  */	    argument = TYPE_ARG_TYPES (type);	    if (argument)	      {		for (arg_num = 1; ; ++arg_num)		  {		    if (argument == 0 || arg_num == format_num)		      break;		    argument = TREE_CHAIN (argument);		  }		if (! argument		    || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE		  || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))		      != char_type_node))		  {		    error ("format string arg not a string type");		    continue;		  }	      }	    if (TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) != POINTER_TYPE		|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (TREE_TYPE (decl))))		    != char_type_node))	      {		error ("function does not return string type");		continue;	      }	    record_international_format (DECL_NAME (decl),					 DECL_ASSEMBLER_NAME (decl),					 format_num);	    break;	  }	case A_WEAK:	  declare_weak (decl);	  break;	case A_ALIAS:	  if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))	      || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))	    error_with_decl (decl,			     "`%s' defined both normally and as an alias");	  else if (decl_function_context (decl) == 0)	    {	      tree id = get_identifier (TREE_STRING_POINTER					(TREE_VALUE (args)));	      if (TREE_CODE (decl) == FUNCTION_DECL)		DECL_INITIAL (decl) = error_mark_node;	      else		DECL_EXTERNAL (decl) = 0;	      assemble_alias (decl, id);	    }	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	}    }}/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two   lists.  SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).   The head of the declspec list is stored in DECLSPECS.   The head of the attribute list is stored in PREFIX_ATTRIBUTES.   Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of   the list elements.  We drop the containing TREE_LIST nodes and link the   resulting attributes together the way decl_attributes expects them.  */voidsplit_specs_attrs (specs_attrs, declspecs, prefix_attributes)     tree specs_attrs;     tree *declspecs, *prefix_attributes;{  tree t, s, a, next, specs, attrs;  /* This can happen in c++ (eg: decl: typespec initdecls ';').  */  if (specs_attrs != NULL_TREE      && TREE_CODE (specs_attrs) != TREE_LIST)    {      *declspecs = specs_attrs;      *prefix_attributes = NULL_TREE;      return;    }  /* Remember to keep the lists in the same order, element-wise.  */  specs = s = NULL_TREE;  attrs = a = NULL_TREE;  for (t = specs_attrs; t; t = next)    {      next = TREE_CHAIN (t);      /* Declspecs have a non-NULL TREE_VALUE.  */      if (TREE_VALUE (t) != NULL_TREE)	{	  if (specs == NULL_TREE)	    specs = s = t;	  else	    {	      TREE_CHAIN (s) = t;	      s = t;	    }	}      else	{	  if (attrs == NULL_TREE)	    attrs = a = TREE_PURPOSE (t);	  else	    {	      TREE_CHAIN (a) = TREE_PURPOSE (t);	      a = TREE_PURPOSE (t);	    }	  /* More attrs can be linked here, move A to the end.  */	  while (TREE_CHAIN (a) != NULL_TREE)	    a = TREE_CHAIN (a);	}    }  /* Terminate the lists.  */  if (s != NULL_TREE)    TREE_CHAIN (s) = NULL_TREE;  if (a != NULL_TREE)    TREE_CHAIN (a) = NULL_TREE;  /* All done.  */  *declspecs = specs;  *prefix_attributes = attrs;}/* Check a printf/fprintf/sprintf/scanf/fscanf/sscanf format against   a parameter list.  */#define T_I	&integer_type_node#define T_L	&long_integer_type_node#define T_LL	&long_long_integer_type_node

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?