Exemplo n.º 1
0
static void readonly_warning(expression e, char *context)
{
  char buf[80];

  strcpy(buf, context);

  if (is_field_ref(e))
    {
      field_ref field = CAST(field_ref, e);

      if (type_readonly(field->arg1->type))
	readonly_warning(field->arg1, context);
      else
	{
	  strcat(buf, " of read-only member `%s'");
	  pedwarn(buf, field->cstring.data);
	}
    }
  else if (is_identifier(e))
    {
      strcat(buf, " of read-only variable `%s'");
      pedwarn(buf, CAST(identifier, e)->cstring.data);
    }
  else
    pedwarn ("%s of read-only location", buf);
}
Exemplo n.º 2
0
static void warn_for_assignment(const char *msg, const char *opname,
				const char *function, int argnum)
{
  static char argstring[] = "passing arg %d of `%s'";
  static char argnofun[] =  "passing arg %d";

  if (opname == 0)
    {
      char *tmpname;

      if (function)
	{
	  /* Function name is known; supply it.  */
	  tmpname = (char *)alloca(strlen(function) + sizeof(argstring) + 25 /*%d*/ + 1);
	  sprintf(tmpname, argstring, argnum, function);
	}
      else
	{
	  /* Function name unknown (call through ptr); just give arg number.  */
	  tmpname = (char *)alloca(sizeof(argnofun) + 25 /*%d*/ + 1);
	  sprintf(tmpname, argnofun, argnum);
	}
      opname = tmpname;
    }
  pedwarn(msg, opname);
}
Exemplo n.º 3
0
void check_sizeof(expression result, type stype)
{
  if (type_function(stype))
    {
      if (pedantic || warn_pointer_arith)
	pedwarn("sizeof applied to a function type");
    }
  else if (type_void(stype))
    {
      if (pedantic || warn_pointer_arith)
	pedwarn("sizeof applied to a void type");
    }
  else if (type_incomplete(stype))
    error("sizeof applied to an incomplete type");

  result->type = size_t_type;
  result->cst = fold_sizeof(result, stype);
}
Exemplo n.º 4
0
/* Return TRUE if TTL and TTR are pointers to types that are equivalent,
   ignoring their qualifiers.  */
static bool compatible_pointer_targets(type ttl, type ttr, bool pedantic)
{
  int val;

  val = type_compatible_unqualified(ttl, ttr);

  if (val == 2 && pedantic)
    pedwarn("types are not quite compatible");
  return val != 0;
}
Exemplo n.º 5
0
bool valid_compare(type t1, type t2, expression e1)
{
  if (type_void(type_points_to(t1)))
    {
      if (pedantic && type_function(type_points_to(t2)) && !definite_null(e1))
	pedwarn("ANSI C forbids comparison of `void *' with function pointer");
      return TRUE;
    }
  return FALSE;
}
Exemplo n.º 6
0
static bool voidstar_conditional(type t1, type t2)
{
  if (type_void(t1))
    {
      if (pedantic && type_function(t2))
	pedwarn("ANSI C forbids conditional expr between `void *' and function pointer");
      return TRUE;
    }
  return FALSE;
}
Exemplo n.º 7
0
static bool pointerint_conditional(type t1, type t2, expression e2)
{
  if (type_pointer(t1) && type_integer(t2))
    {
      if (!definite_zero(e2))
	pedwarn("pointer/integer type mismatch in conditional expression");
      return TRUE;
    }
  return FALSE;
}
Exemplo n.º 8
0
type pointer_int_sum(type ptype, type itype)
{
  type pointed = type_points_to(ptype);

  if (type_void(pointed))
    {
      if (pedantic || warn_pointer_arith)
	pedwarn("pointer of type `void *' used in arithmetic");
    }
  else if (type_function(pointed))
    {
      if (pedantic || warn_pointer_arith)
	pedwarn("pointer to a function used in arithmetic");
    }
  else if (type_incomplete(pointed))
    error("arithmetic on pointer to an incomplete type");

  return ptype;
}
Exemplo n.º 9
0
expression make_label_address(location loc, id_label label)
{
  expression result = CAST(expression, new_label_address(parse_region, loc, label));

  use_label(label);

  result->type = ptr_void_type;
  result->cst = fold_label_address(result);

  if (pedantic)
    pedwarn("ANSI C forbids `&&'");

  return result;
}
Exemplo n.º 10
0
Arquivo: cvt.c Projeto: Fokycnuk/gcc
static void
warn_ref_binding (tree reftype, tree intype, tree decl)
{
  tree ttl = TREE_TYPE (reftype);
  
  if (!CP_TYPE_CONST_NON_VOLATILE_P (ttl))
    {
      const char *msg;

      if (CP_TYPE_VOLATILE_P (ttl) && decl)
	  msg = "initialization of volatile reference type `%#T' from rvalue of type `%T'";
      else if (CP_TYPE_VOLATILE_P (ttl))
	  msg = "conversion to volatile reference type `%#T' from rvalue of type `%T'";
      else if (decl)
	  msg = "initialization of non-const reference type `%#T' from rvalue of type `%T'";
      else
	  msg = "conversion to non-const reference type `%#T' from rvalue of type `%T'";

      pedwarn (msg, reftype, intype);
    }
}
Exemplo n.º 11
0
expression make_address_of(location loc, expression e)
{
  expression result = CAST(expression, new_address_of(parse_region, loc, e));

  result->type = error_type;

  if (e->type == error_type)
    ;
  else if (e->bitfield)
    error("attempt to take address of a bit-field structure member");
  else
    {
      if (e->isregister)
	pedwarn("address of a register variable requested");

      if (!(type_function(e->type) || e->lvalue))
	error("invalid lvalue in unary `&'");

      result->type = make_pointer_type(e->type);
      result->cst = e->static_address;
    }
  return result;
}
Exemplo n.º 12
0
/* Interpret TOKEN, a floating point number with FLAGS as classified
   by cpplib.  */
