aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--common.h1
-rw-r--r--io.c5
-rw-r--r--lex.c24
-rw-r--r--main.c5
-rw-r--r--parse.c41
-rw-r--r--test.c11
6 files changed, 65 insertions, 22 deletions
diff --git a/common.h b/common.h
index 6246f02..1b40000 100644
--- a/common.h
+++ b/common.h
@@ -93,6 +93,7 @@ enum cstd {
};
struct option {
enum cstd cstd;
+ bool pedant;
bool trigraph;
bool nocolor;
};
diff --git a/io.c b/io.c
index 48325d4..9156d27 100644
--- a/io.c
+++ b/io.c
@@ -550,6 +550,11 @@ vbfmt(struct wbuf *out, const char *fmt, va_list ap)
}
if (!ccopt.nocolor) n += bputc(buf, 'm');
break;
+ case 'M': /* cc mode */
+ iowrite(buf, &"C89\0C99\0C11\0C23"[ccopt.cstd*4], 3);
+ n += 3;
+ n += bwriteS(buf, " mode");
+ break;
default:
if (umod || lmod) {
--fmt;
diff --git a/lex.c b/lex.c
index a41bd0d..f172c30 100644
--- a/lex.c
+++ b/lex.c
@@ -24,7 +24,7 @@ intern(const char *s)
}
}
-static void
+static bool
identkeyword(struct token *tk, const char *s, int len)
{
static const struct { const char *s; enum toktag t; enum cstd cstd; } kwtab[] = {
@@ -41,15 +41,17 @@ identkeyword(struct token *tk, const char *s, int len)
cmp = strcmp(kwtab[i].s, s);
if (cmp < 0) l = i + 1;
else if (cmp > 0) h = i - 1;
- else if (kwtab[i].cstd <= ccopt.cstd) {
+ else if (kwtab[i].cstd <= ccopt.cstd || kwtab[i].s[0] == '_') {
+ /* allow future keywords but only if they begin with _ */
tk->t = kwtab[i].t;
tk->s = kwtab[i].s;
- return;
+ return kwtab[i].cstd <= ccopt.cstd;
} else break;
}
ident:
tk->t = TKIDENT;
tk->s = intern(s);
+ return 1;
}
static int
@@ -174,7 +176,7 @@ parsenumlit(uvlong *outi, double *outf, const struct token *tk, bool ispp)
static uvlong max4typ[TYUVLONG-TYINT+1];
uvlong n = 0;
int base = 10, nsx;
- bool dec, u = 0, c99 = ccopt.cstd >= STDC99;
+ bool dec, u = 0, longlongok = ccopt.cstd >= STDC99 || !ccopt.pedant;
enum typetag ty = 0;
const char *sx; /*suffix*/
char c;
@@ -209,13 +211,13 @@ parsenumlit(uvlong *outi, double *outf, const struct token *tk, bool ispp)
if (nsx == 1) /* 'u' */ {}
else if ((sx[1]|32) == 'l') {
if (nsx == 2) /* 'ul' */ goto L;
- if (c99 && sx[1] == sx[2] && nsx == 3) /* 'ull' */ goto LL;
+ if (sx[1] == sx[2] && nsx == 3) /* 'ull' */ goto LL;
return 0;
} else return 0;
} else if ((sx[0]|32) == 'l') {
if (nsx == 1) /* 'l' */ goto L;
if ((sx[1]|32) == 'u' && nsx == 2) /* 'lu' */ { u=1; goto L; }
- if (c99 && sx[1] == sx[0]) {
+ if (sx[1] == sx[0]) {
if (nsx == 2) /* 'll' */ goto LL;
if ((sx[2]|32) == 'u' && nsx == 3) /* 'llu' */ { u=1; goto LL; }
}
@@ -229,8 +231,8 @@ parsenumlit(uvlong *outi, double *outf, const struct token *tk, bool ispp)
if (u || !dec) I(TYUINT)
L:
I(TYLONG)
- if (u || !dec || !c99) I(TYULONG)
- if (c99) {
+ if (u || !dec || !longlongok) I(TYULONG)
+ if (longlongok) {
LL:
I(TYVLONG)
if (u || !dec) I(TYUVLONG)
@@ -247,6 +249,8 @@ parsenumlit(uvlong *outi, double *outf, const struct token *tk, bool ispp)
if (u) return TYUVLONG;
else if (n <= max4typ[TYVLONG-TYINT]) return TYVLONG;
}
+ if (ty >= TYVLONG && !longlongok)
+ warn(&tk->span, "'long long' in %M is an extension");
return ty;
}
}
@@ -482,7 +486,9 @@ Begin:
tmp[n++] = next(pr);
}
tmp[n] = 0;
- identkeyword(tk, tmp, n);
+ if (!identkeyword(tk, tmp, n))
+ warn(&(struct span) {{ idx, pr->chridx - idx, pr->fileid }},
+ "%'tk in %M is an extension", tk);
goto End;
}
}
diff --git a/main.c b/main.c
index 2404fd5..d56cd50 100644
--- a/main.c
+++ b/main.c
@@ -33,12 +33,14 @@ optparse(const char **file, const char **targ, char **args)
continue;
}
if ((x = optval(arg, "std"))) {
- if (!strcmp(x, "c89")) ccopt.cstd = STDC89;
+ if (!strcmp(x, "c89") || !strcmp(x, "c90")) ccopt.cstd = STDC89;
else if (!strcmp(x, "c99")) ccopt.cstd = STDC99;
else if (!strcmp(x, "c11")) ccopt.cstd = STDC11;
else if (!strcmp(x, "c2x")) ccopt.cstd = STDC23;
else if (!strcmp(x, "c23")) ccopt.cstd = STDC23;
else goto Bad;
+ } else if (!strcmp(arg, "pedantic")) {
+ ccopt.pedant = 1;
} else Bad: warn(NULL, "invalid option: %'s", arg-1);
}
}
@@ -61,6 +63,7 @@ main(int argc, char **argv)
atexit(flushstd);
detectcolor();
+ ccopt.cstd = STDC99; /* C99 by default */
optparse(&file, &targ, argv);
if (!file) {
efmt("usage: %s [options] <file>\n", *argv);
diff --git a/parse.c b/parse.c
index c33d162..2fc26be 100644
--- a/parse.c
+++ b/parse.c
@@ -602,7 +602,7 @@ callexpr(struct parser *pr, const struct span *span_, const struct expr *callee)
ty = mkfntype(mktype(TYINT), 0, NULL, NULL, /* kandr */ 1, 0),
.scls = SCEXTERN, .span = callee->span, .name = name
};
- (ccopt.cstd > STDC89 ? error : warn)(&callee->span, "call to undeclared function '%s'", name);
+ warn(&callee->span, "call to undeclared function '%s'", name);
((struct expr *)callee)->sym = putdecl(pr, &decl);
td = &typedata[ty.dat];
}
@@ -1816,7 +1816,7 @@ function(struct parser *pr, struct function *fn, const char **pnames, const stru
}
}
putdecl(pr, &arg);
- } else {
+ } else if (ccopt.cstd < STDC23) {
warn(&pspans[i], "missing name of parameter #%d", i+1);
}
}
@@ -1873,6 +1873,15 @@ buildagg(struct parser *pr, enum typetag tt, const char *name, int id)
uint siz = typesize(decl.ty);
uint off = isunion ? 0 : alignup(td.siz, align);
struct namedfield f = { decl.name, { decl.ty, off, .qual = decl.qual }};
+ if (!decl.name) {
+ if (!isagg(decl.ty) || ttypenames[typedata[decl.ty.dat].id]) {
+ warn(&decl.span, "declaration does not declare anything");
+ continue;
+ } else if (ccopt.cstd < STDC11 && ccopt.pedant) {
+ warn(&decl.span, "anonymous %s in %M is an extension",
+ decl.ty.t == TYUNION ? "union" : "struct");
+ }
+ }
vpush(&fld, f);
td.anyconst |= decl.qual & QCONST;
if (isagg(decl.ty)) {
@@ -1888,6 +1897,8 @@ buildagg(struct parser *pr, enum typetag tt, const char *name, int id)
}
} while (st.more);
}
+ if (td.flexi && ccopt.cstd < STDC99 && ccopt.pedant)
+ warn(&flexspan, "flexible array member in %M is an extension");
if (fld.n == 0) {
struct namedfield dummy = { "", { mktype(TYCHAR), 0 }};
error(&tk.span, "%s cannot have zero members", tag);
@@ -1923,7 +1934,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 parser *pr, const char *name)
+buildenum(struct parser *pr, const char *name, const struct span *span)
{
struct token tk;
vlong tymin, minv = 0;
@@ -1932,6 +1943,7 @@ buildenum(struct parser *pr, const char *name)
union type ty = mktype(td.backing);
struct span maxvspan;
vlong iota = 0;
+ bool somelonglong = 0;
inttyminmax(&tymin, &tymax, td.backing);
while (!match(pr, &tk, '}')) {
@@ -1954,6 +1966,7 @@ buildenum(struct parser *pr, const char *name)
}
while (issigned(ty) ? (iota > (vlong)tymax || iota < tymin) : iota > tymax)
inttyminmax(&tymin, &tymax, ++ty.t);
+ somelonglong |= ty.t >= TYVLONG;
if ((isunsigned(ty) || iota > 0) && iota > maxv)
maxv = iota, maxvspan = tk.span;
else if (issigned(ty) && iota < minv)
@@ -1980,9 +1993,12 @@ buildenum(struct parser *pr, const char *name)
}
}
if (!td.backing) {
- td.backing = TYVLONG;
- warn(&maxvspan, "some enumerators are too large for the enum's backing type (%ty)", mktype(td.backing));
+ td.backing = !somelonglong && ccopt.cstd == STDC89 && ccopt.pedant ? TYLONG : TYVLONG;
+ warn(&maxvspan, "enumerators exceed range of enum's backing type (%ty)", mktype(td.backing));
}
+ 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);
ty.backing = td.backing;
return ty;
@@ -2137,6 +2153,11 @@ declspec(struct declstate *st, struct parser *pr)
default:
if (!span.ex.len) span.ex = tk.span.ex;
goto End;
+ case TKW_BitInt: case TKW_Complex:
+ case TKW_Decimal128: case TKW_Decimal32:
+ case TKW_Decimal64: case TKW_Imaginary:
+ error(&tk.span, "%'tk is unsupported", &tk);
+ arith = arith ? arith : KINT;
}
if (!span.ex.len) span.ex = tk.span.ex;
joinspan(&span.ex, tk.span.ex);
@@ -2148,6 +2169,7 @@ End:
/* combining arith type specifiers and other types */
Bad:
error(&span, "invalid declaration specifier");
+ st->base = mktype(TYINT);
} else if (!st->base.t && arith) {
enum typetag t;
ioflush(&bstderr);
@@ -2155,9 +2177,10 @@ End:
t = TYFLOAT;
else if (arith == KDOUBLE)
t = TYDOUBLE;
- else if (arith == (KLONG | KDOUBLE))
+ else if (arith == (KLONG | KDOUBLE)) {
t = TYLDOUBLE;
- else if (arith == KBOOL)
+ error(&span, "`long double' is unsupported");
+ } else if (arith == KBOOL)
t = TYBOOL;
else if (arith == KCHAR)
t = TYCHAR;
@@ -2183,8 +2206,8 @@ End:
t = TYUVLONG;
else
goto Bad;
- st->base = mktype(t);
- } else if (!st->base.t && ccopt.cstd < STDC99) {
+ st->base = mktype(t ? t : TYINT);
+ } else if (!st->base.t && ccopt.cstd < STDC23) {
warn(&span, "type implicitly declared as int");
st->base = mktype(TYINT);
} else if (!st->base.t)
diff --git a/test.c b/test.c
index 92ab2f2..40b59e6 100644
--- a/test.c
+++ b/test.c
@@ -80,13 +80,18 @@ enum ball {
X = 2147483647,
Y,
Z,
- W = ~0ul
+ W = ~0ull
};
enum ball x;
-main(t) {
- putc(t + 1, t + 2);
+_Bool t(int t)
+{
+ return t;
}
+struct f{
+ union { int x,y;} ;
+ char flex[];
+};
//