aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cc.h1
-rw-r--r--decl.c9
-rw-r--r--expr.c21
-rw-r--r--pp.c48
4 files changed, 60 insertions, 19 deletions
diff --git a/cc.h b/cc.h
index b47853b..774c951 100644
--- a/cc.h
+++ b/cc.h
@@ -401,6 +401,7 @@ void next(void);
_Bool peek(int);
char *expect(enum tokenkind, const char *);
_Bool consume(int);
+char *stringconcat(void);
/* type */
diff --git a/decl.c b/decl.c
index 0d47b8e..ea62f56 100644
--- a/decl.c
+++ b/decl.c
@@ -753,19 +753,18 @@ addmember(struct structbuilder *b, struct qualtype mt, char *name, int align, ui
static bool
staticassert(struct scope *s)
{
- struct expr *e;
uint64_t c;
+ char *msg;
if (!consume(T_STATIC_ASSERT))
return false;
expect(TLPAREN, "after _Static_assert");
c = intconstexpr(s, true);
if (consume(TCOMMA)) {
- e = assignexpr(s);
- if (!e->decayed || e->base->kind != EXPRSTRING)
- error(&tok.loc, "expected string literal after static assertion expression");
+ tokencheck(&tok, TSTRINGLIT, "after static assertion expression");
+ msg = stringconcat();
if (!c)
- error(&tok.loc, "static assertion failed: %.*s", (int)e->base->string.size, e->base->string.data);
+ error(&tok.loc, "static assertion failed: %s", msg + (*msg != '"'));
} else if (!c) {
error(&tok.loc, "static assertion failed");
}
diff --git a/expr.c b/expr.c
index fd8bc63..70aa3bd 100644
--- a/expr.c
+++ b/expr.c
@@ -475,21 +475,14 @@ primaryexpr(struct scope *s)
case TSTRINGLIT:
e = mkexpr(EXPRSTRING, mkarraytype(&typechar, QUALNONE, 0));
e->lvalue = true;
- e->string.size = 0;
- e->string.data = NULL;
- do {
- e->string.data = xreallocarray(e->string.data, e->string.size + strlen(tok.lit) + 1, 1);
- dst = e->string.data + e->string.size;
- src = tok.lit;
- if (*src != '"')
- fatal("wide string literal not yet implemented");
- for (++src; *src != '"'; ++dst)
- *dst = unescape(&src);
- e->string.size = dst - e->string.data;
- next();
- } while (tok.kind == TSTRINGLIT);
+ src = stringconcat();
+ dst = e->string.data = xmalloc(strlen(src) - 1);
+ if (*src != '"')
+ fatal("wide string literal not yet implemented");
+ for (++src; *src != '"'; ++dst)
+ *dst = unescape(&src);
*dst = '\0';
- e->type->array.length = ++e->string.size;
+ e->type->array.length = e->string.size = dst - e->string.data + 1;
e->type->size = e->type->array.length * e->type->base->size;
e->type->incomplete = false;
e = decay(e);
diff --git a/pp.c b/pp.c
index d3f9915..9f0c74d 100644
--- a/pp.c
+++ b/pp.c
@@ -632,3 +632,51 @@ consume(int kind)
next();
return true;
}
+
+char *
+stringconcat(void)
+{
+ static struct array buf;
+ char *lit, *end;
+ int kind = 0, newkind;
+
+ assert(tok.kind == TSTRINGLIT);
+ lit = tok.lit;
+ next();
+ if (tok.kind != TSTRINGLIT) {
+ if (lit[0] == 'u' && lit[1] == '8')
+ lit += 2;
+ return lit;
+ }
+
+ /* concatenate adjacent string literals */
+ buf.len = 0;
+ ((char *)arrayadd(&buf, 2))[1] = '"';
+ for (;;) {
+ switch (*lit) {
+ case 'u': if (lit[1] == '8') ++lit; /* fallthrough */
+ case 'L':
+ case 'U': newkind = *lit, ++lit; break;
+ case '"': newkind = 0; break;
+ default: assert(0);
+ }
+ if (kind != newkind && kind && newkind)
+ error(&tok.loc, "adjacent string literals have differing prefixes");
+ if (newkind)
+ kind = newkind;
+ arrayaddbuf(&buf, lit + 1, strlen(lit) - 2);
+ if (tok.kind != TSTRINGLIT)
+ break;
+ lit = tok.lit;
+ next();
+ }
+ end = arrayadd(&buf, 2);
+ end[0] = '"';
+ end[1] = '\0';
+ lit = buf.val;
+ if (kind && kind != '8')
+ *lit = kind;
+ else
+ ++lit;
+ return lit;
+}