mirror of https://github.com/rui314/chibicc
Add a return type to a function
This commit is contained in:
parent
1cbe40ad02
commit
0ac8705115
4
chibi.h
4
chibi.h
|
@ -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
34
parse.c
|
@ -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
6
tests
|
@ -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;
|
||||
}
|
||||
|
|
11
tokenize.c
11
tokenize.c
|
@ -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
7
type.c
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue