aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--c/c.c66
-rw-r--r--io.c2
-rw-r--r--type.c26
-rw-r--r--type.h4
4 files changed, 50 insertions, 48 deletions
diff --git a/c/c.c b/c/c.c
index 7158bf3..594f38d 100644
--- a/c/c.c
+++ b/c/c.c
@@ -329,9 +329,10 @@ gettagged(struct comp *cm, struct span *span, enum typetag tt, const char *name,
}
}
}
+ if (tt == TYENUM && ccopt.pedant) {
+ warn(span, "forward-declared enum is an extension");
+ }
Break2:
- if (tt == TYENUM)
- return mktype(0);
td.t = tt;
return envaddtagged(cm->env, mktagtype(name, &td), span)->ty;
}
@@ -383,8 +384,10 @@ assigncheck(union type t, const struct expr *src)
warn(&src->span, "usage of '%ty' discards pointer qualifiers", src->ty);
}
return 1;
- }
- if (t.t == TYPTR && iszero(*src)) return 1;
+ } else if (t.t == TYPTR && srcty.t == TYPTR) {
+ warn(&src->span, "converting between incompatible pointer types '%ty' -> '%ty'", srcty, t);
+ return 1;
+ } else if (t.t == TYPTR && iszero(*src)) return 1;
return 0;
}
@@ -448,9 +451,9 @@ static void /* 6.5.3.4 The sizeof and _Alignof operators */
sizeofalignofcheck(const struct span *span, enum toktag tt, union type ty, const struct expr *ex)
{
if (isincomplete(ty))
- error(span, "cannot apply %'tt to incomplete type '%ty'", tt);
+ error(span, "cannot apply %'tt to incomplete type '%ty'", tt, ty);
else if (ty.t == TYFUNC)
- error(span, "cannot apply %'tt to function type '%ty'", tt);
+ error(span, "cannot apply %'tt to function type '%ty'", tt, ty);
else if (tt == TKWsizeof && ex && ex->t == EGETF && ex->fld.bitsiz)
error(span, "cannot apply %'tt to bitfield", tt);
if (tt != TKWsizeof && ex && ccopt.pedant)
@@ -514,7 +517,7 @@ condtype(const struct expr *a, const struct expr *b)
static void
bintypeerr(const struct span *span, enum toktag tt, union type lhs, union type rhs)
{
- error(span, "bad operands to %tt: '%ty', '%ty'", tt, lhs, rhs);
+ error(span, "bad operands to %tt ('%ty', '%ty')", tt, lhs, rhs);
}
enum binopclass { /* binary operator type-checking classes */
@@ -1962,7 +1965,7 @@ inttyminmax(vlong *min, uvlong *max, enum typetag tt)
* prefers to use unsigned types when possible). should add support for -fshort-enums
*/
static union type
-buildenum(struct comp *cm, const char *name, const struct span *span)
+buildenum(struct comp *cm, const char *name, const struct span *span, int id)
{
struct token tk;
vlong tymin, minv = 0;
@@ -2027,7 +2030,10 @@ buildenum(struct comp *cm, const char *name, const struct span *span)
if (td.backing >= TYVLONG && !somelonglong && ccopt.cstd == STDC89 && ccopt.pedant)
warn(span, "enum backing type is '%ty' in %M", mktype(td.backing));
- ty = mktagtype(name, &td);
+ if (id != -1)
+ ty = completetype(name, id, &td);
+ else
+ ty = mktagtype(name, &td);
ty.backing = td.backing;
return ty;
}
@@ -2051,29 +2057,23 @@ tagtype(struct comp *cm, enum toktag kind)
return mktype(0);
}
t = gettagged(cm, &span, tt, tag, /* def? */ peek(cm, NULL) == ';');
- if (tt == TYENUM && !t.t) {
- error(&tk.span, "cannot forward-declare enum");
- return mktype(TYINT);
- }
} else {
- if (tt != TYENUM) {
- if (tag) {
- t = deftagged(cm, &span, tt, tag, mktype(0));
- if (t.t != tt || !isincomplete(t)) {
- if (t.t != tt)
- error(&tk.span,
- "defining tagged type %'tk as %tt clashes with previous definition",
- &tk, kind);
- else
- error(&tk.span, "redefinition of '%tt %s'", kind, tag, mktype(0));
- note(&span, "previous definition:");
- }
+ if (tag) {
+ t = deftagged(cm, &span, tt, tag, mktype(0));
+ if (t.t != tt || !isincomplete(t)) {
+ if (t.t != tt)
+ error(&tk.span,
+ "defining tagged type %'tk as %tt clashes with previous definition",
+ &tk, kind);
+ else
+ error(&tk.span, "redefinition of '%tt %s'", kind, tag);
+ note(&span, "previous definition:");
}
- t = buildagg(cm, tt, tag, tag ? typedata[t.dat].id : -1);
- } else {
- t = buildenum(cm, tag, &span);
- if (tag) deftagged(cm, &span, TYENUM, tag, t);
}
+ if (tt == TYENUM)
+ t = buildenum(cm, tag, &span, tag ? typedata[t.dat].id : -1);
+ else
+ t = buildagg(cm, tt, tag, tag ? typedata[t.dat].id : -1);
}
if (t.t != tt) {
@@ -2485,11 +2485,9 @@ decltypes(struct comp *cm, struct decllist *list, const char **name, struct span
vpush(&names, decl.name);
vpush(&spans, decl.span);
vpush(&qual, decl.qual);
- if (isincomplete(decl.ty)) {
- if (params.n > 1 || decl.ty.t != TYVOID
- || decl.qual || decl.name || peek(cm, &tk) != ')') {
- error(&decl.span,
- "function parameter #%d has incomplete type (%tq)",
+ if (decl.ty.t == TYVOID) {
+ if (params.n > 1 || decl.qual || decl.name || peek(cm, &tk) != ')') {
+ error(&decl.span, "function parameter #%d has void type",
params.n, decl.ty, qual.p[params.n-1]);
}
}
diff --git a/io.c b/io.c
index 529710b..1661e12 100644
--- a/io.c
+++ b/io.c
@@ -213,7 +213,7 @@ pritypebefore(struct wbuf *buf, union type ty, int qual)
case TYPTR:
chld = typechild(ty);
n = pritypebefore(buf, chld, ty.flag & TFCHLDQUAL);
- //if (chld.t != TYPTR) n += ioputc(buf, ' ');
+ n += bputc(buf, ' ');
if (chld.t == TYARRAY || chld.t == TYFUNC)
n += bputc(buf, '(');
n += bputc(buf, '*');
diff --git a/type.c b/type.c
index 53491c9..b18feb2 100644
--- a/type.c
+++ b/type.c
@@ -97,7 +97,7 @@ interntd(const struct typedata *td)
}
return i;
} else if (tdequ(slot, td)) {
- if (td->t == TYSTRUCT || td->t == TYUNION)
+ if (td->t == TYSTRUCT || td->t == TYUNION || td->t == TYENUM)
goto Copy;
return i;
}
@@ -114,6 +114,8 @@ isincomplete(union type t)
case TYSTRUCT:
case TYUNION:
return typedata[t.dat].nmemb == 0;
+ case TYENUM:
+ return !typedata[t.dat].backing;
}
return 0;
}
@@ -124,7 +126,7 @@ typesize(union type t)
if (isprim(t) || t.t == TYPTR) return targ_primsizes[t.t];
switch (t.t) {
case TYENUM:
- return targ_primsizes[t.backing];
+ return targ_primsizes[typedata[t.dat].backing];
case TYARRAY:
if (t.flag & TFCHLDPRIM)
return targ_primsizes[t.child] * t.arrlen;
@@ -142,7 +144,7 @@ typealign(union type t)
if (isprim(t) || t.t == TYPTR) return targ_primalign[t.t];
switch (t.t) {
case TYENUM:
- return targ_primalign[t.backing];
+ return targ_primalign[typedata[t.dat].backing];
case TYARRAY:
return typealign(typechild(t));
case TYSTRUCT:
@@ -190,7 +192,7 @@ completetype(const char *name, int id, struct typedata *td)
assert(ttypenames[id] == name && "bad redefn");
else
ttypenames[id] = name;
- return mktype(td->t, .dat = interntd(td));
+ return mktype(td->t, .dat = interntd(td), .backing = td->t == TYENUM ? td->backing : 0);
}
union type
@@ -244,16 +246,18 @@ typedecay(union type t)
bool /* 6.5.16.1 Simple assignment Constraints */
assigncompat(union type dst, union type src)
{
- union type ds, ss;
if (dst.bits == src.bits) return 1;
if (isarith(dst) && isarith(src)) return 1;
if (dst.t == TYPTR && src.t == TYPTR) {
- ds = typechild(dst);
- ss = typechild(src);
- if (ds.bits == ss.bits) return 1;
- if (ss.t == TYVOID || ds.t == TYVOID) return 1;
- if (ss.t == TYCHAR && in_range(ds.t, TYUCHAR, TYSCHAR)) return 1;
- if (ds.t == TYCHAR && in_range(ss.t, TYUCHAR, TYSCHAR)) return 1;
+ union type ds = typechild(dst), ss = typechild(src);
+ if (ds.bits == ss.bits) return 1; /* T* with different qualifiers */
+ if (ss.t == TYVOID || ds.t == TYVOID) return 1; /* T* <-> void* */
+ enum typetag dt = scalartypet(ds), /* handle enums */
+ st = scalartypet(ss);
+ if (!dt || !st) return 0; /* unequal incomplete enums */
+ /* plain char exception */
+ if (st == TYCHAR && in_range(dt, TYUCHAR, TYSCHAR)) return 1;
+ if (dt == TYCHAR && in_range(st, TYUCHAR, TYSCHAR)) return 1;
} else if (dst.t == TYBOOL && src.t == TYPTR)
return 1;
return 0;
diff --git a/type.h b/type.h
index 4124dff..decef3c 100644
--- a/type.h
+++ b/type.h
@@ -136,7 +136,7 @@ union type cvtarith(union type a, union type b);
static inline union type
typechild(union type t)
{
- if (t.t == TYENUM) return mktype(t.backing);
+ if (t.t == TYENUM) return mktype(t.backing ? t.backing : typedata[t.dat].backing);
if (t.flag & TFCHLDPRIM) return mktype(t.child);
if (t.flag & TFCHLDISDAT) {
union type chld = mktype(typedata[t.dat].t, .dat = t.dat);
@@ -148,7 +148,7 @@ typechild(union type t)
static inline enum typetag
scalartypet(union type t)
{
- if (t.t == TYENUM) return t.backing;
+ if (t.t == TYENUM) return t.backing ? t.backing : typedata[t.dat].backing;
if (isptrcvt(t)) return TYPTR;
return t.t;
}