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:
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'