From 8ca98e23c4e54b1552c819425890584e6357f46a Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 6 Mar 2017 21:45:41 +0100 Subject: [PATCH] Tidy unary() a bit factor code a bit for transforming tokens into SValues. This revealed a bug in TOK_GET (see testcase), which happened to be harmless before. So fix that as well. --- tccgen.c | 45 ++++++++++++++++++--------------------------- tccpp.c | 5 ++++- tests/tcctest.c | 23 +++++++++++++++++++++-- 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/tccgen.c b/tccgen.c index e3ba5cc..2f93796 100644 --- a/tccgen.c +++ b/tccgen.c @@ -4297,14 +4297,6 @@ static void parse_type(CType *type) type_decl(type, &ad, &n, TYPE_ABSTRACT); } -static void vpush_tokc(int t) -{ - CType type; - type.t = t; - type.ref = 0; - vsetc(&type, VT_CONST, &tokc); -} - static void parse_builtin_params(int nc, const char *args) { char c, sep = '('; @@ -4345,33 +4337,32 @@ ST_FUNC void unary(void) case TOK_CINT: case TOK_CCHAR: case TOK_LCHAR: - vpushi(tokc.i); + t = VT_INT; + push_tokc: + type.t = t; + type.ref = 0; + vsetc(&type, VT_CONST, &tokc); next(); break; case TOK_CUINT: - vpush_tokc(VT_INT | VT_UNSIGNED); - next(); - break; + t = VT_INT | VT_UNSIGNED; + goto push_tokc; case TOK_CLLONG: - vpush_tokc(VT_LLONG); - next(); - break; + t = VT_LLONG; + goto push_tokc; case TOK_CULLONG: - vpush_tokc(VT_LLONG | VT_UNSIGNED); - next(); - break; + t =VT_LLONG | VT_UNSIGNED; + goto push_tokc; case TOK_CFLOAT: - vpush_tokc(VT_FLOAT); - next(); - break; + t = VT_FLOAT; + goto push_tokc; case TOK_CDOUBLE: - vpush_tokc(VT_DOUBLE); - next(); - break; + t = VT_DOUBLE; + goto push_tokc; case TOK_CLDOUBLE: - vpush_tokc(VT_LDOUBLE); - next(); - break; + t = VT_LDOUBLE; + goto push_tokc; + case TOK___FUNCTION__: if (!gnu_ext) goto tok_identifier; diff --git a/tccpp.c b/tccpp.c index 1f3b083..4cf0ef5 100644 --- a/tccpp.c +++ b/tccpp.c @@ -1230,10 +1230,13 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv) case TOK_CUINT: case TOK_CCHAR: case TOK_LCHAR: - case TOK_CFLOAT: case TOK_LINENUM: tab[0] = *p++; + cv->i = (*t == TOK_CUINT) ? (unsigned)cv->i : (int)cv->i; break; + case TOK_CFLOAT: + tab[0] = *p++; + break; case TOK_STR: case TOK_LSTR: case TOK_PPNUM: diff --git a/tests/tcctest.c b/tests/tcctest.c index aee0120..e86a2a6 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -3720,8 +3720,6 @@ typedef struct __attribute__((__packed__)) { int c; } Spacked2; Spacked2 spacked2; -/* This doesn't work for now. Requires adjusting field offsets/sizes - after parsing the struct members. */ typedef struct Spacked3_s { char a; short b; @@ -3754,3 +3752,24 @@ void * __attribute__((__unused__)) get_void_ptr (void *a) { return a; } + +/* This part checks for a bug in TOK_GET (used for inline expansion), + where the large long long constant left the the high bits set for + the integer constant token. */ +static inline +int __get_order(unsigned long long size) +{ + int order; + size -= 0xffff880000000000ULL; // this const left high bits set in the token + { + struct S { int i : 1; } s; // constructed for this '1' + } + order = size; + return order; +} + +/* This just forces the above inline function to be actually emitted. */ +int force_get_order(unsigned long s) +{ + return __get_order(s); +}