[PATCH v2 2/2] Support GCC's transparent unions

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

 



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@xxxxxxxxxxxxx>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[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