diff options
Diffstat (limited to 'gcc/c-decl.c')
| -rw-r--r-- | gcc/c-decl.c | 79 | 
1 files changed, 79 insertions, 0 deletions
| diff --git a/gcc/c-decl.c b/gcc/c-decl.c index b2f7bbe42d2..e358ff6408c 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -2797,6 +2797,85 @@ set_array_declarator_inner (tree decl, tree type, bool abstract_p)    return decl;  } +/* 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.  */ + +void +split_specs_attrs (tree specs_attrs, tree *declspecs, tree *prefix_attributes) +{ +  tree t, s, a, next, specs, attrs; + +  /* This can happen after an __extension__ in pedantic mode.  */ +  if (specs_attrs != NULL_TREE +      && TREE_CODE (specs_attrs) == INTEGER_CST) +    { +      *declspecs = NULL_TREE; +      *prefix_attributes = NULL_TREE; +      return; +    } + +  /* 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; +	    } +	} +      /* The TREE_PURPOSE may also be empty in the case of +	 __attribute__(()).  */ +      else if (TREE_PURPOSE (t) != NULL_TREE) +	{ +	  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; +} +  /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */  tree | 

