FreeBSD/contrib/gcc/cp/tree.c
/* Make a variant of TYPE, qualified with the TYPE_QUALS.  Handles
   arrays correctly.  In particular, if TYPE is an array of T's, and
   TYPE_QUALS is non-empty, returns an array of qualified T's.

   FLAGS determines how to deal with illformed qualifications. If
   tf_ignore_bad_quals is set, then bad qualifications are dropped
   (this is permitted if TYPE was introduced via a typedef or template
   type parameter). If bad qualifications are dropped and tf_warning
   is set, then a warning is issued for non-const qualifications.  If
   tf_ignore_bad_quals is not set and tf_error is not set, we
   return error_mark_node. Otherwise, we issue an error, and ignore
   the qualifications.

   Qualification of a reference type is valid when the reference came
   via a typedef or template type argument. [dcl.ref] No such
   dispensation is provided for qualifying a function type.  [dcl.fct]
   DR 295 queries this and the proposed resolution brings it into line
   with qualifying a reference.  We implement the DR.  We also behave
   in a similar manner for restricting non-pointer types.  */
Make a variant of TYPE, qualified with the TYPE_QUALS.  Handles
arrays correctly.  In particular, if TYPE is an array of T's, and
TYPE_QUALS is non-empty, returns an array of qualified T's.

FLAGS determines how to deal with illformed qualifications. If
tf_ignore_bad_quals is set, then bad qualifications are dropped
(this is permitted if TYPE was introduced via a typedef or template
type parameter). If bad qualifications are dropped and tf_warning
is set, then a warning is issued for non-const qualifications.  If
tf_ignore_bad_quals is not set and tf_error is not set, we
return error_mark_node. Otherwise, we issue an error, and ignore
the qualifications.

Qualification of a reference type is valid when the reference came
via a typedef or template type argument. [dcl.ref] No such
dispensation is provided for qualifying a function type.  [dcl.fct]
DR 295 queries this and the proposed resolution brings it into line
with qualifying a reference.  We implement the DR.  We also behave
in a similar manner for restricting non-pointer types.
Make a variant of TYPE qualified with the TYPE_QUALS . Handles arrays correctly . In particular if TYPE is an array of T ' s and TYPE_QUALS is non - empty returns an array of qualified T ' s . FLAGS determines how to deal with illformed qualifications . If tf_ignore_bad_quals is set then bad qualifications are dropped ( this is permitted if TYPE was introduced via a typedef or template type parameter ) . If bad qualifications are dropped and tf_warning is set then a warning is issued for non - const qualifications . If tf_ignore_bad_quals is not set and tf_error is not set we return error_mark_node . Otherwise we issue an error and ignore the qualifications . Qualification of a reference type is valid when the reference came via a typedef or template type argument . [ dcl . ref ] No such dispensation is provided for qualifying a function type . [ dcl . fct ] DR 295 queries this and the proposed resolution brings it into line with qualifying a reference . We implement the DR . We also behave in a similar manner for restricting non - pointer types .
tree
cp_build_qualified_type_real (tree type,
			      int type_quals,
			      tsubst_flags_t complain)
{
  tree result;
  int bad_quals = TYPE_UNQUALIFIED;
  if (type == error_mark_node)
    return type;
  if (type_quals == cp_type_quals (type))
    return type;
  if (TREE_CODE (type) == ARRAY_TYPE)
    {
      tree t;
      tree element_type
	= cp_build_qualified_type_real (TREE_TYPE (type),
					type_quals,
					complain);
      if (element_type == error_mark_node)
	return error_mark_node;
      for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
	if (cp_type_quals (t) == type_quals
	    && TYPE_NAME (t) == TYPE_NAME (type)
	    && TYPE_CONTEXT (t) == TYPE_CONTEXT (type))
	  break;
      if (!t)
	{
	  t = build_variant_type_copy (type);
	  TREE_TYPE (t) = element_type;
	}
      TYPE_NEEDS_CONSTRUCTING (t)
	= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (element_type));
      TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
	= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (element_type));
      return t;
    }
  else if (TYPE_PTRMEMFUNC_P (type))
    {
      tree t;
      t = TYPE_PTRMEMFUNC_FN_TYPE (type);
      t = cp_build_qualified_type_real (t, type_quals, complain);
      return build_ptrmemfunc_type (t);
    }
  if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
      && (TREE_CODE (type) == REFERENCE_TYPE
	  || TREE_CODE (type) == METHOD_TYPE))
    {
      bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
      type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
    }
  if ((type_quals & TYPE_QUAL_RESTRICT)
      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
      && TREE_CODE (type) != TYPENAME_TYPE
      && TREE_CODE (type) != FUNCTION_TYPE
      && !POINTER_TYPE_P (type))
    {
      bad_quals |= TYPE_QUAL_RESTRICT;
      type_quals &= ~TYPE_QUAL_RESTRICT;
    }
  if (bad_quals == TYPE_UNQUALIFIED)
    ;
  else if (!(complain & (tf_error | tf_ignore_bad_quals)))
    return error_mark_node;
  else
    {
      if (complain & tf_ignore_bad_quals)
	bad_quals &= ~TYPE_QUAL_CONST;
      if (bad_quals)
	{
	  tree bad_type = build_qualified_type (ptr_type_node, bad_quals);
	  if (!(complain & tf_ignore_bad_quals))
	    error ("%qV qualifiers cannot be applied to %qT",
		   bad_type, type);
	}
    }
  result = build_qualified_type (type, type_quals);
  if (result != type
      && TREE_CODE (type) == POINTER_TYPE
      && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
    TYPE_LANG_SPECIFIC (result) = NULL;
  return result;
}
tree cp_build_qualified_type_real ( tree type , int type_quals , tsubst_flags_t complain ) { tree result ; int bad_quals = TYPE_UNQUALIFIED ; if ( type == error_mark_node ) return type ; if ( type_quals == cp_type_quals ( type ) ) return type ; if ( TREE_CODE ( type ) == ARRAY_TYPE ) { tree t ; tree element_type = cp_build_qualified_type_real ( TREE_TYPE ( type ) , type_quals , complain ) ; if ( element_type == error_mark_node ) return error_mark_node ; for ( t = TYPE_MAIN_VARIANT ( type ) ; t ; t = TYPE_NEXT_VARIANT ( t ) ) if ( cp_type_quals ( t ) == type_quals && TYPE_NAME ( t ) == TYPE_NAME ( type ) && TYPE_CONTEXT ( t ) == TYPE_CONTEXT ( type ) ) break ; if ( ! t ) { t = build_variant_type_copy ( type ) ; TREE_TYPE ( t ) = element_type ; } TYPE_NEEDS_CONSTRUCTING ( t ) = TYPE_NEEDS_CONSTRUCTING ( TYPE_MAIN_VARIANT ( element_type ) ) ; TYPE_HAS_NONTRIVIAL_DESTRUCTOR ( t ) = TYPE_HAS_NONTRIVIAL_DESTRUCTOR ( TYPE_MAIN_VARIANT ( element_type ) ) ; return t ; } else if ( TYPE_PTRMEMFUNC_P ( type ) ) { tree t ; t = TYPE_PTRMEMFUNC_FN_TYPE ( type ) ; t = cp_build_qualified_type_real ( t , type_quals , complain ) ; return build_ptrmemfunc_type ( t ) ; } if ( type_quals & ( TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE ) && ( TREE_CODE ( type ) == REFERENCE_TYPE || TREE_CODE ( type ) == METHOD_TYPE ) ) { bad_quals |= type_quals & ( TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE ) ; type_quals &= ~ ( TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE ) ; } if ( ( type_quals & TYPE_QUAL_RESTRICT ) && TREE_CODE ( type ) != TEMPLATE_TYPE_PARM && TREE_CODE ( type ) != TYPENAME_TYPE && TREE_CODE ( type ) != FUNCTION_TYPE && ! POINTER_TYPE_P ( type ) ) { bad_quals |= TYPE_QUAL_RESTRICT ; type_quals &= ~ TYPE_QUAL_RESTRICT ; } if ( bad_quals == TYPE_UNQUALIFIED ) ; else if ( ! ( complain & ( tf_error | tf_ignore_bad_quals ) ) ) return error_mark_node ; else { if ( complain & tf_ignore_bad_quals ) bad_quals &= ~ TYPE_QUAL_CONST ; if ( bad_quals ) { tree bad_type = build_qualified_type ( ptr_type_node , bad_quals ) ; if ( ! ( complain & tf_ignore_bad_quals ) ) error ( " " , bad_type , type ) ; } } result = build_qualified_type ( type , type_quals ) ; if ( result != type && TREE_CODE ( type ) == POINTER_TYPE && TREE_CODE ( TREE_TYPE ( type ) ) == METHOD_TYPE ) TYPE_LANG_SPECIFIC ( result ) = NULL ; return result ; }
Make a variant of TYPE, qualified with the TYPE_QUALS.
Make a variant of TYPE qualified with the TYPE_QUALS .
/* In C++, the qualification really applies to the array element
	 type.  Obtain the appropriately qualified element type.  */ /* See if we already have an identically qualified type.  */ /* Make a new array type, just like the old one, but with the
	     appropriately qualified element type.  */ /* Even if we already had this variant, we update
	 TYPE_NEEDS_CONSTRUCTING and TYPE_HAS_NONTRIVIAL_DESTRUCTOR in case
	 they changed since the variant was originally created.

	 This seems hokey; if there is some way to use a previous
	 variant *without* coming through here,
	 TYPE_NEEDS_CONSTRUCTING will never be updated.  */ /* For a pointer-to-member type, we can't just return a
	 cv-qualified version of the RECORD_TYPE.  If we do, we
	 haven't changed the field that contains the actual pointer to
	 a method, and so TYPE_PTRMEMFUNC_FN_TYPE will be wrong.  */ /* A reference or method type shall not be cv qualified.
     [dcl.ref], [dct.fct]  */ /* A restrict-qualified type must be a pointer (or reference)
     to object or incomplete type, or a function type. */ /*OK*/ /* We're not going to warn about constifying things that can't
	   be constified.  */ /* Retrieve (or create) the appropriately qualified variant.  */ /* If this was a pointer-to-method type, and we just made a copy,
     then we need to unshare the record that holds the cached
     pointer-to-member-function type, because these will be distinct
     between the unqualified and qualified types.  */