<commit_before>#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

#include "ops.h"
#include "../../util/alloc.h"
#include "../../util/platform.h"
#include "expr_cast.h"
#include "../out/asm.h"
#include "../sue.h"
#include "../defs.h"

const char *str_expr_cast()
{
	return "cast";
}

static void get_cast_sizes(type_ref *tlhs, type_ref *trhs, int *pl, int *pr)
{
	if(!type_ref_is_void(tlhs)){
		*pl = asm_type_size(tlhs);
		*pr = asm_type_size(trhs);
	}else{
		*pl = *pr = 0;
	}
}

void fold_const_expr_cast(expr *e, consty *k)
{
	const_fold(e->expr, k);

	switch(k->type){
		case CONST_VAL:
#define piv (&k->bits.iv)
			/* need to cast the val down as appropriate */
			if(type_ref_is_type(e->tree_type, type__Bool)){
				piv->val = !!piv->val; /* analagous to out/out.c::out_normalise()'s constant case */

			}else{
				const unsigned sz = type_ref_size(e->tree_type, &e->where);
				const intval_t old = piv->val;
				const int to_sig   = type_ref_is_signed(e->tree_type);
				const int from_sig = type_ref_is_signed(e->expr->tree_type);
				intval_t to_iv, to_iv_sign_ext;

				/* TODO: disallow for ptrs/non-ints */

				/* we don't save the truncated value - we keep the original
				 * so negative numbers, for example, are preserved */
				to_iv = intval_truncate(piv->val, sz, &to_iv_sign_ext);

				if(e->expr_cast_implicit
				&& (to_sig && from_sig ? old != to_iv_sign_ext : old != to_iv))
				{
#define CAST_WARN(pre_fmt, pre_val, post_fmt, post_val)  \
						WARN_AT(&e->where,                           \
								"implicit cast changes value from %"     \
								pre_fmt " to %" post_fmt,                \
								pre_val, post_val)

					/* nice... */
					if(from_sig){
						if(to_sig)
							CAST_WARN(
									INTVAL_FMT_D, (long long signed)old,
									INTVAL_FMT_D, (long long signed)to_iv_sign_ext);
						else
							CAST_WARN(
									INTVAL_FMT_D, (long long signed)old,<commit_msg>Explicit-cast's integer truncation check is a no-op<commit_after>#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

#include "ops.h"
#include "../../util/alloc.h"
#include "../../util/platform.h"
#include "expr_cast.h"
#include "../out/asm.h"
#include "../sue.h"
#include "../defs.h"

const char *str_expr_cast()
{
	return "cast";
}

static void get_cast_sizes(type_ref *tlhs, type_ref *trhs, int *pl, int *pr)
{
	if(!type_ref_is_void(tlhs)){
		*pl = asm_type_size(tlhs);
		*pr = asm_type_size(trhs);
	}else{
		*pl = *pr = 0;
	}
}

void fold_const_expr_cast(expr *e, consty *k)
{
	const_fold(e->expr, k);

	switch(k->type){
		case CONST_VAL:
#define piv (&k->bits.iv)
			/* need to cast the val down as appropriate */
			if(type_ref_is_type(e->tree_type, type__Bool)){
				piv->val = !!piv->val; /* analagous to out/out.c::out_normalise()'s constant case */

			}else if(e->expr_cast_implicit){ /* otherwise this is a no-op */
				const unsigned sz = type_ref_size(e->tree_type, &e->where);
				const intval_t old = piv->val;
				const int to_sig   = type_ref_is_signed(e->tree_type);
				const int from_sig = type_ref_is_signed(e->expr->tree_type);
				intval_t to_iv, to_iv_sign_ext;

				/* TODO: disallow for ptrs/non-ints */

				/* we don't save the truncated value - we keep the original
				 * so negative numbers, for example, are preserved */
				to_iv = intval_truncate(piv->val, sz, &to_iv_sign_ext);

				if(to_sig && from_sig ? old != to_iv_sign_ext : old != to_iv){
#define CAST_WARN(pre_fmt, pre_val, post_fmt, post_val)  \
						WARN_AT(&e->where,                           \
								"implicit cast changes value from %"     \
								pre_fmt " to %" post_fmt,                \
								pre_val, post_val)

					/* nice... */
					if(from_sig){
						if(to_sig)
							CAST_WARN(
									INTVAL_FMT_D, (long long signed)old,
									INTVAL_FMT_D, (long long signed)to_iv_sign_ext);
						else
							CAST_WARN(
									INTVAL_FMT_D, (long long signed)old,
{'fraction_non_alphanumeric': 0.150460593654043, 'fraction_numerical': 0.0005117707267144319, 'mean_word_length': 2.8664688427299705, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2814929', 'n_tokens_mistral': 1775, 'n_tokens_neox': 1498, 'n_words': 332}