static tree
interpret_float (const cpp_token *token, unsigned int flags)
{
  tree type;
  tree value;
  REAL_VALUE_TYPE real;
  char *copy;
  size_t copylen;
  const char *type_name;

  /* FIXME: make %T work in error/warning, then we don't need type_name.  */
  if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
    {
      type = long_double_type_node;
      type_name = "long double";
    }
  else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL
	   || flag_single_precision_constant)
    {
      type = float_type_node;
      type_name = "float";
    }
  else
    {
      type = double_type_node;
      type_name = "double";
    }

  /* Copy the constant to a nul-terminated buffer.  If the constant
     has any suffixes, cut them off; REAL_VALUE_ATOF/ REAL_VALUE_HTOF
     can't handle them.  */
  copylen = token->val.str.len;
  if ((flags & CPP_N_WIDTH) != CPP_N_MEDIUM)
    /* Must be an F or L suffix.  */
    copylen--;
  if (flags & CPP_N_IMAGINARY)
    /* I or J suffix.  */
    copylen--;

  copy = (char *) alloca (copylen + 1);
  memcpy (copy, token->val.str.text, copylen);
  copy[copylen] = '\0';

  real_from_string (&real, copy);
  real_convert (&real, TYPE_MODE (type), &real);

  /* Both C and C++ require a diagnostic for a floating constant
     outside the range of representable values of its type.  Since we
     have __builtin_inf* to produce an infinity, it might now be
     appropriate for this to be a mandatory pedwarn rather than
     conditioned on -pedantic.  */
  if (REAL_VALUE_ISINF (real) && pedantic)
    pedwarn ("floating constant exceeds range of %<%s%>", type_name);

  /* Create a node with determined type and value.  */
  value = build_real (type, real);
  if (flags & CPP_N_IMAGINARY)
    value = build_complex (NULL_TREE, convert (type, integer_zero_node), value);

  return value;
}
Exemplo n.º 13
0
tree
add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
	     bool explicit_init_p)
{
  char *buf;
  tree type, member, name;
  bool vla = false;
  bool variadic = false;
  tree initializer = orig_init;

  if (PACK_EXPANSION_P (initializer))
    {
      initializer = PACK_EXPANSION_PATTERN (initializer);
      variadic = true;
    }

  if (TREE_CODE (initializer) == TREE_LIST)
    initializer = build_x_compound_expr_from_list (initializer, ELK_INIT,
						   tf_warning_or_error);
  type = TREE_TYPE (initializer);
  if (type == error_mark_node)
    return error_mark_node;

  if (array_of_runtime_bound_p (type))
    {
      vla = true;
      if (!by_reference_p)
	error ("array of runtime bound cannot be captured by copy, "
	       "only by reference");

      /* For a VLA, we capture the address of the first element and the
	 maximum index, and then reconstruct the VLA for the proxy.  */
      tree elt = cp_build_array_ref (input_location, initializer,
				     integer_zero_node, tf_warning_or_error);
      initializer = build_constructor_va (init_list_type_node, 2,
					  NULL_TREE, build_address (elt),
					  NULL_TREE, array_type_nelts (type));
      type = vla_capture_type (type);
    }
  else if (!dependent_type_p (type)
	   && variably_modified_type_p (type, NULL_TREE))
    {
      error ("capture of variable-size type %qT that is not an N3639 array "
	     "of runtime bound", type);
      if (TREE_CODE (type) == ARRAY_TYPE
	  && variably_modified_type_p (TREE_TYPE (type), NULL_TREE))
	inform (input_location, "because the array element type %qT has "
		"variable size", TREE_TYPE (type));
      type = error_mark_node;
    }
  else
    {
      type = lambda_capture_field_type (initializer, explicit_init_p);
      if (by_reference_p)
	{
	  type = build_reference_type (type);
	  if (!dependent_type_p (type) && !real_lvalue_p (initializer))
	    error ("cannot capture %qE by reference", initializer);
	}
      else
	{
	  /* Capture by copy requires a complete type.  */
	  type = complete_type (type);
	  if (!dependent_type_p (type) && !COMPLETE_TYPE_P (type))
	    {
	      error ("capture by copy of incomplete type %qT", type);
	      cxx_incomplete_type_inform (type);
	      return error_mark_node;
	    }
	}
    }

  /* Add __ to the beginning of the field name so that user code
     won't find the field with name lookup.  We can't just leave the name
     unset because template instantiation uses the name to find
     instantiated fields.  */
  buf = (char *) alloca (IDENTIFIER_LENGTH (id) + 3);
  buf[1] = buf[0] = '_';
  memcpy (buf + 2, IDENTIFIER_POINTER (id),
	  IDENTIFIER_LENGTH (id) + 1);
  name = get_identifier (buf);

  /* If TREE_TYPE isn't set, we're still in the introducer, so check
     for duplicates.  */
  if (!LAMBDA_EXPR_CLOSURE (lambda))
    {
      if (IDENTIFIER_MARKED (name))
	{
	  pedwarn (input_location, 0,
		   "already captured %qD in lambda expression", id);
	  return NULL_TREE;
	}
      IDENTIFIER_MARKED (name) = true;
    }

  if (variadic)
    type = make_pack_expansion (type);

  /* Make member variable.  */
  member = build_decl (input_location, FIELD_DECL, name, type);
  DECL_VLA_CAPTURE_P (member) = vla;

  if (!explicit_init_p)
    /* Normal captures are invisible to name lookup but uses are replaced
       with references to the capture field; we implement this by only
       really making them invisible in unevaluated context; see
       qualify_lookup.  For now, let's make explicitly initialized captures
       always visible.  */
    DECL_NORMAL_CAPTURE_P (member) = true;

  if (id == this_identifier)
    LAMBDA_EXPR_THIS_CAPTURE (lambda) = member;

  /* Add it to the appropriate closure class if we've started it.  */
  if (current_class_type
      && current_class_type == LAMBDA_EXPR_CLOSURE (lambda))
    finish_member_declaration (member);

  tree listmem = member;
  if (variadic)
    {
      listmem = make_pack_expansion (member);
      initializer = orig_init;
    }
  LAMBDA_EXPR_CAPTURE_LIST (lambda)
    = tree_cons (listmem, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));

  if (LAMBDA_EXPR_CLOSURE (lambda))
    return build_capture_proxy (member);
  /* For explicit captures we haven't started the function yet, so we wait
     and build the proxy from cp_parser_lambda_body.  */
  return NULL_TREE;
}
Exemplo n.º 14
0
/* Interpret TOKEN, an integer with FLAGS as classified by cpplib.  */
static tree
interpret_integer (const cpp_token *token, unsigned int flags)
{
  tree value, type;
  enum integer_type_kind itk;
  cpp_num integer;
  cpp_options *options = cpp_get_options (parse_in);

  integer = cpp_interpret_integer (parse_in, token, flags);
  integer = cpp_num_sign_extend (integer, options->precision);

  /* The type of a constant with a U suffix is straightforward.  */
  if (flags & CPP_N_UNSIGNED)
    itk = narrowest_unsigned_type (integer.low, integer.high, flags);
  else
    {
      /* The type of a potentially-signed integer constant varies
	 depending on the base it's in, the standard in use, and the
	 length suffixes.  */
      enum integer_type_kind itk_u
	= narrowest_unsigned_type (integer.low, integer.high, flags);
      enum integer_type_kind itk_s
	= narrowest_signed_type (integer.low, integer.high, flags);

      /* In both C89 and C99, octal and hex constants may be signed or
	 unsigned, whichever fits tighter.  We do not warn about this
	 choice differing from the traditional choice, as the constant
	 is probably a bit pattern and either way will work.  */
      if ((flags & CPP_N_RADIX) != CPP_N_DECIMAL)
	itk = MIN (itk_u, itk_s);
      else
	{
	  /* In C99, decimal constants are always signed.
	     In C89, decimal constants that don't fit in long have
	     undefined behavior; we try to make them unsigned long.
	     In GCC's extended C89, that last is true of decimal
	     constants that don't fit in long long, too.  */

	  itk = itk_s;
	  if (itk_s > itk_u && itk_s > itk_long)
	    {
	      if (!flag_isoc99)
		{
		  if (itk_u < itk_unsigned_long)
		    itk_u = itk_unsigned_long;
		  itk = itk_u;
		  warning (0, "this decimal constant is unsigned only in ISO C90");
		}
	      else
		warning (OPT_Wtraditional,
			 "this decimal constant would be unsigned in ISO C90");
	    }
	}
    }

  if (itk == itk_none)
    /* cpplib has already issued a warning for overflow.  */
    type = ((flags & CPP_N_UNSIGNED)
	    ? widest_unsigned_literal_type_node
	    : widest_integer_literal_type_node);
  else
    type = integer_types[itk];

  if (itk > itk_unsigned_long
      && (flags & CPP_N_WIDTH) != CPP_N_LARGE
      && !in_system_header && !flag_isoc99)
    pedwarn ("integer constant is too large for %qs type",
	     (flags & CPP_N_UNSIGNED) ? "unsigned long" : "long");

  value = build_int_cst_wide (type, integer.low, integer.high);

  /* Convert imaginary to a complex type.  */
  if (flags & CPP_N_IMAGINARY)
    value = build_complex (NULL_TREE, build_int_cst (type, 0), value);

  return value;
}
Exemplo n.º 15
0
Arquivo: cvt.c Projeto: Fokycnuk/gcc
tree
convert_to_void (tree expr, const char *implicit)
{
  if (expr == error_mark_node 
      || TREE_TYPE (expr) == error_mark_node)
    return error_mark_node;
  if (!TREE_TYPE (expr))
    return expr;
  if (invalid_nonstatic_memfn_p (expr))
    return error_mark_node;
  if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
    {
      error ("pseudo-destructor is not called");
      return error_mark_node;
    }
  if (VOID_TYPE_P (TREE_TYPE (expr)))
    return expr;
  switch (TREE_CODE (expr))
    {
    case COND_EXPR:
      {
        /* The two parts of a cond expr might be separate lvalues.  */
        tree op1 = TREE_OPERAND (expr,1);
        tree op2 = TREE_OPERAND (expr,2);
        tree new_op1 = convert_to_void
	  (op1, (implicit && !TREE_SIDE_EFFECTS (op2)
		 ? "second operand of conditional" : NULL));
        tree new_op2 = convert_to_void
	  (op2, (implicit && !TREE_SIDE_EFFECTS (op1)
		 ? "third operand of conditional" : NULL));
        
	expr = build (COND_EXPR, TREE_TYPE (new_op1),
		      TREE_OPERAND (expr, 0), new_op1, new_op2);
        break;
      }
    
    case COMPOUND_EXPR:
      {
        /* The second part of a compound expr contains the value.  */
        tree op1 = TREE_OPERAND (expr,1);
        tree new_op1 = convert_to_void
	  (op1, (implicit && !TREE_NO_UNUSED_WARNING (expr)
		 ? "right-hand operand of comma" : NULL));
        
        if (new_op1 != op1)
	  {
	    tree t = build (COMPOUND_EXPR, TREE_TYPE (new_op1),
			    TREE_OPERAND (expr, 0), new_op1);
	    expr = t;
	  }

        break;
      }
    
    case NON_LVALUE_EXPR:
    case NOP_EXPR:
      /* These have already decayed to rvalue.  */
      break;
    
    case CALL_EXPR:   /* We have a special meaning for volatile void fn().  */
      break;
    
    case INDIRECT_REF:
      {
        tree type = TREE_TYPE (expr);
        int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
                           == REFERENCE_TYPE;
        int is_volatile = TYPE_VOLATILE (type);
        int is_complete = COMPLETE_TYPE_P (complete_type (type));
        
        if (is_volatile && !is_complete)
          warning ("object of incomplete type `%T' will not be accessed in %s",
                      type, implicit ? implicit : "void context");
        else if (is_reference && is_volatile)
          warning ("object of type `%T' will not be accessed in %s",
                      TREE_TYPE (TREE_OPERAND (expr, 0)),
                      implicit ? implicit : "void context");
        if (is_reference || !is_volatile || !is_complete)
          expr = TREE_OPERAND (expr, 0);
      
        break;
      }
    
    case VAR_DECL:
      {
        /* External variables might be incomplete.  */
        tree type = TREE_TYPE (expr);
        int is_complete = COMPLETE_TYPE_P (complete_type (type));
        
        if (TYPE_VOLATILE (type) && !is_complete)
          warning ("object `%E' of incomplete type `%T' will not be accessed in %s",
                      expr, type, implicit ? implicit : "void context");
        break;
      }

    default:;
    }
  {
    tree probe = expr;
  
    if (TREE_CODE (probe) == ADDR_EXPR)
      probe = TREE_OPERAND (expr, 0);
    if (type_unknown_p (probe))
      {
	/* [over.over] enumerates the places where we can take the address
	   of an overloaded function, and this is not one of them.  */
	pedwarn ("%s cannot resolve address of overloaded function",
		    implicit ? implicit : "void cast");
	expr = void_zero_node;
      }
    else if (implicit && probe == expr && is_overloaded_fn (probe))
      /* Only warn when there is no &.  */
      warning ("%s is a reference, not call, to function `%E'",
		  implicit, expr);
  }
  
  if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr)))
    {
      if (implicit && !TREE_SIDE_EFFECTS (expr) && warn_unused_value)
	warning ("%s has no effect", implicit);
      expr = build1 (CONVERT_EXPR, void_type_node, expr);
    }
  return expr;
}
Exemplo n.º 16
0
void
make_friend_class (tree type, tree friend_type, bool complain)
{
  tree classes;

  /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
     the enclosing class.  FRIEND_DEPTH counts the number of template
     headers used for this friend declaration.  TEMPLATE_MEMBER_P,
     defined inside the `if' block for TYPENAME_TYPE case, is true if
     a template header in FRIEND_DEPTH is intended for DECLARATOR.
     For example, the code

       template <class T> struct A {
	 template <class U> struct B {
	   template <class V> template <class W>
	     friend class C<V>::D;
	 };
       };

     will eventually give the following results

     1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
     2. FRIEND_DEPTH equals 2 (for `V' and `W').
     3. TEMPLATE_MEMBER_P is true (for `W').

     The friend is a template friend iff FRIEND_DEPTH is nonzero.  */

  int class_template_depth = template_class_depth (type);
  int friend_depth = processing_template_decl - class_template_depth;

  if (! MAYBE_CLASS_TYPE_P (friend_type))
    {
      /* N1791: If the type specifier in a friend declaration designates a
	 (possibly cv-qualified) class type, that class is declared as a
	 friend; otherwise, the friend declaration is ignored.

         So don't complain in C++0x mode.  */
      if (cxx_dialect < cxx0x)
	pedwarn (input_location, complain ? 0 : OPT_pedantic,
		 "invalid type %qT declared %<friend%>", friend_type);
      return;
    }

  friend_type = cv_unqualified (friend_type);

  if (check_for_bare_parameter_packs (friend_type))
    return;

  if (friend_depth)
    /* If the TYPE is a template then it makes sense for it to be
       friends with itself; this means that each instantiation is
       friends with all other instantiations.  */
    {
      if (CLASS_TYPE_P (friend_type)
	  && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
	  && uses_template_parms (friend_type))
	{
	  /* [temp.friend]
	     Friend declarations shall not declare partial
	     specializations.  */
	  error ("partial specialization %qT declared %<friend%>",
		 friend_type);
	  return;
	}
    }
  else if (same_type_p (type, friend_type))
    {
      if (complain)
	warning (0, "class %qT is implicitly friends with itself",
		 type);
      return;
    }

  /* [temp.friend]

     A friend of a class or class template can be a function or
     class template, a specialization of a function template or
     class template, or an ordinary (nontemplate) function or
     class.  */
  if (!friend_depth)
    ;/* ok */
  else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
    {
      if (TREE_CODE (TYPENAME_TYPE_FULLNAME (friend_type))
	  == TEMPLATE_ID_EXPR)
	{
	  /* template <class U> friend class T::X<U>; */
	  /* [temp.friend]
	     Friend declarations shall not declare partial
	     specializations.  */
	  error ("partial specialization %qT declared %<friend%>",
		 friend_type);
	  return;
	}
      else
	{
	  /* We will figure this out later.  */
	  bool template_member_p = false;

	  tree ctype = TYPE_CONTEXT (friend_type);
	  tree name = TYPE_IDENTIFIER (friend_type);
	  tree decl;

	  if (!uses_template_parms_level (ctype, class_template_depth
						 + friend_depth))
	    template_member_p = true;

	  if (class_template_depth)
	    {
	      /* We rely on tsubst_friend_class to check the
		 validity of the declaration later.  */
	      if (template_member_p)
		friend_type
		  = make_unbound_class_template (ctype,
						 name,
						 current_template_parms,
						 tf_error);
	      else
		friend_type
		  = make_typename_type (ctype, name, class_type, tf_error);
	    }
	  else
	    {
	      decl = lookup_member (ctype, name, 0, true, tf_warning_or_error);
	      if (!decl)
		{
		  error ("%qT is not a member of %qT", name, ctype);
		  return;
		}
	      if (template_member_p && !DECL_CLASS_TEMPLATE_P (decl))
		{
		  error ("%qT is not a member class template of %qT",
			 name, ctype);
		  error ("%q+D declared here", decl);
		  return;
		}
	      if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL
					 || !CLASS_TYPE_P (TREE_TYPE (decl))))
		{
		  error ("%qT is not a nested class of %qT",
			 name, ctype);
		  error ("%q+D declared here", decl);
		  return;
		}

	      friend_type = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
	    }
	}
    }
  else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
    {
      /* template <class T> friend class T; */
      error ("template parameter type %qT declared %<friend%>", friend_type);
      return;
    }
  else if (!CLASSTYPE_TEMPLATE_INFO (friend_type))
    {
      /* template <class T> friend class A; where A is not a template */
      error ("%q#T is not a template", friend_type);
      return;
    }
  else
    /* template <class T> friend class A; where A is a template */
    friend_type = CLASSTYPE_TI_TEMPLATE (friend_type);

  if (friend_type == error_mark_node)
    return;

  /* See if it is already a friend.  */
  for (classes = CLASSTYPE_FRIEND_CLASSES (type);
       classes;
       classes = TREE_CHAIN (classes))
    {
      tree probe = TREE_VALUE (classes);

      if (TREE_CODE (friend_type) == TEMPLATE_DECL)
	{
	  if (friend_type == probe)
	    {
	      if (complain)
		warning (0, "%qD is already a friend of %qT", probe, type);
	      break;
	    }
	}
      else if (TREE_CODE (probe) != TEMPLATE_DECL)
	{
	  if (same_type_p (probe, friend_type))
	    {
	      if (complain)
		warning (0, "%qT is already a friend of %qT", probe, type);
	      break;
	    }
	}
    }

  if (!classes)
    {
      maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1);

      CLASSTYPE_FRIEND_CLASSES (type)
	= tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
      if (TREE_CODE (friend_type) == TEMPLATE_DECL)
	friend_type = TREE_TYPE (friend_type);
      if (!uses_template_parms (type))
	CLASSTYPE_BEFRIENDING_CLASSES (friend_type)
	  = tree_cons (NULL_TREE, type,
		       CLASSTYPE_BEFRIENDING_CLASSES (friend_type));
    }
}
Exemplo n.º 17
0
Arquivo: cvt.c Projeto: Fokycnuk/gcc
tree
ocp_convert (tree type, tree expr, int convtype, int flags)
{
  tree e = expr;
  enum tree_code code = TREE_CODE (type);

  if (error_operand_p (e) || type == error_mark_node)
    return error_mark_node;

  complete_type (type);
  complete_type (TREE_TYPE (expr));

  e = decl_constant_value (e);

  if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
      /* Some internal structures (vtable_entry_type, sigtbl_ptr_type)
	 don't go through finish_struct, so they don't have the synthesized
	 constructors.  So don't force a temporary.  */
      && TYPE_HAS_CONSTRUCTOR (type))
    /* We need a new temporary; don't take this shortcut.  */;
  else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
    {
      if (same_type_p (type, TREE_TYPE (e)))
	/* The call to fold will not always remove the NOP_EXPR as
	   might be expected, since if one of the types is a typedef;
	   the comparison in fold is just equality of pointers, not a
	   call to comptypes.  We don't call fold in this case because
	   that can result in infinite recursion; fold will call
	   convert, which will call ocp_convert, etc.  */
	return e;
      /* For complex data types, we need to perform componentwise
         conversion.  */
      else if (TREE_CODE (type) == COMPLEX_TYPE)
        return fold (convert_to_complex (type, e));
      else if (TREE_CODE (e) == TARGET_EXPR)
	{
	  /* Don't build a NOP_EXPR of class type.  Instead, change the
	     type of the temporary.  Only allow this for cv-qual changes,
	     though.  */
	  if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)),
			    TYPE_MAIN_VARIANT (type)))
	    abort ();
	  TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
	  return e;
	}
      else if (TREE_ADDRESSABLE (type))
	/* We shouldn't be treating objects of ADDRESSABLE type as rvalues.  */
	abort ();
      else
	return fold (build1 (NOP_EXPR, type, e));
    }

  if (code == VOID_TYPE && (convtype & CONV_STATIC))
    {
      e = convert_to_void (e, /*implicit=*/NULL);
      return e;
    }

  if (INTEGRAL_CODE_P (code))
    {
      tree intype = TREE_TYPE (e);
      /* enum = enum, enum = int, enum = float, (enum)pointer are all
         errors.  */
      if (TREE_CODE (type) == ENUMERAL_TYPE
	  && ((ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC))
	      || (TREE_CODE (intype) == POINTER_TYPE)))
	{
	  pedwarn ("conversion from `%#T' to `%#T'", intype, type);

	  if (flag_pedantic_errors)
	    return error_mark_node;
	}
      if (IS_AGGR_TYPE (intype))
	{
	  tree rval;
	  rval = build_type_conversion (type, e);
	  if (rval)
	    return rval;
	  if (flags & LOOKUP_COMPLAIN)
	    error ("`%#T' used where a `%T' was expected", intype, type);
	  if (flags & LOOKUP_SPECULATIVELY)
	    return NULL_TREE;
	  return error_mark_node;
	}
      if (code == BOOLEAN_TYPE)
	return cp_truthvalue_conversion (e);

      return fold (convert_to_integer (type, e));
    }
  if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
    return fold (cp_convert_to_pointer (type, e, false));
  if (code == VECTOR_TYPE)
    return fold (convert_to_vector (type, e));
  if (code == REAL_TYPE || code == COMPLEX_TYPE)
    {
      if (IS_AGGR_TYPE (TREE_TYPE (e)))
	{
	  tree rval;
	  rval = build_type_conversion (type, e);
	  if (rval)
	    return rval;
	  else
	    if (flags & LOOKUP_COMPLAIN)
	      error ("`%#T' used where a floating point value was expected",
			TREE_TYPE (e));
	}
      if (code == REAL_TYPE)
	return fold (convert_to_real (type, e));
      else if (code == COMPLEX_TYPE)
	return fold (convert_to_complex (type, e));
    }

  /* New C++ semantics:  since assignment is now based on
     memberwise copying,  if the rhs type is derived from the
     lhs type, then we may still do a conversion.  */
  if (IS_AGGR_TYPE_CODE (code))
    {
      tree dtype = TREE_TYPE (e);
      tree ctor = NULL_TREE;

      dtype = TYPE_MAIN_VARIANT (dtype);

      /* Conversion between aggregate types.  New C++ semantics allow
	 objects of derived type to be cast to objects of base type.
	 Old semantics only allowed this between pointers.

	 There may be some ambiguity between using a constructor
	 vs. using a type conversion operator when both apply.  */

      ctor = e;

      if (abstract_virtuals_error (NULL_TREE, type))
	return error_mark_node;

      if ((flags & LOOKUP_ONLYCONVERTING)
	  && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
	/* For copy-initialization, first we create a temp of the proper type
	   with a user-defined conversion sequence, then we direct-initialize
	   the target with the temp (see [dcl.init]).  */
	ctor = build_user_type_conversion (type, ctor, flags);
      else
	ctor = build_special_member_call (NULL_TREE, 
					  complete_ctor_identifier,
					  build_tree_list (NULL_TREE, ctor),
					  TYPE_BINFO (type), flags);
      if (ctor)
	return build_cplus_new (type, ctor);
    }

  if (flags & LOOKUP_COMPLAIN)
    error ("conversion from `%T' to non-scalar type `%T' requested",
	      TREE_TYPE (expr), type);
  if (flags & LOOKUP_SPECULATIVELY)
    return NULL_TREE;
  return error_mark_node;
}
Exemplo n.º 18
0
Arquivo: cvt.c Projeto: Fokycnuk/gcc
static tree
cp_convert_to_pointer (tree type, tree expr, bool force)
{
  tree intype = TREE_TYPE (expr);
  enum tree_code form;
  tree rval;
  if (intype == error_mark_node)
    return error_mark_node;

  if (IS_AGGR_TYPE (intype))
    {
      intype = complete_type (intype);
      if (!COMPLETE_TYPE_P (intype))
	{
	  error ("can't convert from incomplete type `%T' to `%T'",
		    intype, type);
	  return error_mark_node;
	}

      rval = build_type_conversion (type, expr);
      if (rval)
	{
	  if (rval == error_mark_node)
	    error ("conversion of `%E' from `%T' to `%T' is ambiguous",
		      expr, intype, type);
	  return rval;
	}
    }

  /* Handle anachronistic conversions from (::*)() to cv void* or (*)().  */
  if (TREE_CODE (type) == POINTER_TYPE
      && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
	  || VOID_TYPE_P (TREE_TYPE (type))))
    {
      /* Allow an implicit this pointer for pointer to member
	 functions.  */
      if (TYPE_PTRMEMFUNC_P (intype))
	{
	  if (pedantic || warn_pmf2ptr)
	    pedwarn ("converting from `%T' to `%T'", intype, type);
	  if (TREE_CODE (expr) == PTRMEM_CST)
	    expr = build_address (PTRMEM_CST_MEMBER (expr));
	  else
	    {
	      tree decl = maybe_dummy_object (TYPE_PTRMEM_CLASS_TYPE (intype), 
					      0);
	      decl = build_address (decl);
	      expr = get_member_function_from_ptrfunc (&decl, expr);
	    }
	}
      else if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
	{
	  if (pedantic || warn_pmf2ptr)
	    pedwarn ("converting from `%T' to `%T'", intype, type);
	  expr = build_addr_func (expr);
	}
      if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
	return build_nop (type, expr);
      intype = TREE_TYPE (expr);
    }

  if (expr == error_mark_node)
    return error_mark_node;

  form = TREE_CODE (intype);

  if (POINTER_TYPE_P (intype))
    {
      intype = TYPE_MAIN_VARIANT (intype);

      if (TYPE_MAIN_VARIANT (type) != intype
	  && TREE_CODE (type) == POINTER_TYPE
	  && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
	  && IS_AGGR_TYPE (TREE_TYPE (type))
	  && IS_AGGR_TYPE (TREE_TYPE (intype))
	  && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
	{
	  enum tree_code code = PLUS_EXPR;
	  tree binfo;
	  tree intype_class;
	  tree type_class;
	  bool same_p;

	  intype_class = TREE_TYPE (intype);
	  type_class = TREE_TYPE (type);

	  same_p = same_type_p (TYPE_MAIN_VARIANT (intype_class), 
				TYPE_MAIN_VARIANT (type_class));
	  binfo = NULL_TREE;
	  /* Try derived to base conversion.  */
	  if (!same_p)
	    binfo = lookup_base (intype_class, type_class, ba_check, NULL);
	  if (!same_p && !binfo)
	    {
	      /* Try base to derived conversion.  */
	      binfo = lookup_base (type_class, intype_class, ba_check, NULL);
	      code = MINUS_EXPR;
	    }
	  if (binfo == error_mark_node)
	    return error_mark_node;
	  if (binfo || same_p)
	    {
	      if (binfo)
		expr = build_base_path (code, expr, binfo, 0);
	      /* Add any qualifier conversions.  */
	      return build_nop (type, expr);
	    }
	}

      if (TYPE_PTRMEMFUNC_P (type))
	{
	  error ("cannot convert `%E' from type `%T' to type `%T'",
		    expr, intype, type);
	  return error_mark_node;
	}

      return build_nop (type, expr);
    }
  else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
    {
      tree b1; 
      tree b2;
      tree binfo;
      enum tree_code code = PLUS_EXPR;
      base_kind bk;

      b1 = TYPE_PTRMEM_CLASS_TYPE (type);
      b2 = TYPE_PTRMEM_CLASS_TYPE (intype);
      binfo = lookup_base (b1, b2, ba_check, &bk);
      if (!binfo)
	{
	  binfo = lookup_base (b2, b1, ba_check, &bk);
	  code = MINUS_EXPR;
	}
      if (binfo == error_mark_node)
	return error_mark_node;

      if (bk == bk_via_virtual)
	{
	  if (force)
	    warning ("pointer to member cast from `%T' to `%T' is via virtual base",
		     intype, type);
	  else
	    {
	      error ("pointer to member cast from `%T' to `%T' is via virtual base",
		     intype, type);
	      return error_mark_node;
	    }
	  /* This is a reinterpret cast, whose result is unspecified.
	     We choose to do nothing.  */
	  return build1 (NOP_EXPR, type, expr);
	}

      if (TREE_CODE (expr) == PTRMEM_CST)
	expr = cplus_expand_constant (expr);

      if (binfo && !integer_zerop (BINFO_OFFSET (binfo)))
	expr = size_binop (code, 
			   build_nop (sizetype, expr),
			   BINFO_OFFSET (binfo));
      return build_nop (type, expr);
    }
  else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
    return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
  else if (TYPE_PTRMEMFUNC_P (intype))
    {
      if (!warn_pmf2ptr)
	{
	  if (TREE_CODE (expr) == PTRMEM_CST)
	    return cp_convert_to_pointer (type,
					  PTRMEM_CST_MEMBER (expr),
					  force);
	  else if (TREE_CODE (expr) == OFFSET_REF)
	    {
	      tree object = TREE_OPERAND (expr, 0);
	      return get_member_function_from_ptrfunc (&object,
						       TREE_OPERAND (expr, 1));
	    }
	}
      error ("cannot convert `%E' from type `%T' to type `%T'",
		expr, intype, type);
      return error_mark_node;
    }

  if (integer_zerop (expr))
    {
      if (TYPE_PTRMEMFUNC_P (type))
	return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);

      if (TYPE_PTRMEM_P (type))
	/* A NULL pointer-to-member is represented by -1, not by
	   zero.  */
	expr = build_int_2 (-1, -1);
      else
	expr = build_int_2 (0, 0);
      TREE_TYPE (expr) = type;
      /* Fix up the representation of -1 if appropriate.  */
      force_fit_type (expr, 0);
      return expr;
    }
  else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form))
    {
      error ("invalid conversion from '%T' to '%T'", intype, type);
      return error_mark_node;
    }

  if (INTEGRAL_CODE_P (form))
    {
      if (TYPE_PRECISION (intype) == POINTER_SIZE)
	return build1 (CONVERT_EXPR, type, expr);
      expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr);
      /* Modes may be different but sizes should be the same.  */
      if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
	  != GET_MODE_SIZE (TYPE_MODE (type)))
	/* There is supposed to be some integral type
	   that is the same width as a pointer.  */
	abort ();
      return convert_to_pointer (type, expr);
    }

  if (type_unknown_p (expr))
    return instantiate_type (type, expr, tf_error | tf_warning);

  error ("cannot convert `%E' from type `%T' to type `%T'",
	    expr, intype, type);
  return error_mark_node;
}
Exemplo n.º 19
0
Arquivo: cvt.c Projeto: Fokycnuk/gcc
tree
convert_to_reference (tree reftype, tree expr, int convtype,
                      int flags, tree decl)
{
  tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));
  tree intype;
  tree rval = NULL_TREE;
  tree rval_as_conversion = NULL_TREE;
  bool can_convert_intype_to_type;

  if (TREE_CODE (type) == FUNCTION_TYPE 
      && TREE_TYPE (expr) == unknown_type_node)
    expr = instantiate_type (type, expr, 
			     (flags & LOOKUP_COMPLAIN)
			     ? tf_error | tf_warning : tf_none);
  else
    expr = convert_from_reference (expr);

  if (expr == error_mark_node)
    return error_mark_node;

  intype = TREE_TYPE (expr);

  my_friendly_assert (TREE_CODE (intype) != REFERENCE_TYPE, 364);

  intype = TYPE_MAIN_VARIANT (intype);

  can_convert_intype_to_type = can_convert (type, intype);
  if (!can_convert_intype_to_type
      && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype)
      && ! (flags & LOOKUP_NO_CONVERSION))
    {
      /* Look for a user-defined conversion to lvalue that we can use.  */

      rval_as_conversion
	= build_type_conversion (reftype, expr);

      if (rval_as_conversion && rval_as_conversion != error_mark_node
	  && real_lvalue_p (rval_as_conversion))
	{
	  expr = rval_as_conversion;
	  rval_as_conversion = NULL_TREE;
	  intype = type;
	  can_convert_intype_to_type = 1;
	}
    }

  if (((convtype & CONV_STATIC) && can_convert (intype, type))
      || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type))
    {
      if (flags & LOOKUP_COMPLAIN)
	{
	  tree ttl = TREE_TYPE (reftype);
	  tree ttr = lvalue_type (expr);

	  if (! real_lvalue_p (expr))
	    warn_ref_binding (reftype, intype, decl);
	  
	  if (! (convtype & CONV_CONST)
		   && !at_least_as_qualified_p (ttl, ttr))
	    pedwarn ("conversion from `%T' to `%T' discards qualifiers",
			ttr, reftype);
	}

      return build_up_reference (reftype, expr, flags, decl);
    }
  else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr))
    {
      /* When casting an lvalue to a reference type, just convert into
	 a pointer to the new type and deference it.  This is allowed
	 by San Diego WP section 5.2.9 paragraph 12, though perhaps it
	 should be done directly (jason).  (int &)ri ---> *(int*)&ri */

      /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they
         meant.  */
      if (TREE_CODE (intype) == POINTER_TYPE
	  && (comptypes (TREE_TYPE (intype), type,
			 COMPARE_BASE | COMPARE_DERIVED)))
	warning ("casting `%T' to `%T' does not dereference pointer",
		 intype, reftype);
	  
      rval = build_unary_op (ADDR_EXPR, expr, 0);
      if (rval != error_mark_node)
	rval = convert_force (build_pointer_type (TREE_TYPE (reftype)),
			      rval, 0);
      if (rval != error_mark_node)
	rval = build1 (NOP_EXPR, reftype, rval);
    }
  else
    {
      rval = convert_for_initialization (NULL_TREE, type, expr, flags,
					 "converting", 0, 0);
      if (rval == NULL_TREE || rval == error_mark_node)
	return rval;
      warn_ref_binding (reftype, intype, decl);
      rval = build_up_reference (reftype, rval, flags, decl);
    }

  if (rval)
    {
      /* If we found a way to convert earlier, then use it.  */
      return rval;
    }

  if (flags & LOOKUP_COMPLAIN)
    error ("cannot convert type `%T' to type `%T'", intype, reftype);

  if (flags & LOOKUP_SPECULATIVELY)
    return NULL_TREE;

  return error_mark_node;
}
Exemplo n.º 20
0
/* Return TRUE if no error and lhstype and rhstype are not error_type */
bool check_assignment(type lhstype, type rhstype, expression rhs,
		      const char *context, data_declaration fundecl,
		      const char *funname, int parmnum)
{
  bool zerorhs = rhs && definite_zero(rhs);

  if (lhstype == error_type || rhstype == error_type)
    return FALSE;

  if (type_void(rhstype))
    {
      error("void value not ignored as it ought to be");
      return FALSE;
    }

  if (type_equal_unqualified(lhstype, rhstype))
    return TRUE;

  if (type_arithmetic(lhstype) && type_arithmetic(rhstype))
    {
      if (rhs)
	constant_overflow_warning(rhs->cst);
      return check_conversion(lhstype, rhstype);
    }
  if (parmnum && (type_qualifiers(lhstype) & transparent_qualifier))
    {
      /* See if we can match any field of lhstype */
      tag_declaration tag = type_tag(lhstype);
      field_declaration fields, marginal_field = NULL;

      /* I blame gcc for this horrible mess (and it's minor inconsistencies
	 with the regular rules) */
      /* pedantic warnings are skipped in here because we're already
	 issuing a warning for the use of this construct */
      for (fields = tag->fieldlist; fields; fields = fields->next)
	{
	  type ft = fields->type;

	  if (type_compatible(ft, rhstype))
	    break;

	  if (!type_pointer(ft))
	    continue;

	  if (type_pointer(rhstype))
	    {
	      type ttl = type_points_to(ft), ttr = type_points_to(rhstype);
	      bool goodmatch = assignable_pointer_targets(ttl, ttr, FALSE);

	      /* Any non-function converts to a [const][volatile] void *
		 and vice versa; otherwise, targets must be the same.
		 Meanwhile, the lhs target must have all the qualifiers of
		 the rhs.  */
	      if (goodmatch)
		{
		  /* If this type won't generate any warnings, use it.  */
		  if ((type_function(ttr) && type_function(ttl))
		      ? (((!type_const(ttl)) | type_const(ttr))
			 & ((!type_volatile(ttl)) | type_volatile(ttr)))
		      : (((type_const(ttl)) | (!type_const(ttr)))
			 & (type_volatile(ttl) | (!type_volatile(ttr)))))
		    break;

		  /* Keep looking for a better type, but remember this one.  */
		  if (!marginal_field)
		    marginal_field = fields;
		}
	    }

	  /* Can convert integer zero to any pointer type.  */
	  /* Note that this allows passing *any* null pointer (gcc bug?) */
	  if (zerorhs)
	    break;
	}

      if (fields || marginal_field)
	{
	  if (!fields)
	    {
	      /* We have only a marginally acceptable member type;
		 it needs a warning.  */
	      type ttl = type_points_to(marginal_field->type),
		ttr = type_points_to(rhstype);

	      ptrconversion_warnings(ttl, ttr, rhs, context, funname, parmnum,
				     FALSE);
	    }
	  
	  if (pedantic && !(fundecl && fundecl->in_system_header))
	    pedwarn("ANSI C prohibits argument conversion to union type");

	  return TRUE;
	}
    }

  if (type_pointer(lhstype) && type_pointer(rhstype))
    {
      type ttl = type_points_to(lhstype), ttr = type_points_to(rhstype);
      bool goodmatch = assignable_pointer_targets(ttl, ttr, pedantic);

      /* Any non-function converts to a [const][volatile] void *
	 and vice versa; otherwise, targets must be the same.
	 Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
      if (goodmatch || (type_equal_unqualified(make_unsigned_type(ttl),
					       make_unsigned_type(ttr))))
	ptrconversion_warnings(ttl, ttr, rhs, context, funname, parmnum,
			       pedantic);
      else
	warn_for_assignment("%s from incompatible pointer type",
			    context, funname, parmnum);

      return check_conversion(lhstype, rhstype);
    }
  /* enum = ptr and ptr = enum counts as an error, so use type_integral */
  else if (type_pointer(lhstype) && type_integral(rhstype))
    {
      if (!zerorhs)
	warn_for_assignment("%s makes pointer from integer without a cast",
			    context, funname, parmnum);
      return check_conversion(lhstype, rhstype);
    }
  else if (type_integral(lhstype) && type_pointer(rhstype))
    {
      warn_for_assignment("%s makes integer from pointer without a cast",
			  context, funname, parmnum);
      return check_conversion(lhstype, rhstype);
    }

  if (!context)
    if (funname)
      error("incompatible type for argument %d of `%s'", parmnum, funname);
    else
      error("incompatible type for argument %d of indirect function call",
	    parmnum);
  else
    error("incompatible types in %s", context);

  return FALSE;
}
Exemplo n.º 21
0
Arquivo: c-lex.c Projeto: 0mp/freebsd
/* Interpret TOKEN, a floating point number with FLAGS as classified
   by cpplib.  */
static tree
interpret_float (const cpp_token *token, unsigned int flags)
{
  tree type;
  tree value;
  REAL_VALUE_TYPE real;
  char *copy;
  size_t copylen;

  /* Default (no suffix) is double.  */
  if (flags & CPP_N_DEFAULT)
    {
      flags ^= CPP_N_DEFAULT;
      flags |= CPP_N_MEDIUM;
    }

  /* Decode type based on width and properties. */
  if (flags & CPP_N_DFLOAT)
    if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
      type = dfloat128_type_node;
    else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
      type = dfloat32_type_node;
    else
      type = dfloat64_type_node;
  else
    if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
      type = long_double_type_node;
    else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL
	     || flag_single_precision_constant)
      type = float_type_node;
    else
      type = double_type_node;

  /* Copy the constant to a nul-terminated buffer.  If the constant
     has any suffixes, cut them off; REAL_VALUE_ATOF/ REAL_VALUE_HTOF
     can't handle them.  */
  copylen = token->val.str.len;
  if (flags & CPP_N_DFLOAT) 
    copylen -= 2;
  else 
    {
      if ((flags & CPP_N_WIDTH) != CPP_N_MEDIUM)
	/* Must be an F or L suffix.  */
	copylen--;
      if (flags & CPP_N_IMAGINARY)
	/* I or J suffix.  */
	copylen--;
    }

  copy = (char *) alloca (copylen + 1);
  memcpy (copy, token->val.str.text, copylen);
  copy[copylen] = '\0';

  real_from_string3 (&real, copy, TYPE_MODE (type));

  /* Both C and C++ require a diagnostic for a floating constant
     outside the range of representable values of its type.  Since we
     have __builtin_inf* to produce an infinity, it might now be
     appropriate for this to be a mandatory pedwarn rather than
     conditioned on -pedantic.  */
  if (REAL_VALUE_ISINF (real) && pedantic)
    pedwarn ("floating constant exceeds range of %qT", type);

  /* Create a node with determined type and value.  */
  value = build_real (type, real);
  if (flags & CPP_N_IMAGINARY)
    value = build_complex (NULL_TREE, convert (type, integer_zero_node), value);

  return value;
}
Exemplo n.º 22
0
type check_binary(int binop, expression e1, expression e2)
{
  type t1 = default_conversion(e1), t2 = default_conversion(e2);
  type rtype = NULL;
  bool common = FALSE;

  /* XXX: Misc warnings (see build_binary_op) */
  if (t1 == error_type || t2 == error_type)
    rtype = error_type;
  else switch(binop)
    {
    case kind_plus:
      if (type_pointer(t1) && type_integer(t2))
	rtype = pointer_int_sum(t1, t2);
      else if (type_pointer(t2) && type_integer(t1))
	rtype = pointer_int_sum(t2, t1);
      else
	common = TRUE;
      break;

    case kind_minus: 
      if (type_pointer(t1) && type_integer(t2))
	rtype = pointer_int_sum(t1, t2);
      else if (type_pointer(t1) && type_pointer(t2) &&
	       compatible_pointer_types(t1, t2))
	rtype = ptrdiff_t_type;
      else
	common = TRUE;
      break;

    case kind_plus_assign: case kind_minus_assign:
      if (type_pointer(t1) && type_integer(t2))
	rtype = pointer_int_sum(t1, t2);
      else
	common = TRUE;
      break;

    case kind_times: case kind_divide:
    case kind_times_assign: case kind_divide_assign:
      common = TRUE;
      break;

    case kind_modulo: case kind_bitand: case kind_bitor: case kind_bitxor:
    case kind_lshift: case kind_rshift:
    case kind_modulo_assign: case kind_bitand_assign: case kind_bitor_assign:
    case kind_bitxor_assign: case kind_lshift_assign: case kind_rshift_assign:
      if (type_integer(t1) && type_integer(t2))
	rtype = common_type(t1, t2);
      break;

    case kind_leq: case kind_geq: case kind_lt: case kind_gt:
      rtype = int_type; /* Default to assuming success */
      if (type_real(t1) && type_real(t2))
	;
      else if (type_pointer(t1) && type_pointer(t2))
	{
	  if (compatible_pointer_types(t1, t2))
	    {
	      /* XXX: how can this happen ? */
	      if (type_incomplete(t1) != type_incomplete(t2))
		pedwarn("comparison of complete and incomplete pointers");
	      else if (pedantic && type_function(type_points_to(t1)))
		pedwarn("ANSI C forbids ordered comparisons of pointers to functions");
	    }
	  else
	    pedwarn("comparison of distinct pointer types lacks a cast");
	}
      /* XXX: Use of definite_zero may lead to extra warnings when !extra_warnings */
      else if ((type_pointer(t1) && definite_zero(e2)) ||
	       (type_pointer(t2) && definite_zero(e1)))
	{
	  if (pedantic || extra_warnings)
	    pedwarn("ordered comparison of pointer with integer zero");
	}
      else if ((type_pointer(t1) && type_integer(t2)) ||
	       (type_pointer(t2) && type_integer(t1)))
	{
	  if (!flag_traditional)
	    pedwarn("comparison between pointer and integer");
	}
      else
	rtype = NULL; /* Force error */
      break;

    case kind_eq: case kind_ne:
      rtype = int_type; /* Default to assuming success */
      if (type_arithmetic(t1) && type_arithmetic(t2))
	;
      else if (type_pointer(t1) && type_pointer(t2))
	{
	  if (!compatible_pointer_types(t1, t2) &&
	      !valid_compare(t1, t2, e1) &&
	      !valid_compare(t2, t1, e2))
	    pedwarn("comparison of distinct pointer types lacks a cast");
	}
      else if ((type_pointer(t1) && definite_null(e2)) ||
	       (type_pointer(t2) && definite_null(e1)))
	;
      else if ((type_pointer(t1) && type_integer(t2)) ||
	       (type_pointer(t2) && type_integer(t1)))
	{
	  if (!flag_traditional)
	    pedwarn("comparison between pointer and integer");
	}
      else
	rtype = NULL; /* Force error */
      break;

    case kind_andand: case kind_oror:
      if (type_scalar(t1) && type_scalar(t2))
	rtype = int_type;
      break;

    default: assert(0); break;
    }

  if (common && type_arithmetic(t1) && type_arithmetic(t2))
    rtype = common_type(t1, t2);

  if (!rtype)
    {
      error("invalid operands to binary %s", binary_op_name(binop));
      rtype = error_type;
    }

  return rtype;
}
Exemplo n.º 23
0
expression make_cast(location loc, asttype t, expression e)
{
  expression result = CAST(expression, new_cast(parse_region, loc, e, t));
  type castto = t->type;
  
  if (castto == error_type || type_void(castto))
    ; /* Do nothing */
  else if (type_array(castto))
    {
      error("cast specifies array type");
      castto = error_type;
    }
  else if (type_function(castto))
    {
      error("cast specifies function type");
      castto = error_type;
    }
  else if (type_equal_unqualified(castto, e->type))
    {
      if (pedantic && type_aggregate(castto))
	pedwarn("ANSI C forbids casting nonscalar to the same type");
    }
  else
    {
      type etype = e->type;

      /* Convert functions and arrays to pointers,
	 but don't convert any other types.  */
      if (type_function(etype) || type_array(etype))
	etype = default_conversion(e);

      if (type_union(castto))
	{
	  tag_declaration utag = type_tag(castto);
	  field_declaration ufield;

	  /* Look for etype as a field of the union */
	  for (ufield = utag->fieldlist; ufield; ufield = ufield->next)
	    if (ufield->name && type_equal_unqualified(ufield->type, etype))
	      {
		if (pedantic)
		  pedwarn("ANSI C forbids casts to union type");
		break;
	      }
	  if (!ufield)
	    error("cast to union type from type not present in union");
	}
      else 
	{
	  /* Optionally warn about potentially worrisome casts.  */

	  if (warn_cast_qual && type_pointer(etype) && type_pointer(castto))
	    {
	      type ep = type_points_to(etype), cp = type_points_to(castto);

	      if (type_volatile(ep) && !type_volatile(cp))
		pedwarn("cast discards `volatile' from pointer target type");
	      if (type_const(ep) && !type_const(cp))
		pedwarn("cast discards `const' from pointer target type");
	    }

	  /* This warning is weird */
	  if (warn_bad_function_cast && is_function_call(e) &&
	      !type_equal_unqualified(castto, etype))
	    warning ("cast does not match function type");

#if 0
	  /* Warn about possible alignment problems.  */
	  if (STRICT_ALIGNMENT && warn_cast_align
	      && TREE_CODE (type) == POINTER_TYPE
	      && TREE_CODE (otype) == POINTER_TYPE
	      && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
	      && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
	      /* Don't warn about opaque types, where the actual alignment
		 restriction is unknown.  */
	      && !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE
		    || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE)
		   && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode)
	      && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
	    warning ("cast increases required alignment of target type");

	  if (TREE_CODE (type) == INTEGER_TYPE
	      && TREE_CODE (otype) == POINTER_TYPE
	      && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
	      && !TREE_CONSTANT (value))
	    warning ("cast from pointer to integer of different size");

	  if (TREE_CODE (type) == POINTER_TYPE
	      && TREE_CODE (otype) == INTEGER_TYPE
	      && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
#if 0
	      /* Don't warn about converting 0 to pointer,
		 provided the 0 was explicit--not cast or made by folding.  */
	      && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value))
#endif
	      /* Don't warn about converting any constant.  */
	      && !TREE_CONSTANT (value))
	    warning ("cast to pointer from integer of different size");
#endif

	  check_conversion(castto, etype);
	}
    }

  result->lvalue = !pedantic && e->lvalue;
  result->isregister = e->isregister;
  result->bitfield = e->bitfield;
  result->static_address = e->static_address;
  result->type = castto;
  result->cst = fold_cast(result);

  return result;
}