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 test: chibicc
./chibicc tests > tmp.s ./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 -xc -c -o tmp2.o -
gcc -static -o tmp tmp.s tmp2.o gcc -static -o tmp tmp.s tmp2.o
./tmp ./tmp

25
parse.c
View File

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

9
tests
View File

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

View File

@ -150,7 +150,8 @@ static char *starts_with_reserved(char *p) {
static char *kw[] = {"return", "if", "else", "while", "for", "int", static char *kw[] = {"return", "if", "else", "while", "for", "int",
"char", "sizeof", "struct", "typedef", "short", "char", "sizeof", "struct", "typedef", "short",
"long", "void", "_Bool", "enum", "static", "break", "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++) { for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++) {
int len = strlen(kw[i]); int len = strlen(kw[i]);