Ejemplo n.º 1
0
void xml_type_ref(tree t, int indent, FILE *out)
{
    const char *tag;

    /* For non-aggregates, just print the type.  It can't
     * be that bad. */
    if (!AGGREGATE_TYPE_P(t))
        return xml_type(t, NULL, indent, out);

    switch (TREE_CODE(t))
    {
    case UNION_TYPE:
        tag = "union";
        goto write;

    case RECORD_TYPE:
        tag = "structure";
        goto write;

    case ARRAY_TYPE:
        tag = "array";
        goto write;

    default:
        abort();
    }

write:
    lh_memo_type(t);
    fprintf(out, "%s<%s id='%u'", spc(indent), tag, TYPE_UID(t));
    xml_type_quals(TYPE_QUALS(t), out);
    xml_location(t, out);
    fprintf(out, "/>\n");
}
Ejemplo n.º 2
0
void xml_type_aggregate(tree t, int indent, FILE *out)
{
    tree member;
    const char *tag = NULL;

    switch (TREE_CODE(t))
    {
    case UNION_TYPE:
        tag = "union";
    case RECORD_TYPE:
        if (!tag) tag = "structure";
        fprintf(out, "%s<%s id='%d'", spc(indent), tag, TYPE_UID(t));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        fprintf(out, ">\n");

        for (member = TYPE_FIELDS(t);
                member;
                member = TREE_CHAIN(member))
        {
            xml_member_decl(member, indent + INDENT, out);
        }

        fprintf(out, "%s</%s>\n", spc(indent), tag);
        break;

    case ARRAY_TYPE:
        fprintf(out, "%s<array id='%d'", spc(indent), TYPE_UID(t));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        fprintf(out, ">\n");
        fprintf(out, "%s<type>\n", spc(indent + INDENT));
        xml_type(TREE_TYPE(t), NULL, indent + INDENT + INDENT, out);
        fprintf(out, "%s</type>\n", spc(indent + INDENT));
        if (TYPE_DOMAIN(t))
        {
            fprintf(out, "%s<domain>\n", spc(indent + INDENT));
            xml_type(TYPE_DOMAIN(t), NULL, indent + INDENT + INDENT, out);
            fprintf(out, "%s</domain>\n", spc(indent + INDENT));
        }
        fprintf(out, "%s</array>\n", spc(indent));
        break;

    default:
        abort();
    }
}
Ejemplo n.º 3
0
Archivo: cvt.c Proyecto: Fokycnuk/gcc
tree
convert_lvalue (tree totype, tree expr)
{
  totype = cp_build_qualified_type (totype, TYPE_QUALS (TREE_TYPE (expr)));
  totype = build_reference_type (totype);
  expr = convert_to_reference (totype, expr, CONV_IMPLICIT, LOOKUP_NORMAL,
			       NULL_TREE);
  return convert_from_reference (expr);
}
Ejemplo n.º 4
0
GLOBAL TypeQual MergeTypeQuals(TypeQual left, TypeQual right, Coord coord)
{
    TypeQual scl, scr, dql, dqr, tql, tqr;
    TypeQual result = 0;

    scl = STORAGE_CLASS(left);
    scr = STORAGE_CLASS(right);

    if (scl != 0 && scr != 0) {
      if (scl == scr) { /* scl == scr == single storage class */
	WarningCoord(4, coord, "redundant storage class");
      } 
      else {
	char namel[20], namer[20];
	TQtoText(namel, scl);
	TQtoText(namer, scr);
	SyntaxErrorCoord(coord,"conflicting storage classes `%s' and `%s'",
			 namel, namer);
      }
      result |= scl;
    }
    else {
      result |= scl | scr;
    }

    dql = DECL_QUALS(left) & ~scl;
    dqr = DECL_QUALS(right) & ~scr;
    result |= (dql | dqr);

    tql = TYPE_QUALS(left);
    tqr = TYPE_QUALS(right);

    if ((tql & tqr) != 0) {
	WarningCoord(4, coord, "redundant type qualifier");
    }
    result |= (tql | tqr);
    return(result);
}
Ejemplo n.º 5
0
void
pp_c_type_qualifier_list (c_pretty_printer *pp, tree t)
{
   int qualifiers;

  if (!TYPE_P (t))
    t = TREE_TYPE (t);

  qualifiers = TYPE_QUALS (t);
  if (qualifiers & TYPE_QUAL_CONST)
    pp_c_cv_qualifier (pp, "const");
  if (qualifiers & TYPE_QUAL_VOLATILE)
    pp_c_cv_qualifier (pp, "volatile");
  if (qualifiers & TYPE_QUAL_RESTRICT)
    pp_c_cv_qualifier (pp, flag_isoc99 ? "restrict" : "__restrict__");
}
Ejemplo n.º 6
0
static const char *
gen_type (const char *ret_val, tree t, formals_style style)
{
  tree chain_p;

  /* If there is a typedef name for this type, use it.  */
  if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
    data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
  else
    {
      switch (TREE_CODE (t))
	{
	case POINTER_TYPE:
	  if (TYPE_READONLY (t))
	    ret_val = concat ("const ", ret_val, NULL);
	  if (TYPE_VOLATILE (t))
	    ret_val = concat ("volatile ", ret_val, NULL);

	  ret_val = concat ("*", ret_val, NULL);

	  if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
	    ret_val = concat ("(", ret_val, ")", NULL);

	  ret_val = gen_type (ret_val, TREE_TYPE (t), style);

	  return ret_val;

	case ARRAY_TYPE:
	  if (!COMPLETE_TYPE_P (t) || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
	    ret_val = gen_type (concat (ret_val, "[]", NULL),
				TREE_TYPE (t), style);
	  else if (int_size_in_bytes (t) == 0)
	    ret_val = gen_type (concat (ret_val, "[0]", NULL),
				TREE_TYPE (t), style);
	  else
	    {
	      int size = (int_size_in_bytes (t) / int_size_in_bytes (TREE_TYPE (t)));
	      char buff[10];
	      sprintf (buff, "[%d]", size);
	      ret_val = gen_type (concat (ret_val, buff, NULL),
				  TREE_TYPE (t), style);
	    }
	  break;

	case FUNCTION_TYPE:
	  ret_val = gen_type (concat (ret_val,
				      gen_formal_list_for_type (t, style),
				      NULL),
			      TREE_TYPE (t), style);
	  break;

	case IDENTIFIER_NODE:
	  data_type = IDENTIFIER_POINTER (t);
	  break;

	/* The following three cases are complicated by the fact that a
	   user may do something really stupid, like creating a brand new
	   "anonymous" type specification in a formal argument list (or as
	   part of a function return type specification).  For example:

		int f (enum { red, green, blue } color);

	   In such cases, we have no name that we can put into the prototype
	   to represent the (anonymous) type.  Thus, we have to generate the
	   whole darn type specification.  Yuck!  */

	case RECORD_TYPE:
	  if (TYPE_NAME (t))
	    data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
	  else
	    {
	      data_type = "";
	      chain_p = TYPE_FIELDS (t);
	      while (chain_p)
		{
		  data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
				      NULL);
		  chain_p = TREE_CHAIN (chain_p);
		  data_type = concat (data_type, "; ", NULL);
		}
	      data_type = concat ("{ ", data_type, "}", NULL);
	    }
	  data_type = concat ("struct ", data_type, NULL);
	  break;

	case UNION_TYPE:
	  if (TYPE_NAME (t))
	    data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
	  else
	    {
	      data_type = "";
	      chain_p = TYPE_FIELDS (t);
	      while (chain_p)
		{
		  data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
				      NULL);
		  chain_p = TREE_CHAIN (chain_p);
		  data_type = concat (data_type, "; ", NULL);
		}
	      data_type = concat ("{ ", data_type, "}", NULL);
	    }
	  data_type = concat ("union ", data_type, NULL);
	  break;

	case ENUMERAL_TYPE:
	  if (TYPE_NAME (t))
	    data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
	  else
	    {
	      data_type = "";
	      chain_p = TYPE_VALUES (t);
	      while (chain_p)
		{
		  data_type = concat (data_type,
			IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)), NULL);
		  chain_p = TREE_CHAIN (chain_p);
		  if (chain_p)
		    data_type = concat (data_type, ", ", NULL);
		}
	      data_type = concat ("{ ", data_type, " }", NULL);
	    }
	  data_type = concat ("enum ", data_type, NULL);
	  break;

	case TYPE_DECL:
	  data_type = IDENTIFIER_POINTER (DECL_NAME (t));
	  break;

	case INTEGER_TYPE:
	  data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
	  /* Normally, `unsigned' is part of the deal.  Not so if it comes
	     with a type qualifier.  */
	  if (TYPE_UNSIGNED (t) && TYPE_QUALS (t))
	    data_type = concat ("unsigned ", data_type, NULL);
	  break;

	case REAL_TYPE:
	  data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
	  break;

	case VOID_TYPE:
	  data_type = "void";
	  break;

	case ERROR_MARK:
	  data_type = "[ERROR]";
	  break;

	default:
	  gcc_unreachable ();
	}
    }
  if (TYPE_READONLY (t))
    ret_val = concat ("const ", ret_val, NULL);
  if (TYPE_VOLATILE (t))
    ret_val = concat ("volatile ", ret_val, NULL);
  if (TYPE_RESTRICT (t))
    ret_val = concat ("restrict ", ret_val, NULL);
  return ret_val;
}
Ejemplo n.º 7
0
tree
decl_attributes (tree *node, tree attributes, int flags)
{
  tree a;
  tree returned_attrs = NULL_TREE;

  if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
    return NULL_TREE;

  if (!attributes_initialized)
    init_attributes ();

  /* If this is a function and the user used #pragma GCC optimize, add the
     options to the attribute((optimize(...))) list.  */
  if (TREE_CODE (*node) == FUNCTION_DECL && current_optimize_pragma)
    {
      tree cur_attr = lookup_attribute ("optimize", attributes);
      tree opts = copy_list (current_optimize_pragma);

      if (! cur_attr)
	attributes
	  = tree_cons (get_identifier ("optimize"), opts, attributes);
      else
	TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
    }

  if (TREE_CODE (*node) == FUNCTION_DECL
      && optimization_current_node != optimization_default_node
      && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node))
    DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node;

  /* If this is a function and the user used #pragma GCC target, add the
     options to the attribute((target(...))) list.  */
  if (TREE_CODE (*node) == FUNCTION_DECL
      && current_target_pragma
      && targetm.target_option.valid_attribute_p (*node, NULL_TREE,
						  current_target_pragma, 0))
    {
      tree cur_attr = lookup_attribute ("target", attributes);
      tree opts = copy_list (current_target_pragma);

      if (! cur_attr)
	attributes = tree_cons (get_identifier ("target"), opts, attributes);
      else
	TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
    }

  /* A "naked" function attribute implies "noinline" and "noclone" for
     those targets that support it.  */
  if (TREE_CODE (*node) == FUNCTION_DECL
      && attributes
      && lookup_attribute_spec (get_identifier ("naked"))
      && lookup_attribute ("naked", attributes) != NULL)
    {
      if (lookup_attribute ("noinline", attributes) == NULL)
	attributes = tree_cons (get_identifier ("noinline"), NULL, attributes);

      if (lookup_attribute ("noclone", attributes) == NULL)
	attributes = tree_cons (get_identifier ("noclone"),  NULL, attributes);
    }

  targetm.insert_attributes (*node, &attributes);

  for (a = attributes; a; a = TREE_CHAIN (a))
    {
      tree ns = get_attribute_namespace (a);
      tree name = get_attribute_name (a);
      tree args = TREE_VALUE (a);
      tree *anode = node;
      const struct attribute_spec *spec =
	lookup_scoped_attribute_spec (ns, name);
      bool no_add_attrs = 0;
      int fn_ptr_quals = 0;
      tree fn_ptr_tmp = NULL_TREE;

      if (spec == NULL)
	{
	  if (!(flags & (int) ATTR_FLAG_BUILT_IN))
	    {
	      if (ns == NULL_TREE || !cxx11_attribute_p (a))
		warning (OPT_Wattributes, "%qE attribute directive ignored",
			 name);
	      else
		warning (OPT_Wattributes,
			 "%<%E::%E%> scoped attribute directive ignored",
			 ns, name);
	    }
	  continue;
	}
      else if (list_length (args) < spec->min_length
	       || (spec->max_length >= 0
		   && list_length (args) > spec->max_length))
	{
	  error ("wrong number of arguments specified for %qE attribute",
		 name);
	  continue;
	}
      gcc_assert (is_attribute_p (spec->name, name));

      if (TYPE_P (*node)
	  && cxx11_attribute_p (a)
	  && !(flags & ATTR_FLAG_TYPE_IN_PLACE))
	{
	  /* This is a c++11 attribute that appertains to a
	     type-specifier, outside of the definition of, a class
	     type.  Ignore it.  */
	  warning (OPT_Wattributes, "attribute ignored");
	  inform (input_location,
		  "an attribute that appertains to a type-specifier "
		  "is ignored");
	  continue;
	}

      if (spec->decl_required && !DECL_P (*anode))
	{
	  if (flags & ((int) ATTR_FLAG_DECL_NEXT
		       | (int) ATTR_FLAG_FUNCTION_NEXT
		       | (int) ATTR_FLAG_ARRAY_NEXT))
	    {
	      /* Pass on this attribute to be tried again.  */
	      returned_attrs = tree_cons (name, args, returned_attrs);
	      continue;
	    }
	  else
	    {
	      warning (OPT_Wattributes, "%qE attribute does not apply to types",
		       name);
	      continue;
	    }
	}

      /* If we require a type, but were passed a decl, set up to make a
	 new type and update the one in the decl.  ATTR_FLAG_TYPE_IN_PLACE
	 would have applied if we'd been passed a type, but we cannot modify
	 the decl's type in place here.  */
      if (spec->type_required && DECL_P (*anode))
	{
	  anode = &TREE_TYPE (*anode);
	  flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
	}

      if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
	  && TREE_CODE (*anode) != METHOD_TYPE)
	{
	  if (TREE_CODE (*anode) == POINTER_TYPE
	      && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
		  || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
	    {
	      /* OK, this is a bit convoluted.  We can't just make a copy
		 of the pointer type and modify its TREE_TYPE, because if
		 we change the attributes of the target type the pointer
		 type needs to have a different TYPE_MAIN_VARIANT.  So we
		 pull out the target type now, frob it as appropriate, and
		 rebuild the pointer type later.

		 This would all be simpler if attributes were part of the
		 declarator, grumble grumble.  */
	      fn_ptr_tmp = TREE_TYPE (*anode);
	      fn_ptr_quals = TYPE_QUALS (*anode);
	      anode = &fn_ptr_tmp;
	      flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
	    }
	  else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
	    {
	      /* Pass on this attribute to be tried again.  */
	      returned_attrs = tree_cons (name, args, returned_attrs);
	      continue;
	    }

	  if (TREE_CODE (*anode) != FUNCTION_TYPE
	      && TREE_CODE (*anode) != METHOD_TYPE)
	    {
	      warning (OPT_Wattributes,
		       "%qE attribute only applies to function types",
		       name);
	      continue;
	    }
	}

      if (TYPE_P (*anode)
	  && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
	  && TYPE_SIZE (*anode) != NULL_TREE)
	{
	  warning (OPT_Wattributes, "type attributes ignored after type is already defined");
	  continue;
	}

      if (spec->handler != NULL)
	{
	  int cxx11_flag =
	    cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;

	  returned_attrs = chainon ((*spec->handler) (anode, name, args,
						      flags|cxx11_flag,
						      &no_add_attrs),
				    returned_attrs);
	}

      /* Layout the decl in case anything changed.  */
      if (spec->type_required && DECL_P (*node)
	  && (TREE_CODE (*node) == VAR_DECL
	      || TREE_CODE (*node) == PARM_DECL
	      || TREE_CODE (*node) == RESULT_DECL))
	relayout_decl (*node);

      if (!no_add_attrs)
	{
	  tree old_attrs;
	  tree a;

	  if (DECL_P (*anode))
	    old_attrs = DECL_ATTRIBUTES (*anode);
	  else
	    old_attrs = TYPE_ATTRIBUTES (*anode);

	  for (a = lookup_attribute (spec->name, old_attrs);
	       a != NULL_TREE;
	       a = lookup_attribute (spec->name, TREE_CHAIN (a)))
	    {
	      if (simple_cst_equal (TREE_VALUE (a), args) == 1)
		break;
	    }

	  if (a == NULL_TREE)
	    {
	      /* This attribute isn't already in the list.  */
	      if (DECL_P (*anode))
		DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
	      else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
		{
		  TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
		  /* If this is the main variant, also push the attributes
		     out to the other variants.  */
		  if (*anode == TYPE_MAIN_VARIANT (*anode))
		    {
		      tree variant;
		      for (variant = *anode; variant;
			   variant = TYPE_NEXT_VARIANT (variant))
			{
			  if (TYPE_ATTRIBUTES (variant) == old_attrs)
			    TYPE_ATTRIBUTES (variant)
			      = TYPE_ATTRIBUTES (*anode);
			  else if (!lookup_attribute
				   (spec->name, TYPE_ATTRIBUTES (variant)))
			    TYPE_ATTRIBUTES (variant) = tree_cons
			      (name, args, TYPE_ATTRIBUTES (variant));
			}
		    }
		}
	      else
		*anode = build_type_attribute_variant (*anode,
						       tree_cons (name, args,
								  old_attrs));
	    }
	}

      if (fn_ptr_tmp)
	{
	  /* Rebuild the function pointer type and put it in the
	     appropriate place.  */
	  fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
	  if (fn_ptr_quals)
	    fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals);
	  if (DECL_P (*node))
	    TREE_TYPE (*node) = fn_ptr_tmp;
	  else
	    {
	      gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
	      *node = fn_ptr_tmp;
	    }
	}
    }

  return returned_attrs;
}
Ejemplo n.º 8
0
void xml_type(tree t, tree opt_decl, int indent, FILE *out)
{
    tree a = NULL;

    if (AGGREGATE_TYPE_P(t))
        return xml_type_ref(t, indent, out);

    switch (TREE_CODE(t))
    {
    case POINTER_TYPE:
        fprintf(out, "%s<addr-of", spc(indent));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        fprintf(out, ">\n");
        xml_type(TREE_TYPE(t), NULL, indent + INDENT, out);
        fprintf(out, "%s</addr-of>\n", spc(indent));
        break;

    case REAL_TYPE:
        fprintf(out, "%s<float", spc(indent));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        fprintf(out, " precision='%d'", TYPE_PRECISION(t));
        fprintf(out, " />\n");
        break;

    case INTEGER_TYPE:
        fprintf(out, "%s<integer", spc(indent));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        if (TYPE_UNSIGNED(t))
            fprintf(out, " unsigned='1'");
        fprintf(out, " precision='%d'", TYPE_PRECISION(t));

        /* TREE_TYPE here indicates that there is an interesting domain. */
        if (TREE_TYPE(t) && TYPE_MIN_VALUE(t))
            fprintf(out, (TYPE_UNSIGNED(t) ? " min='%llu'" : " min='%lld'"), double_int_to_ll(TREE_INT_CST(TYPE_MIN_VALUE(t))));
        if (TREE_TYPE(t) && TYPE_MAX_VALUE(t))
            fprintf(out, (TYPE_UNSIGNED(t) ? " max='%llu'" : " max='%lld'"), double_int_to_ll(TREE_INT_CST(TYPE_MAX_VALUE(t))));
        fprintf(out, " />\n");
        break;

    case VOID_TYPE:
        fprintf(out, "%s<void />\n", spc(indent));
        break;

    case BOOLEAN_TYPE:
        fprintf(out, "%s<boolean />\n", spc(indent));
        break;

    case RESULT_DECL:
        fprintf(out, "%s<result />\n", spc(indent));
        break;

    case ENUMERAL_TYPE:
        /* TODO: finish this (output tags). */
        fprintf(out, "%s<enum", spc(indent));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        fprintf(out, " />\n");
        break;

    case METHOD_TYPE:
    case FUNCTION_TYPE:
        fprintf(out, "%s<function", spc(indent));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        xml_type_attribs(TYPE_ATTRIBUTES(t),
                         (opt_decl && TREE_THIS_VOLATILE(opt_decl)) ? "noreturn" : NULL,
                         out);
        indent += INDENT;
        fprintf(out, ">\n%s<return>\n", spc(indent));
        xml_type(TREE_TYPE(t), NULL, indent + INDENT, out);
        fprintf(out, "%s</return>\n", spc(indent));

        /* varargs if last is not void. */
        for (a = TYPE_ARG_TYPES(t); a && TREE_CHAIN(a); a = TREE_CHAIN(a))
            ;

        fprintf(out, "%s<arguments %s>\n", spc(indent),
                (!a || TREE_CODE(TREE_VALUE(a)) == VOID_TYPE) ? "" : "varargs='1' ");

        for (a = TYPE_ARG_TYPES(t); a; a = TREE_CHAIN(a))
        {
            xml_type(TREE_VALUE(a), NULL, indent + INDENT, out);
        }

        fprintf(out, "%s</arguments>\n", spc(indent));
        indent -= INDENT;
        fprintf(out, "%s</function>\n", spc(indent));
        break;

    case REFERENCE_TYPE:
        fprintf(stderr, "lighthouse warning: ignoring unhandled tree type '%s'.\n",
                tree_code_name[TREE_CODE(t)]);
        break;

    default:
        fprintf(stderr, "failing: unhandled tree type %s\n",
                tree_code_name[TREE_CODE(t)]);
        assert(0);
        abort();
    }
}
Ejemplo n.º 9
0
/* Check whether the arguments in ARGLIST match the function type
   DEF_TYPE. Return the number of argument types which required
   conversion/promotion in order to make it match.
   0 stands for a perfect match - all operand types match without changes
   INT_MAX stands for a mismatch.  */
