Re: [PATCH 4/5] propagate function modifiers only to functions

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

 




On 20/11/2019 00:02, Luc Van Oostenryck wrote:
> Function attributes need to be parsed differently
> than the usual specifiers: For example, in code like:
> 	#define __noreturn __attribute__((noreturn))
> 	__noreturn void foo(int a);
> the __noreturn attribute should apply to the function type
> while a specifier like 'const' would apply to its return type.
> 
> The situation is quite similar to how storage specifiers
> must not be handled by alloc_indirect_symbol().
> However, the solution used for storage specifiers (apply the
> modifier bits only after the declarator is reached: cfr.commit
> 233d4e17c ("function attributes apply to the function declaration"))
> can't be used here (because the storage modifiers can be applied
> to the outermost declarator and function attributes may be
> applied more deeper if function pointers are present).

s/deeper/deeply/

> 
> Fix this by:
> 1) reverting the previous storage-specifier-like solution
> 2) collect function specifiers MODs in a new separate
>    field in the declaration context (f_modifiers)
> 3) apply these modifiers when the declarator for the
>    function type is reached (note: it must not be
>    applied to the SYM_FN itself since this correspond
>    to the function's return type; it must be applied to
>    the parent node which can be a SYM_NODE or a SYM_PTR).
> 4) also apply these modifiers to the declarated symbol,

s/declarated/declared/

>    if this symbol is a function declaration, to take
>    into account attributes which are placed at the end
>    of the declaration and not in front.
> 
> Reported-by: Ramsay Jones <ramsay@xxxxxxxxxxxxxxxxxxxx>
> Fixes: 233d4e17c544e1de252aed8f409630599104dbc7
> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
> ---
>  parse.c                                 | 49 +++++++++++++------------
>  symbol.h                                |  3 +-
>  validation/function-attribute-inner.c   |  1 -
>  validation/function-attribute-pointer.c |  1 -
>  4 files changed, 28 insertions(+), 26 deletions(-)
> 
> diff --git a/parse.c b/parse.c
> index 37ffede72..acae63af2 100644
> --- a/parse.c
> +++ b/parse.c
> @@ -82,6 +82,7 @@ typedef struct token *attr_t(struct token *, struct symbol *,
>  
>  static attr_t
>  	attribute_packed, attribute_aligned, attribute_modifier,
> +	attribute_function,
>  	attribute_ext_visible,
>  	attribute_bitwise,
>  	attribute_address_space, attribute_context,
> @@ -375,6 +376,10 @@ static struct symbol_op attr_mod_op = {
>  	.attribute = attribute_modifier,
>  };
>  
> +static struct symbol_op attr_fun_op = {
> +	.attribute = attribute_function,
> +};
> +
>  static struct symbol_op ext_visible_op = {
>  	.attribute = attribute_ext_visible,
>  };
> @@ -566,13 +571,13 @@ static struct init_keyword {
>  	{ "__designated_init__",	NS_KEYWORD,	.op = &designated_init_op },
>  	{ "transparent_union",	NS_KEYWORD,	.op = &transparent_union_op },
>  	{ "__transparent_union__",	NS_KEYWORD,	.op = &transparent_union_op },
> -	{ "noreturn",	NS_KEYWORD,	MOD_NORETURN,	.op = &attr_mod_op },
> -	{ "__noreturn__",	NS_KEYWORD,	MOD_NORETURN,	.op = &attr_mod_op },
> -	{ "pure",	NS_KEYWORD,	MOD_PURE,	.op = &attr_mod_op },
> -	{"__pure__",	NS_KEYWORD,	MOD_PURE,	.op = &attr_mod_op },
> -	{"const",	NS_KEYWORD,	MOD_PURE,	.op = &attr_mod_op },
> -	{"__const",	NS_KEYWORD,	MOD_PURE,	.op = &attr_mod_op },
> -	{"__const__",	NS_KEYWORD,	MOD_PURE,	.op = &attr_mod_op },
> +	{ "noreturn",	NS_KEYWORD,	MOD_NORETURN,	.op = &attr_fun_op },
> +	{ "__noreturn__",	NS_KEYWORD,	MOD_NORETURN,	.op = &attr_fun_op },
> +	{ "pure",	NS_KEYWORD,	MOD_PURE,	.op = &attr_fun_op },
> +	{"__pure__",	NS_KEYWORD,	MOD_PURE,	.op = &attr_fun_op },

Hmm, shouldn't these:

> +	{"const",	NS_KEYWORD,	MOD_PURE,	.op = &attr_fun_op },
> +	{"__const",	NS_KEYWORD,	MOD_PURE,	.op = &attr_fun_op },
> +	{"__const__",	NS_KEYWORD,	MOD_PURE,	.op = &attr_fun_op },

... be attr_mod_op? (I'm just reading this in my email client, so I
haven't given it much thought, but it just seems wrong ...)

ATB,
Ramsay Jones


>  	{"externally_visible",	NS_KEYWORD,	.op = &ext_visible_op },
>  	{"__externally_visible__",	NS_KEYWORD,	.op = &ext_visible_op },
>  
> @@ -1117,6 +1122,15 @@ static struct token *attribute_modifier(struct token *token, struct symbol *attr
>  	return token;
>  }
>  
> +static struct token *attribute_function(struct token *token, struct symbol *attr, struct decl_state *ctx)
> +{
> +	unsigned long mod = attr->ctype.modifiers;
> +	if (ctx->f_modifiers & mod)
> +		warning(token->pos, "duplicate %s", modifier_string(mod));
> +	ctx->f_modifiers |= mod;
> +	return token;
> +}
> +
>  static struct token *attribute_ext_visible(struct token *token, struct symbol *attr, struct decl_state *ctx)
>  {
>  	ctx->is_ext_visible = 1;
> @@ -1862,6 +1876,7 @@ static struct token *direct_declarator(struct token *token, struct decl_state *c
>  		enum kind kind = which_func(token, p, ctx->prefer_abstract);
>  		struct symbol *fn;
>  		fn = alloc_indirect_symbol(token->pos, ctype, SYM_FN);
> +		ctype->modifiers |= ctx->f_modifiers;
>  		token = token->next;
>  		if (kind == K_R)
>  			token = identifier_list(token, fn);
> @@ -2900,21 +2915,6 @@ static struct token *toplevel_asm_declaration(struct token *token, struct symbol
>  	return token;
>  }
>  
> -static unsigned long declaration_modifiers(struct decl_state *ctx)
> -{
> -	unsigned long mods;
> -
> -	// Storage modifiers only relates to the declaration
> -	mods = storage_modifiers(ctx);
> -
> -	// Function attributes also only relates to the declaration
> -	// and must not be present in the function/return type.
> -	mods |= ctx->ctype.modifiers & MOD_FUN_ATTR;
> -	ctx->ctype.modifiers &=~ MOD_FUN_ATTR;
> -
> -	return mods;
> -}
> -
>  struct token *external_declaration(struct token *token, struct symbol_list **list,
>  		validate_decl_t validate_decl)
>  {
> @@ -2935,7 +2935,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis
>  
>  	/* Parse declaration-specifiers, if any */
>  	token = declaration_specifiers(token, &ctx);
> -	mod = declaration_modifiers(&ctx);
> +	mod = storage_modifiers(&ctx);
>  	decl = alloc_symbol(token->pos, SYM_NODE);
>  	/* Just a type declaration? */
>  	if (match_op(token, ';')) {
> @@ -2988,6 +2988,9 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis
>  				show_ident(decl->ident));
>  			base_type->ctype.base_type = &int_ctype;
>  		}
> +		/* apply attributes placed after the declarator */
> +		decl->ctype.modifiers |= ctx.f_modifiers;
> +
>  		/* K&R argument declaration? */
>  		if (lookup_type(token))
>  			return parse_k_r_arguments(token, decl, list);
> diff --git a/symbol.h b/symbol.h
> index 2465d6d88..d8a4f3b68 100644
> --- a/symbol.h
> +++ b/symbol.h
> @@ -107,6 +107,7 @@ struct decl_state {
>  	struct ctype ctype;
>  	struct ident **ident;
>  	struct symbol_op *mode;
> +	unsigned long f_modifiers;		// function attributes
>  	unsigned char prefer_abstract, is_inline, storage_class, is_tls;
>  	unsigned char is_ext_visible;
>  };
> @@ -251,7 +252,7 @@ struct symbol {
>  #define MOD_PTRINHERIT	(MOD_QUALIFIER | MOD_NODEREF | MOD_NORETURN | MOD_NOCAST)
>  /* modifiers preserved by typeof() operator */
>  #define MOD_TYPEOF	(MOD_QUALIFIER | MOD_NOCAST | MOD_SPECIFIER)
> -/* modifiers for funtion attributes */
> +/* modifiers for function attributes */
>  #define MOD_FUN_ATTR	(MOD_PURE|MOD_NORETURN)
>  /* like cvr-qualifiers but 'reversed' (OK: source <= target) */
>  #define MOD_REV_QUAL	(MOD_PURE|MOD_NORETURN)
> diff --git a/validation/function-attribute-inner.c b/validation/function-attribute-inner.c
> index 178c7c019..3a8a8407f 100644
> --- a/validation/function-attribute-inner.c
> +++ b/validation/function-attribute-inner.c
> @@ -6,5 +6,4 @@ _Static_assert([void (__noreturn *)(void)] == [typeof(&fun)], "");
>  
>  /*
>   * check-name: function-attribute-inner
> - * check-known-to-fail
>   */
> diff --git a/validation/function-attribute-pointer.c b/validation/function-attribute-pointer.c
> index 27f43bfb6..fd08ac710 100644
> --- a/validation/function-attribute-pointer.c
> +++ b/validation/function-attribute-pointer.c
> @@ -21,7 +21,6 @@ static void foo(void)
>  
>  /*
>   * check-name: function-attribute-pointer
> - * check-known-to-fail
>   *
>   * check-error-start
>  function-attribute-pointer.c:14:20: warning: incorrect type in argument 1 (different modifiers)
> 



[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