/*	$NetBSD: queries.c,v 1.6 2022/09/24 19:55:44 rillig Exp $	*/
# 3 "queries.c"

/*
 * Demonstrate the case-by-case queries.  Unlike warnings, queries do not
 * point to questionable code but rather to code that may be interesting to
 * inspect manually on a case-by-case basis.
 *
 * Possible use cases are:
 *
 *	Understanding how C works internally, by making the usual arithmetic
 *	conversions visible.
 *
 * 	Finding code that intentionally suppresses a regular lint warning,
 * 	such as casts between arithmetic types.
 */

/* lint1-extra-flags: -q 1,2,3,4,5,6,7 */

typedef unsigned char u8_t;
typedef unsigned short u16_t;
typedef unsigned int u32_t;
typedef unsigned long long u64_t;
typedef signed char s8_t;
typedef signed short s16_t;
typedef signed int s32_t;
typedef signed long long s64_t;

typedef float f32_t;
typedef double f64_t;
typedef float _Complex c32_t;
typedef double _Complex c64_t;

typedef char *str_t;
typedef const char *cstr_t;
typedef volatile char *vstr_t;

_Bool cond;

u8_t u8;
u16_t u16;
u32_t u32;
u64_t u64;

s8_t s8;
s16_t s16;
s32_t s32;
s64_t s64;

struct {
	unsigned u8:8;
	unsigned u9:9;
	unsigned u10:10;
	unsigned u32:32;
	int s8:8;
	int s9:9;
	int s10:10;
	int s32:32;
} bits;

f32_t f32;
f64_t f64;

c32_t c32;
c64_t c64;

char *str;
const char *cstr;
volatile char *vstr;

int
Q1(double dbl)
{
	/* expect+1: implicit conversion from floating point 'double' to integer 'int' [Q1] */
	return dbl;
}

int
Q2(double dbl)
{
	/* expect+1: cast from floating point 'double' to integer 'int' [Q2] */
	return (int)dbl;
}

void
Q3(int i, unsigned u)
{
	/* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */
	u = i;

	/* expect+1: implicit conversion changes sign from 'unsigned int' to 'int' [Q3] */
	i = u;
}

unsigned long long
Q4(signed char *ptr, int i, unsigned long long ull)
{
	/*
	 * The conversion from 'signed char' to 'int' is done by the integer
	 * promotions (C11 6.3.1.1p2), not by the usual arithmetic
	 * conversions (C11 6.3.1.8p1).
	 */
	/* expect+2: usual arithmetic conversion for '+' from 'int' to 'unsigned long long' [Q4] */
	/* expect+1: implicit conversion changes sign from 'int' to 'unsigned long long' [Q3] */
	return ptr[0] + ptr[1] + i + ull;
}

void
Q5(signed char *ptr, int i)
{
	if (ptr + i > ptr)
		return;

	/* expect+1: pointer addition has integer on the left-hand side [Q5] */
	if (i + ptr > ptr)
		return;

	if (ptr[i] != '\0')
		return;

	/* expect+1: pointer addition has integer on the left-hand side [Q5] */
	if (i[ptr] != '\0')
		return;
}

void
Q6(int i)
{
	/* expect+1: no-op cast from 'int' to 'int' [Q6] */
	i = (int)4;

	/* expect+1: no-op cast from 'int' to 'int' [Q6] */
	i = (int)i + 1;
}

extern void *allocate(void);

