bugfixes, parse initializers
authorMatthias Braun <matze@braunis.de>
Fri, 28 Sep 2007 21:06:38 +0000 (21:06 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 28 Sep 2007 21:06:38 +0000 (21:06 +0000)
[r18366]

Makefile
ast.c
ast.h
ast_t.h
lexer.c
parser.c
tokens.inc
type_hash.c

index 99d3e86..1e85905 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,12 @@
 GOAL = cparser
 
-CFLAGS += -Wall -W -Werror -O0 -g3 -std=c99 -pedantic
+CFLAGS += -Wall -W -Werror -std=c99 -pedantic
 CFLAGS += -DHAVE_CONFIG_H
 CFLAGS += -I .
+CFLAGS += -O0 -g3
+#CFLAGS += -O3 -march=pentium4 -fomit-frame-pointer -DNDEBUG
 
-LFLAGS = -g3
+LFLAGS =
 
 SOURCES := \
        adt/array.c \
diff --git a/ast.c b/ast.c
index 5fe9918..0d283f8 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -208,6 +208,15 @@ static void print_conditional(const conditional_expression_t *expression)
        fputs(")", out);
 }
 
+static void print_va_arg(const va_arg_expression_t *expression)
+{
+       fputs("__builtin_va_arg(", out);
+       print_expression(expression->arg);
+       fputs(", ", out);
+       print_type(expression->expression.datatype);
+       fputs(")", out);
+}
+
 void print_expression(const expression_t *expression)
 {
        switch(expression->type) {
@@ -246,6 +255,9 @@ void print_expression(const expression_t *expression)
        case EXPR_CONDITIONAL:
                print_conditional((const conditional_expression_t*) expression);
                break;
+       case EXPR_VA_ARG:
+               print_va_arg((const va_arg_expression_t*) expression);
+               break;
 
        case EXPR_OFFSETOF:
        case EXPR_STATEMENT:
diff --git a/ast.h b/ast.h
index cbcdcaa..e599dc8 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -24,6 +24,7 @@ typedef struct comma_expression_t           comma_expression_t;
 typedef struct statement_expression_t       statement_expression_t;
 typedef struct member_designator_t          member_designator_t;
 typedef struct offsetof_expression_t        offsetof_expression_t;
+typedef struct va_arg_expression_t          va_arg_expression_t;
 typedef struct builtin_symbol_expression_t  builtin_symbol_expression_t;
 
 typedef struct declaration_t                declaration_t;
diff --git a/ast_t.h b/ast_t.h
index 99340b3..5cddf05 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -26,6 +26,7 @@ typedef enum {
        EXPR_PRETTY_FUNCTION,
        EXPR_BUILTIN_SYMBOL,
        EXPR_OFFSETOF,
+       EXPR_VA_ARG,
        EXPR_STATEMENT
 } expresion_type_t;
 
@@ -171,6 +172,12 @@ struct offsetof_expression_t {
        member_designator_t *member_designators;
 };
 
+struct va_arg_expression_t {
+       expression_t  expression;
+       expression_t *arg;
+       type_t       *type;
+};
+
 struct conditional_expression_t {
        expression_t  expression;
        expression_t *condition;
diff --git a/lexer.c b/lexer.c
index 9dbd2fa..9ff748a 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -88,11 +88,7 @@ static inline void next_char(void);
                lexer_token.source_position.linenr++; \
                code;
 
-static inline void eat(char c_type)
-{
-       assert(c == c_type);
-       next_char();
-}
+#define eat(c_type)  do { assert(c == c_type); next_char(); } while(0)
 
 static void maybe_concat_lines(void)
 {
@@ -113,6 +109,7 @@ static inline void next_char(void)
 {
        next_real_char();
 
+#if 0
        /* filter trigraphs */
        if(UNLIKELY(c == '\\')) {
                maybe_concat_lines();
@@ -148,6 +145,8 @@ static inline void next_char(void)
        }
 
 end_of_next_char:
+#endif
+       (void) maybe_concat_lines;
 #ifdef DEBUG_CHARS
        printf("nchar '%c'\n", c);
 #else
index eabb57e..033033e 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -117,6 +117,11 @@ static inline void *allocate_type_zero(size_t size)
        return res;
 }
 
+static inline void free_type(void *type)
+{
+       obstack_free(type_obst, type);
+}
+
 /**
  * returns the top element of the environment stack
  */
@@ -148,11 +153,7 @@ static inline const token_t *look_ahead(int num)
        return & lookahead_buffer[pos];
 }
 
-static inline void eat(token_type_t type)
-{
-       assert(token.type == type);
-       next_token();
-}
+#define eat(token_type)  do { assert(token.type == token_type); next_token(); } while(0)
 
 void error(void)
 {
@@ -428,6 +429,70 @@ struct declaration_specifiers_t {
        type_t          *type;
 };
 
+static const char *parse_string_literals(void)
+{
+       assert(token.type == T_STRING_LITERAL);
+       const char *result = token.v.string;
+
+       next_token();
+
+       while(token.type == T_STRING_LITERAL) {
+               result = concat_strings(result, token.v.string);
+               next_token();
+       }
+
+       return result;
+}
+
+static void parse_attributes(void)
+{
+       while(true) {
+               switch(token.type) {
+               case T___attribute__:
+                       next_token();
+
+                       expect_void('(');
+                       int depth = 1;
+                       while(depth > 0) {
+                               switch(token.type) {
+                               case T_EOF:
+                                       parse_error("EOF while parsing attribute");
+                                       break;
+                               case '(':
+                                       next_token();
+                                       depth++;
+                                       break;
+                               case ')':
+                                       next_token();
+                                       depth--;
+                                       break;
+                               default:
+                                       next_token();
+                               }
+                       }
+                       break;
+               case T_asm:
+                       next_token();
+                       expect_void('(');
+                       if(token.type != T_STRING_LITERAL) {
+                               parse_error_expected("while parsing assembler attribute",
+                                                    T_STRING_LITERAL);
+                               eat_brace();
+                               break;
+                       } else {
+                               parse_string_literals();
+                       }
+                       expect_void(')');
+                       break;
+               default:
+                       goto attributes_finished;
+               }
+       }
+
+attributes_finished:
+       ;
+}
+
 static compound_type_t *find_compound_type(compound_type_t *types,
                                            const symbol_t *symbol)
 {
@@ -500,6 +565,7 @@ static type_t *parse_compound_type_specifier(bool is_struct)
                set_context(&compound_type->context);
 
                parse_compound_type_entries();
+               parse_attributes();
 
                assert(context == &compound_type->context);
                set_context(last_context);
@@ -599,6 +665,7 @@ static type_t *parse_enum_specifier(void)
                declaration_t *before = last_declaration;
 
                parse_enum_entries();
+               parse_attributes();
 
                if(before == NULL) {
                        enum_type->entries_begin = context->declarations;
@@ -658,70 +725,6 @@ restart:
        return result;
 }
 
-static const char *parse_string_literals(void)
-{
-       assert(token.type == T_STRING_LITERAL);
-       const char *result = token.v.string;
-
-       next_token();
-
-       while(token.type == T_STRING_LITERAL) {
-               result = concat_strings(result, token.v.string);
-               next_token();
-       }
-
-       return result;
-}
-
-static void parse_attributes(void)
-{
-       while(true) {
-               switch(token.type) {
-               case T___attribute__:
-                       next_token();
-
-                       expect_void('(');
-                       int depth = 1;
-                       while(depth > 0) {
-                               switch(token.type) {
-                               case T_EOF:
-                                       parse_error("EOF while parsing attribute");
-                                       break;
-                               case '(':
-                                       next_token();
-                                       depth++;
-                                       break;
-                               case ')':
-                                       next_token();
-                                       depth--;
-                                       break;
-                               default:
-                                       next_token();
-                               }
-                       }
-                       break;
-               case T_asm:
-                       next_token();
-                       expect_void('(');
-                       if(token.type != T_STRING_LITERAL) {
-                               parse_error_expected("while parsing assembler attribute",
-                                                    T_STRING_LITERAL);
-                               eat_brace();
-                               break;
-                       } else {
-                               parse_string_literals();
-                       }
-                       expect_void(')');
-                       break;
-               default:
-                       goto attributes_finished;
-               }
-       }
-
-attributes_finished:
-       ;
-}
-
 typedef enum {
        SPECIFIER_SIGNED    = 1 << 0,
        SPECIFIER_UNSIGNED  = 1 << 1,
@@ -750,7 +753,7 @@ static type_t *create_builtin_type(symbol_t *symbol)
 
        type_t *result = typehash_insert((type_t*) type);
        if(result != (type_t*) type) {
-               obstack_free(type_obst, type);
+               free_type(type);
        }
 
        return result;
@@ -1010,7 +1013,7 @@ finish_specifiers:
 
        type_t *result = typehash_insert(type);
        if(newtype && result != (type_t*) type) {
-               obstack_free(type_obst, type);
+               free_type(type);
        }
 
        specifiers->type = result;
@@ -1359,7 +1362,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
 
                type_t *hashed_type = typehash_insert((type_t*) type);
                if(hashed_type != type) {
-                       obstack_free(type_obst, type);
+                       free_type(type);
                        type = hashed_type;
                }
        }
@@ -1429,6 +1432,66 @@ static void parser_error_multiple_definition(declaration_t *previous,
        error();
 }
 
+static void parse_designation(void)
+{
+       if(token.type != '[' && token.type != '.')
+               return;
+
+       while(1) {
+               switch(token.type) {
+               case '[':
+                       next_token();
+                       parse_constant_expression();
+                       expect_void(']');
+                       break;
+               case '.':
+                       next_token();
+                       expect_void(T_IDENTIFIER);
+                       break;
+               default:
+                       expect_void('=');
+                       return;
+               }
+       }
+}
+
+static void parse_initializer_list(void);
+
+static void parse_initializer(void)
+{
+       parse_designation();
+
+       if(token.type == '{') {
+               parse_initializer_list();
+       } else {
+               parse_assignment_expression();
+       }
+}
+
+static void parse_initializer_list(void)
+{
+       eat('{');
+
+       while(1) {
+               parse_initializer();
+               if(token.type == '}')
+                       break;
+
+               if(token.type != ',') {
+                       parse_error_expected("problem while parsing initializer list",
+                                            ',', '}', 0);
+                       eat_block();
+                       return;
+               }
+               eat(',');
+
+               if(token.type == '}')
+                       break;
+       }
+
+       expect_void('}');
+}
+
 static void parse_init_declarators(const declaration_specifiers_t *specifiers)
 {
        while(true) {
@@ -1447,12 +1510,7 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers)
                                parser_error_multiple_definition(declaration, ndeclaration);
                        }
 
-                       if(token.type == '{') {
-                               // TODO
-                               expect_void('}');
-                       } else {
-                               declaration->initializer = parse_assignment_expression();
-                       }
+                       parse_initializer();
                } else if(token.type == '{') {
                        if(declaration->type->type != TYPE_METHOD) {
                                parser_print_error_prefix();
@@ -1654,7 +1712,7 @@ static declaration_t *create_implicit_function(symbol_t *symbol,
 
        type_t *type = typehash_insert((type_t*) method_type);
        if(type != (type_t*) method_type) {
-               obstack_free(type_obst, method_type);
+               free_type(method_type);
        }
 
        declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
@@ -1891,6 +1949,22 @@ static expression_t *parse_offsetof(void)
        return (expression_t*) expression;
 }
 
+static expression_t *parse_va_arg(void)
+{
+       eat(T___builtin_va_arg);
+
+       va_arg_expression_t *expression = allocate_ast_zero(sizeof(expression[0]));
+       expression->expression.type     = EXPR_VA_ARG;
+
+       expect('(');
+       expression->arg = parse_assignment_expression();
+       expect(',');
+       expression->expression.datatype = parse_typename();
+       expect(')');
+
+       return (expression_t*) expression;
+}
+
 static expression_t *parse_builtin_symbol(void)
 {
        builtin_symbol_expression_t *expression
@@ -1923,9 +1997,10 @@ static expression_t *parse_primary_expression(void)
                return parse_pretty_function_keyword();
        case T___builtin_offsetof:
                return parse_offsetof();
+       case T___builtin_va_arg:
+               return parse_va_arg();
        case T___builtin_expect:
        case T___builtin_va_start:
-       case T___builtin_va_arg:
        case T___builtin_va_end:
                return parse_builtin_symbol();
 
index 0c40e9b..8692cff 100644 (file)
@@ -42,6 +42,7 @@ S(while)
 S(_Bool)
 S(_Complex)
 S(_Imaginary)
+S(__thread)
 S(__extension__)
 S(__attribute__)
 S(__builtin_va_list)
index 4120940..d031913 100644 (file)
@@ -75,7 +75,7 @@ static unsigned hash_enum_type(const enum_type_t *type)
 
 static unsigned hash_type(const type_t *type)
 {
-       unsigned hash;
+       unsigned hash = 0;
 
        switch(type->type) {
        case TYPE_INVALID: