scc

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

commit e1dec2bf0bdbd5b8f8cea993a48093bd411cd4ba
parent 64122b83087c57a0fc5eb7a272816212f4994ab1
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed,  6 Aug 2014 11:43:18 +0200

Make explicit checks of type in castings and sizeof

The grammar we are using doesn't allow specify a function type
name, but C standard allows it. This is a desviation from the
standard, which is obvius wrong here. Accepting function types
in typenames (or abstract declarators) make the grammar ambiguous
because it is impossible difference between:

	(int (f))  -> function returning int with one parameter of type f
	(int (f))  -> integer variable f

Function type names are stupid, because they are used as an alias
of the function pointer types, but it makes stupid that something
like sizeof(int (int)) is not allowed (because here should be
understood as the size of a function), but it is allowed f(int (int))
because it is understood as a parameter with function pointer type.

Although we don't allow function types names, we add checks against
function types in sizeof and casting, becaues id adds documentation
to the code and prepare it for the future.

Diffstat:
cc1/code.c | 2++
cc1/decl.c | 16+++++++---------
cc1/expr.c | 17+++++++++++------
3 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/cc1/code.c b/cc1/code.c @@ -305,6 +305,8 @@ sizeofcode(Type *tp) { if (!tp->defined) error("invalid use of indefined type"); + if (tp->op == FTN) + error("sizeof of a function"); return node(emitsizeof, inttype, TYP(tp), 0); } diff --git a/cc1/decl.c b/cc1/decl.c @@ -23,7 +23,7 @@ struct dcldata { }; static struct dcldata * -enqueue(struct dcldata *dp, uint8_t op, union dclunion u) +queue(struct dcldata *dp, uint8_t op, union dclunion u) { if (dp->op == 255) error("too much declarators"); @@ -32,14 +32,12 @@ enqueue(struct dcldata *dp, uint8_t op, union dclunion u) return dp + 1; } -static struct dcldata *declarator0(struct dcldata *dp); - static struct dcldata * arydcl(struct dcldata *dp) { expect('['); expect(']'); - return enqueue(dp, ARY, (union dclunion) {.nelem = 0}); + return queue(dp, ARY, (union dclunion) {.nelem = 0}); } static Type *parameter(void); @@ -79,7 +77,7 @@ fundcl(struct dcldata *dp) ret: expect(')');; - return enqueue(dp, FTN, (union dclunion) {.pars = fp}); + return queue(dp, FTN, (union dclunion) {.pars = fp}); } static Symbol * @@ -95,6 +93,8 @@ newiden(void) return sym; } +static struct dcldata *declarator0(struct dcldata *dp); + static struct dcldata * directdcl(struct dcldata *dp) { @@ -108,7 +108,7 @@ directdcl(struct dcldata *dp) sym = newiden(); else sym = install("", NS_IDEN); - dp = enqueue(dp, IDEN, (union dclunion) {.sym = sym}); + dp = queue(dp, IDEN, (union dclunion) {.sym = sym}); } for (;;) { @@ -133,7 +133,7 @@ declarator0(struct dcldata *dp) dp = directdcl(dp); while (n--) - dp = enqueue(dp, PTR, (union dclunion) {}); + dp = queue(dp, PTR, (union dclunion) {}); return dp; } @@ -490,8 +490,6 @@ typename(void) tp = specifier(&sclass); if (sclass) error("class storage in type name"); - if (yytoken == '(') - error("type name specifies a function type"); sym = declarator(tp, ID_FORBIDDEN); return sym->type; } diff --git a/cc1/expr.c b/cc1/expr.c @@ -551,13 +551,18 @@ cast2(void) case TQUALIFIER: case TYPE: tp = typename(); expect(')'); - if (tp->op == ARY) + switch (tp->op) { + case ARY: error("cast specify an array type"); - if ((np1 = eval(cast())) == NULL) - unexpected(); - if ((np2 = convert(np1, tp, 1)) == NULL) - error("bad type convertion requested"); - np2->b.lvalue = np1->b.lvalue; + case FTN: + error("cast specify a function type"); + default: + if ((np1 = eval(cast())) == NULL) + unexpected(); + if ((np2 = convert(np1, tp, 1)) == NULL) + error("bad type convertion requested"); + np2->b.lvalue = np1->b.lvalue; + } break; default: np2 = unary();