void
Q7(void)
{

	/* expect+2: no-op cast from '_Bool' to '_Bool' [Q6] */
	/* expect+1: redundant cast from '_Bool' to '_Bool' before assignment [Q7] */
	cond = (_Bool)cond;
	cond = (_Bool)u8;
	u8 = (u8_t)cond;

	/* expect+2: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */
	/* expect+1: redundant cast from 'unsigned char' to 'unsigned char' before assignment [Q7] */
	u8 = (u8_t)u8;
	u8 = (u8_t)u16;
	u8 = (u16_t)u8;
	/* expect+1: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */
	u8 = (u16_t)u16;
	/* expect+1: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */
	u16 = (u8_t)u8;
	u16 = (u8_t)u16;
	/* expect+1: redundant cast from 'unsigned char' to 'unsigned short' before assignment [Q7] */
	u16 = (u16_t)u8;
	/* expect+2: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */
	/* expect+1: redundant cast from 'unsigned short' to 'unsigned short' before assignment [Q7] */
	u16 = (u16_t)u16;

	/* Mixing signed and unsigned types. */
	u8 = (u8_t)s8;
	s8 = (s8_t)u8;
	/* expect+1: redundant cast from 'unsigned char' to 'short' before assignment [Q7] */
	s16 = (s16_t)u8;
	/* expect+1: redundant cast from 'signed char' to 'short' before assignment [Q7] */
	s16 = (s16_t)s8;


	/*
	 * Neither GCC nor Clang accept typeof(bit-field), as that would add
	 * unnecessary complexity.  Lint accepts it but silently discards the
	 * bit-field portion from the type; see dcs_add_type.
	 */
	/* expect+1: redundant cast from 'unsigned char' to 'unsigned int' before assignment [Q7] */
	bits.u9 = (typeof(bits.u9))u8;


	/* expect+2: no-op cast from 'float' to 'float' [Q6] */
	/* expect+1: redundant cast from 'float' to 'float' before assignment [Q7] */
	f32 = (f32_t)f32;
	f32 = (f32_t)f64;
	f32 = (f64_t)f32;
	/* expect+1: no-op cast from 'double' to 'double' [Q6] */
	f32 = (f64_t)f64;
	/* expect+1: no-op cast from 'float' to 'float' [Q6] */
	f64 = (f32_t)f32;
	f64 = (f32_t)f64;
	/* expect+1: redundant cast from 'float' to 'double' before assignment [Q7] */
	f64 = (f64_t)f32;
	/* expect+2: no-op cast from 'double' to 'double' [Q6] */
	/* expect+1: redundant cast from 'double' to 'double' before assignment [Q7] */
	f64 = (f64_t)f64;


	/* expect+2: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */
	/* expect+1: redundant cast from 'float _Complex' to 'float _Complex' before assignment [Q7] */
	c32 = (c32_t)c32;
	c32 = (c32_t)c64;
	c32 = (c64_t)c32;
	/* expect+1: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */
	c32 = (c64_t)c64;
	/* expect+1: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */
	c64 = (c32_t)c32;
	c64 = (c32_t)c64;
	/* expect+1: redundant cast from 'float _Complex' to 'double _Complex' before assignment [Q7] */
	c64 = (c64_t)c32;
	/* expect+2: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */
	/* expect+1: redundant cast from 'double _Complex' to 'double _Complex' before assignment [Q7] */
	c64 = (c64_t)c64;


	/* Mixing real and complex floating point types. */
	/* expect+1: no-op cast from 'float' to 'float' [Q6] */
	c32 = (f32_t)f32;
	c32 = (c32_t)f32;
	/* expect+1: no-op cast from 'float' to 'float' [Q6] */
	c64 = (f32_t)f32;
	c64 = (f64_t)f32;
	c64 = (c32_t)f32;
	c64 = (c64_t)f32;


	/* expect+1: redundant cast from 'pointer to void' to 'pointer to char' before assignment [Q7] */
	str = (char *)allocate();
	/* expect+1: redundant cast from 'pointer to void' to 'pointer to const char' before assignment [Q7] */
	cstr = (const char *)allocate();
	cstr = (char *)allocate();

	/* expect+2: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
	/* expect+1: redundant cast from 'pointer to char' to 'pointer to char' before assignment [Q7] */
	str = (str_t)str;
	str = (str_t)cstr;
	/* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'const char' [128] */
	str = (cstr_t)str;
	/* expect+2: no-op cast from 'pointer to const char' to 'pointer to const char' [Q6] */
	/* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'const char' [128] */
	str = (cstr_t)cstr;
	/* expect+1: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
	cstr = (str_t)str;
	cstr = (str_t)cstr;
	cstr = (cstr_t)str;
	/* expect+2: no-op cast from 'pointer to const char' to 'pointer to const char' [Q6] */
	/* expect+1: redundant cast from 'pointer to const char' to 'pointer to const char' before assignment [Q7] */
	cstr = (cstr_t)cstr;

	/* expect+2: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
	/* expect+1: redundant cast from 'pointer to char' to 'pointer to char' before assignment [Q7] */
	str = (str_t)str;
	str = (str_t)vstr;
	/* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'volatile char' [128] */
	str = (vstr_t)str;
	/* expect+2: no-op cast from 'pointer to volatile char' to 'pointer to volatile char' [Q6] */
	/* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'volatile char' [128] */
	str = (vstr_t)vstr;
	/* expect+1: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
	vstr = (str_t)str;
	vstr = (str_t)vstr;
	vstr = (vstr_t)str;
	/* expect+2: no-op cast from 'pointer to volatile char' to 'pointer to volatile char' [Q6] */
	/* expect+1: redundant cast from 'pointer to volatile char' to 'pointer to volatile char' before assignment [Q7] */
	vstr = (vstr_t)vstr;
}


/*
 * Since queries do not affect the exit status, force a warning to make this
 * test conform to the general expectation that a test that produces output
 * exits non-successfully.
 */
/* expect+1: warning: static variable 'unused' unused [226] */
static int unused;
