aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Triplett <josh@joshtriplett.org>2009-10-11 22:51:56 +0000
committerChristopher <sparse@chrisli.org>2010-03-28 17:51:36 -0700
commitf09699fa80b3b15b94b3e1878ac6cdfdb48f43ac (patch)
treee29fe5fb76dbba97a7dad2eda54de4a694c53a51 /parse.c
parentRename -Wall to Wsparse-all, so it doesn't get turned on unintentionally (diff)
downloadsparse-f09699fa80b3b15b94b3e1878ac6cdfdb48f43ac.tar.gz
sparse-f09699fa80b3b15b94b3e1878ac6cdfdb48f43ac.tar.bz2
sparse-f09699fa80b3b15b94b3e1878ac6cdfdb48f43ac.zip
New attribute designated_init: mark a struct as requiring designated init
Some structure types provide a set of fields of which most users will only initialize the subset they care about. Users of these types should always use designated initializers, to avoid relying on the specific structure layout. Examples of this type of structure include the many *_operations structures in Linux, which contain a set of function pointers; these structures occasionally gain a new field, lose an obsolete field, or change the function signature for a field. Add a new attribute designated_init; when used on a struct, it tells Sparse to warn on any positional initialization of a field in that struct. The new flag -Wdesignated-init controls these warnings. Since these warnings only fire for structures explicitly tagged with the attribute, enable the warning by default. Includes documentation and test case. Signed-off-by: Josh Triplett <josh@joshtriplett.org> Signed-off-by: Christopher Li <sparse@chrisli.org>
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/parse.c b/parse.c
index 6ab2ac4..c956265 100644
--- a/parse.c
+++ b/parse.c
@@ -64,6 +64,7 @@ typedef struct token *attr_t(struct token *, struct symbol *,
static attr_t
attribute_packed, attribute_aligned, attribute_modifier,
attribute_address_space, attribute_context,
+ attribute_designated_init,
attribute_transparent_union, ignore_attribute,
attribute_mode, attribute_force;
@@ -319,6 +320,10 @@ static struct symbol_op context_op = {
.attribute = attribute_context,
};
+static struct symbol_op designated_init_op = {
+ .attribute = attribute_designated_init,
+};
+
static struct symbol_op transparent_union_op = {
.attribute = attribute_transparent_union,
};
@@ -454,6 +459,7 @@ static struct init_keyword {
{ "address_space",NS_KEYWORD, .op = &address_space_op },
{ "mode", NS_KEYWORD, .op = &mode_op },
{ "context", NS_KEYWORD, .op = &context_op },
+ { "designated_init", NS_KEYWORD, .op = &designated_init_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 },
@@ -1145,6 +1151,15 @@ static struct token *attribute_context(struct token *token, struct symbol *attr,
return token;
}
+static struct token *attribute_designated_init(struct token *token, struct symbol *attr, struct decl_state *ctx)
+{
+ if (ctx->ctype.base_type && ctx->ctype.base_type->type == SYM_STRUCT)
+ ctx->ctype.base_type->designated_init = 1;
+ else
+ warning(token->pos, "attribute designated_init applied to non-structure type");
+ return token;
+}
+
static struct token *attribute_transparent_union(struct token *token, struct symbol *attr, struct decl_state *ctx)
{
if (Wtransparent_union)