diff options
| author | Alberto Bertogli <albertito@blitiri.com.ar> | 2009-05-16 15:36:58 +0000 |
|---|---|---|
| committer | Christopher Li <sparse@chrisli.org> | 2009-07-18 05:30:10 +0000 |
| commit | 5d4c7fc7cc88175c1732313af4911cf494b14f89 (patch) | |
| tree | 97319ca53cae2b5ceac9f9b88d5dc10721445956 | |
| parent | 78798b4f946a37b1ffbbc6853765e479eca553e8 (diff) | |
| download | sparse-dev-5d4c7fc7cc88175c1732313af4911cf494b14f89.tar.gz | |
Support the __thread storage class
GCC supports a __thread storage class, used to indicate thread-local
storage. It may be used alone, or with extern or static.
This patch makes sparse aware of it, and check those restrictions.
Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>
Signed-off-by: Christopher Li <sparse@chrisli.org>
| -rw-r--r-- | parse.c | 34 | ||||
| -rw-r--r-- | symbol.h | 3 |
2 files changed, 33 insertions, 4 deletions
@@ -41,7 +41,7 @@ static declarator_t attribute_specifier, typeof_specifier, parse_asm_declarator, typedef_specifier, inline_specifier, auto_specifier, register_specifier, static_specifier, extern_specifier, - const_qualifier, volatile_qualifier; + thread_specifier, const_qualifier, volatile_qualifier; static struct token *parse_if_statement(struct token *token, struct statement *stmt); static struct token *parse_return_statement(struct token *token, struct statement *stmt); @@ -125,6 +125,11 @@ static struct symbol_op extern_op = { .declarator = extern_specifier, }; +static struct symbol_op thread_op = { + .type = KW_MODIFIER, + .declarator = thread_specifier, +}; + static struct symbol_op const_op = { .type = KW_QUALIFIER, .declarator = const_qualifier, @@ -407,6 +412,7 @@ static struct init_keyword { { "register", NS_TYPEDEF, .op = ®ister_op }, { "static", NS_TYPEDEF, .op = &static_op }, { "extern", NS_TYPEDEF, .op = &extern_op }, + { "__thread", NS_TYPEDEF, .op = &thread_op }, /* Statement */ { "if", NS_KEYWORD, .op = &if_op }, @@ -1169,11 +1175,19 @@ static unsigned long storage_modifiers(struct decl_state *ctx) [SStatic] = MOD_STATIC, [SRegister] = MOD_REGISTER }; - return mod[ctx->storage_class] | (ctx->is_inline ? MOD_INLINE : 0); + return mod[ctx->storage_class] | (ctx->is_inline ? MOD_INLINE : 0) + | (ctx->is_tls ? MOD_TLS : 0); } static void set_storage_class(struct position *pos, struct decl_state *ctx, int class) { + /* __thread can be used alone, or with extern or static */ + if (ctx->is_tls && (class != SStatic && class != SExtern)) { + sparse_error(*pos, "__thread can only be used alone, or with " + "extern or static"); + return; + } + if (!ctx->storage_class) { ctx->storage_class = class; return; @@ -1214,6 +1228,20 @@ static struct token *extern_specifier(struct token *next, struct decl_state *ctx 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) { + ctx->is_tls = 1; + } else { + sparse_error(next->pos, "__thread can only be used alone, or " + "with extern or static"); + } + + return next; +} + static struct token *attribute_force(struct token *token, struct symbol *attr, struct decl_state *ctx) { set_storage_class(&token->pos, ctx, SForced); @@ -1875,7 +1903,7 @@ static struct statement *start_function(struct symbol *sym) start_function_scope(); ret = alloc_symbol(sym->pos, SYM_NODE); ret->ctype = sym->ctype.base_type->ctype; - ret->ctype.modifiers &= ~(MOD_STORAGE | MOD_CONST | MOD_VOLATILE | MOD_INLINE | MOD_ADDRESSABLE | MOD_NOCAST | MOD_NODEREF | MOD_ACCESSED | MOD_TOPLEVEL); + ret->ctype.modifiers &= ~(MOD_STORAGE | MOD_CONST | MOD_VOLATILE | MOD_TLS | MOD_INLINE | MOD_ADDRESSABLE | MOD_NOCAST | MOD_NODEREF | MOD_ACCESSED | MOD_TOPLEVEL); ret->ctype.modifiers |= (MOD_AUTO | MOD_REGISTER); bind_symbol(ret, &return_ident, NS_ITERATOR); stmt->ret = ret; @@ -93,7 +93,7 @@ struct decl_state { struct ctype ctype; struct ident **ident; struct symbol_op *mode; - unsigned char prefer_abstract, is_inline, storage_class; + unsigned char prefer_abstract, is_inline, storage_class, is_tls; }; struct symbol_op { @@ -199,6 +199,7 @@ struct symbol { #define MOD_TYPEDEF 0x1000 +#define MOD_TLS 0x20000 #define MOD_INLINE 0x40000 #define MOD_ADDRESSABLE 0x80000 |
