- fixed parse_error_expected()
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 20 Mar 2008 16:11:15 +0000 (16:11 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 20 Mar 2008 16:11:15 +0000 (16:11 +0000)
- microsoft __try, __except, __finally added

[r19003]

ast.c
ast.h
ast2firm.c
ast_t.h
parser.c
parsetest/MS/try.c [new file with mode: 0644]

diff --git a/ast.c b/ast.c
index 175f632..b203ee8 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1096,6 +1096,26 @@ end_of_print_asm_statement:
        fputs(");\n", out);
 }
 
+/**
+ * Print a microsoft __try statement.
+ *
+ * @param statement   the statement
+ */
+static void print_ms_try_statement(const ms_try_statement_t *statement)
+{
+       fputs("__try ", out);
+       print_statement(statement->try_statement);
+       print_indent();
+       if(statement->except_expression != NULL) {
+               fputs("__except(", out);
+               print_expression(statement->except_expression);
+               fputs(") ", out);
+       } else {
+               fputs("__finally ", out);
+       }
+       print_statement(statement->final_statement);
+}
+
 /**
  * Print a statement.
  *
@@ -1152,6 +1172,9 @@ void print_statement(const statement_t *statement)
        case STATEMENT_ASM:
                print_asm_statement(&statement->asms);
                break;
+       case STATEMENT_MS_TRY:
+               print_ms_try_statement(&statement->ms_try);
+               break;
        case STATEMENT_INVALID:
                fprintf(out, "$invalid statement$");
                break;
diff --git a/ast.h b/ast.h
index 1ca1240..d8109e4 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -84,6 +84,7 @@ typedef struct for_statement_t              for_statement_t;
 typedef struct asm_constraint_t             asm_constraint_t;
 typedef struct asm_clobber_t                asm_clobber_t;
 typedef struct asm_statement_t              asm_statement_t;
+typedef struct ms_try_statement_t           ms_try_statement_t;
 typedef union  statement_t                  statement_t;
 
 typedef struct translation_unit_t           translation_unit_t;
index be8549e..ac287d6 100644 (file)
@@ -4275,6 +4275,11 @@ static void asm_statement_to_firm(const asm_statement_t *statement)
 #endif
 }
 
+static void    ms_try_statement_to_firm(ms_try_statement_t *statement) {
+       statement_to_firm(statement->try_statement);
+       warningf(&statement->base.source_position, "structured exception handling ignored");
+}
+
 static void statement_to_firm(statement_t *statement)
 {
        switch(statement->kind) {
@@ -4329,6 +4334,9 @@ static void statement_to_firm(statement_t *statement)
        case STATEMENT_ASM:
                asm_statement_to_firm(&statement->asms);
                return;
+       case STATEMENT_MS_TRY:
+               ms_try_statement_to_firm(&statement->ms_try);
+               return;
        }
        panic("Statement not implemented\n");
 }
@@ -4543,6 +4551,15 @@ static int count_decls_in_stmts(const statement_t *stmt)
                                count += count_decls_in_expression(ret_stmt->value);
                                break;
                        }
+
+                       case STATEMENT_MS_TRY: {
+                               const ms_try_statement_t *const try_stmt = &stmt->ms_try;
+                               count += count_decls_in_stmts(try_stmt->try_statement);
+                               if(try_stmt->except_expression != NULL)
+                                       count += count_decls_in_expression(try_stmt->except_expression);
+                               count += count_decls_in_stmts(try_stmt->final_statement);
+                               break;
+                       }
                }
        }
        return count;
diff --git a/ast_t.h b/ast_t.h
index fe49a7c..aa556a1 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -585,7 +585,8 @@ typedef enum {
        STATEMENT_WHILE,
        STATEMENT_DO_WHILE,
        STATEMENT_FOR,
-       STATEMENT_ASM
+       STATEMENT_ASM,
+       STATEMENT_MS_TRY,
 } statement_kind_t;
 
 struct statement_base_t {
@@ -701,6 +702,13 @@ struct asm_statement_t {
        bool              is_volatile;
 };
 
+struct ms_try_statement_t {
+       statement_base_t  base;
+       statement_t      *try_statement;
+       expression_t     *except_expression; /**< non-null for except, NULL for finally */
+       statement_t      *final_statement;
+};
+
 union statement_t {
        statement_kind_t         kind;
        statement_base_t         base;
@@ -717,6 +725,7 @@ union statement_t {
        do_while_statement_t     do_while;
        for_statement_t          fors;
        asm_statement_t          asms;
+       ms_try_statement_t       ms_try;
 };
 
 struct translation_unit_t {
index 2577cb1..9b68f38 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -245,7 +245,8 @@ static size_t get_statement_struct_size(statement_kind_t kind)
                [STATEMENT_WHILE]       = sizeof(while_statement_t),
                [STATEMENT_DO_WHILE]    = sizeof(do_while_statement_t),
                [STATEMENT_FOR]         = sizeof(for_statement_t),
-               [STATEMENT_ASM]         = sizeof(asm_statement_t)
+               [STATEMENT_ASM]         = sizeof(asm_statement_t),
+               [STATEMENT_MS_TRY]      = sizeof(ms_try_statement_t)
        };
        assert(kind <= sizeof(sizes) / sizeof(sizes[0]));
        assert(sizes[kind] != 0);
@@ -585,7 +586,7 @@ static void parse_error_expected(const char *message, ...)
        }
        va_list ap;
        va_start(ap, message);
