[PATCH] teach sparse about -funsigned-bitfields

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

 



Currently, Sparse treats 'plain' bitfields as unsigned.

However, this is this is inconsistent with how non-bitfield integers
are handled and with how GCC & clang handle bitfields.

So, teach sparse about '-funsigned-bitfields' and by default treat
these bitfields are signed, like done by GCC & clang and like done
for non-bitfield integers.

Also, avoid plain bitfields in IR related testcases.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
---
 options.c                                  |  3 +++
 options.h                                  |  1 +
 sparse.1                                   |  6 ++++++
 symbol.c                                   |  4 ++--
 validation/linear/bitfield-sign-default.c  | 13 +++++++++++++
 validation/linear/bitfield-sign-signed.c   | 13 +++++++++++++
 validation/linear/bitfield-sign-unsigned.c | 13 +++++++++++++
 validation/linear/bitfield-size.c          | 10 +++++-----
 validation/optim/bitfield-size.c           | 15 ++-------------
 validation/optim/bitfield-store-loads.c    |  4 ++--
 10 files changed, 60 insertions(+), 22 deletions(-)
 create mode 100644 validation/linear/bitfield-sign-default.c
 create mode 100644 validation/linear/bitfield-sign-signed.c
 create mode 100644 validation/linear/bitfield-sign-unsigned.c

diff --git a/options.c b/options.c
index 294dfd3be77a..a12d28669e05 100644
--- a/options.c
+++ b/options.c
@@ -81,6 +81,7 @@ unsigned long fpasses = ~0UL;
 int fpic = 0;
 int fpie = 0;
 int fshort_wchar = 0;
+int funsigned_bitfields = 0;
 int funsigned_char = 0;
 
 int Waddress = 0;
@@ -524,6 +525,8 @@ static struct flag fflags[] = {
 	{ "PIC",		&fpic,	handle_switch_setval, 2 },
 	{ "pie",		&fpie,	handle_switch_setval, 1 },
 	{ "PIE",		&fpie,	handle_switch_setval, 2 },
+	{ "signed-bitfields",	&funsigned_bitfields, NULL, OPT_INVERSE },
+	{ "unsigned-bitfields",	&funsigned_bitfields, NULL, },
 	{ "signed-char",	&funsigned_char, NULL,	OPT_INVERSE },
 	{ "short-wchar",	&fshort_wchar },
 	{ "unsigned-char",	&funsigned_char, NULL, },
diff --git a/options.h b/options.h
index abdf08645ad2..8e3071a755be 100644
--- a/options.h
+++ b/options.h
@@ -80,6 +80,7 @@ extern unsigned long fpasses;
 extern int fpic;
 extern int fpie;
 extern int fshort_wchar;
+extern int funsigned_bitfields;
 extern int funsigned_char;
 
 extern int Waddress;
diff --git a/sparse.1 b/sparse.1
index 48dab7a9a5c1..2a8eb1249da1 100644
--- a/sparse.1
+++ b/sparse.1
@@ -518,6 +518,12 @@ column numbers in warnings or errors.  If the value is less than 1 or
 greater than 100, the option is ignored.  The default is 8.
 .
 .TP
+.B \-f[no-]unsigned-bitfields, \-f[no-]signed-bitfields
+Determine the signedness of bitfields declared without an
+explicit sign ('signed' or 'unsigned').
+By default such bitfields are signed, like others plain integers.
+.
+.TP
 .B \-f[no-]unsigned-char, \-f[no-]signed-char
 Let plain 'char' be unsigned or signed.
 By default chars are signed.
diff --git a/symbol.c b/symbol.c
index 7f0c85580f06..aaeb8c100436 100644
--- a/symbol.c
+++ b/symbol.c
@@ -286,8 +286,8 @@ static struct symbol *examine_bitfield_type(struct symbol *sym)
 		sym->ctype.alignment = alignment;
 	modifiers = base_type->ctype.modifiers;
 
-	/* Bitfields are unsigned, unless the base type was explicitly signed */
-	if (!(modifiers & MOD_EXPLICITLY_SIGNED))
+	/* use -funsigned-bitfields to determine the sign if not explicit */
+	if (!(modifiers & MOD_EXPLICITLY_SIGNED) && funsigned_bitfields)
 		modifiers = (modifiers & ~MOD_SIGNED) | MOD_UNSIGNED;
 	sym->ctype.modifiers |= modifiers & MOD_SIGNEDNESS;
 	return sym;
diff --git a/validation/linear/bitfield-sign-default.c b/validation/linear/bitfield-sign-default.c
new file mode 100644
index 000000000000..9a2854e63c47
--- /dev/null
+++ b/validation/linear/bitfield-sign-default.c
@@ -0,0 +1,13 @@
+struct s {
+	int f:2;
+};
+
+static int getf(struct s s) { return s.f; }
+
+/*
+ * check-name: bitfield-sign-default
+ * check-command: test-linearize -fdump-ir=linearize $file
+ *
+ * check-output-ignore
+ * check-output-contains: sext\\.
+ */
diff --git a/validation/linear/bitfield-sign-signed.c b/validation/linear/bitfield-sign-signed.c
new file mode 100644
index 000000000000..59a07cebebc7
--- /dev/null
+++ b/validation/linear/bitfield-sign-signed.c
@@ -0,0 +1,13 @@
+struct s {
+	int f:2;
+};
+
+static int getf(struct s s) { return s.f; }
+
+/*
+ * check-name: bitfield-sign-signed
+ * check-command: test-linearize -fdump-ir=linearize -fsigned-bitfields $file
+ *
+ * check-output-ignore
+ * check-output-contains: sext\\.
+ */
diff --git a/validation/linear/bitfield-sign-unsigned.c b/validation/linear/bitfield-sign-unsigned.c
new file mode 100644
index 000000000000..099edaad979a
--- /dev/null
+++ b/validation/linear/bitfield-sign-unsigned.c
@@ -0,0 +1,13 @@
+struct s {
+	int f:2;
+};
+
+static int getf(struct s s) { return s.f; }
+
+/*
+ * check-name: bitfield-sign-unsigned
+ * check-command: test-linearize -fdump-ir=linearize -funsigned-bitfields $file
+ *
+ * check-output-ignore
+ * check-output-contains: zext\\.
+ */
diff --git a/validation/linear/bitfield-size.c b/validation/linear/bitfield-size.c
index dcda930dc510..719b0ab85fcc 100644
--- a/validation/linear/bitfield-size.c
+++ b/validation/linear/bitfield-size.c
@@ -19,7 +19,7 @@ void ucpy(struct u *d, const struct u *s)
 
 
 struct s {
-	int f:3;
+	signed int f:3;
 };
 
 int spostinc(struct s *x)
@@ -118,7 +118,7 @@ spostinc:
 	load.64     %r33 <- 0[x]
 	load.32     %r34 <- 0[%r33]
 	trunc.3     %r35 <- (32) %r34
-	zext.32     %r36 <- (3) %r35
+	sext.32     %r36 <- (3) %r35
 	add.32      %r37 <- %r36, $1
 	trunc.3     %r38 <- (32) %r37
 	load.32     %r39 <- 0[%r33]
@@ -126,7 +126,7 @@ spostinc:
 	and.32      %r41 <- %r39, $0xfffffff8
 	or.32       %r42 <- %r41, %r40
 	store.32    %r42 -> 0[%r33]
-	zext.32     %r43 <- (3) %r36
+	sext.32     %r43 <- (3) %r36
 	phisrc.32   %phi3(return) <- %r43
 	br          .L7
 
@@ -142,7 +142,7 @@ spreinc:
 	load.64     %r45 <- 0[x]
 	load.32     %r46 <- 0[%r45]
 	trunc.3     %r47 <- (32) %r46
-	zext.32     %r48 <- (3) %r47
+	sext.32     %r48 <- (3) %r47
 	add.32      %r49 <- %r48, $1
 	trunc.3     %r50 <- (32) %r49
 	load.32     %r51 <- 0[%r45]
@@ -150,7 +150,7 @@ spreinc:
 	and.32      %r53 <- %r51, $0xfffffff8
 	or.32       %r54 <- %r53, %r52
 	store.32    %r54 -> 0[%r45]
-	zext.32     %r55 <- (3) %r50
+	sext.32     %r55 <- (3) %r50
 	phisrc.32   %phi4(return) <- %r55
 	br          .L9
 
diff --git a/validation/optim/bitfield-size.c b/validation/optim/bitfield-size.c
index 0d2deeeac2dd..ea1ed57fb8fe 100644
--- a/validation/optim/bitfield-size.c
+++ b/validation/optim/bitfield-size.c
@@ -19,17 +19,6 @@ signed int get__bfs_b(struct bfs bf) { return bf.b; }
 signed int get_pbfs_a(struct bfs *bf) { return bf->a; }
 signed int get_pbfs_b(struct bfs *bf) { return bf->b; }
 
-
-struct bfi {
-	int a:4;
-	int  :2;
-	int b:4;
-};
-unsigned int get__bfi_a(struct bfi bf) { return bf.a; }
-unsigned int get__bfi_b(struct bfi bf) { return bf.b; }
-unsigned int get_pbfi_a(struct bfi *bf) { return bf->a; }
-unsigned int get_pbfi_b(struct bfi *bf) { return bf->b; }
-
 /*
  * check-name: bitfield size
  * check-command: test-linearize -Wno-decl $file
@@ -37,8 +26,8 @@ unsigned int get_pbfi_b(struct bfi *bf) { return bf->b; }
  *
  * check-output-excludes: and\\..*\\$960
  * check-output-excludes: zext\\.
- * check-output-pattern(8): and\\..*\\$15
+ * check-output-pattern(4): and\\..*\\$15
  * check-output-pattern(4): sext\\.
  * check-output-pattern(4): trunc\\.4
- * check-output-pattern(6): lsr\\..*\\$6
+ * check-output-pattern(4): lsr\\..*\\$6
  */
diff --git a/validation/optim/bitfield-store-loads.c b/validation/optim/bitfield-store-loads.c
index dc625131e188..f946715bffa3 100644
--- a/validation/optim/bitfield-store-loads.c
+++ b/validation/optim/bitfield-store-loads.c
@@ -1,6 +1,6 @@
 struct s {
-	char :2;
-	char f:3;
+	unsigned char :2;
+	unsigned char f:3;
 };
 
 int foo(struct s s, int a)
-- 
2.28.0




[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