aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-05-29 00:29:46 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-12-29 22:42:45 +0100
commitd1ad9561e9cd43373f692394567f627230a511d1 (patch)
treea8017d22f5c1a75edee3f03f556a26fb1e76047c
parent95ae484069ebcf6d2d1f754451f898b0f23d3211 (diff)
downloadsparse-dev-d1ad9561e9cd43373f692394567f627230a511d1.tar.gz
add support for '-f[no-][un]signed-char'
Till now, sparse's plain chars where signed with no possibility to change it. This is a problem when using sparse on code for architectures like ARM where chars are by default unsigned or simply for code compiled with GCC's '-f[no-][un]signed-char'. Change this by parsing these options and adjusting the type of plain chars accordingly. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--lib.c3
-rw-r--r--lib.h1
-rw-r--r--sparse.15
-rw-r--r--symbol.c6
-rw-r--r--validation/char-signed.c9
-rw-r--r--validation/char-unsigned.c11
6 files changed, 35 insertions, 0 deletions
diff --git a/lib.c b/lib.c
index b018eb97..fb11738c 100644
--- a/lib.c
+++ b/lib.c
@@ -263,6 +263,7 @@ unsigned long fdump_ir;
int fmem_report = 0;
unsigned long long fmemcpy_max_count = 100000;
unsigned long fpasses = ~0UL;
+int funsigned_char = 0;
int preprocess_only;
@@ -878,6 +879,8 @@ static struct flag fflags[] = {
{ "tabstop=", NULL, handle_ftabstop },
{ "mem2reg", NULL, handle_fpasses, PASS_MEM2REG },
{ "optim", NULL, handle_fpasses, PASS_OPTIM },
+ { "signed-char", &funsigned_char, NULL, OPT_INVERSE },
+ { "unsigned-char", &funsigned_char, NULL, },
{ },
};
diff --git a/lib.h b/lib.h
index b0f34265..37d48672 100644
--- a/lib.h
+++ b/lib.h
@@ -171,6 +171,7 @@ extern int fmem_report;
extern unsigned long fdump_ir;
extern unsigned long long fmemcpy_max_count;
extern unsigned long fpasses;
+extern int funsigned_char;
extern int arch_m64;
extern int arch_msize_long;
diff --git a/sparse.1 b/sparse.1
index 5b2bcd9c..efb01293 100644
--- a/sparse.1
+++ b/sparse.1
@@ -381,6 +381,11 @@ Set the distance between tab stops. This helps sparse report correct
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-char, \-f[no-]signed-char
+Let plain 'char' be unsigned or signed.
+By default chars are signed.
+.
.SH SEE ALSO
.BR cgcc (1)
.
diff --git a/symbol.c b/symbol.c
index 2f4afd51..773060ec 100644
--- a/symbol.c
+++ b/symbol.c
@@ -767,4 +767,10 @@ void init_ctype(void)
sym->ctype.base_type = ctype->base_type;
sym->ctype.modifiers = ctype->modifiers;
}
+
+ // and now some adjustments
+ if (funsigned_char) {
+ char_ctype.ctype.modifiers |= MOD_UNSIGNED;
+ char_ctype.ctype.modifiers &= ~MOD_SIGNED;
+ }
}
diff --git a/validation/char-signed.c b/validation/char-signed.c
new file mode 100644
index 00000000..7f657dac
--- /dev/null
+++ b/validation/char-signed.c
@@ -0,0 +1,9 @@
+void foo(void)
+{
+ _Static_assert((char) -1 == -1, "plain char is not signed");
+}
+
+/*
+ * check-name: fsigned-char
+ * check-command: sparse -fsigned-char -Wno-decl $file
+ */
diff --git a/validation/char-unsigned.c b/validation/char-unsigned.c
new file mode 100644
index 00000000..19cadbda
--- /dev/null
+++ b/validation/char-unsigned.c
@@ -0,0 +1,11 @@
+#define MASK ((1 << __CHAR_BIT__) - 1)
+
+void foo(void)
+{
+ _Static_assert((char) -1 == (-1 & MASK), "plain char is not unsigned");
+}
+
+/*
+ * check-name: fsigned-char
+ * check-command: sparse -funsigned-char -Wno-decl $file
+ */