static int
s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex,
			  vec<tree, va_gc> *arglist)
{
  unsigned int i;
  int match_type = 0;

  for (i = 0; i < vec_safe_length (arglist); i++)
    {
      tree b_arg_type = s390_builtin_types[s390_builtin_ov_types[typeindex][i + 1]];
      tree in_arg = (*arglist)[i];
      tree in_type = TREE_TYPE (in_arg);

      if (TREE_CODE (b_arg_type) == VECTOR_TYPE)
	{
	  /* Vector types have to match precisely.  */
	  if (b_arg_type != in_type
	      && TYPE_MAIN_VARIANT (b_arg_type) != TYPE_MAIN_VARIANT (in_type))
	    goto mismatch;
	}

      if (lang_hooks.types_compatible_p (in_type, b_arg_type))
	continue;

      if (lang_hooks.types_compatible_p (
	    lang_hooks.types.type_promotes_to (in_type),
	    lang_hooks.types.type_promotes_to (b_arg_type)))
	{
	  match_type++;
	  continue;
	}

      /* In this stage the C++ frontend would go ahead trying to find
	 implicit conversion chains for the argument to match the
	 target type.  We will mimic this here only for our limited
	 subset of argument types.  */
      if (TREE_CODE (b_arg_type) == INTEGER_TYPE
	  && TREE_CODE (in_type) == INTEGER_TYPE)
	{
	  match_type++;
	  continue;
	}

      /* If the incoming pointer argument has more qualifiers than the
	 argument type it can still be an imperfect match.  */
      if (POINTER_TYPE_P (b_arg_type) && POINTER_TYPE_P (in_type)
	  && !(TYPE_QUALS (TREE_TYPE (in_type))
	       & ~TYPE_QUALS (TREE_TYPE (b_arg_type)))
	  && (TYPE_QUALS (TREE_TYPE (b_arg_type))
	      & ~TYPE_QUALS (TREE_TYPE (in_type))))
	{
	  tree qual_in_type =
	    build_qualified_type (TREE_TYPE (in_type),
				  TYPE_QUALS (TREE_TYPE (b_arg_type)));

	  if (lang_hooks.types_compatible_p (qual_in_type,
					     TREE_TYPE (b_arg_type)))
	    {
	      match_type++;
	      continue;
	    }
	}

    mismatch:
      if (TARGET_DEBUG_ARG)
	fprintf (stderr, " mismatch in operand: %d\n", i + 1);
      return INT_MAX;
    }

  return match_type;
}
Ejemplo n.º 10
0
/* 
   NodeTypeQuals, NodeStorageClass, and NodeDeclQuals only work
   properly AFTER the parse is over, when storage class and
   decl qualifiers have been moved to the decl.
*/
GLOBAL TypeQual NodeTypeQuals(Node *node)
{ return TYPE_QUALS(NodeTq(node)); }
Ejemplo n.º 11
0
static void
do_build_copy_constructor (tree fndecl)
{
  tree parm = FUNCTION_FIRST_USER_PARM (fndecl);
  bool move_p = DECL_MOVE_CONSTRUCTOR_P (fndecl);

  parm = convert_from_reference (parm);

  if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)
      && is_empty_class (current_class_type))
    /* Don't copy the padding byte; it might not have been allocated
       if *this is a base subobject.  */;
  else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
    {
      tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
      finish_expr_stmt (t);
    }
  else
    {
      tree fields = TYPE_FIELDS (current_class_type);
      tree member_init_list = NULL_TREE;
      int cvquals = cp_type_quals (TREE_TYPE (parm));
      int i;
      tree binfo, base_binfo;
      tree init;
      VEC(tree,gc) *vbases;

      /* Initialize all the base-classes with the parameter converted
	 to their type so that we get their copy constructor and not
	 another constructor that takes current_class_type.  We must
	 deal with the binfo's directly as a direct base might be
	 inaccessible due to ambiguity.  */
      for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
	   VEC_iterate (tree, vbases, i, binfo); i++)
	{
	  init = build_base_path (PLUS_EXPR, parm, binfo, 1);
	  if (move_p)
	    init = move (init);
	  member_init_list
	    = tree_cons (binfo,
			 build_tree_list (NULL_TREE, init),
			 member_init_list);
	}

      for (binfo = TYPE_BINFO (current_class_type), i = 0;
	   BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
	{
	  if (BINFO_VIRTUAL_P (base_binfo))
	    continue;

	  init = build_base_path (PLUS_EXPR, parm, base_binfo, 1);
	  if (move_p)
	    init = move (init);
	  member_init_list
	    = tree_cons (base_binfo,
			 build_tree_list (NULL_TREE, init),
			 member_init_list);
	}

      for (; fields; fields = TREE_CHAIN (fields))
	{
	  tree field = fields;
	  tree expr_type;

	  if (TREE_CODE (field) != FIELD_DECL)
	    continue;

	  expr_type = TREE_TYPE (field);
	  if (DECL_NAME (field))
	    {
	      if (VFIELD_NAME_P (DECL_NAME (field)))
		continue;
	    }
	  else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type))
	    /* Just use the field; anonymous types can't have
	       nontrivial copy ctors or assignment ops.  */;
	  else
	    continue;

	  /* Compute the type of "init->field".  If the copy-constructor
	     parameter is, for example, "const S&", and the type of
	     the field is "T", then the type will usually be "const
	     T".  (There are no cv-qualified variants of reference
	     types.)  */
	  if (TREE_CODE (expr_type) != REFERENCE_TYPE)
	    {
	      int quals = cvquals;

	      if (DECL_MUTABLE_P (field))
		quals &= ~TYPE_QUAL_CONST;
	      quals |= TYPE_QUALS (expr_type);
	      expr_type = cp_build_qualified_type (expr_type, quals);
	    }

	  init = build3 (COMPONENT_REF, expr_type, parm, field, NULL_TREE);
	  if (move_p && TREE_CODE (expr_type) != REFERENCE_TYPE)
	    init = move (init);
	  init = build_tree_list (NULL_TREE, init);

	  member_init_list = tree_cons (field, init, member_init_list);
	}
      finish_mem_initializers (member_init_list);
    }
}