diff options
-rw-r--r-- | cc.h | 1 | ||||
-rw-r--r-- | decl.c | 9 | ||||
-rw-r--r-- | expr.c | 21 | ||||
-rw-r--r-- | pp.c | 48 |
4 files changed, 60 insertions, 19 deletions
@@ -401,6 +401,7 @@ void next(void); _Bool peek(int); char *expect(enum tokenkind, const char *); _Bool consume(int); +char *stringconcat(void); /* type */ @@ -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"); } @@ -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); @@ -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; +} |