aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2017-07-10 22:20:34 +0200
committerMichael Matz <matz@suse.de>2017-07-10 22:20:34 +0200
commit2240422da9b55b71cfb32220bb0246ec92bfc432 (patch)
treed1f9ad8ad518efd9244d45b4a6f0df8b27729340
parenta9e502cc3bae649fe4f9adffcd0715eb0a71d085 (diff)
downloadtinycc-2240422da9b55b71cfb32220bb0246ec92bfc432.tar.gz
tinycc-2240422da9b55b71cfb32220bb0246ec92bfc432.tar.bz2
enums: Accept GNU extension
See testcase. Happens e.g. in the linux kernel.
-rw-r--r--tccgen.c4
-rw-r--r--tests/tests2/17_enum.c43
-rw-r--r--tests/tests2/17_enum.expect1
3 files changed, 46 insertions, 2 deletions
diff --git a/tccgen.c b/tccgen.c
index d8676a4..c3185ca 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -3683,7 +3683,7 @@ static void struct_decl(CType *type, int u)
v = anon_sym++;
}
/* Record the original enum/struct/union token. */
- type1.t = u;
+ type1.t = u == VT_ENUM ? u | VT_INT | VT_UNSIGNED : u;
type1.ref = NULL;
/* we put an undefined size for struct/union */
s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
@@ -3736,7 +3736,7 @@ do_decl:
skip('}');
/* set integral type of the enum */
t.t = VT_INT;
- if (nl == 0) {
+ if (nl >= 0) {
if (pl != (unsigned)pl)
t.t = VT_LLONG;
t.t |= VT_UNSIGNED;
diff --git a/tests/tests2/17_enum.c b/tests/tests2/17_enum.c
index 0853c42..e2bc736 100644
--- a/tests/tests2/17_enum.c
+++ b/tests/tests2/17_enum.c
@@ -12,9 +12,49 @@ enum fred
h
};
+/* All following uses of enum efoo should compile
+ without warning. While forward enums aren't ISO C,
+ it's accepted by GCC also in strict mode, and only warned
+ about with -pedantic. This happens in the real world. */
+/* Strict ISO C doesn't allow this kind of forward declaration of
+ enums, but GCC accepts it (and gives only pedantic warning), and
+ it occurs in the wild. */
+enum efoo;
+struct Sforward_use {
+ int (*fmember) (enum efoo x);
+};
+
+extern enum efoo it_real_fn(void);
+enum efoo {
+ ONE,
+ TWO,
+};
+struct S2 {
+ enum efoo (*f2) (void);
+};
+void should_compile(struct S2 *s)
+{
+ s->f2 = it_real_fn;
+}
+
+enum efoo it_real_fn(void)
+{
+ return TWO;
+}
+
+static unsigned int deref_uintptr(unsigned int *p)
+{
+ return *p;
+}
+
+enum Epositive {
+ epos_one, epos_two
+};
+
int main()
{
enum fred frod;
+ enum Epositive epos = epos_two;
printf("%d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h);
/* printf("%d\n", frod); */
@@ -23,6 +63,9 @@ int main()
frod = e;
printf("%d\n", frod);
+ /* Following should compile without warning. */
+ printf ("enum to int: %u\n", deref_uintptr(&epos));
+
return 0;
}
diff --git a/tests/tests2/17_enum.expect b/tests/tests2/17_enum.expect
index 0c4e153..d453a61 100644
--- a/tests/tests2/17_enum.expect
+++ b/tests/tests2/17_enum.expect
@@ -1,3 +1,4 @@
0 1 2 3 54 73 74 75
12
54
+enum to int: 1