aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-12-07 23:17:07 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-07-22 01:38:24 +0200
commitc03ffb3212281d01b304781e67ea6fc38feb224e (patch)
tree25b902785b910205d468f4c622125f0e8256049a
parente140005c44ef962f5ee2a72735ea727e5db7f7f6 (diff)
downloadsparse-c03ffb3212281d01b304781e67ea6fc38feb224e.tar.gz
delay 'empty character constant' warning to phase 5
A subset of C syntax regarding character constants is: char-constant: ' c-char-sequence ' c-char-sequence: char c-char-sequence char In short, when tokenized, a character constant must have at least one character between the quotes. Consequently, sparse will issue an error on empty character constants (unlike GCC). However, sparse issues the error during tokenization (phase 3), before preprocessing directives are handled (phase 4). This means that code like: #if 0 ... '' #endif will throw an error although the corresponding code is discarded. Fix this by 1) silently accept empty char constants during tokenization 2) issue the diagnostic only when escape sequences are handled. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--char.c5
-rw-r--r--tokenize.c7
-rw-r--r--validation/empty-char-constant.c9
-rw-r--r--validation/preprocessor/empty-char-constant.c13
4 files changed, 28 insertions, 6 deletions
diff --git a/char.c b/char.c
index f26b2a80..730ae3f5 100644
--- a/char.c
+++ b/char.c
@@ -76,6 +76,11 @@ void get_char_constant(struct token *token, unsigned long long *val)
case TOKEN_WIDE_CHAR:
p = token->string->data;
end = p + token->string->length - 1;
+ if (end == p) {
+ sparse_error(token->pos, "empty character constant");
+ *val = 0;
+ return;
+ }
break;
case TOKEN_CHAR_EMBEDDED_0 ... TOKEN_CHAR_EMBEDDED_3:
end = p + type - TOKEN_CHAR;
diff --git a/tokenize.c b/tokenize.c
index c5ba6e6b..a7b6625b 100644
--- a/tokenize.c
+++ b/tokenize.c
@@ -619,12 +619,7 @@ static int eat_string(int next, stream_t *stream, enum token_type type)
warning(stream_pos(stream), "string too long (%d bytes, %d bytes max)", len, MAX_STRING);
len = MAX_STRING;
}
- if (delim == '\'' && len <= 4) {
- if (len == 0) {
- sparse_error(stream_pos(stream),
- "empty character constant");
- return nextchar(stream);
- }
+ if (delim == '\'' && len && len <= 4) {
token_type(token) = type + len;
memset(buffer + len, '\0', 4 - len);
memcpy(token->embedded, buffer, 4);
diff --git a/validation/empty-char-constant.c b/validation/empty-char-constant.c
new file mode 100644
index 00000000..f674037a
--- /dev/null
+++ b/validation/empty-char-constant.c
@@ -0,0 +1,9 @@
+static int a = '';
+
+/*
+ * check-name: empty-char-constant
+ *
+ * check-error-start
+empty-char-constant.c:1:16: error: empty character constant
+ * check-error-end
+ */
diff --git a/validation/preprocessor/empty-char-constant.c b/validation/preprocessor/empty-char-constant.c
new file mode 100644
index 00000000..2c248159
--- /dev/null
+++ b/validation/preprocessor/empty-char-constant.c
@@ -0,0 +1,13 @@
+#if 0
+ ''
+#endif
+
+/*
+ * check-name: empty-char-constant
+ * check-command: sparse -E $file
+ *
+ * check-output-start
+
+
+ * check-output-end
+ */