Esempio n. 1
0
/* Obtain decimal value of arguments for binary operation, converting from
   other types if one of them is not decimal floating point.  */
static void
value_args_as_decimal (struct value *arg1, struct value *arg2,
		       gdb_byte *x, int *len_x, enum bfd_endian *byte_order_x,
		       gdb_byte *y, int *len_y, enum bfd_endian *byte_order_y)
{
  struct type *type1, *type2;

  type1 = check_typedef (value_type (arg1));
  type2 = check_typedef (value_type (arg2));

  /* At least one of the arguments must be of decimal float type.  */
  gdb_assert (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
	      || TYPE_CODE (type2) == TYPE_CODE_DECFLOAT);

  if (TYPE_CODE (type1) == TYPE_CODE_FLT
      || TYPE_CODE (type2) == TYPE_CODE_FLT)
    /* The DFP extension to the C language does not allow mixing of
     * decimal float types with other float types in expressions
     * (see WDTR 24732, page 12).  */
    error (_("Mixing decimal floating types with "
	     "other floating types is not allowed."));

  /* Obtain decimal value of arg1, converting from other types
     if necessary.  */

  if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
    {
      *byte_order_x = gdbarch_byte_order (get_type_arch (type1));
      *len_x = TYPE_LENGTH (type1);
      memcpy (x, value_contents (arg1), *len_x);
    }
  else if (is_integral_type (type1))
    {
      *byte_order_x = gdbarch_byte_order (get_type_arch (type2));
      *len_x = TYPE_LENGTH (type2);
      decimal_from_integral (arg1, x, *len_x, *byte_order_x);
    }
  else
    error (_("Don't know how to convert from %s to %s."), TYPE_NAME (type1),
	     TYPE_NAME (type2));

  /* Obtain decimal value of arg2, converting from other types
     if necessary.  */

  if (TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
    {
      *byte_order_y = gdbarch_byte_order (get_type_arch (type2));
      *len_y = TYPE_LENGTH (type2);
      memcpy (y, value_contents (arg2), *len_y);
    }
  else if (is_integral_type (type2))
    {
      *byte_order_y = gdbarch_byte_order (get_type_arch (type1));
      *len_y = TYPE_LENGTH (type1);
      decimal_from_integral (arg2, y, *len_y, *byte_order_y);
    }
  else
    error (_("Don't know how to convert from %s to %s."), TYPE_NAME (type1),
	     TYPE_NAME (type2));
}
Esempio n. 2
0
/* Obtain argument values for binary operation, converting from
   other types if one of them is not floating point.  */
static void
value_args_as_target_float (struct value *arg1, struct value *arg2,
			    gdb_byte *x, struct type **eff_type_x,
			    gdb_byte *y, struct type **eff_type_y)
{
  struct type *type1, *type2;

  type1 = check_typedef (value_type (arg1));
  type2 = check_typedef (value_type (arg2));

  /* At least one of the arguments must be of floating-point type.  */
  gdb_assert (is_floating_type (type1) || is_floating_type (type2));

  if (is_floating_type (type1) && is_floating_type (type2)
      && TYPE_CODE (type1) != TYPE_CODE (type2))
    /* The DFP extension to the C language does not allow mixing of
     * decimal float types with other float types in expressions
     * (see WDTR 24732, page 12).  */
    error (_("Mixing decimal floating types with "
	     "other floating types is not allowed."));

  /* Obtain value of arg1, converting from other types if necessary.  */

  if (is_floating_type (type1))
    {
      *eff_type_x = type1;
      memcpy (x, value_contents (arg1), TYPE_LENGTH (type1));
    }
  else if (is_integral_type (type1))
    {
      *eff_type_x = type2;
      if (TYPE_UNSIGNED (type1))
	target_float_from_ulongest (x, *eff_type_x, value_as_long (arg1));
      else
	target_float_from_longest (x, *eff_type_x, value_as_long (arg1));
    }
  else
    error (_("Don't know how to convert from %s to %s."), TYPE_NAME (type1),
	     TYPE_NAME (type2));

  /* Obtain value of arg2, converting from other types if necessary.  */

  if (is_floating_type (type2))
    {
      *eff_type_y = type2;
      memcpy (y, value_contents (arg2), TYPE_LENGTH (type2));
    }
  else if (is_integral_type (type2))
    {
      *eff_type_y = type1;
      if (TYPE_UNSIGNED (type2))
	target_float_from_ulongest (y, *eff_type_y, value_as_long (arg2));
      else
	target_float_from_longest (y, *eff_type_y, value_as_long (arg2));
    }
  else
    error (_("Don't know how to convert from %s to %s."), TYPE_NAME (type1),
	     TYPE_NAME (type2));
}
Esempio n. 3
0
bool is_signed(IDL_tree typ)
{
	assert(is_integral_type(typ));
	return IDL_NODE_TYPE(typ) == IDLN_TYPE_CHAR
		|| IDL_NODE_TYPE(typ) == IDLN_TYPE_WIDE_CHAR
		|| (IDL_NODE_TYPE(typ) == IDLN_TYPE_INTEGER
			&& IDL_TYPE_INTEGER(typ).f_signed);
}
Esempio n. 4
0
File: type.c Progetto: certik/nwcc
/*
 * XXX  warn about ``unsigned char *'' vs ``char *'',
 * unlike gcc
 */
static int
compare_tlist(struct type_node *dest, struct type_node *src, int flag) {
	struct type_node	*dest_start = dest;

	for (;
		dest != NULL && src != NULL;
		dest = dest->next, src = src->next) {

		if (src->type == TN_FUNCTION
			|| dest->type == TN_FUNCTION) {
			if (dest->type != src->type) {
				/* XXX fix this later */
				if (dest == dest_start) {
					/*
					 * Ordinary function symbols are
					 * compatible with pointers to
					 * functions
					 */
					if (dest->type == TN_FUNCTION) {
						if (src->type
							== TN_POINTER_TO) {
							src = src->next;
						} else {
							return -1;
						}	
					} else {
						if (dest->type
							== TN_POINTER_TO) {
							dest = dest->next;
						} else {
							return -1;
						}	
					}	
				}	
			}
		}

		if (dest->type != src->type) {
			/* Pointer vs array vs function */
			if (flag & CMPTY_ARRAYPTR) {
				if ((dest->type == TN_ARRAY_OF
					|| src->type == TN_ARRAY_OF
					|| dest->type == TN_VARARRAY_OF
					|| src->type == TN_VARARRAY_OF)

					&& (dest->type == TN_POINTER_TO
					|| src->type == TN_POINTER_TO)) {
					continue;
				}	
			}
			return -1;
		}

		switch (dest->type) {
		case TN_ARRAY_OF:
		case TN_VARARRAY_OF:	
			if (flag & CMPTY_TENTDEC) {
#if REMOVE_ARRARG
				if (!dest->have_array_size
					|| !src->have_array_size) {	
#else
				if (dest->arrarg->const_value == NULL
					|| src->arrarg->const_value == NULL) {
#endif
					/*
					 * probably
					 * extern int foo[];
					 * int foo[123];
					 * -> OK!
					 */
					break;
				}
			}
			if (dest->arrarg_const != src->arrarg_const
				&& ((flag & CMPTY_ARRAYPTR) == 0
				|| dest_start != dest)) {
#if REMOVE_ARRARG
				if (!src->have_array_size
					|| !dest->have_array_size) {	
#else
				if (src->arrarg->const_value == NULL
					|| dest->arrarg->const_value == NULL) {
#endif
					/*
					 * One side has unspecified size, this
					 * is OK!
					 * extern char foo[];
					 * char (*p)[5] = &foo;
					 * char bar[5];
					 * char (*p2)[] = &bar;
					 */
					break;
				} else {
					/* Array sizes differ */
					return -1;
				}	
			}
			break;
		case TN_POINTER_TO:
			break;
		case TN_FUNCTION:
			if (compare_tfunc(dest->tfunc, src->tfunc) == -1) {
				return -1;
			}
			break;
		}
	}
	if (dest != NULL || src != NULL) {
		/* One list is longer, so it differs by definition */
		return -1;
	}
	return 0;
}
#endif /* #ifndef PREPROCESSOR */

int
compare_types(struct type *dest, struct type *src, int flag) {
	int	is_void_ptr = 0;


	/* 04/08/08: Changed this (for the better, hopefully!) */
	if (dest->tlist != NULL
		&& dest->tlist->type == TN_POINTER_TO	
		&& dest->tlist->next == NULL
		&& dest->code == TY_VOID) {
		is_void_ptr = 1;
	} else if (src->tlist != NULL
		&& src->tlist->type == TN_POINTER_TO
		&& src->tlist->next == NULL
		&& src->code == TY_VOID) {
		is_void_ptr = 1;
	}
	
	if (dest->code != src->code) {
		/*
		 * Differing base type - This is ok if we have a void
		 * pointer vs a non-void pointer, otherwise return error
		 */
		if (!is_void_ptr || src->tlist == NULL || dest->tlist == NULL) {
			return -1;
		}
	}

	if (flag & CMPTY_SIGN) {
		if (dest->sign != dest->sign) {
			/* Differing sign */
			return -1;
		}
	}
	if (flag & CMPTY_CONST) {
		if (IS_CONST(dest->flags) != IS_CONST(src->flags)) {
			/* One is const-qualified */
			/*return -1;*/
		}
	}

	/*
	 * 04/08/08: Skip the tlist comparison if this is void pointer
	 * vs non-void pointer; Otherwise tlists of different length
	 * will compare uneven, as in void * vs int **, which is wrong
	 */
	if (is_void_ptr) {
		return 0;
	}

#ifndef PREPROCESSOR
	return compare_tlist(dest->tlist, src->tlist, flag);
#else
	return -1;
#endif
}


int
check_init_type(struct type *ofwhat, struct expr *init) {
	if (ofwhat->tlist == NULL) {
		if (init->next != NULL) {
		}
	} else if (ofwhat->tlist->type == TN_ARRAY_OF) {
		if (init->type->code == TOK_STRING_LITERAL) {
			return 0;
		} else {
			struct expr	*ex;
			for (ex = init; ex != NULL; ex = ex->next) {
		}
		}
	}
	return 0;
}

void
copy_type(struct type *dest, const struct type *src, int fullcopy) {
	if (fullcopy) {
		memcpy(dest, src, sizeof *dest);
	} else {
		memcpy(dest, src, sizeof *dest);
	}
}

struct type_node *
copy_tlist(struct type_node **dest, const struct type_node *src) {
	struct type_node	*head;
	struct type_node	*tail;
	struct type_node	*tn;

	if (src == NULL) {
		*dest = NULL;
		return NULL;
	}
	head = tail = NULL;
	do {
		tn = n_xmalloc(sizeof *tn);
		memcpy(tn, src, sizeof *tn);
		if (head == NULL) {
			head = tail = tn;
		} else {
			tail->next = tn;
			tail = tail->next;
		}	
	} while ((src = src->next) != NULL);	
	*dest = head;
	return tail;
}
		

void
set_type_sign(struct type *ty) {
	if (ty->code == TY_UCHAR
		|| ty->code == TY_USHORT
		|| ty->code == TY_UINT
		|| ty->code == TY_ULONG
		|| ty->code == TY_ULLONG) {
		ty->sign = TOK_KEY_UNSIGNED;
	} else if (!IS_FLOATING(ty->code)
		&& ty->code != TY_STRUCT
		&& ty->code != TY_UNION) {
		ty->sign = TOK_KEY_SIGNED;
	}
}
			

struct type *
make_basic_type(int code) {
#define N_TYPES (TY_MAX - TY_MIN)
#if 0
	static struct type	basic_types[N_TYPES];
#endif
	static int		inited;
	static struct type	*basic_types;

	if (!inited) {
		int	i;
		int	nbytes = N_TYPES * sizeof(struct type);
		int	need_mprotect = 1;

		basic_types = debug_malloc_pages(nbytes);
		if (basic_types == NULL) {
			/*
			 * Probably debug_malloc_pages() doesn't work
		 	 * on this system
			 */
			basic_types = n_xmalloc(nbytes);
			need_mprotect = 0;
		}
		memset(basic_types, 0, nbytes);
		for (i = 0; i < N_TYPES; ++i) {
			basic_types[i].code = i + TY_MIN;
			set_type_sign(&basic_types[i]);
		}		
		inited = 1;

		if (need_mprotect) {
			/*
			 * We make the array unwritable because it really
			 * should not be written to; Modifying it is a bug
			 * that has happend more than once. 
			 * 
			 * The void cast is necessary because of a broken
			 * Solaris prototype that takes caddr_t :-/
			 */
			mprotect((void *)basic_types, nbytes, PROT_READ); 
		}
	}
	if (code < 0 || (code - TY_MIN) >= N_TYPES) {
		printf("BUG: bad code for make_basic_type: %d\n", code);
		abort();
	}

#if 0 
	if (code == TY_PSEUDEO_SIZE_T) {
		static struct type	ty;
		static struct type	*p;

		if (p == NULL) {
			ty = basic_types[TY_UINT];
		}
	}
#endif

#if 0
	/* As of Jan 6 2007, the basic types may not be modified anymore */
	basic_types[code - TY_MIN].tlist = NULL;
#endif
	return &basic_types[code - TY_MIN];
}

struct type *
make_void_ptr_type(void) {
	static struct type	*ty;

	if (ty == NULL) {
		ty = make_basic_type(TY_VOID);
		ty = n_xmemdup(ty, sizeof *ty);
		append_typelist(ty, TN_POINTER_TO, NULL, NULL, NULL);
	}
	return ty;
}

struct type *
make_array_type(int size, int is_wide_char) {
	struct type	*ret = alloc_type();

	if (is_wide_char) {
		ret->code = backend->get_wchar_t()->code;
		ret->sign = backend->get_wchar_t()->sign;
	} else {
		ret->code = TY_CHAR;
		if (CHAR_MAX == UCHAR_MAX) { /* XXX */
			ret->sign = TOK_KEY_UNSIGNED;
		} else {
			ret->sign = TOK_KEY_SIGNED;
		}
	}
	ret->storage = TOK_KEY_STATIC;

	ret->tlist = alloc_type_node();
	ret->tlist->type = TN_ARRAY_OF;
	ret->tlist->arrarg_const = size;
#if REMOVE_ARRARG
	ret->tlist->have_array_size = 1;
#endif
	return ret;
}


/*
 * Helper function for parse_declarator()- stores pointer/array-of/function
 * property (specified by ``type'' argument) with optional arguments type_arg
 * (for pointer/array-of) and tf (for function) in type specified by t
 *
 * 01/26/08: Extended to do some sanity checking (functions may not return
 * functions or arrays). This means some type constructions are now REQUIRED
 * to go through append_typelist()! May not be the best approach, needs
 * testing?!
 */
void
append_typelist(struct type *t, 
		int type,
		void *type_arg,
		struct ty_func *tf,
		struct token *tok) {
	struct type_node	*te;
	struct expr		*ex;

	(void) tok; /* XXX unneeded?!?! */

	/* Allocate and insert new type node */
	if (t->tlist == NULL) {
		te = t->tlist = t->tlist_tail = alloc_type_node();
		te->prev = NULL;
		if (type == TN_FUNCTION) {
			/*
			 * If the first node in the type list is a function
			 * designator, this means we are dealing with a genuine
			 * function declaration/definition (as opposed to a
			 * pointer)
			 */
			t->is_func = 1;
		}
	} else {
		/*
		 * 01/26/08: Some sanity checking!
		 */
		int	tailtype = t->tlist_tail->type;

		if (tailtype == TN_ARRAY_OF || tailtype == TN_VARARRAY_OF) {
			if (type == TN_FUNCTION) {
				errorfl(tok, "Invalid declaration of `array of "
					"functions' - Maybe you meant `array "
					"of pointer to function'; `void (*ar[N])();'?");
				return /* -1  XXX */   ;
			}
		} else if (tailtype == TN_FUNCTION) {
			if (type == TN_ARRAY_OF || type == TN_VARARRAY_OF) {
				errorfl(tok, "Invalid declaration of `function "
					"returning array' - If you really want "
					"to return an array by value, put it "
					"into a structure!");
				return /* -1  XXX */   ;
			} else if (type == TN_FUNCTION) {
				errorfl(tok, "Invalid declaration of `function "
					"returning function' - You can at most "
					"return a pointer to a function; "
					"`void (*foo())();'");
				return /* -1 XXX */   ;
			}
		}

		te = alloc_type_node();
		te->prev = t->tlist_tail;
		t->tlist_tail->next = te;
		t->tlist_tail = t->tlist_tail->next;
	}

	te->next = NULL;

	te->type = type;

	switch (type) {
	case TN_VARARRAY_OF:	
	case TN_ARRAY_OF:
#if REMOVE_ARRARG
		ex = type_arg;
		if (ex->const_value == NULL) {
			/* Size not specified - extern char buf[]; */
			te->have_array_size = 0;
		} else {
			te->have_array_size = 1;
			ex->const_value->type =
				n_xmemdup(ex->const_value->type,
						sizeof(struct type));
			cross_convert_tyval(ex->const_value, NULL, NULL);
			te->arrarg_const = cross_to_host_size_t(
					ex->const_value);
			if (te->arrarg_const == 0) {
				/*
				 * In GNU C,
				 * int foo[0];
				 * may be a flexible array member
				 */
				te->have_array_size = 0;
#if 0
				errorfl(tok,
					"Cannot create zero-sized arrays");
#endif
			}	
		}
		if (type == TN_VARARRAY_OF) {
			te->variable_arrarg = ex;
		}
#else /* Using arrarg */
		te->arrarg = type_arg;
		if (te->arrarg->const_value) {
			te->arrarg->const_value->type =
				n_xmemdup(te->arrarg->const_value->type,
				sizeof(struct type));
			cross_convert_tyval(te->arrarg->const_value, NULL, NULL);
			te->arrarg_const = /* *(size_t *) */
				cross_to_host_size_t(
				te->arrarg->const_value);  /*->value; */
			if (te->arrarg_const == 0) {
				/*
				 * In GNU C,
				 * int foo[0];
				 * may be a flexible array member
				 */
				te->arrarg->const_value = NULL;
#if 0
				errorfl(tok,
					"Cannot create zero-sized arrays");
#endif
			}	
		}	
#endif /* REMOVE_ARRARG is disabled */
		break;
	case TN_POINTER_TO:
		te->ptrarg = type_arg? *(int *)type_arg: 0;
		break;
	case TN_FUNCTION:
		te->tfunc = tf; 
		break;
	}
}

static struct {
	char	*name;
	int	code;
} basic_type_names[] = {
	{ "char", TY_CHAR },
	{ "unsigned char", TY_UCHAR },
	{ "signed char", TY_SCHAR },
	{ "short", TY_SHORT },
	{ "unsigned short", TY_USHORT },
	{ "int", TY_INT },
	{ "unsigned int", TY_UINT },
	{ "long", TY_LONG },
	{ "unsigned long", TY_ULONG },
	{ "float", TY_FLOAT },
	{ "double", TY_DOUBLE },
	{ "long double", TY_LDOUBLE },
	{ "struct", TY_STRUCT },
	{ "union", TY_UNION },
	{ "enum", TY_ENUM },
	{ "void", TY_VOID },
	{ "long long", TY_LLONG },
	{ "unsigned long long", TY_ULLONG },
	{ "_Bool", TY_BOOL },
	{ NULL, 0 }
};

char *
ret_type_to_text(struct type *ty) {
	struct type_node	*orig_tlist = NULL;
	char			*ret;

	if (ty->tlist != NULL) {
		orig_tlist = ty->tlist;
		if (ty->tlist->type == TN_FUNCTION) {
			ty->tlist = ty->tlist->next;
		} else if (ty->tlist->type == TN_POINTER_TO
			&& ty->tlist->next != NULL
			&& ty->tlist->next->type == TN_FUNCTION) {
			ty->tlist = ty->tlist->next->next;
		}
		ret = type_to_text(ty);
		ty->tlist = orig_tlist;
	} else {
		ret = type_to_text(ty);
	}
	return ret;
}

char *
type_to_text(struct type *dt) {
	struct type_node	*t;
	char			*buf = NULL;
	char			*p = NULL;
	size_t			size = 0;
	size_t			used = 0;
	int			i;

	for (t = dt->tlist; t != NULL; t = t->next) {
		switch (t->type) {
		case TN_ARRAY_OF:
		case TN_VARARRAY_OF:
			make_room(&buf, &size, used + 64);
			used += sprintf(buf+used, "an array of %d ",
				(int)t->arrarg_const);
			break;
		case TN_POINTER_TO: {
			char	*quali = "";
			if (t->ptrarg != 0) {
				switch (t->ptrarg) {
				case TOK_KEY_VOLATILE:
					quali = "volatile";
					break;
				case TOK_KEY_CONST:
					quali = "constant";
					break;
				case TOK_KEY_RESTRICT:
					quali = "restricted";
					break;
				}
			}
			make_room(&buf, &size, used + 32);
			used += sprintf(buf+used, "a %s pointer to ", quali);
			break;
		}
		case TN_FUNCTION:
			make_room(&buf, &size, used + 32);
			used += sprintf(buf+used, "a function (with %d args) returning ", t->tfunc->nargs);
			break;
		}
	}	

#if 0
	p = basic_type_names[dt->code - TY_MIN];
#endif
	for (i = 0; basic_type_names[i].name != NULL; ++i) {
		if (dt->code == basic_type_names[i].code) {
			p = basic_type_names[i].name;
			break;
		}
	}
	make_room(&buf, &size, strlen(p) + 5);
	used += sprintf(buf+used, "%s", p);
	if (dt->code == TY_STRUCT) {
		if (dt->tstruc && dt->tstruc->tag) {
			make_room(&buf, &size,
				used + strlen(dt->tstruc->tag) + 2);
			sprintf(buf+used, " %s", dt->tstruc->tag);
		}	
	}	

	return buf;
}

#ifndef PREPROCESSOR

extern void	put_ppc_llong(struct num *);

/*
 * XXX same stupid size_t cross-compilaion bug as const_from_value()..
 * this stuff SUCKS!!!
 */
struct token *
const_from_type(struct type *ty, int from_alignment, int extype, struct token *t) {
	struct token	*ret = alloc_token();
	size_t		size;
	int		size_t_size;

#if 0
	ret->type = TY_ULONG; /* XXX size_t */
#endif
	ret->type = backend->get_size_t()->code;
	if (from_alignment) {
		size = backend->get_align_type(ty);
	} else {	
		size = backend->get_sizeof_type(ty, t);
	}
	/*ret->data = n_xmemdup(&size, sizeof size);*/
	ret->data = n_xmalloc(16); /* XXX */

	size_t_size = backend->get_sizeof_type(backend->get_size_t(), NULL);
	if (sizeof size == size_t_size) {
		memcpy(ret->data, &size, sizeof size);
	} else if (sizeof(int) == size_t_size) {
		unsigned int	i = (unsigned int)size;
		memcpy(ret->data, &i, sizeof i);
	} else if (sizeof(long) == size_t_size) {
		unsigned long	l = (unsigned long)size;
		memcpy(ret->data, &l, sizeof l);
	} else if (sizeof(long long) == size_t_size) {
		unsigned long long ll = (unsigned long long)size;
		memcpy(ret->data, &ll, sizeof ll);
	} else {
		unimpl();
	}	
	  
	if (backend->abi == ABI_POWER64
		&& extype != EXPR_CONST
		&& extype != EXPR_CONSTINIT
		/* What about EXPR_OPTCONSTINIT?! */ ) {
		struct num	*n = n_xmalloc(sizeof *n);
		
		/*
		 * XXX see definition of put_ppc_llong() for an
		 * explanation of this mess
		 */
		n->type = ret->type;
		n->value = ret->data;
		put_ppc_llong(n);
		/*ret->data = llong_const;*/
		ret->data2 = llong_const;
	}	
	return ret;
}


/*
 * XXX this interface is ROTTEN!!
 * too easy to pass a ``size_t'' for value with ty=NULL by accident!!
 *
 * XXXX WOAH this was totally broken WRT cross-compilation! ``type''
 * is interpreted as host type when dealing with ``value'', and as
 * target type too by making it the type of the token! Current ad-hoc
 * kludge sucks!
 */
struct token *
const_from_value(void *value, struct type *ty) {
	struct token	*ret = alloc_token();
	size_t		size;

	if (ty == NULL) {
		ret->type = TY_INT;
		size = backend->get_sizeof_type(make_basic_type(
			TY_INT), NULL);;
	} else {
		ret->type = ty->code;
		size = backend->get_sizeof_type(ty, NULL);
	}
	if (ty && (IS_LONG(ty->code) || IS_LLONG(ty->code))) {
		if (sizeof(long) == size) {
			/* Size matches - nothing to do */
			;
		} else {
			static long long	llv;
			llv = *(int *)value;
			value = &llv;
		}
	}
	ret->data = n_xmemdup(value, size);
	if (backend->abi == ABI_POWER64
		&& ty != NULL
		&& is_integral_type(ty)
		&& size == 8) {
		struct num	*n = n_xmalloc(sizeof *n);
		static struct num nullnum;
		*n = nullnum;
		n->type = ret->type;
		n->value = ret->data;
		put_ppc_llong(n);
		ret->data2 = llong_const;
	}
	return ret;
}	

/*
 * Construct a floating point constant token of type ``type'' 
 * containing ``value'' (which must be a string parsable by sscanf().)
 */
struct token *
fp_const_from_ascii(const char *value, int type) {
	struct num	*n;
	struct token	*ret = n_xmalloc(sizeof *ret);

	n = cross_scan_value(value, type, 0, 0, 1);
	if (n == NULL) {
		return NULL;
	}
	
	/*
	 * XXX token.data is ``struct ty_float'', not 
	 * ``struct num''. Because the interfaces are
	 * still messed up, we have to get the current
	 * ty_float corresponding to ``n'' from the
	 * float list. This SUCKS!
	 */
	ret->data = float_const/*n->value*/;
	ret->type = type;
	ret->ascii = n_xstrdup(value);
	return ret;
}


struct token *
const_from_string(const char *value) {
	struct token		*ret = alloc_token();
	struct type		*ty;
	struct ty_string        *tmpstr;
	
	tmpstr = alloc_ty_string();
	tmpstr->size = strlen(value) + 1;
	tmpstr->str = n_xmemdup(value, tmpstr->size);
	tmpstr->is_wide_char = 0;

	ret->type = TOK_STRING_LITERAL;
	ty = make_array_type(tmpstr->size, tmpstr->is_wide_char);
	tmpstr->ty = ty;

	ret->data = tmpstr;
	return ret;
}


int
is_integral_type(struct type *t) {
	if (t->tlist != NULL) {
		return 0;
	}
	if (IS_CHAR(t->code)
		|| IS_SHORT(t->code)
		|| IS_INT(t->code)
		|| IS_LONG(t->code)
		|| IS_LLONG(t->code)
		|| t->code == TY_ENUM) {
		return 1;
	}
	return 0;
}

int
is_floating_type(struct type *t) {
	if (t->tlist != NULL) {
		return 0;
	}
	if (t->code == TY_FLOAT
		|| t->code == TY_DOUBLE
		|| t->code == TY_LDOUBLE) {
		return 1;
	}
	return 0;
}	
			

int
is_arithmetic_type(struct type *t) {
	if (t->tlist != NULL) {
		return 0;
	}
	if (IS_FLOATING(t->code)
		|| is_integral_type(t)) {
		return 1;
	}
	return 0;
}


int
is_array_type(struct type *t) {
	struct type_node	*tn;

	if (t->tlist == NULL) {
		return 0;
	}	
	for (tn = t->tlist; tn != NULL; tn = tn->next) {
		if (tn->type != TN_ARRAY_OF) {
			return 0;
		} else {
			break;
		}	
	}
	return 1;
}	


int
is_basic_agg_type(struct type *t) {
	if (t->tlist == NULL) {
		if (t->code == TY_STRUCT || t->code == TY_UNION) {
			return 1;
		}
	} else if (is_array_type(t)) {
		return 1;
	}
	return 0;
}

int
is_scalar_type(struct type *t) {
	if (t->tlist == NULL
		&& (t->code == TY_STRUCT
		|| t->code == TY_UNION
		|| t->code == TY_VOID)) {
		return 0;
	}
	return 1;
}	

int
is_arr_of_ptr(struct type *t) {
	struct type_node	*tn;

	for (tn = t->tlist; tn != NULL; tn = tn->next) {
		if (tn->type == TN_POINTER_TO) {
			return 1;
		} else if (tn->type == TN_FUNCTION) {
			return 0;
		}	
	}
	return 0;
}

int
is_nullptr_const(struct token *constant, struct type *ty) {
	if (IS_INT(ty->code)
		&& *(unsigned *)constant->data == 0) {
		return 1;
	} else if (IS_LONG(ty->code)
		&& *(unsigned long *)constant->data == 0) {
		return 1;
	}
	return 0;
}



/*
 * The source type must be passed with a vreg because we need the null
 * pointer constant and object backing information it gives us
 */
int
check_types_assign(
	struct token *t,
	struct type *left,
	struct vreg *right,
	int to_const_ok,
	int silent) {

	struct type	*ltype = left;
	struct type	*rtype = right->type;

	if (ltype == NULL || rtype == NULL) {
		printf("attempt to assign to/from value without type :(\n");
		abort();
	}

	/*
	 * 01/26/08: Changed this to call is_modifyable(), which also
	 * rules out assignment to const-qualified pointers
	 */
	/*if (ltype->tlist == NULL && ltype->is_const && !to_const_ok) { */
	if (!is_modifyable(ltype) && !to_const_ok) {
		if (!silent) {
			errorfl(t,
				"Assignment to const-qualified object");	
		}
		return -1;
	}	

	if (is_arithmetic_type(ltype)) {
		if (!is_arithmetic_type(rtype)) {
			if (ltype->code == TY_BOOL
				&& rtype->tlist != NULL) {
				/* ok - pointer to bool */
				return 0;
			} else {
				int	allow = 0;

				if (rtype->tlist != NULL
					&& is_integral_type(ltype)) {
					/*
					 * 03/09/09: Give in and allow pointer
					 * to integer assignment with a warning
					 */
					allow = 1;
				}

				if (!silent) {
					if (allow) {
						warningfl(t,
						"Assignment from non-arithmetic to "
						"arithmetic type");
					} else {
						errorfl(t,
						"Assignment from non-arithmetic to "
						"arithmetic type");
					}
				}
				if (allow) {
					return 0;
				} else {
					return -1;
				}
			}	
		} else if (ltype->sign != rtype->sign
			&& !right->from_const) {
			/*
			 * Do not warn about signedness differences if the
			 * right side is a constant!
			 */
#if 0
			/* XXX Too verbose */
			warningfl(t,
			"Assignment from type of differing signedness");
#endif
			return 0;
		}
		return 0;		
	} else if (ltype->tlist == NULL) {
		/* Must be struct/union */
		if (rtype->tlist != NULL) {
			if (ltype->code == TY_BOOL) {
				return 0;
			} else {	
				if (!silent) {
					/* 06/01/08: Warn, not error */
					warningfl(t,
				"Assignment from pointer to non-pointer type");
				}

				/*
				 * 07/20/08: The return below was commented out!
				 * That's wrong because pointer to struct will
				 * compare assignable to struct
				 * Why was this removed?
				 */
				return -1;
			}	
		} else if (ltype->code == TY_BOOL) {
			return 0; /* _Bool b = ptr; is OK */
		} else if (rtype->code != ltype->code
			|| rtype->tstruc != ltype->tstruc) {
			if (!silent) {
				errorfl(t,
				"Assignment from incompatible type");
			}
			return -1;
		} else {
			return 0;
		}
	} else {
		/* Left is pointer of some sort */
		if (right->is_nullptr_const) {
			; /* ok */
		} else if (rtype->tlist == NULL) {
			if (!silent) {
				warningfl(t, "Assignment from non-pointer "
					"to pointer type");
			}
/*			return -1;*/
		} else if (rtype->code == TY_VOID
			&& rtype->tlist->type == TN_POINTER_TO
			&& rtype->tlist->next == NULL) {
			; /* void pointer - compatible */
		} else if (ltype->code == TY_VOID
			&& ltype->tlist->type == TN_POINTER_TO
			&& ltype->tlist->next == NULL) {
			; /* void pointer - compatible */
		} else if (compare_tlist(ltype->tlist, rtype->tlist,
				CMPTY_ARRAYPTR)) {
			if (!silent) {
			warningfl(t, "Assignment from incompatible pointer type"
					" (illegal in ISO C, and very "
					"probably not what you want)");
			} else {
				/*
				 * This is only used for transparent_union
				 * right now... in that case we do not want
				 * to allow this assignment because type-
				 * checking is the whole point of that
				 * language extension
				 */
				return -1;
			}
			return 0;
		} else if (!IS_CONST(ltype->flags) && IS_CONST(rtype->flags)) {
			if (!silent) {
				warningfl(t,
					"Assignment from const-qualified type "
					"to unqualified one");
			}
			return 0;
		} else if (rtype->code != ltype->code
			&& rtype->code != TY_VOID
			&& ltype->code != TY_VOID
		/* XXX */ && (!IS_CHAR(ltype->code) || !IS_CHAR(rtype->code))) {
			if (type_without_sign(ltype->code)
				== type_without_sign(rtype->code)) {
				if (!silent) {
					warningfl(t, "Assignment from pointer of "
						"differing signedness");
				} else {
					return -1;
				}	
				return 0;
			} else {	
				if (!silent) {
					warningfl(t, "Assignment from incompatible "
					"pointer type (illegal in ISO C, and "
					"very probably not what you want)");
				} else {
					return -1;
				}
#if 0
				return -1;
#endif
				return 0;
			}	
		} else if (IS_CONST(ltype->flags) && !IS_CONST(rtype->flags)
			&& ltype->tlist != NULL
			&& ltype->tlist->next != NULL) {
			if (!silent) {
				warningfl(t, "ISO C does not allow assignment "
					"from `T **' to `const T **' without a "
					"cast (otherwise invalid code like "
					"`const char dont_modify; char *p; const "
					"char **cp = &p; *cp = &dont_modify; *p = 0;' "
					"would pass without warning)");
			}
			return 0;
		}
	}	

	return 0;
}

struct type *
addrofify_type(struct type *ty) {
	struct type		*ret = n_xmemdup(ty, sizeof *ty);
	struct type_node	*tn;

	copy_tlist(&ret->tlist, ret->tlist);
	tn = alloc_type_node();
	tn->type = TN_POINTER_TO;
	tn->next = ret->tlist;
	ret->tlist = tn;
	return ret;
}

int
type_without_sign(int code) {
	int	rc = code;

	if (code == TY_UCHAR) rc = TY_CHAR;
	else if (code == TY_USHORT) rc = TY_SHORT;
	else if (code == TY_UINT) rc = TY_INT;
	else if (code == TY_ULONG) rc = TY_LONG;
	else if (code == TY_ULLONG) rc = TY_LLONG;
	return rc;
}	
Esempio n. 5
0
void
check_format_string(struct token *tok,
		struct type *fty,
		struct ty_func *fdecl,
		struct vreg **args,
		struct token **from_consts,
		int nargs) {
	
	struct attrib		*a;
	struct ty_string	*ts;
	int			i;
	int			fmtidx;
	int			checkidx;
	int			cur_checkidx;

	a = lookup_attr(fty->attributes, ATTRF_FORMAT);
	assert(a != NULL);

	fmtidx = a->iarg2;
	checkidx = a->iarg3;

	if (fdecl->nargs == -1) {
		/* Function takes no parameters?! */
		return;
	}
	if (fmtidx + 1 > nargs) {
		/* No format string passed?! */
		return;
	}
	if (checkidx + 1 > nargs) {
		/* No arguments to check */
		return;
	}
	cur_checkidx = checkidx;

	if (from_consts[fmtidx] == NULL) {
		/*
		 * Format string isn't a string constant so we can't
		 * check it
		 */
		return;
	}

	ts = from_consts[fmtidx]->data;
	for (i = 0; i < (int)ts->size; ++i) {
		if (ts->str[i] == '%') {
			if (i + 1 == (int)ts->size) {
				warningfl(tok, "Invalid trailing `%%' char "
					"without conversion specifier");
			} else if (ts->str[i + 1] == '%') {
				/* % char */
				++i;
			} else {
				struct type	*passed_ty;
				int		ch = 0;
				char		*p = NULL;

				if (cur_checkidx + 1 > nargs) {
					warningfl(tok, "Format specifier "
						"%d has no corresponding "
						"argument!",
						cur_checkidx - checkidx);
					++cur_checkidx;
					continue;
				}

				passed_ty = args[cur_checkidx]->type;

				/*
				 * We only handle simple obvious cases for
				 * now, i.e. %s vs int argument, %d vs
				 * string argument, etc.
				 */
				if (ts->str[i + 1] == 'l') {
					if (i + 2 == (int)ts->size) {
						warningfl(tok, "Incomplete "
							"conversion specifier "
							"`%%l'");
					} else if (ts->str[i + 2] == 'l') {
						if (i + 3 == (int)ts->size) {
							warningfl(tok, "Incomplete "
								"conversion specifier "
								"`%%ll'");
						} else {
							ch = get_type_by_fmt(
								ts->str[i+1],
								ts->str[i+2],
								ts->str[i+3]);
						}
					} else {
						ch = get_type_by_fmt(
							ts->str[i+1],
							ts->str[i+2],
							0);
					}
				} else {
					ch = get_type_by_fmt(ts->str[i+1], 0, 0);
				}


				switch (ch) {
				case TY_INT:
				case TY_UINT:
				case TY_LONG:
				case TY_ULONG:
				case TY_LLONG:
				case TY_ULLONG:
					if (!is_integral_type(passed_ty)) {
						p = type_to_text(passed_ty);
						warningfl(tok, "Format "
						"specifier %d expects integral "
						"type, but received argument "
						"of type `%s'",
						cur_checkidx-checkidx+1,
						p);
					} else {
						static struct type dummy;
						char			*p2;

						/* OK, both are integral */
						if ( (IS_INT(ch)
							&& IS_LONG(passed_ty->code)) 
							|| (IS_LONG(ch)
							&& IS_INT(passed_ty->code))) {
							static int warned;
							dummy.code = ch;
							p = type_to_text(passed_ty);
							p2 = type_to_text(&dummy);
							/*
							 * Keep the number of
							 * warnings down because
							 * this can happen lots
							 * of times with %d vs
							 * size_t; That will
							 * work on all supported
							 * systems, and a user
							 * who cares will pay
							 * attention to 1 warning
							 * just as well
							 */
							if (!warned) {
								warningfl(tok,
"Format specifier %d expects argument of type `%s', but received `%s'",
cur_checkidx-checkidx+1,
p2, p);
								warned = 1;
							}
							free(p2);
						} else if (IS_LLONG(ch)
							!= IS_LLONG(passed_ty->code)) {
							dummy.code = ch;
							p = type_to_text(passed_ty);
							p2 = type_to_text(&dummy);
warningfl(tok, "Format specifier %d expects argument of type `%s', but received `%s'",
		cur_checkidx-checkidx+1,
		p2, p);
							free(p2);
						}
					}
					break;
				case TY_DOUBLE:
				case TY_LDOUBLE:
					if (!is_floating_type(passed_ty)) {
						p = type_to_text(passed_ty);
						warningfl(tok, "Format "
						"specifier %d expects floating "
						"point type, but received "
						"argument of type `%s'",
						cur_checkidx-checkidx+1,
						p);
					} else if (passed_ty->code != ch) {
						p = type_to_text(passed_ty);
						warningfl(tok, "Format "
						"specifier %d expects type "
						"`%s', but received argument "
						"of type `%s'",
						cur_checkidx-checkidx+1,
						ch == TY_DOUBLE? "double":
							"long double",
						p);
					}
					break;
				default:
					if (ts->str[i+1] == 's') {
						if (passed_ty->tlist == NULL
							|| (passed_ty->tlist->type != TN_ARRAY_OF
							&& passed_ty->tlist->type != TN_POINTER_TO)
							|| passed_ty->tlist->next != NULL
							|| passed_ty->code != TY_CHAR
							|| passed_ty->code != TY_VOID) {
							p = type_to_text(passed_ty);
							warningfl(tok, "Format "
							"specifier %d expects string, "
							"but received argument of type "
							"`%s'",
							cur_checkidx-checkidx+1,
							p);
						}
					}
					break;
				}
				if (p != NULL) {
					free(p);
				}
				++cur_checkidx;
			}
		}
	}
}
Esempio n. 6
0
static struct value *
scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
{
  struct value *val;
  struct type *type1, *type2, *result_type;

  arg1 = coerce_ref (arg1);
  arg2 = coerce_ref (arg2);

  type1 = check_typedef (value_type (arg1));
  type2 = check_typedef (value_type (arg2));

  if ((TYPE_CODE (type1) != TYPE_CODE_FLT
       && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT
       && !is_integral_type (type1))
      || (TYPE_CODE (type2) != TYPE_CODE_FLT
	  && TYPE_CODE (type2) != TYPE_CODE_DECFLOAT
	  && !is_integral_type (type2)))
    error (_("Argument to arithmetic operation not a number or boolean."));

  if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
      || TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
    {
      int len_v1, len_v2, len_v;
      enum bfd_endian byte_order_v1, byte_order_v2, byte_order_v;
      gdb_byte v1[16], v2[16];
      gdb_byte v[16];

      /* If only one type is decimal float, use its type.
	 Otherwise use the bigger type.  */
      if (TYPE_CODE (type1) != TYPE_CODE_DECFLOAT)
	result_type = type2;
      else if (TYPE_CODE (type2) != TYPE_CODE_DECFLOAT)
	result_type = type1;
      else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1))
	result_type = type2;
      else
	result_type = type1;

      len_v = TYPE_LENGTH (result_type);
      byte_order_v = gdbarch_byte_order (get_type_arch (result_type));

      value_args_as_decimal (arg1, arg2, v1, &len_v1, &byte_order_v1,
					 v2, &len_v2, &byte_order_v2);

      switch (op)
	{
	case BINOP_ADD:
	case BINOP_SUB:
	case BINOP_MUL:
	case BINOP_DIV:
	case BINOP_EXP:
	  decimal_binop (op, v1, len_v1, byte_order_v1,
			     v2, len_v2, byte_order_v2,
			     v, len_v, byte_order_v);
	  break;

	default:
	  error (_("Operation not valid for decimal floating point number."));
	}

      val = value_from_decfloat (result_type, v);
    }
  else if (TYPE_CODE (type1) == TYPE_CODE_FLT
	   || TYPE_CODE (type2) == TYPE_CODE_FLT)
    {
      /* FIXME-if-picky-about-floating-accuracy: Should be doing this
         in target format.  real.c in GCC probably has the necessary
         code.  */
      DOUBLEST v1, v2, v = 0;

      v1 = value_as_double (arg1);
      v2 = value_as_double (arg2);

      switch (op)
	{
	case BINOP_ADD:
	  v = v1 + v2;
	  break;

	case BINOP_SUB:
	  v = v1 - v2;
	  break;

	case BINOP_MUL:
	  v = v1 * v2;
	  break;

	case BINOP_DIV:
	  v = v1 / v2;
	  break;

	case BINOP_EXP:
	  errno = 0;
	  v = pow (v1, v2);
	  if (errno)
	    error (_("Cannot perform exponentiation: %s"),
		   safe_strerror (errno));
	  break;

	case BINOP_MIN:
	  v = v1 < v2 ? v1 : v2;
	  break;
	      
	case BINOP_MAX:
	  v = v1 > v2 ? v1 : v2;
	  break;

	default:
	  error (_("Integer-only operation on floating point number."));
	}

      /* If only one type is float, use its type.
	 Otherwise use the bigger type.  */
      if (TYPE_CODE (type1) != TYPE_CODE_FLT)
	result_type = type2;
      else if (TYPE_CODE (type2) != TYPE_CODE_FLT)
	result_type = type1;
      else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1))
	result_type = type2;
      else
	result_type = type1;

      val = allocate_value (result_type);
      store_typed_floating (value_contents_raw (val), value_type (val), v);
    }
  else if (TYPE_CODE (type1) == TYPE_CODE_BOOL
	   || TYPE_CODE (type2) == TYPE_CODE_BOOL)
    {
      LONGEST v1, v2, v = 0;

      v1 = value_as_long (arg1);
      v2 = value_as_long (arg2);

      switch (op)
	{
	case BINOP_BITWISE_AND:
	  v = v1 & v2;
	  break;

	case BINOP_BITWISE_IOR:
	  v = v1 | v2;
	  break;

	case BINOP_BITWISE_XOR:
	  v = v1 ^ v2;
          break;
              
        case BINOP_EQUAL:
          v = v1 == v2;
          break;
          
        case BINOP_NOTEQUAL:
          v = v1 != v2;
	  break;

	default:
	  error (_("Invalid operation on booleans."));
	}

      result_type = type1;

      val = allocate_value (result_type);
      store_signed_integer (value_contents_raw (val),
			    TYPE_LENGTH (result_type),
			    gdbarch_byte_order (get_type_arch (result_type)),
			    v);
    }
  else
    /* Integral operations here.  */
    {
      /* Determine type length of the result, and if the operation should
	 be done unsigned.  For exponentiation and shift operators,
	 use the length and type of the left operand.  Otherwise,
	 use the signedness of the operand with the greater length.
	 If both operands are of equal length, use unsigned operation
	 if one of the operands is unsigned.  */
      if (op == BINOP_RSH || op == BINOP_LSH || op == BINOP_EXP)
	result_type = type1;
      else if (TYPE_LENGTH (type1) > TYPE_LENGTH (type2))
	result_type = type1;
      else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1))
	result_type = type2;
      else if (TYPE_UNSIGNED (type1))
	result_type = type1;
      else if (TYPE_UNSIGNED (type2))
	result_type = type2;
      else
	result_type = type1;

      if (TYPE_UNSIGNED (result_type))
	{
	  LONGEST v2_signed = value_as_long (arg2);
	  ULONGEST v1, v2, v = 0;

	  v1 = (ULONGEST) value_as_long (arg1);
	  v2 = (ULONGEST) v2_signed;

	  switch (op)
	    {
	    case BINOP_ADD:
	      v = v1 + v2;
	      break;

	    case BINOP_SUB:
	      v = v1 - v2;
	      break;

	    case BINOP_MUL:
	      v = v1 * v2;
	      break;

	    case BINOP_DIV:
	    case BINOP_INTDIV:
	      if (v2 != 0)
		v = v1 / v2;
	      else
		error (_("Division by zero"));
	      break;

	    case BINOP_EXP:
              v = uinteger_pow (v1, v2_signed);
	      break;

	    case BINOP_REM:
	      if (v2 != 0)
		v = v1 % v2;
	      else
		error (_("Division by zero"));
	      break;

	    case BINOP_MOD:
	      /* Knuth 1.2.4, integer only.  Note that unlike the C '%' op,
	         v1 mod 0 has a defined value, v1.  */
	      if (v2 == 0)
		{
		  v = v1;
		}
	      else
		{
		  v = v1 / v2;
		  /* Note floor(v1/v2) == v1/v2 for unsigned.  */
		  v = v1 - (v2 * v);
		}
	      break;

	    case BINOP_LSH:
	      v = v1 << v2;
	      break;

	    case BINOP_RSH:
	      v = v1 >> v2;
	      break;

	    case BINOP_BITWISE_AND:
	      v = v1 & v2;
	      break;

	    case BINOP_BITWISE_IOR:
	      v = v1 | v2;
	      break;

	    case BINOP_BITWISE_XOR:
	      v = v1 ^ v2;
	      break;

	    case BINOP_LOGICAL_AND:
	      v = v1 && v2;
	      break;

	    case BINOP_LOGICAL_OR:
	      v = v1 || v2;
	      break;

	    case BINOP_MIN:
	      v = v1 < v2 ? v1 : v2;
	      break;

	    case BINOP_MAX:
	      v = v1 > v2 ? v1 : v2;
	      break;

	    case BINOP_EQUAL:
	      v = v1 == v2;
	      break;

            case BINOP_NOTEQUAL:
              v = v1 != v2;
              break;

	    case BINOP_LESS:
	      v = v1 < v2;
	      break;

	    case BINOP_GTR:
	      v = v1 > v2;
	      break;

	    case BINOP_LEQ:
	      v = v1 <= v2;
	      break;

	    case BINOP_GEQ:
	      v = v1 >= v2;
	      break;

	    default:
	      error (_("Invalid binary operation on numbers."));
	    }

	  val = allocate_value (result_type);
	  store_unsigned_integer (value_contents_raw (val),
				  TYPE_LENGTH (value_type (val)),
				  gdbarch_byte_order
				    (get_type_arch (result_type)),
				  v);
	}
      else
	{
	  LONGEST v1, v2, v = 0;

	  v1 = value_as_long (arg1);
	  v2 = value_as_long (arg2);

	  switch (op)
	    {
	    case BINOP_ADD:
	      v = v1 + v2;
	      break;

	    case BINOP_SUB:
	      v = v1 - v2;
	      break;

	    case BINOP_MUL:
	      v = v1 * v2;
	      break;

	    case BINOP_DIV:
	    case BINOP_INTDIV:
	      if (v2 != 0)
		v = v1 / v2;
	      else
		error (_("Division by zero"));
              break;

	    case BINOP_EXP:
              v = integer_pow (v1, v2);
	      break;

	    case BINOP_REM:
	      if (v2 != 0)
		v = v1 % v2;
	      else
		error (_("Division by zero"));
	      break;

	    case BINOP_MOD:
	      /* Knuth 1.2.4, integer only.  Note that unlike the C '%' op,
	         X mod 0 has a defined value, X.  */
	      if (v2 == 0)
		{
		  v = v1;
		}
	      else
		{
		  v = v1 / v2;
		  /* Compute floor.  */
		  if (TRUNCATION_TOWARDS_ZERO && (v < 0) && ((v1 % v2) != 0))
		    {
		      v--;
		    }
		  v = v1 - (v2 * v);
		}
	      break;

	    case BINOP_LSH:
	      v = v1 << v2;
	      break;

	    case BINOP_RSH:
	      v = v1 >> v2;
	      break;

	    case BINOP_BITWISE_AND:
	      v = v1 & v2;
	      break;

	    case BINOP_BITWISE_IOR:
	      v = v1 | v2;
	      break;

	    case BINOP_BITWISE_XOR:
	      v = v1 ^ v2;
	      break;

	    case BINOP_LOGICAL_AND:
	      v = v1 && v2;
	      break;

	    case BINOP_LOGICAL_OR:
	      v = v1 || v2;
	      break;

	    case BINOP_MIN:
	      v = v1 < v2 ? v1 : v2;
	      break;

	    case BINOP_MAX:
	      v = v1 > v2 ? v1 : v2;
	      break;

	    case BINOP_EQUAL:
	      v = v1 == v2;
	      break;

            case BINOP_NOTEQUAL:
              v = v1 != v2;
              break;

	    case BINOP_LESS:
	      v = v1 < v2;
	      break;

	    case BINOP_GTR:
	      v = v1 > v2;
	      break;

	    case BINOP_LEQ:
	      v = v1 <= v2;
	      break;

	    case BINOP_GEQ:
	      v = v1 >= v2;
	      break;

	    default:
	      error (_("Invalid binary operation on numbers."));
	    }

	  val = allocate_value (result_type);
	  store_signed_integer (value_contents_raw (val),
				TYPE_LENGTH (value_type (val)),
				gdbarch_byte_order
				  (get_type_arch (result_type)),
				v);
	}
    }
