aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2017-03-06 21:45:41 +0100
committerMichael Matz <matz@suse.de>2017-05-02 03:07:37 +0200
commit8ca98e23c4e54b1552c819425890584e6357f46a (patch)
tree726ade8adcde484eaec9f1c1161ea78a7ed86481
parent21b12ea10d3c04d66c81633b67be29c42d5dcb3a (diff)
downloadtinycc-8ca98e23c4e54b1552c819425890584e6357f46a.tar.gz
tinycc-8ca98e23c4e54b1552c819425890584e6357f46a.tar.bz2
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.
-rw-r--r--tccgen.c45
-rw-r--r--tccpp.c5
-rw-r--r--tests/tcctest.c23
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);
+}