Beispiel #1
0
void check_return(expression e)
{
  type ret = current_return_type();
 
  if (type_void(ret))
    {
      if (pedantic || !type_void(e->type))
	warning("`return' with a value, in function returning void");
    }
  else
    {
      check_assignment(ret, default_conversion_for_assignment(e), e, "return", NULL, NULL, 0);
      /* XXX: Missing warning about returning address of local var */
    }
}
Beispiel #2
0
static void check_dereference(expression result, type dereferenced,
			      const char *errorstring)
{
  if (type_pointer(dereferenced))
    {
      type t = type_points_to(dereferenced);

      result->type = t;
#if 0
      if (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE)
	{
	  error ("dereferencing pointer to incomplete type");
	  return error_mark_node;
	}
#endif
      if (type_void(t) && unevaluated_expression == 0)
	warning("dereferencing `void *' pointer");
      result->side_effects |= type_volatile(t) || flag_volatile;
    }
  else
    {
      result->type = error_type;
      if (dereferenced != error_type)
	error("invalid type argument of `%s'", errorstring);
    }
  result->lvalue = TRUE;
}
Beispiel #3
0
void check_void_return(void)
{
  type ret = current_return_type();

  if (warn_return_type && ret != error_type && !type_void(ret))
    warning("`return' with no value, in function returning non-void");
}
Beispiel #4
0
static void incomplete_type_error(expression e, type t)
{
  /* Avoid duplicate error message.  */
  if (t == error_type)
    return;

  if (e && is_identifier(e))
    error("`%s' has an incomplete type", CAST(identifier, e)->cstring.data);
  else
    {
      while (type_array(t) && type_array_size(t))
	t = type_array_of(t);

      if (type_struct(t))
	error("invalid use of undefined type `struct %s'", type_tag(t)->name);
      else if (type_union(t))
	error("invalid use of undefined type `union %s'", type_tag(t)->name);
      else if (type_enum(t))
	error("invalid use of undefined type `enum %s'", type_tag(t)->name);
      else if (type_void(t))
	error("invalid use of void expression");
      else if (type_array(t))
	error("invalid use of array with unspecified bounds");
      else
	assert(0);
      /* XXX: Missing special message for typedef's */
    }
}
Beispiel #5
0
value type_num(value f)
	{
	if (f->N == 0)
		{
		num_free(get_num(f));
		return 0;
		}
	return type_void(f);
	}
Beispiel #6
0
value type_var(value f)
	{
	if (f->N == 0)
		{
		drop(get_var(f));
		return 0;
		}
	return type_void(f);
	}
Beispiel #7
0
static void ptrconversion_warnings(type ttl, type ttr, expression rhs,
				   const char *context,
				   const char *funname, int parmnum,
				   bool pedantic)
{
  if (pedantic
      && ((type_void(ttl) && type_function(ttr)) ||
	  (type_function(ttl) && type_void(ttr) &&
	   !(rhs && definite_null(rhs)))))
    warn_for_assignment("ANSI forbids %s between function pointer and `void *'",
			context, funname, parmnum);

  /* Const and volatile mean something different for function
     types, so the usual warnings are not appropriate.  */
  else if (type_function(ttl) && type_function(ttr))
    {
      /* Because const and volatile on functions are
	 restrictions that say the function will not do
	 certain things, it is okay to use a const or volatile
	 function where an ordinary one is wanted, but not
	 vice-versa.  */
      if (type_const(ttl) && !type_const(ttr))
	warn_for_assignment("%s makes `const *' function pointer from non-const",
			    context, funname, parmnum);
      if (type_volatile(ttl) && !type_volatile(ttr))
	warn_for_assignment("%s makes `volatile *' function pointer from non-volatile",
			    context, funname, parmnum);
    }
  else if (!type_function(ttl) && !type_function(ttr))
    {
      if (!type_const(ttl) && type_const(ttr))
	warn_for_assignment("%s discards `const' from pointer target type",
			    context, funname, parmnum);
      if (!type_volatile(ttl) && type_volatile(ttr))
	warn_for_assignment("%s discards `volatile' from pointer target type",
			    context, funname, parmnum);

      /* If this is not a case of ignoring a mismatch in signedness,
	 no warning.  */
      if (!assignable_pointer_targets(ttl, ttr, FALSE) && pedantic)
	warn_for_assignment("pointer targets in %s differ in signedness",
			    context, funname, parmnum);
    }
}
Beispiel #8
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;
}
Beispiel #9
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;
}
Beispiel #10
0
type default_conversion(expression e)
{
  type from = e->type;

  if (type_enum(from))
    from = type_tag(from)->reptype;

  if (type_smallerthanint(from))
    {
      /* Traditionally, unsignedness is preserved in default promotions. */
      if (flag_traditional && type_unsigned(from))
	return unsigned_int_type;
      else
	return int_type;
    }

  if (flag_traditional && !flag_allow_single_precision && type_float(from))
    return double_type;

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

  if (type_function(from))
    {
      assert(!e->cst);
      e->cst = e->static_address;
      return make_pointer_type(from);
    }

  if (type_array(from))
    {
      if (!e->lvalue)
	{
	  error("invalid use of non-lvalue array");
	  return error_type;
	}
      assert(!e->cst);
      e->cst = e->static_address;
      /* It's being used as a pointer, so is not an lvalue */
      e->lvalue = FALSE;
      return make_pointer_type(type_array_of(from));
    }

  return from;
}
Beispiel #11
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);
}
Beispiel #12
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;
}
Beispiel #13
0
value type_file(value f)
	{
	if (f->N == 0)
		return 0;
	return type_void(f);
	}
Beispiel #14
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;
}
Beispiel #15
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;
}
Beispiel #16
0
static bool assignable_pointer_targets(type tt1, type tt2, bool pedantic)
{
  return type_void(tt1) || type_void(tt2)
    || compatible_pointer_targets(tt1, tt2, pedantic);
}
Beispiel #17
0
bool check_conversion(type to, type from)
{
  if (type_equal_unqualified(to, from))
    return TRUE;

  if (to == error_type || from == error_type)
    return FALSE;

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

  if (type_void(to))
    return TRUE;

  if (type_integer(to))
    {
      if (!type_scalar(from))
	{
	  error("aggregate value used where an integer was expected");
	  return FALSE;
	}
    }
  else if (type_pointer(to))
    {
      if (!(type_integer(from) || type_pointer(from)))
	{
	  error("cannot convert to a pointer type");
	  return FALSE;
	}
    }
  else if (type_floating(to))
    {
      if (type_pointer(from))
	{
	  error("pointer value used where a floating point value was expected");
	  return FALSE;
	}
      else if (!type_arithmetic(from))
	{
	  error("aggregate value used where a float was expected");
	  return FALSE;
	}
    }
  else if (type_complex(to))
    {
      if (type_pointer(from))
	{
	  error("pointer value used where a complex was expected");
	  return FALSE;
	}
      else if (!type_arithmetic(from))
	{
	  error("aggregate value used where a complex was expected");
	  return FALSE;
	}
    }
  else
    {
      error("conversion to non-scalar type requested");
      return FALSE;
    }
  return TRUE;
}