Add compound literals

This commit is contained in:
Rui Ueyama 2019-08-24 07:45:14 +09:00
parent a4a0a84848
commit a554dff9d1
3 changed files with 78 additions and 6 deletions

View File

@ -16,6 +16,9 @@ static void gen(Node *node);
static void gen_addr(Node *node) {
switch (node->kind) {
case ND_VAR: {
if (node->init)
gen(node->init);
Var *var = node->var;
if (var->is_local) {
printf(" lea rax, [rbp-%d]\n", var->offset);
@ -216,6 +219,12 @@ static void gen(Node *node) {
printf(" add rsp, 8\n");
return;
case ND_VAR:
if (node->init)
gen(node->init);
gen_addr(node);
if (node->ty->kind != TY_ARRAY)
load(node->ty);
return;
case ND_MEMBER:
gen_addr(node);
if (node->ty->kind != TY_ARRAY)

41
parse.c
View File

@ -205,6 +205,7 @@ static Node *mul(void);
static Node *cast(void);
static Node *unary(void);
static Node *postfix(void);
static Node *compound_literal(void);
static Node *primary(void);
// Determine whether the next top-level item is a function
@ -1580,11 +1581,13 @@ static Node *cast(void) {
if (is_typename()) {
Type *ty = type_name();
expect(")");
if (!consume("{")) {
Node *node = new_unary(ND_CAST, cast(), tok);
add_type(node->lhs);
node->ty = ty;
return node;
}
}
token = tok;
}
@ -1637,11 +1640,17 @@ static Node *struct_ref(Node *lhs) {
return node;
}
// postfix = primary ("[" expr "]" | "." ident | "->" ident | "++" | "--")*
// postfix = compound-literal
// | primary ("[" expr "]" | "." ident | "->" ident | "++" | "--")*
static Node *postfix(void) {
Node *node = primary();
Token *tok;
Node *node = compound_literal();
if (node)
return node;
node = primary();
for (;;) {
if (tok = consume("[")) {
// x[y] is short for *(x+y)
@ -1677,6 +1686,34 @@ static Node *postfix(void) {
}
}
// compound-literal = "(" type-name ")" "{" (gvar-initializer | lvar-initializer) "}"
static Node *compound_literal(void) {
Token *tok = token;
if (!consume("(") || !is_typename()) {
token = tok;
return NULL;
}
Type *ty = type_name();
expect(")");
if (!peek("{")) {
token = tok;
return NULL;
}
if (scope_depth == 0) {
Var *var = new_gvar(new_label(), ty, true);
var->initializer = gvar_initializer(ty);
return new_var_node(var, tok);
}
Var *var = new_lvar(new_label(), ty);
Node *node = new_var_node(var, tok);
node->init = lvar_initializer(var, tok);
return node;
}
// stmt-expr = "(" "{" stmt stmt* "}" ")"
//
// Statement expression is a GNU C extension.

26
tests
View File

@ -42,6 +42,22 @@ int *g25=&g24;
int g26[3] = {1, 2, 3};
int *g27 = g26 + 1;
typedef struct Tree {
int val;
struct Tree *lhs;
struct Tree *rhs;
} Tree;
Tree *tree = &(Tree){
1,
&(Tree){
2,
&(Tree){ 3, 0, 0 },
&(Tree){ 4, 0, 0 },
},
0,
};
extern int ext1;
extern int *ext2;
@ -652,6 +668,16 @@ int main() {
assert(4, counter(), "counter()");
assert(6, counter(), "counter()");
assert(1, (int){1}, "(int){1}");
assert(2, ((int[]){0,1,2})[2], "(int[]){0,1,2}[2]");
assert('a', ((struct {char a; int b;}){'a', 3}).a, "((struct {char a; int b;}){'a', 3}).a");
assert(3, ({ int x=3; (int){x}; }), "int x=3; (int){x};");
assert(1, tree->val, "tree->val");
assert(2, tree->lhs->val, "tree->lhs->val");
assert(3, tree->lhs->lhs->val, "tree->lhs->lhs->val");
assert(4, tree->lhs->rhs->val, "tree->lhs->rhs->val");
printf("OK\n");
return 0;
}