Add extern

This commit is contained in:
Rui Ueyama 2019-08-21 08:14:15 +09:00
parent 342e5b8b13
commit f92ef39970
4 changed files with 30 additions and 10 deletions

View File

@ -9,7 +9,8 @@ $(OBJS): chibi.h
test: chibicc
./chibicc tests > tmp.s
echo 'int char_fn() { return 257; } int static_fn() { return 5; }' | \
echo 'int ext1; int *ext2; int char_fn() { return 257; }' \
'int static_fn() { return 5; }' | \
gcc -xc -c -o tmp2.o -
gcc -static -o tmp tmp.s tmp2.o
./tmp

25
parse.c
View File

@ -168,6 +168,7 @@ static char *new_label(void) {
typedef enum {
TYPEDEF = 1 << 0,
STATIC = 1 << 1,
EXTERN = 1 << 2,
} StorageClass;
static Function *function(void);
@ -277,7 +278,7 @@ static Type *basetype(StorageClass *sclass) {
Token *tok = token;
// Handle storage class specifiers.
if (peek("typedef") || peek("static")) {
if (peek("typedef") || peek("static") || peek("extern")) {
if (!sclass)
error_tok(tok, "storage class specifier is not allowed");
@ -285,9 +286,11 @@ static Type *basetype(StorageClass *sclass) {
*sclass |= TYPEDEF;
else if (consume("static"))
*sclass |= STATIC;
else if (consume("extern"))
*sclass |= EXTERN;
if (*sclass & (*sclass - 1))
error_tok(tok, "typedef and static may not be used together");
error_tok(tok, "typedef, static and extern may not be used together");
continue;
}
@ -850,16 +853,21 @@ static void global_var(void) {
return;
}
Var *var = new_gvar(name, ty, true);
Var *var = new_gvar(name, ty, sclass != EXTERN);
if (!consume("=")) {
if (ty->is_incomplete)
error_tok(tok, "incomplete type");
if (sclass == EXTERN) {
expect(";");
return;
}
var->initializer = gvar_initializer(ty);
if (consume("=")) {
var->initializer = gvar_initializer(ty);
expect(";");
return;
}
if (ty->is_incomplete)
error_tok(tok, "incomplete type");
expect(";");
}
@ -1082,7 +1090,8 @@ static Node *read_expr_stmt(void) {
static bool is_typename(void) {
return peek("void") || peek("_Bool") || peek("char") || peek("short") ||
peek("int") || peek("long") || peek("enum") || peek("struct") ||
peek("typedef") || peek("static") || find_typedef(token);
peek("typedef") || peek("static") || peek("extern") ||
find_typedef(token);
}
static Node *stmt(void) {

9
tests
View File

@ -42,6 +42,9 @@ int *g25=&g24;
int g26[3] = {1, 2, 3};
int *g27 = g26 + 1;
extern int ext1;
extern int *ext2;
int assert(long expected, long actual, char *code) {
if (expected == actual) {
printf("%s => %ld\n", code, actual);
@ -617,6 +620,12 @@ int main() {
assert(3, *g25, "*g25");
assert(2, *g27, "*g27");
ext1 = 5;
assert(5, ext1, "ext1");
ext2 = &ext1;
assert(5, *ext2, "*ext2");
printf("OK\n");
return 0;
}

View File

@ -150,7 +150,8 @@ static char *starts_with_reserved(char *p) {
static char *kw[] = {"return", "if", "else", "while", "for", "int",
"char", "sizeof", "struct", "typedef", "short",
"long", "void", "_Bool", "enum", "static", "break",
"continue", "goto", "switch", "case", "default"};
"continue", "goto", "switch", "case", "default",
"extern"};
for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++) {
int len = strlen(kw[i]);