Re: [PATCH] sparse: add support for static assert

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jan 06, 2016 at 01:35:17PM -0500, Lance Richardson wrote:
> This patch introduces support for _Static_assert() in global,
> function, and struct/union declaration contexts (as currently supported
> by gcc).
> 
> Tested via:
>    - kernel build with C=1 CF=-D__CHECK_ENDIAN__
>    - build/check large code base making heavy use of _Static_assert()
>    - "make check" with added test case for static assert support

Nice, it was something that was indeed missing.

I have a few remarks, mostly nitpicking, here under.


Luc

> @@ -437,6 +443,10 @@ static struct init_keyword {
>  	{ "__restrict",	NS_TYPEDEF, .op = &restrict_op},
>  	{ "__restrict__",	NS_TYPEDEF, .op = &restrict_op},
>  
> +
> +	/* Static assertion */
> +	{ "_Static_assert", NS_TYPEDEF, .op = &static_assert_op },
> +

It seems a bit strange to me to use NS_TYPEDEF, as this is unrelated types.
OTOH, the other namespaces deosn't seems better suited,
and yes C11 define this as sort of declaration, so ...

> @@ -2004,6 +2014,27 @@ static struct token *parse_asm_declarator(struct token *token, struct decl_state
>  	return token;
>  }
>  
> +
> +static struct token *static_assert_specifier(struct token *token, struct decl_state *ctx)
> +{
> +	struct expression *expr = NULL;
> +	int val;
> +
> +	token = constant_expression(token->next, &expr);
> +	if (!expr)
> +		sparse_error(token->pos, "Expected constant expression");
> +	val = get_expression_value(expr);
> +	token = expect(token, ',', "after first argument of _Static_assert");
> +	token = parse_expression(token, &expr);
> +	token = expect(token, ')', "after second argument of _Static_assert");
> +
> +	if (!val)
> +		sparse_error(token->pos, "static assertion failed: %s",
> +                             show_string(expr->string));

By using token->pos here, the error message will indicate that the problem is
situated at the very end of the assertion; more exactly, at the ending ";".
This is a little annoying I find.
It would be better to use the some position as the expression
(expr->pos, or the same as for "Expected constant expression").

I find also a bit strange to have this sort of semantic check inside the parser.
 
> diff --git a/validation/static_assert.c b/validation/static_assert.c
> new file mode 100644
> index 0000000..baab346
> --- /dev/null
> +++ b/validation/static_assert.c
> @@ -0,0 +1,20 @@
> +_Static_assert(1, "global ok");
> +
> +struct foo {
> +	_Static_assert(1, "struct ok");
> +};
> +
> +void bar(void)
> +{
> +	_Static_assert(1, " func ok");
> +}
> +
> +_Static_assert(0, "expected failure");
> +/*
> + * check-name: static assertion
> + *
> + * check-error-start
> +static_assert.c:12:38: error: static assertion failed: "expected failure"
> + * check-error-end
> + */

It would be nice to add a few more test cases,
I'm thinbking to things like:
	static int f;
	_Static_assert(f, "non-constant expression");
	static int *p;
	_Static_assert(p, "non-integer expression");
	_Static_assert(0.1, "float expression");
	
	_Static_assert(!0 == 1, "non-trivial expression");
	
	static int array[4];
	_Static_assert(sizeof(array), "sizeof expression");
	
	static const char non_literal_string[] = "non literal string";
	_Static_assert(0, non_literal_string);

Also, what should happen with:
	_Static_assert(1 / 0, "invalid expression: should not show up?");
(The C11 standard is not clear to me, GCC outputs an "invalid expression"
message and ignore the assertion).

Finally, the standard also allow to place the assertion
inside a struct or union declaration; like:
	struct s {
		char c;
		_Static_assert(1, "inside struct");
	};
which is working fine.
And also, I think:
	struct s2 {
		char c;
		_Static_assert(sizeof(struct s) == 1, "own struct sizeof");
	};
which doesn't.


Yours,
Luc
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux