linux-sparse.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
To: linux-sparse@vger.kernel.org
Cc: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Subject: [PATCH 4/8] parse: rework handling of storage_class
Date: Sun,  9 Aug 2020 18:52:25 +0200	[thread overview]
Message-ID: <20200809165229.36677-5-luc.vanoostenryck@gmail.com> (raw)
In-Reply-To: <20200809165229.36677-1-luc.vanoostenryck@gmail.com>

The handling of the storage class modifiers is done
differently than the other modifiers:
* they don't use MOD_... but their own enums
* consequently they can't use modifier_string() and have
  their own string table to display them.
* the attribute 'force' is considered as a kind of storage
  class. Fine, but it means that 'register' or '__tls' can't
  be used with 'force' (which is probably very fine but
  seems more as a side-effect than something really desired).

The real justification for these difference seems to be
that storage class modifiers *must* be treated differently
than the other modifiers because they don't apply at the same
level. For example, in a declaration like:
	static const int a[N];
'static' applies to the array/the whole object, while 'const'
only applies to the (type of the) elements of the array.

Storage class specifiers must thus be parsed, stored aside
and only be applied after the whole declarator have been parsed.
But other modifiers are also in the same situation (for example,
'__noreturn' or '__pure' for functions).

So, use the generic keyword/attribute handling of modifiers
for storage class specifiers but for simplicity, store them
separately in decl_state to easily do duplication tests on them.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 parse.c  | 71 ++++++++++++++++++--------------------------------------
 symbol.h |  4 +++-
 2 files changed, 25 insertions(+), 50 deletions(-)

diff --git a/parse.c b/parse.c
index cc46f1a6c5a6..2711022aba69 100644
--- a/parse.c
+++ b/parse.c
@@ -116,10 +116,6 @@ enum {
 	CInt = 0, CSInt, CUInt, CReal,
 };
 
-enum {
-	SNone = 0, STypedef, SAuto, SRegister, SExtern, SStatic, SForced, SMax,
-};
-
 static void asm_modifier(struct token *token, unsigned long *mods, unsigned long mod)
 {
 	if (*mods & mod)
@@ -1389,85 +1385,67 @@ static struct token *attribute_specifier(struct token *token, struct decl_state
 	return token;
 }
 
-static const char *storage_class[] = 
-{
-	[STypedef] = "typedef",
-	[SAuto] = "auto",
-	[SExtern] = "extern",
-	[SStatic] = "static",
-	[SRegister] = "register",
-	[SForced] = "[force]"
-};
-
 static unsigned long decl_modifiers(struct decl_state *ctx)
 {
-	static unsigned long mod[SMax] =
-	{
-		[SAuto] = MOD_AUTO,
-		[SExtern] = MOD_EXTERN,
-		[SStatic] = MOD_STATIC,
-		[SRegister] = MOD_REGISTER
-	};
 	unsigned long mods = ctx->ctype.modifiers & MOD_DECLARE;
 	ctx->ctype.modifiers &= ~MOD_DECLARE;
-	return mod[ctx->storage_class] | mods;
+	return ctx->storage_class | mods;
 }
 
-static void set_storage_class(struct position *pos, struct decl_state *ctx, int class)
+static void set_storage_class(struct position *pos, struct decl_state *ctx, unsigned long class)
 {
 	int is_tls = ctx->ctype.modifiers & MOD_TLS;
+	const char *storage = modifier_string(class);
+
 	/* __thread can be used alone, or with extern or static */
-	if (is_tls && (class != SStatic && class != SExtern)) {
+	if (is_tls && (class & ~(MOD_STATIC|MOD_EXTERN))) {
 		sparse_error(*pos, "__thread can only be used alone, or with "
 				"extern or static");
 		return;
 	}
 
-	if (!ctx->storage_class) {
+	if (!ctx->storage_class)
 		ctx->storage_class = class;
-		return;
-	}
-	if (ctx->storage_class == class)
-		sparse_error(*pos, "duplicate %s", storage_class[class]);
+	else if (ctx->storage_class == class)
+		sparse_error(*pos, "duplicate %s", storage);
 	else
 		sparse_error(*pos, "multiple storage classes");
 }
 
 static struct token *typedef_specifier(struct token *next, struct decl_state *ctx)
 {
-	set_storage_class(&next->pos, ctx, STypedef);
+	set_storage_class(&next->pos, ctx, MOD_USERTYPE);
 	return next;
 }
 
 static struct token *auto_specifier(struct token *next, struct decl_state *ctx)
 {
-	set_storage_class(&next->pos, ctx, SAuto);
+	set_storage_class(&next->pos, ctx, MOD_AUTO);
 	return next;
 }
 
 static struct token *register_specifier(struct token *next, struct decl_state *ctx)
 {
-	set_storage_class(&next->pos, ctx, SRegister);
+	set_storage_class(&next->pos, ctx, MOD_REGISTER);
 	return next;
 }
 
 static struct token *static_specifier(struct token *next, struct decl_state *ctx)
 {
-	set_storage_class(&next->pos, ctx, SStatic);
+	set_storage_class(&next->pos, ctx, MOD_STATIC);
 	return next;
 }
 
 static struct token *extern_specifier(struct token *next, struct decl_state *ctx)
 {
-	set_storage_class(&next->pos, ctx, SExtern);
+	set_storage_class(&next->pos, ctx, MOD_EXTERN);
 	return next;
 }
 
 static struct token *thread_specifier(struct token *next, struct decl_state *ctx)
 {
 	/* This GCC extension can be used alone, or with extern or static */
-	if (!ctx->storage_class || ctx->storage_class == SStatic
-			|| ctx->storage_class == SExtern) {
+	if (!(ctx->storage_class & ~(MOD_STATIC|MOD_EXTERN))) {
 		apply_qualifier(&next->pos, &ctx->ctype, MOD_TLS);
 	} else {
 		sparse_error(next->pos, "__thread can only be used alone, or "
@@ -1479,7 +1457,7 @@ static struct token *thread_specifier(struct token *next, struct decl_state *ctx
 
 static struct token *attribute_force(struct token *token, struct symbol *attr, struct decl_state *ctx)
 {
-	set_storage_class(&token->pos, ctx, SForced);
+	ctx->forced = 1;
 	return token;
 }
 
@@ -2070,14 +2048,14 @@ static struct token *parameter_declaration(struct token *token, struct symbol *s
 	sym->ctype = ctx.ctype;
 	sym->ctype.modifiers |= decl_modifiers(&ctx);
 	sym->endpos = token->pos;
-	sym->forced_arg = ctx.storage_class == SForced;
+	sym->forced_arg = ctx.forced;
 	return token;
 }
 
 struct token *typename(struct token *token, struct symbol **p, int *forced)
 {
 	struct decl_state ctx = {.prefer_abstract = 1};
-	int class;
+	unsigned long class;
 	struct symbol *sym = alloc_symbol(token->pos, SYM_NODE);
 	*p = sym;
 	token = declaration_specifiers(token, &ctx);
@@ -2086,16 +2064,11 @@ struct token *typename(struct token *token, struct symbol **p, int *forced)
 	sym->ctype = ctx.ctype;
 	sym->endpos = token->pos;
 	class = ctx.storage_class;
-	if (forced) {
-		*forced = 0;
-		if (class == SForced) {
-			*forced = 1;
-			class = 0;
-		}
-	}
+	if (forced)
+		*forced = ctx.forced;
 	if (class)
-		warning(sym->pos, "storage class in typename (%s %s)",
-			storage_class[class], show_typename(sym));
+		warning(sym->pos, "storage class in typename (%s%s)",
+			modifier_string(class), show_typename(sym));
 	return token;
 }
 
@@ -3048,7 +3021,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis
 	}
 
 	/* type define declaration? */
-	is_typedef = ctx.storage_class == STypedef;
+	is_typedef = ctx.storage_class == MOD_USERTYPE;
 
 	/* Typedefs don't have meaningful storage */
 	if (is_typedef)
diff --git a/symbol.h b/symbol.h
index 4792b008efe3..d2ca3d2ded0e 100644
--- a/symbol.h
+++ b/symbol.h
@@ -108,8 +108,10 @@ struct decl_state {
 	struct ident **ident;
 	struct symbol_op *mode;
 	unsigned long f_modifiers;		// function attributes
-	unsigned char prefer_abstract, storage_class;
+	unsigned long storage_class;
+	unsigned char prefer_abstract;
 	unsigned char autotype;
+	unsigned char forced;
 };
 
 struct pseudo;
-- 
2.28.0


  parent reply	other threads:[~2020-08-09 16:52 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-09 16:52 [PATCH 0/8] simplify parsing of storage modifiers Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 1/8] show-mod: add helper to show the modifiers but without ending space Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 2/8] show-mod: no ending space when showing a single modifier Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 3/8] show-mod: no extra space when showing modifiers + ident Luc Van Oostenryck
2020-08-09 16:52 ` Luc Van Oostenryck [this message]
2020-08-09 16:52 ` [PATCH 5/8] parse: associate modifiers with their keyword Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 6/8] parse: let asm_modifier() use the keyword modifier Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 7/8] parse: improve error messages concerning storage specifiers Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 8/8] parse: simplify set_storage_class() Luc Van Oostenryck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200809165229.36677-5-luc.vanoostenryck@gmail.com \
    --to=luc.vanoostenryck@gmail.com \
    --cc=linux-sparse@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).