aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-01-07 14:16:12 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2013-02-12 10:13:10 -0500
commit3dbed8ac24a2b4b24bc9776d89ea5328f1424a63 (patch)
tree3086bdde5dc203c7ac354a20ea52623c3380d2f8
parent959bd8973bfcfced69715a522007662929ae6d48 (diff)
downloadsparse-master.tar.gz
L ## 'a' is valid; so's L ## "a"HEADmaster
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--pre-process.c27
-rw-r--r--validation/preprocessor/wide.c15
2 files changed, 41 insertions, 1 deletions
diff --git a/pre-process.c b/pre-process.c
index 9e5df5c3..e5f56b40 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -407,6 +407,8 @@ static void expand_arguments(int count, struct arg *args)
* Possibly valid combinations:
* - ident + ident -> ident
* - ident + number -> ident unless number contains '.', '+' or '-'.
+ * - 'L' + char constant -> wide char constant
+ * - 'L' + string literal -> wide string literal
* - number + number -> number
* - number + ident -> number
* - number + '.' -> number
@@ -422,6 +424,13 @@ static enum token_type combine(struct token *left, struct token *right, char *p)
if (t1 != TOKEN_IDENT && t1 != TOKEN_NUMBER && t1 != TOKEN_SPECIAL)
return TOKEN_ERROR;
+ if (t1 == TOKEN_IDENT && left->ident == &L_ident) {
+ if (t2 >= TOKEN_CHAR && t2 < TOKEN_WIDE_CHAR)
+ return t2 + TOKEN_WIDE_CHAR - TOKEN_CHAR;
+ if (t2 == TOKEN_STRING)
+ return TOKEN_WIDE_STRING;
+ }
+
if (t2 != TOKEN_IDENT && t2 != TOKEN_NUMBER && t2 != TOKEN_SPECIAL)
return TOKEN_ERROR;
@@ -464,9 +473,10 @@ static enum token_type combine(struct token *left, struct token *right, char *p)
static int merge(struct token *left, struct token *right)
{
static char buffer[512];
+ enum token_type res = combine(left, right, buffer);
int n;
- switch (combine(left, right, buffer)) {
+ switch (res) {
case TOKEN_IDENT:
left->ident = built_in_ident(buffer);
left->pos.noexpand = 0;
@@ -489,6 +499,21 @@ static int merge(struct token *left, struct token *right)
return 1;
}
}
+ break;
+
+ case TOKEN_WIDE_CHAR:
+ case TOKEN_WIDE_STRING:
+ token_type(left) = res;
+ left->pos.noexpand = 0;
+ left->string = right->string;
+ return 1;
+
+ case TOKEN_WIDE_CHAR + 1 ... TOKEN_WIDE_CHAR + 4:
+ token_type(left) = res;
+ left->pos.noexpand = 0;
+ memcpy(left->embedded, right->embedded, 4);
+ return 1;
+
default:
;
}
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
+ */
+