scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 9347ef0944f6076bd5f016e85b2627f519bd51a9
parent 928508eccd9699691f7ef41f508b669953e60b06
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 28 Sep 2015 10:32:18 +0200

Merge remote-tracking branch 'origin/master'

Conflicts:
	cc1/tests/test001.c
	cc1/tests/test004.c
	cc1/tests/test005.c
	cc1/tests/test006.c
	cc1/tests/test007.c
	cc1/tests/test008.c
	cc1/tests/test009.c
	cc1/tests/test010.c
	cc1/tests/test011.c
	cc1/tests/test012.c
	cc1/tests/test017.c
	cc1/tests/test018.c

Diffstat:
Makefile | 3+--
cc1/cc1.h | 3++-
cc1/code.c | 6++++--
cc1/cpp.c | 15+++++++--------
cc1/decl.c | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
cc1/expr.c | 47+++++++++++++++++++++++++++++++++++------------
cc1/symbol.c | 18+++++++++---------
cc1/tests/test001.c | 4++--
cc1/tests/test004.c | 2+-
cc1/tests/test005.c | 2+-
cc1/tests/test006.c | 2+-
cc1/tests/test007.c | 2+-
cc1/tests/test008.c | 2+-
cc1/tests/test009.c | 2+-
cc1/tests/test010.c | 2+-
cc1/tests/test011.c | 2+-
cc1/tests/test012.c | 2+-
cc1/tests/test017.c | 2+-
cc1/tests/test018.c | 2+-
cc1/tests/test025.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/tests/test026.c | 37+++++++++++++++++++++++++++++++++++++
cc1/tests/test027.c | 26++++++++++++++++++++++++++
cc1/tests/test028.c | 22++++++++++++++++++++++
cc1/tests/test029.c | 36++++++++++++++++++++++++++++++++++++
cc1/types.c | 9++++++++-
inc/cc.h | 1+
26 files changed, 326 insertions(+), 78 deletions(-)