-       errorf(HERE, "got %K, expected %#k", &token, &ap, "a ");
+       errorf(HERE, "got %K, expected %#k", &token, &ap, ", ");
        va_end(ap);
 }
 
@@ -1115,7 +1116,7 @@ end_error:
 static void parse_gnu_attribute_string_arg(gnu_attribute_t *attribute, string_t *string) {
        add_anchor_token('(');
        if(token.type != T_STRING_LITERAL) {
-               parse_error_expected("while parsing attribute directive", T_STRING_LITERAL);
+               parse_error_expected("while parsing attribute directive", T_STRING_LITERAL, 0);
                goto end_error;
        }
        *string = parse_string_literals();
@@ -1235,7 +1236,7 @@ static void parse_gnu_attribute_format_args(gnu_attribute_t *attribute) {
        int i;
 
        if(token.type != T_IDENTIFIER) {
-               parse_error_expected("while parsing format attribute directive", T_IDENTIFIER);
+               parse_error_expected("while parsing format attribute directive", T_IDENTIFIER, 0);
                goto end_error;
        }
        const char *name = token.v.symbol->string;
@@ -1370,7 +1371,7 @@ static void parse_gnu_attribute(gnu_attribute_t **attributes)
                                /* __attribute__((cdecl)), WITH ms mode */
                                name = "cdecl";
                        } else if(token.type != T_IDENTIFIER) {
-                               parse_error_expected("while parsing GNU attribute", T_IDENTIFIER);
+                               parse_error_expected("while parsing GNU attribute", T_IDENTIFIER, 0);
                                break;
                        }
                        const symbol_t *sym = token.v.symbol;
@@ -1574,7 +1575,7 @@ static void parse_attributes(gnu_attribute_t **attributes)
                        expect('(');
                        if(token.type != T_STRING_LITERAL) {
                                parse_error_expected("while parsing assembler attribute",
-                                                    T_STRING_LITERAL);
+                                                    T_STRING_LITERAL, 0);
                                eat_until_matching_token('(');
                                break;
                        } else {
@@ -7556,6 +7557,47 @@ end_error:
        return create_invalid_statement();
 }
 
+/**
+ * Parse a microsoft __try { } __finally { } or
+ * __try{ } __except() { }
+ */
+static statement_t *parse_ms_try_statment(void) {
+       statement_t *statement = allocate_statement_zero(STATEMENT_MS_TRY);
+
+       statement->base.source_position  = token.source_position;
+       eat(T___try);
+
+       statement->ms_try.try_statement = parse_compound_statement();
+
+       if(token.type == T___except) {
+               eat(T___except);
+               expect('(');
+               add_anchor_token(')');
+               expression_t *const expr = parse_expression();
+               type_t       *      type = skip_typeref(expr->base.type);
+               if (is_type_integer(type)) {
+                       type = promote_integer(type);
+               } else if (is_type_valid(type)) {
+                       errorf(&expr->base.source_position,
+                              "__expect expression is not an integer, but '%T'", type);
+                       type = type_error_type;
+               }
+               statement->ms_try.except_expression = create_implicit_cast(expr, type);
+               rem_anchor_token(')');
+               expect(')');
+               statement->ms_try.final_statement = parse_compound_statement();
+       } else if(token.type == T__finally) {
+               eat(T___finally);
+               statement->ms_try.final_statement = parse_compound_statement();
+       } else {
+               parse_error_expected("while parsing __try statement", T___except, T___finally, 0);
+               return create_invalid_statement();
+       }
+       return statement;
+end_error:
+       return create_invalid_statement();
+}
+
 /**
  * Parse a statement.
  */
@@ -7653,6 +7695,10 @@ static statement_t *parse_statement(void)
                statement = parse_declaration_statement();
                break;
 
+       case T___try:
+               statement = parse_ms_try_statment();
+               break;
+
        default:
                statement = parse_expression_statement();
                break;
diff --git a/parsetest/MS/try.c b/parsetest/MS/try.c
new file mode 100644 (file)
index 0000000..ffeb663
--- /dev/null
@@ -0,0 +1,19 @@
+int test(int a, int b) {
+       __try {
+               a = a / b;
+       }
+       if(0) {
+               a = 0;
+       }
+}
+
+int main(int argc, char *argv[]) {
+       int x;
+       __try {
+               x = argc / 0;
+       }
+       __finally {
+               printf("Should always print this!\n");
+       }
+       return 0;
+}