Esempio n. 7
0
static struct value *
scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
{
  struct value *val;
  struct type *type1, *type2, *result_type;

  arg1 = coerce_ref (arg1);
  arg2 = coerce_ref (arg2);

  type1 = check_typedef (value_type (arg1));
  type2 = check_typedef (value_type (arg2));

  if ((!is_floating_value (arg1) && !is_integral_type (type1))
      || (!is_floating_value (arg2) && !is_integral_type (type2)))
    error (_("Argument to arithmetic operation not a number or boolean."));

  if (is_floating_type (type1) || is_floating_type (type2))
    {
      /* If only one type is floating-point, use its type.
	 Otherwise use the bigger type.  */
      if (!is_floating_type (type1))
	result_type = type2;
      else if (!is_floating_type (type2))
	result_type = type1;
      else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1))
	result_type = type2;
      else
	result_type = type1;

      val = allocate_value (result_type);

      struct type *eff_type_v1, *eff_type_v2;
      gdb::byte_vector v1, v2;
      v1.resize (TYPE_LENGTH (result_type));
      v2.resize (TYPE_LENGTH (result_type));

      value_args_as_target_float (arg1, arg2,
				  v1.data (), &eff_type_v1,
				  v2.data (), &eff_type_v2);
      target_float_binop (op, v1.data (), eff_type_v1,
			      v2.data (), eff_type_v2,
			      value_contents_raw (val), result_type);
    }
  else if (TYPE_CODE (type1) == TYPE_CODE_BOOL
	   || TYPE_CODE (type2) == TYPE_CODE_BOOL)
    {
      LONGEST v1, v2, v = 0;

      v1 = value_as_long (arg1);
      v2 = value_as_long (arg2);

      switch (op)
	{
	case BINOP_BITWISE_AND:
	  v = v1 & v2;
	  break;

	case BINOP_BITWISE_IOR:
	  v = v1 | v2;
	  break;

	case BINOP_BITWISE_XOR:
	  v = v1 ^ v2;
          break;
              
        case BINOP_EQUAL:
          v = v1 == v2;
          break;
          
        case BINOP_NOTEQUAL:
          v = v1 != v2;
	  break;

	default:
	  error (_("Invalid operation on booleans."));
	}

      result_type = type1;

      val = allocate_value (result_type);
      store_signed_integer (value_contents_raw (val),
			    TYPE_LENGTH (result_type),
			    gdbarch_byte_order (get_type_arch (result_type)),
			    v);
    }
  else
    /* Integral operations here.  */
    {
      /* Determine type length of the result, and if the operation should
	 be done unsigned.  For exponentiation and shift operators,
	 use the length and type of the left operand.  Otherwise,
	 use the signedness of the operand with the greater length.
	 If both operands are of equal length, use unsigned operation
	 if one of the operands is unsigned.  */
      if (op == BINOP_RSH || op == BINOP_LSH || op == BINOP_EXP)
	result_type = type1;
      else if (TYPE_LENGTH (type1) > TYPE_LENGTH (type2))
	result_type = type1;
      else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1))
	result_type = type2;
      else if (TYPE_UNSIGNED (type1))
	result_type = type1;
      else if (TYPE_UNSIGNED (type2))
	result_type = type2;
      else
	result_type = type1;

      if (TYPE_UNSIGNED (result_type))
	{
	  LONGEST v2_signed = value_as_long (arg2);
	  ULONGEST v1, v2, v = 0;

	  v1 = (ULONGEST) value_as_long (arg1);
	  v2 = (ULONGEST) v2_signed;

	  switch (op)
	    {
	    case BINOP_ADD:
	      v = v1 + v2;
	      break;

	    case BINOP_SUB:
	      v = v1 - v2;
	      break;

	    case BINOP_MUL:
	      v = v1 * v2;
	      break;

	    case BINOP_DIV:
	    case BINOP_INTDIV:
	      if (v2 != 0)
		v = v1 / v2;
	      else
		error (_("Division by zero"));
	      break;

	    case BINOP_EXP:
              v = uinteger_pow (v1, v2_signed);
	      break;

	    case BINOP_REM:
	      if (v2 != 0)
		v = v1 % v2;
	      else
		error (_("Division by zero"));
	      break;

	    case BINOP_MOD:
	      /* Knuth 1.2.4, integer only.  Note that unlike the C '%' op,
	         v1 mod 0 has a defined value, v1.  */
	      if (v2 == 0)
		{
		  v = v1;
		}
	      else
		{
		  v = v1 / v2;
		  /* Note floor(v1/v2) == v1/v2 for unsigned.  */
		  v = v1 - (v2 * v);
		}
	      break;

	    case BINOP_LSH:
	      v = v1 << v2;
	      break;

	    case BINOP_RSH:
	      v = v1 >> v2;
	      break;

	    case BINOP_BITWISE_AND:
	      v = v1 & v2;
	      break;

	    case BINOP_BITWISE_IOR:
	      v = v1 | v2;
	      break;

	    case BINOP_BITWISE_XOR:
	      v = v1 ^ v2;
	      break;

	    case BINOP_LOGICAL_AND:
	      v = v1 && v2;
	      break;

	    case BINOP_LOGICAL_OR:
	      v = v1 || v2;
	      break;

	    case BINOP_MIN:
	      v = v1 < v2 ? v1 : v2;
	      break;

	    case BINOP_MAX:
	      v = v1 > v2 ? v1 : v2;
	      break;

	    case BINOP_EQUAL:
	      v = v1 == v2;
	      break;

            case BINOP_NOTEQUAL:
              v = v1 != v2;
              break;

	    case BINOP_LESS:
	      v = v1 < v2;
	      break;

	    case BINOP_GTR:
	      v = v1 > v2;
	      break;

	    case BINOP_LEQ:
	      v = v1 <= v2;
	      break;

	    case BINOP_GEQ:
	      v = v1 >= v2;
	      break;

	    default:
	      error (_("Invalid binary operation on numbers."));
	    }

	  val = allocate_value (result_type);
	  store_unsigned_integer (value_contents_raw (val),
				  TYPE_LENGTH (value_type (val)),
				  gdbarch_byte_order
				    (get_type_arch (result_type)),
				  v);
	}
      else
	{
	  LONGEST v1, v2, v = 0;

	  v1 = value_as_long (arg1);
	  v2 = value_as_long (arg2);

	  switch (op)
	    {
	    case BINOP_ADD:
	      v = v1 + v2;
	      break;

	    case BINOP_SUB:
	      v = v1 - v2;
	      break;

	    case BINOP_MUL:
	      v = v1 * v2;
	      break;

	    case BINOP_DIV:
	    case BINOP_INTDIV:
	      if (v2 != 0)
		v = v1 / v2;
	      else
		error (_("Division by zero"));
              break;

	    case BINOP_EXP:
              v = integer_pow (v1, v2);
	      break;

	    case BINOP_REM:
	      if (v2 != 0)
		v = v1 % v2;
	      else
		error (_("Division by zero"));
	      break;

	    case BINOP_MOD:
	      /* Knuth 1.2.4, integer only.  Note that unlike the C '%' op,
	         X mod 0 has a defined value, X.  */
	      if (v2 == 0)
		{
		  v = v1;
		}
	      else
		{
		  v = v1 / v2;
		  /* Compute floor.  */
		  if (TRUNCATION_TOWARDS_ZERO && (v < 0) && ((v1 % v2) != 0))
		    {
		      v--;
		    }
		  v = v1 - (v2 * v);
		}
	      break;

	    case BINOP_LSH:
	      v = v1 << v2;
	      break;

	    case BINOP_RSH:
	      v = v1 >> v2;
	      break;

	    case BINOP_BITWISE_AND:
	      v = v1 & v2;
	      break;

	    case BINOP_BITWISE_IOR:
	      v = v1 | v2;
	      break;

	    case BINOP_BITWISE_XOR:
	      v = v1 ^ v2;
	      break;

	    case BINOP_LOGICAL_AND:
	      v = v1 && v2;
	      break;

	    case BINOP_LOGICAL_OR:
	      v = v1 || v2;
	      break;

	    case BINOP_MIN:
	      v = v1 < v2 ? v1 : v2;
	      break;

	    case BINOP_MAX:
	      v = v1 > v2 ? v1 : v2;
	      break;

	    case BINOP_EQUAL:
	      v = v1 == v2;
	      break;

            case BINOP_NOTEQUAL:
              v = v1 != v2;
              break;

	    case BINOP_LESS:
	      v = v1 < v2;
	      break;

	    case BINOP_GTR:
	      v = v1 > v2;
	      break;

	    case BINOP_LEQ:
	      v = v1 <= v2;
	      break;

	    case BINOP_GEQ:
	      v = v1 >= v2;
	      break;

	    default:
	      error (_("Invalid binary operation on numbers."));
	    }

	  val = allocate_value (result_type);
	  store_signed_integer (value_contents_raw (val),
				TYPE_LENGTH (value_type (val)),
				gdbarch_byte_order
				  (get_type_arch (result_type)),
				v);
	}
    }
Esempio n. 8
0
/// Returns true if e has integral type.
bool
is_integral_expression(const expr& e)
{
  return is_integral_type(e.get_type());
}