c-common.c

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

C
2,225
字号
/* Subroutines shared by all languages that are variants of C.   Copyright (C) 1992, 93, 94, 95, 96, 1997 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, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "config.h"#include <stdio.h>#include "tree.h"#include "c-lex.h"#include "c-tree.h"#include "flags.h"#include "obstack.h"#include <ctype.h>#ifndef WCHAR_TYPE_SIZE#ifdef INT_TYPE_SIZE#define WCHAR_TYPE_SIZE INT_TYPE_SIZE#else#define WCHAR_TYPE_SIZE	BITS_PER_WORD#endif#endifextern struct obstack permanent_obstack;/* Nonzero means the expression being parsed will never be evaluated.   This is a count, since unevaluated expressions can nest.  */int skip_evaluation;enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,	    A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,	    A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS};static void declare_hidden_char_array	PROTO((char *, char *));static void add_attribute		PROTO((enum attrs, char *,					       int, int, int));static void init_attributes		PROTO((void));static void record_international_format	PROTO((tree, tree, int));/* Keep a stack of if statements.  The value recorded is the number of   compound statements seen up to the if keyword.  */static int *if_stack;/* Amount of space in the if statement stack.  */static int if_stack_space = 0;/* Stack pointer.  */static int if_stack_pointer = 0;voidc_expand_start_cond (cond, exitflag, compstmt_count)     tree cond;     int exitflag;     int compstmt_count;{  /* Make sure there is enough space on the stack.  */  if (if_stack_space == 0)    {      if_stack_space = 10;      if_stack = (int *)xmalloc (10 * sizeof (int));    }  else if (if_stack_space == if_stack_pointer)    {      if_stack_space += 10;      if_stack = (int *)xrealloc (if_stack, if_stack_space * sizeof (int));    }    /* Record this if statement.  */  if_stack[if_stack_pointer++] = compstmt_count;  expand_start_cond (cond, exitflag);}voidc_expand_end_cond (){  if_stack_pointer--;  expand_end_cond ();}voidc_expand_start_else (){  if (warn_parentheses      && if_stack_pointer > 1      && if_stack[if_stack_pointer - 1] == if_stack[if_stack_pointer - 2])    warning ("suggest explicit braces to avoid ambiguous `else'");    /* This if statement can no longer cause a dangling else.  */  if_stack[if_stack_pointer - 1]--;  expand_start_else ();}/* Make bindings for __FUNCTION__ and __PRETTY_FUNCTION__.  */voiddeclare_function_name (){  char *name, *printable_name;  if (current_function_decl == NULL)    {      name = "";      printable_name = "top level";    }  else    {      /* 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, 2);    }  declare_hidden_char_array ("__FUNCTION__", name);  declare_hidden_char_array ("__PRETTY_FUNCTION__", printable_name);}static voiddeclare_hidden_char_array (name, value)     char *name, *value;{  tree decl, type, init;  int vlen;  /* If the default size of char arrays isn't big enough for the name,     or if we want to give warnings for large objects, make a bigger one.  */  vlen = strlen (value) + 1;  type = char_array_type_node;  if (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TREE_TYPE (type))) < vlen      || warn_larger_than)    type = build_array_type (char_type_node,			     build_index_type (build_int_2 (vlen, 0)));  push_obstacks_nochange ();  decl = build_decl (VAR_DECL, get_identifier (name), type);  TREE_STATIC (decl) = 1;  TREE_READONLY (decl) = 1;  TREE_ASM_WRITTEN (decl) = 1;  DECL_SOURCE_LINE (decl) = 0;  DECL_ARTIFICIAL (decl) = 1;  DECL_IN_SYSTEM_HEADER (decl) = 1;  DECL_IGNORED_P (decl) = 1;  init = build_string (vlen, value);  TREE_TYPE (init) = type;  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++)		{		  if (WCHAR_TYPE_SIZE == HOST_BITS_PER_SHORT)		    ((short *) q)[i] = TREE_STRING_POINTER (t)[i];		  else		    ((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;}/* To speed up processing of attributes, we maintain an array of   IDENTIFIER_NODES and the corresponding attribute types.  *//* Array to hold attribute information.  */static struct {enum attrs id; tree name; int min, max, decl_req;} attrtab[50];static int attrtab_idx = 0;/* Add an entry to the attribute table above.  */static voidadd_attribute (id, string, min_len, max_len, decl_req)     enum attrs id;     char *string;     int min_len, max_len;     int decl_req;{  char buf[100];  attrtab[attrtab_idx].id = id;  attrtab[attrtab_idx].name = get_identifier (string);  attrtab[attrtab_idx].min = min_len;  attrtab[attrtab_idx].max = max_len;  attrtab[attrtab_idx++].decl_req = decl_req;  sprintf (buf, "__%s__", string);  attrtab[attrtab_idx].id = id;  attrtab[attrtab_idx].name = get_identifier (buf);  attrtab[attrtab_idx].min = min_len;  attrtab[attrtab_idx].max = max_len;  attrtab[attrtab_idx++].decl_req = decl_req;}/* Initialize attribute table.  */static voidinit_attributes (){  add_attribute (A_PACKED, "packed", 0, 0, 0);  add_attribute (A_NOCOMMON, "nocommon", 0, 0, 1);  add_attribute (A_COMMON, "common", 0, 0, 1);  add_attribute (A_NORETURN, "noreturn", 0, 0, 1);  add_attribute (A_NORETURN, "volatile", 0, 0, 1);  add_attribute (A_UNUSED, "unused", 0, 0, 0);  add_attribute (A_CONST, "const", 0, 0, 1);  add_attribute (A_T_UNION, "transparent_union", 0, 0, 0);  add_attribute (A_CONSTRUCTOR, "constructor", 0, 0, 1);  add_attribute (A_DESTRUCTOR, "destructor", 0, 0, 1);  add_attribute (A_MODE, "mode", 1, 1, 1);  add_attribute (A_SECTION, "section", 1, 1, 1);  add_attribute (A_ALIGNED, "aligned", 0, 1, 0);  add_attribute (A_FORMAT, "format", 3, 3, 1);  add_attribute (A_FORMAT_ARG, "format_arg", 1, 1, 1);  add_attribute (A_WEAK, "weak", 0, 0, 1);  add_attribute (A_ALIAS, "alias", 1, 1, 1);}/* Process the attributes listed in ATTRIBUTES and PREFIX_ATTRIBUTES   and install them in NODE, which is either a DECL (including a TYPE_DECL)   or a TYPE.  PREFIX_ATTRIBUTES can appear after the declaration specifiers   and declaration modifiers but before the declaration proper.  */voiddecl_attributes (node, attributes, prefix_attributes)     tree node, attributes, prefix_attributes;{  tree decl = 0, type;  int is_type;  tree a;  if (attrtab_idx == 0)    init_attributes ();  if (TREE_CODE_CLASS (TREE_CODE (node)) == 'd')    {      decl = node;      type = TREE_TYPE (decl);      is_type = TREE_CODE (node) == TYPE_DECL;    }  else if (TREE_CODE_CLASS (TREE_CODE (node)) == 't')    type = node, is_type = 1;  attributes = chainon (prefix_attributes, attributes);  for (a = attributes; a; a = TREE_CHAIN (a))    {      tree name = TREE_PURPOSE (a);      tree args = TREE_VALUE (a);      int i;      enum attrs id;            for (i = 0; i < attrtab_idx; i++)	if (attrtab[i].name == name)	  break;      if (i == attrtab_idx)	{	  if (! valid_machine_attribute (name, args, decl, type))	    warning ("`%s' attribute directive ignored",		     IDENTIFIER_POINTER (name));	  else if (decl != 0)	    type = TREE_TYPE (decl);	  continue;	}      else if (attrtab[i].decl_req && decl == 0)	{	  warning ("`%s' attribute does not apply to types",		   IDENTIFIER_POINTER (name));	  continue;	}      else if (list_length (args) < attrtab[i].min	       || list_length (args) > attrtab[i].max)	{	  error ("wrong number of arguments specified for `%s' attribute",		 IDENTIFIER_POINTER (name));	  continue;	}      id = attrtab[i].id;      switch (id)	{	case A_PACKED:	  if (is_type)	    TYPE_PACKED (type) = 1;	  else 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	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_NOCOMMON:	  if (TREE_CODE (decl) == VAR_DECL)	    DECL_COMMON (decl) = 0;	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_COMMON:	  if (TREE_CODE (decl) == VAR_DECL)	    DECL_COMMON (decl) = 1;	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_NORETURN:	  if (TREE_CODE (decl) == FUNCTION_DECL)	    TREE_THIS_VOLATILE (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),				     TREE_READONLY (TREE_TYPE (type)), 1));	  else	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));	  break;	case A_UNUSED:	  if (is_type)	    TREE_USED (type) = 1;	  else if (TREE_CODE (decl) == PARM_DECL 

⌨️ 快捷键说明

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