mirror of https://github.com/rui314/chibicc
Add extern
This commit is contained in:
parent
342e5b8b13
commit
f92ef39970
3
Makefile
3
Makefile
|
@ -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
25
parse.c
|
@ -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
9
tests
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
Loading…
Reference in New Issue