~mcf/cproc

0e9e97e37571c913864cc4d8d986fa9fda964e8a — Michael Forney a month ago 38d9062
Revert "Add stringconcat function to concatenate adjacent string literals"

This reverts commit c16f07acf655b9f4fb006d8256b4027fb5a13aa8.

This incorrectly allows octal escapes to span between adjacent
string literals (e.g. "\0" "1" is not the same as "\01").
4 files changed, 19 insertions(+), 60 deletions(-)

M cc.h
M decl.c
M expr.c
M pp.c
M cc.h => cc.h +0 -1
@@ 405,7 405,6 @@ void next(void);
_Bool peek(int);
char *expect(enum tokenkind, const char *);
_Bool consume(int);
char *stringconcat(void);

/* type */


M decl.c => decl.c +5 -4
@@ 748,18 748,19 @@ 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)) {
		tokencheck(&tok, TSTRINGLIT, "after static assertion expression");
		msg = stringconcat();
		e = assignexpr(s);
		if (!e->decayed || e->base->kind != EXPRSTRING)
			error(&tok.loc, "expected string literal after static assertion expression");
		if (!c)
			error(&tok.loc, "static assertion failed: %s", msg + (*msg != '"'));
			error(&tok.loc, "static assertion failed: %.*s", (int)e->base->string.size, e->base->string.data);
	} else if (!c) {
		error(&tok.loc, "static assertion failed");
	}

M expr.c => expr.c +14 -7
@@ 476,14 476,21 @@ primaryexpr(struct scope *s)
	case TSTRINGLIT:
		e = mkexpr(EXPRSTRING, mkarraytype(&typechar, QUALNONE, 0));
		e->lvalue = true;
		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);
		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);
		*dst = '\0';
		e->type->array.length = e->string.size = dst - e->string.data + 1;
		e->type->array.length = ++e->string.size;
		e->type->size = e->type->array.length * e->type->base->size;
		e->type->incomplete = false;
		e = decay(e);

M pp.c => pp.c +0 -48
@@ 650,51 650,3 @@ 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;
}