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

📄 c-common.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Subroutines shared by all languages that are variants of C.   Copyright (C) 1992 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */#include "config.h"#include "tree.h"#include "c-lex.h"#include "c-tree.h"#include "flags.h"#include <stdio.h>/* Make bindings for __FUNCTION__ and __PRETTY_FUNCTION__.  */voiddeclare_function_name (){  tree decl, init;  char *name, *printable_name;  if (current_function_decl == NULL)    {      name = "";      printable_name = "top level";    }  else    {      char *kind = "function";      if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE)	kind = "method";      /* Allow functions to be nameless (such as artificial ones).  */      if (DECL_NAME (current_function_decl))        name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));      else	name = "";      printable_name = (*decl_printable_name) (current_function_decl, &kind);    }  push_obstacks_nochange ();  decl = build_decl (VAR_DECL, get_identifier ("__FUNCTION__"),		     char_array_type_node);  TREE_STATIC (decl) = 1;  TREE_READONLY (decl) = 1;  DECL_SOURCE_LINE (decl) = 0;  DECL_IN_SYSTEM_HEADER (decl) = 1;  DECL_IGNORED_P (decl) = 1;  init = build_string (strlen (name) + 1, name);  TREE_TYPE (init) = char_array_type_node;  DECL_INITIAL (decl) = init;  finish_decl (pushdecl (decl), init, NULL_TREE);  push_obstacks_nochange ();  decl = build_decl (VAR_DECL, get_identifier ("__PRETTY_FUNCTION__"),		     char_array_type_node);  TREE_STATIC (decl) = 1;  TREE_READONLY (decl) = 1;  DECL_SOURCE_LINE (decl) = 0;  DECL_IN_SYSTEM_HEADER (decl) = 1;  DECL_IGNORED_P (decl) = 1;  init = build_string (strlen (printable_name) + 1, printable_name);  TREE_TYPE (init) = char_array_type_node;  DECL_INITIAL (decl) = init;  finish_decl (pushdecl (decl), init, NULL_TREE);}/* Given a chain of STRING_CST nodes,   concatenate them into one STRING_CST   and give it a suitable array-of-chars data type.  */treecombine_strings (strings)     tree strings;{  register tree value, t;  register int length = 1;  int wide_length = 0;  int wide_flag = 0;  int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;  int nchars;  if (TREE_CHAIN (strings))    {      /* More than one in the chain, so concatenate.  */      register char *p, *q;      /* Don't include the \0 at the end of each substring,	 except for the last one.	 Count wide strings and ordinary strings separately.  */      for (t = strings; t; t = TREE_CHAIN (t))	{	  if (TREE_TYPE (t) == wchar_array_type_node)	    {	      wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes);	      wide_flag = 1;	    }	  else	    length += (TREE_STRING_LENGTH (t) - 1);	}      /* If anything is wide, the non-wides will be converted,	 which makes them take more space.  */      if (wide_flag)	length = length * wchar_bytes + wide_length;      p = savealloc (length);      /* Copy the individual strings into the new combined string.	 If the combined string is wide, convert the chars to ints	 for any individual strings that are not wide.  */      q = p;      for (t = strings; t; t = TREE_CHAIN (t))	{	  int len = (TREE_STRING_LENGTH (t)		     - ((TREE_TYPE (t) == wchar_array_type_node)			? wchar_bytes : 1));	  if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)	    {	      bcopy (TREE_STRING_POINTER (t), q, len);	      q += len;	    }	  else	    {	      int i;	      for (i = 0; i < len; i++)		((int *) q)[i] = TREE_STRING_POINTER (t)[i];	      q += len * wchar_bytes;	    }	}      if (wide_flag)	{	  int i;	  for (i = 0; i < wchar_bytes; i++)	    *q++ = 0;	}      else	*q = 0;      value = make_node (STRING_CST);      TREE_STRING_POINTER (value) = p;      TREE_STRING_LENGTH (value) = length;      TREE_CONSTANT (value) = 1;    }  else    {      value = strings;      length = TREE_STRING_LENGTH (value);      if (TREE_TYPE (value) == wchar_array_type_node)	wide_flag = 1;    }  /* Compute the number of elements, for the array type.  */   nchars = wide_flag ? length / wchar_bytes : length;  /* Create the array type for the string constant.     -Wwrite-strings says make the string constant an array of const char     so that copying it to a non-const pointer will get a warning.  */  if (warn_write_strings      && (! flag_traditional  && ! flag_writable_strings))    {      tree elements	= build_type_variant (wide_flag ? wchar_type_node : char_type_node,			      1, 0);      TREE_TYPE (value)	= build_array_type (elements,			    build_index_type (build_int_2 (nchars - 1, 0)));    }  else    TREE_TYPE (value)      = build_array_type (wide_flag ? wchar_type_node : char_type_node,			  build_index_type (build_int_2 (nchars - 1, 0)));  TREE_CONSTANT (value) = 1;  TREE_STATIC (value) = 1;  return value;}/* Process the attributes listed in ATTRIBUTES   and install them in DECL.  */voiddecl_attributes (decl, attributes)     tree decl, attributes;{  tree a;  for (a = attributes; a; a = TREE_CHAIN (a))    if (TREE_VALUE (a) == get_identifier ("packed"))      {	if (TREE_CODE (decl) == FIELD_DECL)	  DECL_PACKED (decl) = 1;	/* We can't set DECL_PACKED for a VAR_DECL, because the bit is	   used for DECL_REGISTER.  It wouldn't mean anything anyway.  */      }    else if (TREE_VALUE (a) != 0	     && TREE_CODE (TREE_VALUE (a)) == TREE_LIST	     && TREE_PURPOSE (TREE_VALUE (a)) == get_identifier ("mode"))      {	int i;	char *specified_name	  = IDENTIFIER_POINTER (TREE_VALUE (TREE_VALUE (a)));	/* Give this decl a type with the specified mode.  */	for (i = 0; i < NUM_MACHINE_MODES; i++)	  if (!strcmp (specified_name, GET_MODE_NAME (i)))	    {	      tree type		= type_for_mode (i, TREE_UNSIGNED (TREE_TYPE (decl)));	      if (type != 0)		{		  TREE_TYPE (decl) = type;		  DECL_SIZE (decl) = 0;		  layout_decl (decl, 0);		}	      else		error ("no data type for mode `%s'", specified_name);	      break;	    }	if (i == NUM_MACHINE_MODES)	  error ("unknown machine mode `%s'", specified_name);      }    else if (TREE_VALUE (a) != 0	     && TREE_CODE (TREE_VALUE (a)) == TREE_LIST	     && TREE_PURPOSE (TREE_VALUE (a)) == get_identifier ("aligned"))      {	int align = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (a)))		    * BITS_PER_UNIT;		if (exact_log2 (align) == -1)	  error_with_decl (decl,			   "requested alignment of `%s' is not a power of 2");	else if (TREE_CODE (decl) != VAR_DECL		 && TREE_CODE (decl) != FIELD_DECL)	  error_with_decl (decl,			   "alignment specified for `%s'");	else	  DECL_ALIGN (decl) = align;      }    else if (TREE_VALUE (a) != 0	     && TREE_CODE (TREE_VALUE (a)) == TREE_LIST	     && TREE_PURPOSE (TREE_VALUE (a)) == get_identifier ("format"))      {        tree list = TREE_VALUE (TREE_VALUE (a));        tree format_type = TREE_PURPOSE (list);	int format_num = TREE_INT_CST_LOW (TREE_PURPOSE (TREE_VALUE (list)));	int first_arg_num = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (list)));	int is_scan;		if (TREE_CODE (decl) != FUNCTION_DECL)	  {	    error_with_decl (decl,			     "argument format specified for non-function `%s'");	    return;	  }		if (format_type == get_identifier ("printf"))	  is_scan = 0;	else if (format_type == get_identifier ("scanf"))	  is_scan = 1;	else	  {	    error_with_decl (decl, "unrecognized format specifier for `%s'");	    return;	  }		if (first_arg_num != 0 && first_arg_num <= format_num)	  {	    error_with_decl (decl,		"format string arg follows the args to be formatted, for `%s'");	    return;	  }		record_format_info (DECL_NAME (decl), is_scan, format_num,			    first_arg_num);      }}/* Print a warning if a constant expression had overflow in folding.  */voidconstant_expression_warning (value)     tree value;{  if (TREE_CODE (value) == INTEGER_CST && TREE_CONSTANT_OVERFLOW (value))    pedwarn ("overflow in constant expression");}voidc_expand_expr_stmt (expr)     tree expr;{  /* Do default conversion if safe and possibly important,     in case within ({...}).  */  if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE && lvalue_p (expr))      || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)    expr = default_conversion (expr);  if (TREE_TYPE (expr) != error_mark_node      && TYPE_SIZE (TREE_TYPE (expr)) == 0      && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)    error ("expression statement has incomplete type");  expand_expr_stmt (expr);}/* Validate the expression after `case' and apply default promotions.  */treecheck_case_value (value)     tree value;{  if (value == NULL_TREE)    return value;  /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */  STRIP_TYPE_NOPS (value);  if (TREE_CODE (value) != INTEGER_CST      && value != error_mark_node)    {      error ("case label does not reduce to an integer constant");      value = error_mark_node;    }  else    /* Promote char or short to int.  */    value = default_conversion (value);  constant_expression_warning (value);  return value;}/* Return an integer type with BITS bits of precision,   that is unsigned if UNSIGNEDP is nonzero, otherwise signed.  */treetype_for_size (bits, unsignedp)     unsigned bits;     int unsignedp;{  if (bits == TYPE_PRECISION (signed_char_type_node))    return unsignedp ? unsigned_char_type_node : signed_char_type_node;  if (bits == TYPE_PRECISION (short_integer_type_node))    return unsignedp ? short_unsigned_type_node : short_integer_type_node;  if (bits == TYPE_PRECISION (integer_type_node))    return unsignedp ? unsigned_type_node : integer_type_node;  if (bits == TYPE_PRECISION (long_integer_type_node))    return unsignedp ? long_unsigned_type_node : long_integer_type_node;  if (bits == TYPE_PRECISION (long_long_integer_type_node))    return (unsignedp ? long_long_unsigned_type_node	    : long_long_integer_type_node);  if (bits <= TYPE_PRECISION (intQI_type_node))    return unsignedp ? unsigned_intQI_type_node : intQI_type_node;  if (bits <= TYPE_PRECISION (intHI_type_node))    return unsignedp ? unsigned_intHI_type_node : intHI_type_node;  if (bits <= TYPE_PRECISION (intSI_type_node))    return unsignedp ? unsigned_intSI_type_node : intSI_type_node;  if (bits <= TYPE_PRECISION (intDI_type_node))    return unsignedp ? unsigned_intDI_type_node : intDI_type_node;  return 0;}/* Return a data type that has machine mode MODE.   If the mode is an integer,   then UNSIGNEDP selects between signed and unsigned types.  */treetype_for_mode (mode, unsignedp)     enum machine_mode mode;     int unsignedp;{  if (mode == TYPE_MODE (signed_char_type_node))    return unsignedp ? unsigned_char_type_node : signed_char_type_node;  if (mode == TYPE_MODE (short_integer_type_node))    return unsignedp ? short_unsigned_type_node : short_integer_type_node;  if (mode == TYPE_MODE (integer_type_node))    return unsignedp ? unsigned_type_node : integer_type_node;  if (mode == TYPE_MODE (long_integer_type_node))    return unsignedp ? long_unsigned_type_node : long_integer_type_node;  if (mode == TYPE_MODE (long_long_integer_type_node))    return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;  if (mode == TYPE_MODE (intQI_type_node))    return unsignedp ? unsigned_intQI_type_node : intQI_type_node;  if (mode == TYPE_MODE (intHI_type_node))    return unsignedp ? unsigned_intHI_type_node : intHI_type_node;  if (mode == TYPE_MODE (intSI_type_node))    return unsignedp ? unsigned_intSI_type_node : intSI_type_node;  if (mode == TYPE_MODE (intDI_type_node))    return unsignedp ? unsigned_intDI_type_node : intDI_type_node;  if (mode == TYPE_MODE (float_type_node))    return float_type_node;  if (mode == TYPE_MODE (double_type_node))    return double_type_node;  if (mode == TYPE_MODE (long_double_type_node))    return long_double_type_node;  if (mode == TYPE_MODE (build_pointer_type (char_type_node)))    return build_pointer_type (char_type_node);  if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))    return build_pointer_type (integer_type_node);  return 0;}/* Print an error message for invalid operands to arith operation CODE.   NOP_EXPR is used as a special case (see truthvalue_conversion).  */voidbinary_op_error (code)     enum tree_code code;{  register char *opname;  switch (code)    {    case NOP_EXPR:      error ("invalid truth-value expression");      return;    case PLUS_EXPR:      opname = "+"; break;    case MINUS_EXPR:      opname = "-"; break;    case MULT_EXPR:      opname = "*"; break;    case MAX_EXPR:      opname = "max"; break;    case MIN_EXPR:      opname = "min"; break;    case EQ_EXPR:      opname = "=="; break;    case NE_EXPR:      opname = "!="; break;    case LE_EXPR:      opname = "<="; break;    case GE_EXPR:      opname = ">="; break;    case LT_EXPR:      opname = "<"; break;    case GT_EXPR:      opname = ">"; break;    case LSHIFT_EXPR:      opname = "<<"; break;    case RSHIFT_EXPR:      opname = ">>"; break;    case TRUNC_MOD_EXPR:    case FLOOR_MOD_EXPR:      opname = "%"; break;    case TRUNC_DIV_EXPR:    case FLOOR_DIV_EXPR:      opname = "/"; break;    case BIT_AND_EXPR:      opname = "&"; break;    case BIT_IOR_EXPR:      opname = "|"; break;    case TRUTH_ANDIF_EXPR:      opname = "&&"; break;    case TRUTH_ORIF_EXPR:      opname = "||"; break;    case BIT_XOR_EXPR:      opname = "^"; break;    case LROTATE_EXPR:    case RROTATE_EXPR:      opname = "rotate"; break;    }  error ("invalid operands to binary %s", opname);}/* Subroutine of build_binary_op, used for comparison operations.   See if the operands have both been converted from subword integer types   and, if so, perhaps change them both back to their original type.   The arguments of this function are all pointers to local variables

⌨️ 快捷键说明

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