Skip to content

Commit

Permalink
delay 'empty character constant' warning to phase 5
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
lucvoo committed Jul 21, 2020
1 parent e140005 commit c03ffb3
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 6 deletions.
5 changes: 5 additions & 0 deletions char.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 1 addition & 6 deletions tokenize.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 9 additions & 0 deletions validation/empty-char-constant.c
Original file line number Diff line number Diff line change
@@ -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
*/
13 changes: 13 additions & 0 deletions validation/preprocessor/empty-char-constant.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#if 0
''
#endif

/*
* check-name: empty-char-constant
* check-command: sparse -E $file
*
* check-output-start
* check-output-end
*/

0 comments on commit c03ffb3

Please sign in to comment.