aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/validation
diff options
authorChristopher Li <sparse@chrisli.org>2013-02-12 23:01:45 -0800
committerChristopher Li <sparse@chrisli.org>2013-02-13 14:55:26 -0800
commit1b8e012d10d2a5af2d4935e4a47df9c527399219 (patch)
treeeb5c93ce49e6bc718f6da55fdb59c85df7a7f011 /validation
parent6558e30ec635e26e767cee027936a0d0cae79bcb (diff)
parent3dbed8ac24a2b4b24bc9776d89ea5328f1424a63 (diff)
downloadsparse-dev-1b8e012d10d2a5af2d4935e4a47df9c527399219.tar.gz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/viro/sparse into marge
Pull preprocessor fix from Al Viro. 1) we really, really shouldn't convert escape sequences too early; #define A(x) #x A('\12') should yield "'\\12'", *not* "'\\n'". 2) literal merging handles all sequences of string/wide string literals; result is wide if any of them is wide. string_expression() is handling that wrong - "ab"L"c" is L"abc" 3) with support (no matter how cursory) of wide char constants and wide string literals, we really ought to handle #define A(x,y) A(L,'a') properly; it's not that tricky - combine() needs to recognize <IDENT["L"],CHAR> and <IDENT["L"],STRING> pairs. 4) '\777' is an error, while L'\777' is valid - the value should fit into unsigned char or unsigned counterpart of wchar_t. Note that for string literals this happens *after* phase 6 - what matters is the type of literal after joining the adjacent ones (see (2) above). 5) stringifying should only quote \ and " in character constants and string literals, #define A(x) #x A(\n) should produce "\n", not "\\n" 6) we are losing L when stringifying wide string literals; that's wrong. I've patches hopefully fixing the above. Basically, I delay interpreting escape sequences (past the bare minimum needed to find where the token ends) until we are handling an expression with character constant or string literal in it. For character constants I'm keeping the token body in token->embedded - 4-character array replacing token->character. That covers practically all realistic instances; character constant *may* be longer than that, but it has to be something like '\x000000000000000000000000041' - sure, that's 100% legitimate C and it's going to be the same as '\x41' on everything, but when was the last time you've seen something like that? So I've split TOKEN_CHAR into 5 values - TOKEN_CHAR+1--TOKEN_CHAR+4 meaning 1--4 characters kept in ->embedded[], TOKEN_CHAR itself used for extremely rare cases longer than that (token->string holds the body in that case). TOKEN_WIDE_CHAR got the same treatment. AFAICS, with those fixes we get the same behaviour as in gcc for silently ignored by cpp if the string/char constant doesn't make it out of preprocessor. sparse still warns about those. The situation with this one is frustrating; on one hand C99 is saying that e.g. '\x' is not a token. Moreover, in a footnote in 6.4.4.4 it flat-out requires diagnostics for such. On the other hand... footnotes are informative-only and having "other character" token match ' would puts us in nasal daemon country, so gcc is free to do whatever it feels like doing. I think we shouldn't play that kind of standard-lawyering *and* sparse has always warned on that, so I've left that warning in place. Note that real wchar_t handling is still not there; at the very least, we need to decide what type will be used for that sucker (for gcc it's int on all targets we care about), fix the handling of wide string literals in initializers and evaluate_string() and stop dropping upper bits in get_string_constant(). That would probably mean not using struct string for wide ones, as well... Hell knows; I don't want to touch that right now. If anything, I'd rather wait until we get to C11 support - they've got much saner variants of wide strings there (char16_t/char32_t with u and U as token prefix as L is used for wchar_t; there's also u8"..." for UTF8 strings).
Diffstat (limited to 'validation')
-rw-r--r--validation/__func__.c15
-rw-r--r--validation/escapes.c17
-rw-r--r--validation/foul-bitwise.c6
-rw-r--r--validation/preprocessor/preprocessor14.c1
-rw-r--r--validation/preprocessor/preprocessor23.c47
-rw-r--r--validation/preprocessor/stringify.c29
-rw-r--r--validation/preprocessor/wide.c15
-rw-r--r--validation/wide.c9
8 files changed, 127 insertions, 12 deletions
diff --git a/validation/__func__.c b/validation/__func__.c
new file mode 100644
index 00000000..65ce9282
--- /dev/null
+++ b/validation/__func__.c
@@ -0,0 +1,15 @@
+static void f(void)
+{
+ char *s1 = __func__;
+ char arr[2 * (sizeof __func__ == 2) - 1];
+ char *s2 = __func__ __func__;
+}
+/*
+ * check-name: __func__
+ * check-command: sparse -Wall $file
+ *
+ * check-error-start
+__func__.c:5:29: error: Expected ; at end of declaration
+__func__.c:5:29: error: got __func__
+ * check-error-end
+ */
diff --git a/validation/escapes.c b/validation/escapes.c
index 13f8f9c8..4a1b030e 100644
--- a/validation/escapes.c
+++ b/validation/escapes.c
@@ -8,14 +8,13 @@ static int bad_e[] = { '\c', '\0123', '\789', '\xdefg' };
* check-name: Character escape sequences
*
* check-error-start
-escapes.c:6:27: warning: Unknown escape 'c'
-escapes.c:6:35: error: Bad character constant
-escapes.c:6:38: error: Bad character constant
-escapes.c:6:42: error: Bad character constant
-escapes.c:6:46: error: Bad character constant
-escapes.c:6:53: error: Bad character constant
-escapes.c:6:56: error: Bad character constant
-escapes.c:6:42: error: Expected } at end of initializer
-escapes.c:6:42: error: got 89
+escapes.c:6:26: warning: Unknown escape 'c'
+escapes.c:3:34: warning: hex escape sequence out of range
+escapes.c:3:44: warning: hex escape sequence out of range
+escapes.c:4:18: warning: hex escape sequence out of range
+escapes.c:6:30: warning: multi-character character constant
+escapes.c:6:39: warning: multi-character character constant
+escapes.c:6:47: warning: hex escape sequence out of range
+escapes.c:6:47: warning: multi-character character constant
* check-error-end
*/
diff --git a/validation/foul-bitwise.c b/validation/foul-bitwise.c
index 9e21eab7..4b542cf9 100644
--- a/validation/foul-bitwise.c
+++ b/validation/foul-bitwise.c
@@ -24,7 +24,9 @@ static __le16 bar(__le16 a)
* check-error-start
foul-bitwise.c:9:16: warning: restricted __le16 degrades to integer
foul-bitwise.c:9:22: warning: restricted __le16 degrades to integer
-foul-bitwise.c:19:16: error: incompatible types for operation (-)
-foul-bitwise.c:19:16: argument has type restricted __le16 [usertype] a
+foul-bitwise.c:19:16: warning: restricted __le16 degrades to integer
+foul-bitwise.c:19:16: warning: incorrect type in return expression (different base types)
+foul-bitwise.c:19:16: expected restricted __le16
+foul-bitwise.c:19:16: got int
* check-error-end
*/
diff --git a/validation/preprocessor/preprocessor14.c b/validation/preprocessor/preprocessor14.c
index 05fc248b..027af040 100644
--- a/validation/preprocessor/preprocessor14.c
+++ b/validation/preprocessor/preprocessor14.c
@@ -7,7 +7,6 @@ A(,1)
B(,1)
/*
* check-name: Preprocessor #14
- * check-known-to-fail
* check-command: sparse -E $file
*
* check-output-start
diff --git a/validation/preprocessor/preprocessor23.c b/validation/preprocessor/preprocessor23.c
new file mode 100644
index 00000000..25be5085
--- /dev/null
+++ b/validation/preprocessor/preprocessor23.c
@@ -0,0 +1,47 @@
+#define H(x,...) ,##x##__VA_ARGS__##,##__VA_ARGS__
+H()
+H(x)
+H(,)
+H(x,)
+H(,x)
+H(x,x)
+#define I(x,...) ,##x##__VA_ARGS__
+I()
+I(x)
+I(,)
+I(x,)
+I(,x)
+I(x,x)
+/*
+ * check-name: Preprocessor #23
+ * check-command: sparse -E $file
+ *
+ * check-output-start
+
+,
+,x
+,,
+,x,
+,x,x
+,xx,x
+,x
+,
+,x
+,x
+,xx
+ * check-output-end
+ *
+ * check-error-start
+preprocessor/preprocessor23.c:3:1: error: '##' failed: concatenation is not a valid token
+preprocessor/preprocessor23.c:4:1: error: '##' failed: concatenation is not a valid token
+preprocessor/preprocessor23.c:5:1: error: '##' failed: concatenation is not a valid token
+preprocessor/preprocessor23.c:5:1: error: '##' failed: concatenation is not a valid token
+preprocessor/preprocessor23.c:6:1: error: '##' failed: concatenation is not a valid token
+preprocessor/preprocessor23.c:6:1: error: '##' failed: concatenation is not a valid token
+preprocessor/preprocessor23.c:7:1: error: '##' failed: concatenation is not a valid token
+preprocessor/preprocessor23.c:7:1: error: '##' failed: concatenation is not a valid token
+preprocessor/preprocessor23.c:10:1: error: '##' failed: concatenation is not a valid token
+preprocessor/preprocessor23.c:12:1: error: '##' failed: concatenation is not a valid token
+preprocessor/preprocessor23.c:14:1: error: '##' failed: concatenation is not a valid token
+ * check-error-end
+ */
diff --git a/validation/preprocessor/stringify.c b/validation/preprocessor/stringify.c
new file mode 100644
index 00000000..7fe965d5
--- /dev/null
+++ b/validation/preprocessor/stringify.c
@@ -0,0 +1,29 @@
+#define A(x) #x
+A('a')
+A("a")
+A(a)
+A(\n)
+A('\n')
+A("\n")
+A('"')
+A("a\nb")
+A(L"a\nb")
+A('\12')
+/*
+ * check-name: Preprocessor #14
+ * check-command: sparse -E $file
+ *
+ * check-output-start
+
+"'a'"
+"\"a\""
+"a"
+"\n"
+"'\\n'"
+"\"\\n\""
+"'\"'"
+"\"a\\nb\""
+"L\"a\\nb\""
+"'\\12'"
+ * check-output-end
+ */
diff --git a/validation/preprocessor/wide.c b/validation/preprocessor/wide.c
new file mode 100644
index 00000000..21b643ce
--- /dev/null
+++ b/validation/preprocessor/wide.c
@@ -0,0 +1,15 @@
+#define A(x) L##x
+A('a')
+A("bc")
+/*
+ * check-name: wide char token-pasting
+ * check-description: Used to cause infinite recursion.
+ * check-command: sparse -E $file
+ *
+ * check-output-start
+
+L'a'
+L"bc"
+ * check-output-end
+ */
+
diff --git a/validation/wide.c b/validation/wide.c
new file mode 100644
index 00000000..847a680f
--- /dev/null
+++ b/validation/wide.c
@@ -0,0 +1,9 @@
+static char c = L'\x41';
+static int n = 1/(0x41 - L'\x41');
+/*
+ * check-name: wide character constants
+ *
+ * check-error-start
+wide.c:2:17: warning: division by zero
+ * check-error-end
+ */