Exemplo n.º 1
0
Arquivo: type.c Projeto: certik/nwcc
struct ty_string *
make_ty_string(const char *str, size_t size) {
	struct ty_string	*ret = alloc_ty_string();
	ret->str = (char *)str;
	ret->count = ts_count++;
	ret->size = size;
	ret->ty = make_array_type(size, 0); /* not wchar_t */
	return ret;
}	
Exemplo n.º 2
0
Arquivo: type.c Projeto: 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;
}	
Exemplo n.º 3
0
static type set_array_length(type t, largest_int length)
{
  return make_array_type(type_array_of(t),
			 build_uint_constant(parse_region, dummy_location,
					     size_t_type, length));
}
Exemplo n.º 4
0
void init_predefined_types(void)
{
	static const type_base_t error = { TYPE_ERROR, TYPE_QUALIFIER_NONE, NULL };

	type_error_type         = (type_t*)&error;
	type_bool               = make_atomic_type(ATOMIC_TYPE_BOOL,        TYPE_QUALIFIER_NONE);
	type_signed_char        = make_atomic_type(ATOMIC_TYPE_SCHAR,       TYPE_QUALIFIER_NONE);
	type_unsigned_char      = make_atomic_type(ATOMIC_TYPE_UCHAR,       TYPE_QUALIFIER_NONE);
	type_short              = make_atomic_type(ATOMIC_TYPE_SHORT,       TYPE_QUALIFIER_NONE);
	type_unsigned_short     = make_atomic_type(ATOMIC_TYPE_USHORT,      TYPE_QUALIFIER_NONE);
	type_int                = make_atomic_type(ATOMIC_TYPE_INT,         TYPE_QUALIFIER_NONE);
	type_unsigned_int       = make_atomic_type(ATOMIC_TYPE_UINT,        TYPE_QUALIFIER_NONE);
	type_long               = make_atomic_type(ATOMIC_TYPE_LONG,        TYPE_QUALIFIER_NONE);
	type_unsigned_long      = make_atomic_type(ATOMIC_TYPE_ULONG,       TYPE_QUALIFIER_NONE);
	type_long_long          = make_atomic_type(ATOMIC_TYPE_LONGLONG,    TYPE_QUALIFIER_NONE);
	type_unsigned_long_long = make_atomic_type(ATOMIC_TYPE_ULONGLONG,   TYPE_QUALIFIER_NONE);
	type_long_double        = make_atomic_type(ATOMIC_TYPE_LONG_DOUBLE, TYPE_QUALIFIER_NONE);
	type_double             = make_atomic_type(ATOMIC_TYPE_DOUBLE,      TYPE_QUALIFIER_NONE);
	type_float              = make_atomic_type(ATOMIC_TYPE_FLOAT,       TYPE_QUALIFIER_NONE);
	type_char               = make_atomic_type(ATOMIC_TYPE_CHAR,        TYPE_QUALIFIER_NONE);

	type_void       = make_void_type(TYPE_QUALIFIER_NONE);
	type_const_void = make_void_type(TYPE_QUALIFIER_CONST);

	type_builtin_template = allocate_type_zero(TYPE_BUILTIN_TEMPLATE);
	type_builtin_template = identify_new_type(type_builtin_template);

	int8_type_kind  = find_signed_int_atomic_type_kind_for_size(1);
	int16_type_kind = find_signed_int_atomic_type_kind_for_size(2);
	int32_type_kind = find_signed_int_atomic_type_kind_for_size(4);
	int64_type_kind = find_signed_int_atomic_type_kind_for_size(8);

	type_int32_t = make_atomic_type(int32_type_kind, TYPE_QUALIFIER_NONE);
	type_int64_t = make_atomic_type(int64_type_kind, TYPE_QUALIFIER_NONE);

	/* pointer types */
	type_void_ptr                = make_pointer_type(type_void,              TYPE_QUALIFIER_NONE);
	type_const_void_ptr          = make_pointer_type(type_const_void,        TYPE_QUALIFIER_NONE);
	type_void_ptr_restrict       = make_pointer_type(type_void,              TYPE_QUALIFIER_RESTRICT);
	type_const_void_ptr_restrict = make_pointer_type(type_const_void,        TYPE_QUALIFIER_RESTRICT);
	type_char_ptr                = make_pointer_type(type_char,              TYPE_QUALIFIER_NONE);
	type_char_ptr_restrict       = make_pointer_type(type_char,              TYPE_QUALIFIER_RESTRICT);
	type_signed_char_ptr         = make_pointer_type(type_signed_char,       TYPE_QUALIFIER_NONE);
	type_short_ptr               = make_pointer_type(type_short,             TYPE_QUALIFIER_NONE);
	type_int_ptr                 = make_pointer_type(type_int,               TYPE_QUALIFIER_NONE);
	type_long_ptr                = make_pointer_type(type_long,              TYPE_QUALIFIER_NONE);
	type_unsigned_char_ptr       = make_pointer_type(type_unsigned_char,     TYPE_QUALIFIER_NONE);
	type_unsigned_short_ptr      = make_pointer_type(type_unsigned_short,    TYPE_QUALIFIER_NONE);
	type_unsigned_int_ptr        = make_pointer_type(type_unsigned_int,      TYPE_QUALIFIER_NONE);
	type_unsigned_long_ptr       = make_pointer_type(type_unsigned_long,     TYPE_QUALIFIER_NONE);
	type_unsigned_long_long_ptr  = make_pointer_type(type_unsigned_long,     TYPE_QUALIFIER_NONE);
	type_long_long_ptr           = make_pointer_type(type_long_long,         TYPE_QUALIFIER_NONE);
	type_long_double_ptr         = make_pointer_type(type_long_double,       TYPE_QUALIFIER_NONE);
	type_double_ptr              = make_pointer_type(type_double,            TYPE_QUALIFIER_NONE);
	type_float_ptr               = make_pointer_type(type_float,             TYPE_QUALIFIER_NONE);

	type_char_ptr_ptr            = make_pointer_type(type_char_ptr,          TYPE_QUALIFIER_NONE);

	type_builtin_template_ptr    = make_pointer_type(type_builtin_template,  TYPE_QUALIFIER_NONE);

	backend_params const *const be_params = be_get_backend_param();
	ir_type *be_va_list_type = be_params->vararg.va_list_type;
	if (!be_va_list_type) {
		/* Backend has no vararg support. Just hope the the program will not be
		 * using any. If it does, the parse_va_* functions will complain. */
		type_valist     = type_error_type;
		type_valist_arg = type_error_type;
	} else if (is_Pointer_type(be_va_list_type)) {
		type_valist     = type_void_ptr;
		type_valist_arg = type_void_ptr;
	} else if (is_Struct_type(be_va_list_type)) {
		entity_t *ent = allocate_entity_zero(ENTITY_STRUCT, NAMESPACE_NORMAL, sym_anonymous, &builtin_position);
		ent->compound.alignment = get_type_alignment_bytes(be_va_list_type);
		ent->compound.size      = get_type_size_bytes(be_va_list_type);
		ent->compound.complete  = true;
		ent->compound.members   = (scope_t){
			.first_entity = NULL,
			.last_entity  = NULL,
			.depth = 0
		};

		type_t *type_valist_struct = allocate_type_zero(TYPE_COMPOUND_STRUCT);
		type_valist_struct->base.firm_type = be_va_list_type;
		type_valist_struct->compound.compound = &ent->compound;

		type_valist     = make_array_type(type_valist_struct, 1, TYPE_QUALIFIER_NONE);
		type_valist_arg = automatic_type_conversion(type_valist);
	}

	/* const character types */
	type_const_char         = make_atomic_type(ATOMIC_TYPE_CHAR,        TYPE_QUALIFIER_CONST);
	type_const_char_ptr     = make_pointer_type(type_const_char,        TYPE_QUALIFIER_NONE);
	type_const_char_ptr_restrict = make_pointer_type(type_const_char,        TYPE_QUALIFIER_RESTRICT);

	atomic_type_kind_t pointer_sized_int  = dialect.pointer_sized_int;
	atomic_type_kind_t pointer_sized_uint = dialect.pointer_sized_uint;
	type_size_t     = make_atomic_type(pointer_sized_uint, TYPE_QUALIFIER_NONE);
	type_ssize_t    = make_atomic_type(pointer_sized_int, TYPE_QUALIFIER_NONE);
	type_uptrdiff_t = type_size_t;
	type_ptrdiff_t  = type_ssize_t;

	type_intmax_t  = type_long_long;
	type_uintmax_t = type_unsigned_long_long;
	type_wint_t    = type_unsigned_int;
	type_intmax_t_ptr   = make_pointer_type(type_intmax_t,   TYPE_QUALIFIER_NONE);
	type_uintmax_t_ptr  = make_pointer_type(type_uintmax_t,  TYPE_QUALIFIER_NONE);
	type_ptrdiff_t_ptr  = make_pointer_type(type_ptrdiff_t,  TYPE_QUALIFIER_NONE);
	type_uptrdiff_t_ptr = make_pointer_type(type_uptrdiff_t, TYPE_QUALIFIER_NONE);
	type_ssize_t_ptr    = make_pointer_type(type_ssize_t,    TYPE_QUALIFIER_NONE);
	type_size_t_ptr     = make_pointer_type(type_size_t,     TYPE_QUALIFIER_NONE);

	atomic_type_kind_t akind
		= dialect.cpp ? ATOMIC_TYPE_WCHAR_T : dialect.wchar_atomic_kind;
	type_wchar_t       = make_atomic_type(akind, TYPE_QUALIFIER_NONE);
	type_const_wchar_t = make_atomic_type(akind, TYPE_QUALIFIER_CONST);
	type_wchar_t_ptr   = make_pointer_type(type_wchar_t, TYPE_QUALIFIER_NONE);
	type_const_wchar_t_ptr
		= make_pointer_type(type_const_wchar_t, TYPE_QUALIFIER_NONE);

	atomic_type_kind_t const u2 = find_unsigned_int_atomic_type_kind_for_size(2);
	type_char16_t           = make_atomic_type(u2, TYPE_QUALIFIER_NONE);
	type_char16_t_const     = make_atomic_type(u2, TYPE_QUALIFIER_CONST);
	type_char16_t_ptr       = make_pointer_type(type_char16_t,       TYPE_QUALIFIER_NONE);
	type_char16_t_const_ptr = make_pointer_type(type_char16_t_const, TYPE_QUALIFIER_NONE);

	atomic_type_kind_t const u4 = find_unsigned_int_atomic_type_kind_for_size(4);
	type_char32_t           = make_atomic_type(u4, TYPE_QUALIFIER_NONE);
	type_char32_t_const     = make_atomic_type(u4, TYPE_QUALIFIER_CONST);
	type_char32_t_ptr       = make_pointer_type(type_char32_t,       TYPE_QUALIFIER_NONE);
	type_char32_t_const_ptr = make_pointer_type(type_char32_t_const, TYPE_QUALIFIER_NONE);

	if (dialect.ms)
		init_ms_types();
}
Exemplo n.º 5
0
static expression build_taskid(module m, data_declaration taskdecl)
{
  /* Build a unique identifier for a task whose declaration is taskdecl,
     in module m.
     Method: we add enum { m$taskdecl = unique("task-unique-string") };
             to all_cdecls
	     and return an identifier-expression referring to m$taskdecl
  */

  location loc = taskdecl->ast->location;
  region r = parse_region;
  cstring idname;
  enumerator idast;
  struct data_declaration tempdecl;
  enum_ref idenum;
  tag_declaration enumdecl;
  data_decl iddecl;
  expression unique_id, unique_fn, unique_args, use_id;
  cstring silly_name;
  identifier_declarator silly_id;
  declarator silly_d;
  type_element silly_modifiers;
  rid silly_typedef;
  type silly_type;
  variable_decl silly_vd;
  data_decl silly_decl;

  /* Build unique("task-unique-string") */
  unique_fn = build_identifier(r, loc, magic_unique);
  unique_args = build_string(r, loc, scheduler_unique_name);
  default_conversion(unique_args);
  unique_id = build_function_call(r, loc, unique_fn, unique_args);

  /* Build, declare enumerator taskdecl */
  idname = str2cstring(r, taskdecl->name);
  idast = new_enumerator(r, loc, idname, unique_id, NULL);
  init_data_declaration(&tempdecl, CAST(declaration, idast), idname.data,
			int_type);
  tempdecl.kind = decl_constant;
  tempdecl.definition = tempdecl.ast;
  tempdecl.value = unique_id->cst;
  idast->ddecl = declare(m->ienv, &tempdecl, FALSE);

  /* Build the enum declaration */
  idenum = new_enum_ref(r, loc, NULL, NULL, NULL, TRUE);
  idenum->fields = CAST(declaration, idast);
  idenum->tdecl = enumdecl = declare_tag(idenum);
  layout_enum_start(enumdecl);
  enumdecl->definition = idenum;
  enumdecl->defined = TRUE;
  layout_enum_end(enumdecl);

  /* Build the expression we will use in the wiring. */
  use_id = build_identifier(r, loc, idast->ddecl);

  /* Hack: the use_id expression needs to be in the module's AST so
     that we do instantiation and constant folding on it. We build
     a silly typedef for that purpose:
       typedef int __nesc_sillytask_taskdecl[use_id]
  */
  silly_name = alloc_cstring(r, strlen(taskdecl->name) + 17);
  sprintf(silly_name.data, "__nesc_sillytask_%s", taskdecl->name);
  silly_id = new_identifier_declarator(r, loc, silly_name);
  silly_type = make_array_type(int_type, use_id);
  type2ast(r, loc, silly_type, CAST(declarator, silly_id), 
	   &silly_d, &silly_modifiers);

  silly_typedef = new_rid(r, loc, RID_TYPEDEF);

  silly_vd = new_variable_decl(r, loc, silly_d, NULL, NULL, NULL,
			       NULL/*ddecl*/);
  init_data_declaration(&tempdecl, CAST(declaration, silly_vd),
			silly_name.data, silly_type);
  tempdecl.kind = decl_typedef;
  tempdecl.definition = tempdecl.ast;
  silly_vd->ddecl = declare(m->ienv, &tempdecl, FALSE);
  silly_vd->declared_type = silly_type;
  silly_decl =
    new_data_decl(r, loc, type_element_chain(CAST(type_element, silly_typedef),
					     silly_modifiers),
		  CAST(declaration, silly_vd));
  m->decls = declaration_chain(CAST(declaration, silly_decl), m->decls);

  /* Build the declaration and add it to the module's decls */
  iddecl = new_data_decl(r, loc, CAST(type_element, idenum), NULL);
  m->decls = declaration_chain(CAST(declaration, iddecl), m->decls);

  return use_id;
}
Exemplo n.º 6
0
Type&
Parser::on_array_type(Type& t, Expr& e)
{
  return make_array_type(cxt, t, e);
}