diff --git a/Makefile b/Makefile @@ -4,8 +4,7 @@ include config.mk SUBDIRS = \ lib \ - cc1 \ - cc2 + cc1 all clean: @echo scc build options: diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -416,4 +416,5 @@ extern Type *voidtype, *pvoidtype, *booltype, *ushortype, *shortype, *longtype, *ulongtype, *ullongtype, *llongtype, - *floattype, *doubletype, *ldoubletype; + *floattype, *doubletype, *ldoubletype, + *ellipsistype; diff --git a/cc1/code.c b/cc1/code.c @@ -359,9 +359,11 @@ emitfun(unsigned op, void *arg) n = sym->type->n.elem; for (sp = sym->u.pars; n-- > 0; ++sp) { + if ((sym = *sp) == NULL) + continue; /* enable non used warnings in parameters */ - (*sp)->flags &= ~ISUSED; - emit(ODECL, *sp); + sym->flags &= ~ISUSED; + emit(ODECL, sym); } puts("\\"); } diff --git a/cc1/cpp.c b/cc1/cpp.c @@ -26,13 +26,7 @@ int disexpand; static Symbol * defmacro(char *s) { - Symbol *sym; - - strcpy(yytext, s); - sym = lookup(NS_CPP, yytext); - /* FIXME: We have a problem here */ - sym->flags |= ISDECLARED; - return sym; + return install(NS_CPP, lookup(NS_CPP, s)); } void @@ -73,6 +67,8 @@ nextcpp(void) if (yylen + 1 > arglen) error("argument overflow invoking macro \"%s\"", macroname); + if (yytoken == IDEN) + yylval.sym->flags |= ISUSED; memcpy(argp, yytext, yylen); argp += yylen; *argp++ = ' '; @@ -253,6 +249,7 @@ static int getpars(Symbol *args[NR_MACROARG]) { int n = -1; + Symbol *sym; if (!accept('(')) return n; @@ -269,7 +266,9 @@ getpars(Symbol *args[NR_MACROARG]) cpperror("macro arguments must be identifiers"); return NR_MACROARG; } - args[n++] = yylval.sym; + sym = install(NS_IDEN, yylval.sym); + sym->flags |= ISUSED; + args[n++] = sym; next(); } while (accept(',')); expect(')'); diff --git a/cc1/decl.c b/cc1/decl.c @@ -126,9 +126,6 @@ parameter(struct decl *dcl) sym->type = tp; - if (n == -1) - error("'void' must be the only parameter"); - switch (dcl->sclass) { case STATIC: case EXTERN: @@ -145,32 +142,31 @@ parameter(struct decl *dcl) switch (tp->op) { case VOID: - if (n != 0) - error("incorrect void parameter"); - if (dcl->sclass) - error("void as unique parameter may not be qualified"); + if (n != 0) { + errorp("incorrect void parameter"); + return NULL; + } funtp->n.elem = -1; + if (dcl->sclass) + errorp("void as unique parameter may not be qualified"); return NULL; case ARY: tp = mktype(tp->type, PTR, 0, NULL); break; case FTN: - error("incorrect function type for a function parameter"); + errorp("incorrect function type for a function parameter"); + return NULL; } if (name) { - if ((sym = install(NS_IDEN, sym)) == NULL) - error("redefinition of parameter '%s'", name); + if ((sym = install(NS_IDEN, sym)) == NULL) { + errorp("redefinition of parameter '%s'", name); + return NULL; + } } sym->type = tp; sym->flags |= ISUSED; /* avoid non used warnings in prototypes */ - if (n == NR_FUNPARAM) - error("too much parameters in function definition"); - funtp->p.pars = xrealloc(funtp->p.pars, ++n * sizeof(Type *)); - funtp->p.pars[n-1] = tp; - funtp->n.elem = n; - return sym; } @@ -182,27 +178,62 @@ static Symbol *dodcl(int rep, static void fundcl(struct declarators *dp) { - Type type = {.n = {.elem = -1}, .p = {.pars= NULL}}; - Symbol *syms[NR_FUNPARAM], **sp; + Type type, *types[NR_FUNPARAM], *tp; + Symbol *syms[NR_FUNPARAM], *sym; TINT size; - Symbol *pars = NULL; + Symbol *pars; + int toomany = 0, toovoid = 0; pushctx(); expect('('); + type.n.elem = 0; - if (!accept(')')) { - type.n.elem = 0; - sp = syms; - do - *sp++ = dodcl(0, parameter, NS_IDEN, &type); - while (accept(',')); + if (yytoken == ')') { + ++type.n.elem; + syms[0] = NULL; + types[0] = ellipsistype; + goto end_params; + } + do { + if (type.n.elem == -1) { + if (!toovoid) + errorp("'void' must be the only parameter"); + toovoid = 1; + } + if (!accept(ELLIPSIS)) { + sym = dodcl(0, parameter, NS_IDEN, &type); + if (!sym) + continue; + tp = sym->type; + } else { + if (type.n.elem == 0) + errorp("a named argument is requiered before '...'"); + tp = ellipsistype; + sym = NULL; + } + if (type.n.elem == NR_FUNPARAM) { + if (toomany) + continue; + errorp("too much parameters in function definition"); + toomany = 1; + } else if (type.n.elem >= 0) { + syms[type.n.elem] = sym; + types[type.n.elem] = tp; + ++type.n.elem; + } + } while (tp != ellipsistype && accept(',')); - expect(')'); +end_params: + expect(')'); - if (type.n.elem != -1) { - size = type.n.elem * sizeof(Symbol *); - pars = memcpy(xmalloc(size), syms, size); - } + if (type.n.elem > 0) { + size = type.n.elem * sizeof(Symbol *); + pars = memcpy(xmalloc(size), syms, size); + size = type.n.elem * sizeof(Type *); + type.p.pars = memcpy(xmalloc(size), types, size); + } else { + pars = NULL; + type.p.pars = NULL; } push(dp, FTN, type.n.elem, type.p.pars, pars); } diff --git a/cc1/expr.c b/cc1/expr.c @@ -535,7 +535,7 @@ arguments(Node *np) int toomany;; TINT n; Node *par = NULL, *arg; - Type **targs, *tp = np->type; + Type *argtype, **targs, *tp = np->type; if (tp->op == PTR && tp->type->op == FTN) { np = content(OPTR, np); @@ -554,21 +554,40 @@ arguments(Node *np) do { arg = decay(assign()); - if (--n < 0 && !toomany) { - errorp("too many arguments in function call"); + argtype = *targs; + if (argtype == ellipsistype) { + n = 0; + switch (arg->type->op) { + case INT: + arg = promote(arg); + break; + case FLOAT: + if (arg->type == floattype) + arg = convert(arg, doubletype, 1); + break; + } + if (arg->type->op == INT) + arg = promote(arg); + par = node(OPAR, arg->type, par, arg); + continue; + } + if (--n < 0) { + if (!toomany) + errorp("too many arguments in function call"); toomany = 1; continue; } - if ((arg = convert(arg, *targs++, 0)) != NULL) { + ++targs; + if ((arg = convert(arg, argtype, 0)) != NULL) { par = node(OPAR, arg->type, par, arg); continue; } errorp("incompatible type for argument %d in function call", - tp->n.elem - n + 1); + tp->n.elem - n + 1); } while (accept(',')); no_pars: - if (n > 0) + if (n > 0 && *targs != ellipsistype) errorp("too few arguments in function call"); expect(')'); @@ -1071,17 +1090,19 @@ initlist(Symbol *sym, Type *tp) } switch (tp->op) { case ARY: - if (tp->defined && n >= tp->n.elem && !toomany) { + if (tp->defined && n >= tp->n.elem) { + if (!toomany) + warn("excess elements in array initializer"); toomany = 1; - warn("excess elements in array initializer"); sym = NULL; } newtp = tp->type; break; case STRUCT: - if (n >= tp->n.elem && !toomany) { + if (n >= tp->n.elem) { + if (!toomany) + warn("excess elements in struct initializer"); toomany = 1; - warn("excess elements in struct initializer"); sym = NULL; } else { sym = tp->p.fields[n]; @@ -1091,9 +1112,11 @@ initlist(Symbol *sym, Type *tp) default: newtp = tp; warn("braces around scalar initializer"); - if (n > 0 && !toomany) { + if (n > 0) { + if (!toomany) + warn("excess elements in scalar initializer"); toomany = 1; - warn("excess elements in scalar initializer"); + sym = NULL; } break; } diff --git a/cc1/symbol.c b/cc1/symbol.c @@ -29,15 +29,15 @@ dumpstab(char *msg) continue; fprintf(stderr, "%d", (int) (bp - htab)); for (sym = *bp; sym; sym = sym->hash) - fprintf(stderr, "->[%d,%d:%s]", - sym->ns, sym->ctx, sym->name); + fprintf(stderr, "->[%d,%d:'%s'=%p]", + sym->ns, sym->ctx, sym->name, (void *) sym); putc('\n', stderr); } fputs("head:", stderr); for (sym = head; sym; sym = sym->next) { - fprintf(stderr, "->[%d,%d:'%s']", + fprintf(stderr, "->[%d,%d:'%s'=%p]", sym->ns, sym->ctx, - (sym->name) ? sym->name : ""); + (sym->name) ? sym->name : "", (void *) sym); } putc('\n', stderr); } @@ -58,6 +58,8 @@ unlinkhash(Symbol *sym) { Symbol **h, *p, *prev; + if ((sym->flags & ISDECLARED) == 0) + return; h = &htab[hash(sym->name)]; for (prev = p = *h; p != sym; prev = p, p = p->hash) /* nothing */; @@ -248,9 +250,7 @@ lookup(int ns, char *name) if (sns == NS_KEYWORD || sns == NS_CPP || sns == ns) return sym; } - sym = allocsym(ns, name); - - return sym; + return allocsym(ns, name); } void @@ -279,9 +279,9 @@ nextsym(Symbol *sym, int ns) for (p = sym->hash; p; p = p->hash) { t = p->name; if (c == *t && !strcmp(s, t)) - return sym; + return p; } - return linkhash(allocsym(ns, s)); + return allocsym(ns, s); } Symbol * diff --git a/cc1/tests/test001.c b/cc1/tests/test001.c @@ -2,7 +2,7 @@ name: TEST001 description: Basic hello world test output: -F3 I P +F3 I P E X4 F3 printf F5 I G6 F5 main @@ -13,7 +13,7 @@ G6 F5 main } */ -int printf(char *fmt); +int printf(char *fmt, ...); int main(void) diff --git a/cc1/tests/test004.c b/cc1/tests/test004.c @@ -2,7 +2,7 @@ name: TEST004 description: Test integer operations output: -F1 I +F1 I E G2 F1 main { \ diff --git a/cc1/tests/test005.c b/cc1/tests/test005.c @@ -2,7 +2,7 @@ name: TEST005 description: Test unary integer operations output: -F1 I +F1 I E G2 F1 main { \ diff --git a/cc1/tests/test006.c b/cc1/tests/test006.c @@ -6,7 +6,7 @@ test006.c:6: warning: conditional expression is constant test006.c:8: warning: conditional expression is constant test006.c:11: warning: conditional expression is constant G1 K c -F2 I +F2 I E G3 F2 main { \ diff --git a/cc1/tests/test007.c b/cc1/tests/test007.c @@ -2,7 +2,7 @@ name: TEST007 description: basic while test output: -F1 I +F1 I E G2 F1 main { \ diff --git a/cc1/tests/test008.c b/cc1/tests/test008.c @@ -2,7 +2,7 @@ name: TEST008 description: Basic do while loop output: -F1 I +F1 I E G2 F1 main { \ diff --git a/cc1/tests/test009.c b/cc1/tests/test009.c @@ -2,7 +2,7 @@ name: TEST009 description: Basic test for loops output: -F1 I +F1 I E G2 F1 main { \ diff --git a/cc1/tests/test010.c b/cc1/tests/test010.c @@ -5,7 +5,7 @@ output: test010.c:9: warning: conditional expression is constant test010.c:11: warning: conditional expression is constant test010.c:31: warning: conditional expression is constant -F1 I +F1 I E G2 F1 main { \ diff --git a/cc1/tests/test011.c b/cc1/tests/test011.c @@ -4,7 +4,7 @@ description: Basic test for goto output: test011.c:14: warning: 'foo' defined but not used test011.c:14: warning: 'start' defined but not used -F1 I +F1 I E G2 F1 main { \ diff --git a/cc1/tests/test012.c b/cc1/tests/test012.c @@ -3,7 +3,7 @@ name: TEST012 description: Basic switch test output: test012.c:39: warning: 'foo' defined but not used -F1 I +F1 I E G2 F1 main { \ diff --git a/cc1/tests/test017.c b/cc1/tests/test017.c @@ -2,7 +2,7 @@ name: TEST017 description: Basic test about pointers and structs output: -F9 I +F9 I E G10 F9 main { \ diff --git a/cc1/tests/test018.c b/cc1/tests/test018.c @@ -2,7 +2,7 @@ name: TEST018 description: Basic test for arrays output: -F1 I +F1 I E G2 F1 main { \ diff --git a/cc1/tests/test025.c b/cc1/tests/test025.c @@ -0,0 +1,64 @@ + +/* +name: TEST025 +descritpion: Test of ifdef and ifndef +output: +G1 I a +G2 I b +G3 I c +G4 I d +G5 I _1 +G6 I _2 +G7 I e_ +G8 I f_ +G9 I h +G10 I i +*/ + +#define FOO + +#ifdef FOO + int a; + int b; + #undef FOO + #ifndef FOO + int c; + int d; + #else + int e; + int f; + #endif + int _1; + int _2; + #ifdef FOO + int c_; + int d_; + #else + int e_; + int f_; + #endif + int h; + int i; +#else + int j; + int k; + #ifdef FOO + int l; + int m; + #else + int n; + int o; + #endif + int p; + int q; + #ifndef FOO + int r; + int s; + #else + int t; + int u; + #endif + int v; + int w; +#endif + diff --git a/cc1/tests/test026.c b/cc1/tests/test026.c @@ -0,0 +1,37 @@ + +/* +name: TEST026 +descritpion: Test of predefined cpp macros +output: +F2 I +G3 F2 main +{ +\ +A4 I y +A6 P p + A6 "746573743032362E63 'P :P + A4 #I1E :I + A4 #I1 :I + A4 #I1 :I + A4 #I1 :I + A4 #I1 :I +} +*/ + +#define x(y) (y) + +int +main(void) +{ + int y; + char *p; + + p = __FILE__; + y = __LINE__; +/* p = __DATE__; __DATE__ generates different value each time */ + y = __STDC__; +/* p = __TIME__; __TIME__ generates different value each time */ + y = __STDC_HOSTED__; + y = __SCC__; + y = x(1); +} diff --git a/cc1/tests/test027.c b/cc1/tests/test027.c @@ -0,0 +1,26 @@ + +/* +name: TEST027 +description: Test of cpp stringizer +output: +F2 I +G3 F2 main +{ +\ +A5 P p + A5 "68656C6C6F20697320626574746572207468616E20627965 'P :P + r A5 @K gK +} +*/ + +#define x(y) #y + +int +main(void) +{ + char *p; + p = x(hello) " is better than bye"; + + return *p; +} + diff --git a/cc1/tests/test028.c b/cc1/tests/test028.c @@ -0,0 +1,22 @@ + +/* +name: TEST028 +description: Test of reinterpretation in define +output: +F5 P +G6 F5 foo +{ +\ + r "6869 'P +} +*/ + + +#define M(x) x +#define A(a,b) a(b) + +char * +foo(void) +{ + return A(M,"hi"); +} diff --git a/cc1/tests/test029.c b/cc1/tests/test029.c @@ -0,0 +1,36 @@ + +/* +name: TEST029 +description: Test of nested expansion and refusing macro without arguments +comments: f(2) will expand to 2*g, which will expand to 2*f, and in this + moment f will not be expanded because the macro definition is + a function alike macro, and in this case there is no arguments. +output: +test029.c:34: error: redefinition of 'f1' +F2 I +G3 F2 f1 +{ +\ +A4 I f + A4 #I2 *I +} +test029.c:35: error: 'f' undeclared +*/ + + +#define f(a) a*g +#define g f + +int +f1(void) +{ + int f; + + f(2); +} + +int +f1(void) +{ + f(2); +} diff --git a/cc1/types.c b/cc1/types.c @@ -241,6 +241,12 @@ static Type types[] = { .align = 1, .n.rank = RANK_UINT, .printed = 1 + }, + { /* 18 = ellipsis */ + .op = ELLIPSIS, + .letter = L_ELLIPSIS, + .defined = 1, + .printed = 1 } }; @@ -252,7 +258,8 @@ Type *voidtype = &types[0], *pvoidtype = &types[1], *longtype = &types[10], *ulongtype = &types[11], *ullongtype = &types[12], *llongtype = &types[13], *floattype = &types[14], *doubletype = &types[15], - *ldoubletype = &types[16], *sizettype = &types[17]; + *ldoubletype = &types[16], *sizettype = &types[17], + *ellipsistype = &types[18]; static Symbol dummy0 = {.u.i = 0, .type = &types[9]}, dummy1 = {.u.i = 1, .type = &types[9]}; diff --git a/inc/cc.h b/inc/cc.h @@ -21,6 +21,7 @@ typedef unsigned bool; #define L_UINT16 'N' #define L_UINT32 'Z' #define L_UINT64 'O' +#define L_ELLIPSIS 'E' #define L_VOID '0' #define L_POINTER 'P'