Add a return type to a function

This commit is contained in:
Rui Ueyama 2019-08-11 09:53:31 +09:00
parent 1cbe40ad02
commit 0ac8705115
5 changed files with 51 additions and 11 deletions

View File

@ -41,6 +41,7 @@ struct Token {
void error(char *fmt, ...);
void error_at(char *loc, char *fmt, ...);
void error_tok(Token *tok, char *fmt, ...);
void warn_tok(Token *tok, char *fmt, ...);
Token *peek(char *s);
Token *consume(char *op);
Token *consume_ident(void);
@ -171,6 +172,7 @@ typedef enum {
TY_PTR,
TY_ARRAY,
TY_STRUCT,
TY_FUNC,
} TypeKind;
struct Type {
@ -180,6 +182,7 @@ struct Type {
Type *base; // pointer or array
int array_len; // array
Member *members; // struct
Type *return_ty; // function
};
// Struct member
@ -199,6 +202,7 @@ bool is_integer(Type *ty);
int align_to(int n, int align);
Type *pointer_to(Type *base);
Type *array_of(Type *base, int size);
Type *func_type(Type *return_ty);
void add_type(Node *node);
//

34
parse.c
View File

@ -122,14 +122,16 @@ static Var *new_lvar(char *name, Type *ty) {
return var;
}
static Var *new_gvar(char *name, Type *ty) {
static Var *new_gvar(char *name, Type *ty, bool emit) {
Var *var = new_var(name, ty, false);
push_scope(name)->var = var;
VarList *vl = calloc(1, sizeof(VarList));
vl->var = var;
vl->next = globals;
globals = vl;
if (emit) {
VarList *vl = calloc(1, sizeof(VarList));
vl->var = var;
vl->next = globals;
globals = vl;
}
return var;
}
@ -357,8 +359,12 @@ static Function *function(void) {
Type *ty = basetype();
char *name = NULL;
declarator(ty, &name);
ty = declarator(ty, &name);
// Add a function type to the scope
new_gvar(name, func_type(ty), false);
// Construct a function object
Function *fn = calloc(1, sizeof(Function));
fn->name = name;
expect("(");
@ -371,6 +377,7 @@ static Function *function(void) {
return NULL;
}
// Read function body
Node head = {};
Node *cur = &head;
expect("{");
@ -392,7 +399,7 @@ static void global_var(void) {
ty = declarator(ty, &name);
ty = type_suffix(ty);
expect(";");
new_gvar(name, ty);
new_gvar(name, ty, true);
}
// declaration = basetype declarator type-suffix ("=" expr)? ";"
@ -764,6 +771,17 @@ static Node *primary(void) {
Node *node = new_node(ND_FUNCALL, tok);
node->funcname = strndup(tok->str, tok->len);
node->args = func_args();
add_type(node);
VarScope *sc = find_var(tok);
if (sc) {
if (!sc->var || sc->var->ty->kind != TY_FUNC)
error_tok(tok, "not a function");
node->ty = sc->var->ty->return_ty;
} else {
warn_tok(node->tok, "implicit declaration of a function");
node->ty = int_type;
}
return node;
}
@ -779,7 +797,7 @@ static Node *primary(void) {
token = token->next;
Type *ty = array_of(char_type, tok->cont_len);
Var *var = new_gvar(new_label(), ty);
Var *var = new_gvar(new_label(), ty, true);
var->contents = tok->contents;
var->cont_len = tok->cont_len;
return new_var_node(var, tok);

6
tests
View File

@ -54,6 +54,10 @@ int sub_long(long a, long b, long c) {
return a - b - c;
}
int *g1_ptr() {
return &g1;
}
int fib(int x) {
if (x<=1)
return 1;
@ -274,6 +278,8 @@ int main() {
assert(3, ({ int *x[3]; int y; x[0]=&y; y=3; x[0][0]; }), "int *x[3]; int y; x[0]=&y; y=3; x[0][0];");
assert(4, ({ int x[3]; int (*y)[3]=x; y[0][0]=4; y[0][0]; }), "int x[3]; int (*y)[3]=x; y[0][0]=4; y[0][0];");
assert(3, *g1_ptr(), "*g1_ptr()");
printf("OK\n");
return 0;
}

View File

@ -13,7 +13,7 @@ void error(char *fmt, ...) {
exit(1);
}
// Reports an error message in the following format and exit.
// Reports an error message in the following format.
//
// foo.c:10: x = y + 1;
// ^ <error message here>
@ -43,7 +43,6 @@ static void verror_at(char *loc, char *fmt, va_list ap) {
fprintf(stderr, "^ ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
exit(1);
}
// Reports an error location and exit.
@ -51,6 +50,7 @@ void error_at(char *loc, char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
verror_at(loc, fmt, ap);
exit(1);
}
// Reports an error location and exit.
@ -58,6 +58,13 @@ void error_tok(Token *tok, char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
verror_at(tok->str, fmt, ap);
exit(1);
}
void warn_tok(Token *tok, char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
verror_at(tok->str, fmt, ap);
}
// Consumes the current token if it matches `op`.

7
type.c
View File

@ -36,6 +36,12 @@ Type *array_of(Type *base, int len) {
return ty;
}
Type *func_type(Type *return_ty) {
Type *ty = new_type(TY_FUNC, 1, 1);
ty->return_ty = return_ty;
return ty;
}
void add_type(Node *node) {
if (!node || node->ty)
return;
@ -63,7 +69,6 @@ void add_type(Node *node) {
case ND_NE:
case ND_LT:
case ND_LE:
case ND_FUNCALL:
case ND_NUM:
node->ty = long_type;
return;