* [PATCH v2 1/2] evaluate: split out implementation of compatible_assignment_types
@ 2014-03-09 11:32 John Keeping
2014-03-09 11:32 ` [PATCH v2 2/2] Support GCC's transparent unions John Keeping
2014-04-01 7:46 ` [PATCH v2 1/2] evaluate: split out implementation of compatible_assignment_types Christopher Li
0 siblings, 2 replies; 4+ messages in thread
From: John Keeping @ 2014-03-09 11:32 UTC (permalink / raw)
To: linux-sparse; +Cc: John Keeping
This will allow us to reuse the logic when processing a transparent
union by checking each member in turn without printing a warning unless
none of the members match.
Signed-off-by: John Keeping <john@keeping.me.uk>
---
evaluate.c | 57 ++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 34 insertions(+), 23 deletions(-)
diff --git a/evaluate.c b/evaluate.c
index 6655615..2e6511b 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1307,10 +1307,9 @@ static int whitelist_pointers(struct symbol *t1, struct symbol *t2)
return !Wtypesign;
}
-static int compatible_assignment_types(struct expression *expr, struct symbol *target,
- struct expression **rp, const char *where)
+static int check_assignment_types(struct symbol *target, struct expression **rp,
+ const char **typediff)
{
- const char *typediff;
struct symbol *source = degenerate(*rp);
struct symbol *t, *s;
int tclass = classify_type(target, &t);
@@ -1327,8 +1326,8 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
return 1;
} else if (!(sclass & TYPE_RESTRICT))
goto Cast;
- typediff = "different base types";
- goto Err;
+ *typediff = "different base types";
+ return 0;
}
if (tclass == TYPE_PTR) {
@@ -1342,8 +1341,8 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
goto Cast;
}
if (!(sclass & TYPE_PTR)) {
- typediff = "different base types";
- goto Err;
+ *typediff = "different base types";
+ return 0;
}
b1 = examine_pointer_target(t);
b2 = examine_pointer_target(s);
@@ -1356,19 +1355,19 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
* or mix address spaces [sparse].
*/
if (t->ctype.as != s->ctype.as) {
- typediff = "different address spaces";
- goto Err;
+ *typediff = "different address spaces";
+ return 0;
}
if (mod2 & ~mod1) {
- typediff = "different modifiers";
- goto Err;
+ *typediff = "different modifiers";
+ return 0;
}
goto Cast;
}
/* It's OK if the target is more volatile or const than the source */
- typediff = type_difference(&t->ctype, &s->ctype, 0, mod1);
- if (typediff)
- goto Err;
+ *typediff = type_difference(&t->ctype, &s->ctype, 0, mod1);
+ if (*typediff)
+ return 0;
return 1;
}
@@ -1379,22 +1378,34 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
/* XXX: need to turn into comparison with NULL */
if (t == &bool_ctype && (sclass & TYPE_PTR))
goto Cast;
- typediff = "different base types";
- goto Err;
+ *typediff = "different base types";
+ return 0;
}
- typediff = "invalid types";
-
-Err:
- warning(expr->pos, "incorrect type in %s (%s)", where, typediff);
- info(expr->pos, " expected %s", show_typename(target));
- info(expr->pos, " got %s", show_typename(source));
- *rp = cast_to(*rp, target);
+ *typediff = "invalid types";
return 0;
+
Cast:
*rp = cast_to(*rp, target);
return 1;
}
+static int compatible_assignment_types(struct expression *expr, struct symbol *target,
+ struct expression **rp, const char *where)
+{
+ const char *typediff;
+ struct symbol *source = degenerate(*rp);
+
+ if (!check_assignment_types(target, rp, &typediff)) {
+ warning(expr->pos, "incorrect type in %s (%s)", where, typediff);
+ info(expr->pos, " expected %s", show_typename(target));
+ info(expr->pos, " got %s", show_typename(source));
+ *rp = cast_to(*rp, target);
+ return 0;
+ }
+
+ return 1;
+}
+
static void mark_assigned(struct expression *expr)
{
struct symbol *sym;
--
1.9.0.6.g037df60.dirty
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/2] Support GCC's transparent unions
2014-03-09 11:32 [PATCH v2 1/2] evaluate: split out implementation of compatible_assignment_types John Keeping
@ 2014-03-09 11:32 ` John Keeping
2014-04-01 7:46 ` [PATCH v2 1/2] evaluate: split out implementation of compatible_assignment_types Christopher Li
1 sibling, 0 replies; 4+ messages in thread
From: John Keeping @ 2014-03-09 11:32 UTC (permalink / raw)
To: linux-sparse; +Cc: John Keeping
This stops warnings in code using socket operations with a modern glibc,
which otherwise result in warnings of the form:
warning: incorrect type in argument 2 (invalid types)
expected union __CONST_SOCKADDR_ARG [usertype] __addr
got struct sockaddr *<noident>
Since transparent unions are only applicable to function arguments, we
create a new function to check that the types are compatible
specifically in this context.
Also change the wording of the existing warning slightly since sparse
does now support them. The warning is left in case people want to avoid
using transparent unions.
Signed-off-by: John Keeping <john@keeping.me.uk>
---
evaluate.c | 28 +++++++++++++++++++++++++++-
parse.c | 7 ++++++-
symbol.h | 3 ++-
validation/transparent-union.c | 25 +++++++++++++++++++++++++
4 files changed, 60 insertions(+), 3 deletions(-)
create mode 100644 validation/transparent-union.c
diff --git a/evaluate.c b/evaluate.c
index 2e6511b..1def2af 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1406,6 +1406,32 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
return 1;
}
+static int compatible_transparent_union(struct symbol *target,
+ struct expression **rp)
+{
+ struct symbol *t, *member;
+ classify_type(target, &t);
+ if (t->type != SYM_UNION || !t->transparent_union)
+ return 0;
+
+ FOR_EACH_PTR(t->symbol_list, member) {
+ const char *typediff;
+ if (check_assignment_types(member, rp, &typediff))
+ return 1;
+ } END_FOR_EACH_PTR(member);
+
+ return 0;
+}
+
+static int compatible_argument_type(struct expression *expr, struct symbol *target,
+ struct expression **rp, const char *where)
+{
+ if (compatible_transparent_union(target, rp))
+ return 1;
+
+ return compatible_assignment_types(expr, target, rp, where);
+}
+
static void mark_assigned(struct expression *expr)
{
struct symbol *sym;
@@ -2172,7 +2198,7 @@ static int evaluate_arguments(struct symbol *f, struct symbol *fn, struct expres
static char where[30];
examine_symbol_type(target);
sprintf(where, "argument %d", i);
- compatible_assignment_types(expr, target, p, where);
+ compatible_argument_type(expr, target, p, where);
}
i++;
diff --git a/parse.c b/parse.c
index 9cc5f65..785630a 100644
--- a/parse.c
+++ b/parse.c
@@ -1208,7 +1208,12 @@ static struct token *attribute_designated_init(struct token *token, struct symbo
static struct token *attribute_transparent_union(struct token *token, struct symbol *attr, struct decl_state *ctx)
{
if (Wtransparent_union)
- warning(token->pos, "ignoring attribute __transparent_union__");
+ warning(token->pos, "attribute __transparent_union__");
+
+ if (ctx->ctype.base_type && ctx->ctype.base_type->type == SYM_UNION)
+ ctx->ctype.base_type->transparent_union = 1;
+ else
+ warning(token->pos, "attribute __transparent_union__ applied to non-union type");
return token;
}
diff --git a/symbol.h b/symbol.h
index 43c165b..ccb5dcb 100644
--- a/symbol.h
+++ b/symbol.h
@@ -174,7 +174,8 @@ struct symbol {
evaluated:1,
string:1,
designated_init:1,
- forced_arg:1;
+ forced_arg:1,
+ transparent_union:1;
struct expression *array_size;
struct ctype ctype;
struct symbol_list *arguments;
diff --git a/validation/transparent-union.c b/validation/transparent-union.c
new file mode 100644
index 0000000..149c7d9
--- /dev/null
+++ b/validation/transparent-union.c
@@ -0,0 +1,25 @@
+struct a {
+ int field;
+};
+struct b {
+ int field;
+};
+
+typedef union {
+ struct a *a;
+ struct b *b;
+} transparent_arg __attribute__((__transparent_union__));
+
+static void foo(transparent_arg arg)
+{
+}
+
+static void bar(void)
+{
+ struct b arg = { 0 };
+ foo((struct a *) &arg);
+}
+
+/*
+ * check-name: Transparent union attribute.
+ */
--
1.9.0.6.g037df60.dirty
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/2] evaluate: split out implementation of compatible_assignment_types
2014-03-09 11:32 [PATCH v2 1/2] evaluate: split out implementation of compatible_assignment_types John Keeping
2014-03-09 11:32 ` [PATCH v2 2/2] Support GCC's transparent unions John Keeping
@ 2014-04-01 7:46 ` Christopher Li
2014-04-01 14:31 ` Ramsay Jones
1 sibling, 1 reply; 4+ messages in thread
From: Christopher Li @ 2014-04-01 7:46 UTC (permalink / raw)
To: John Keeping; +Cc: Linux-Sparse
On Sun, Mar 9, 2014 at 4:32 AM, John Keeping <john@keeping.me.uk> wrote:
> This will allow us to reuse the logic when processing a transparent
> union by checking each member in turn without printing a warning unless
> none of the members match.
Both patches applied.
Chris
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/2] evaluate: split out implementation of compatible_assignment_types
2014-04-01 7:46 ` [PATCH v2 1/2] evaluate: split out implementation of compatible_assignment_types Christopher Li
@ 2014-04-01 14:31 ` Ramsay Jones
0 siblings, 0 replies; 4+ messages in thread
From: Ramsay Jones @ 2014-04-01 14:31 UTC (permalink / raw)
To: Christopher Li, John Keeping; +Cc: Linux-Sparse
On 01/04/14 08:46, Christopher Li wrote:
> On Sun, Mar 9, 2014 at 4:32 AM, John Keeping <john@keeping.me.uk> wrote:
>> This will allow us to reuse the logic when processing a transparent
>> union by checking each member in turn without printing a warning unless
>> none of the members match.
>
> Both patches applied.
>
> Chris
I 'tested' these patches (on Linux), by running sparse over the git.git
sources, as soon as they were posted. They worked beautifully. (git.git
on Linux (32-bit) only has a single sparse warning now - yay! :)
I forgot to report that here, since I had intended to test the patches
on Cygwin and (my version of sparse) on MinGW first, but I didn't get
around to it ... sorry! (Hmm, I may have time tonight ...)
ATB,
Ramsay Jones
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-04-01 14:37 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-09 11:32 [PATCH v2 1/2] evaluate: split out implementation of compatible_assignment_types John Keeping
2014-03-09 11:32 ` [PATCH v2 2/2] Support GCC's transparent unions John Keeping
2014-04-01 7:46 ` [PATCH v2 1/2] evaluate: split out implementation of compatible_assignment_types Christopher Li
2014-04-01 14:31 ` Ramsay Jones
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).