- add __declspec restrict and noalias
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 14 Mar 2008 16:08:42 +0000 (16:08 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 14 Mar 2008 16:08:42 +0000 (16:08 +0000)
- add an internal_errof_f() as panic replacement
- true_statement is always != NULL

[r18942]

TODO
ast.c
ast_t.h
diagnostic.c
diagnostic.h
lexer.c
parser.c
parsetest/MS/declspec.c

diff --git a/TODO b/TODO
index 2e086bb..272f5aa 100644 (file)
--- a/TODO
+++ b/TODO
@@ -9,10 +9,7 @@ Lexer:
   compressed table) and only storing pointers to it on the AST.
 
 Parser:
-- disallow storage class specifiers in sturct/union members
-- the expect macros abort functions directly. This leads to some functions
-  not resetting the current context properly (parse_for); expect in expressions
-  suddenly return NULL which triggers asserts
+- disallow storage class specifiers in struct/union members
 - label: declaration; is no valid C99 but we parse it anyway
 - add constant folding code (optional, ast2firm already does it)
 - Refactor code, so code to handle number values (and strings?) is an own
diff --git a/ast.c b/ast.c
index d15ece7..23ad48f 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -869,9 +869,7 @@ static void print_if_statement(const if_statement_t *statement)
        fputs("if (", out);
        print_expression(statement->condition);
        fputs(") ", out);
-       if(statement->true_statement != NULL) {
-               print_statement(statement->true_statement);
-       }
+       print_statement(statement->true_statement);
 
        if(statement->false_statement != NULL) {
                print_indent();
@@ -1254,6 +1252,12 @@ static void print_ms_modifiers(const declaration_t *declaration) {
                if(declaration->alignment != 0) {
                        fputs(next, out); next = ", "; fprintf(out, "align(%u)", declaration->alignment);
                }
+               if(modifiers & DM_RESTRICT) {
+                       fputs(next, out); next = ", "; fputs("restrict", out);
+               }
+               if(modifiers & DM_NOALIAS) {
+                       fputs(next, out); next = ", "; fputs("noalias", out);
+               }
            if(declaration->get_property_sym != NULL || declaration->put_property_sym != NULL) {
                char *comma = "";
                        fputs(next, out); next = ", "; fprintf(out, "property(");
diff --git a/ast_t.h b/ast_t.h
index 4d32e54..6dfa8f0 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -430,7 +430,9 @@ typedef enum {
        DM_NOVTABLE         = (1 <<  8),
        DM_NORETURN         = (1 <<  9),
        DM_NOINLINE         = (1 << 10),
-       DM_DEPRECATED       = (1 << 11)
+       DM_DEPRECATED       = (1 << 11),
+       DM_RESTRICT         = (1 << 12),
+       DM_NOALIAS          = (1 << 13)
 } decl_modifier_t;
 
 typedef unsigned short decl_modifiers_t;
index 02008d9..8a15ef8 100644 (file)
@@ -199,3 +199,20 @@ void warningf(const source_position_t pos, const char *const fmt, ...)
        }
        va_end(ap);
 }
+
+static void internal_errorvf(const source_position_t pos,
+                    const char *const fmt, va_list ap)
+{
+       fprintf(stderr, "%s:%u: internal error: ", pos.input_name, pos.linenr);
+       diagnosticvf(fmt, ap);
+       fputc('\n', stderr);
+}
+
+void internal_errorf(const source_position_t pos, const char *const fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       internal_errorvf(pos, fmt, ap);
+       va_end(ap);
+       abort();
+}
index 5e8e0aa..820c719 100644 (file)
 #include <stdbool.h>
 #include "token_t.h"
 
+/* define a NORETURN attribute */
+#ifndef NORETURN
+# if defined(__GNUC__)
+#  if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 70)
+#   define NORETURN void __attribute__ ((noreturn))
+#  endif /* __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 70) */
+# endif /* defined(__GNUC__) */
+
+# if defined(_MSC_VER)
+#  define NORETURN void __declspec(noreturn)
+# endif /* defined(_MSC_VER) */
+
+/* If not set above, use "void" for DOES_NOT_RETURN. */
+# ifndef NORETURN
+# define NORETURN void
+# endif /* ifndef NORETURN */
+#endif /* ifndef NORETURN */
+
 void diagnosticf(const char *fmt, ...);
 void errorf(source_position_t pos, const char *fmt, ...);
 void warningf(source_position_t pos, const char *fmt, ...);
+NORETURN internal_errorf(source_position_t pos, const char *fmt, ...);
 
 extern unsigned diagnostic_count;
 extern unsigned error_count;
diff --git a/lexer.c b/lexer.c
index 3ba2c37..9643ec5 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -67,6 +67,16 @@ static void parse_error(const char *msg)
        errorf(lexer_token.source_position,  "%s", msg);
 }
 
+/**
+ * Prints an internal error message at the current token.
+ *
+ * @param msg   the error message
+ */
+static NORETURN internal_error(const char *msg)
+{
+       internal_errorf(lexer_token.source_position,  "%s", msg);
+}
+
 static inline void next_real_char(void)
 {
        assert(bufpos <= bufend);
@@ -481,7 +491,7 @@ static void parse_number_hex(void)
 
        if(c == '.' || c == 'p' || c == 'P') {
                next_char();
-               panic("Hex floating point numbers not implemented yet");
+               internal_error("Hex floating point numbers not implemented yet");
        }
        if(*string == '\0') {
                parse_error("invalid hex number");
@@ -679,7 +689,7 @@ static int digit_value(int digit) {
        case 'f':
        case 'F': return 15;
        default:
-               panic("wrong character given");
+               internal_error("wrong character given");
        }
 }
 
index ab73613..3784034 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -108,6 +108,8 @@ static const symbol_t *sym_selectany  = NULL;
 static const symbol_t *sym_thread     = NULL;
 static const symbol_t *sym_uuid       = NULL;
 static const symbol_t *sym_deprecated = NULL;
+static const symbol_t *sym_restrict   = NULL;
+static const symbol_t *sym_noalias    = NULL;
 
 /** The token anchor set */
 static unsigned char token_anchor_set[T_LAST_TOKEN];
@@ -1723,7 +1725,7 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env)
                        break;
 
                default:
-                       panic("invalid initializer type");
+                       internal_errorf(HERE, "invalid initializer type");
                }
 
                expression_t *cnst       = allocate_expression_zero(EXPR_CONST);
@@ -2044,11 +2046,16 @@ static bool check_elignment_value(long long intvalue) {
 
 static void parse_microsoft_extended_decl_modifier(declaration_specifiers_t *specifiers)
 {
-       symbol_t         *symbol;
        decl_modifiers_t *modifiers = &specifiers->decl_modifiers;
 
-       while(token.type == T_IDENTIFIER) {
-               symbol = token.v.symbol;
+       while(true) {
+               if(token.type == T_restrict) {
+                       next_token();
+                       DET_MOD(restrict, DM_RESTRICT);
+                       goto end_loop;
+               } else if(token.type != T_IDENTIFIER)
+                       break;
+               symbol_t *symbol = token.v.symbol;
                if(symbol == sym_align) {
                        next_token();
                        expect('(');
@@ -2154,12 +2161,16 @@ static void parse_microsoft_extended_decl_modifier(declaration_specifiers_t *spe
                                }
                                expect(')');
                        }
+               } else if(symbol == sym_noalias) {
+                       next_token();
+                       DET_MOD(noalias, DM_NOALIAS);
                } else {
                        warningf(HERE, "Unknown modifier %Y ignored", token.v.symbol);
                        next_token();
                        if(token.type == '(')
                                skip_until(')');
                }
+end_loop:
                if (token.type == ',')
                        next_token();
        }
@@ -2846,7 +2857,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
        for( ; iter != NULL; iter = iter->next) {
                switch(iter->kind) {
                case CONSTRUCT_INVALID:
-                       panic("invalid type construction found");
+                       internal_errorf(HERE, "invalid type construction found");
                case CONSTRUCT_FUNCTION: {
                        construct_function_type_t *construct_function_type
                                = (construct_function_type_t*) iter;
@@ -4084,7 +4095,7 @@ static type_t *get_builtin_symbol_type(symbol_t *symbol)
        case T___builtin_va_end:
                return make_function_1_type(type_void, type_valist);
        default:
-               panic("not implemented builtin symbol found");
+               internal_errorf(HERE, "not implemented builtin symbol found");
        }
 }
 
@@ -4593,7 +4604,7 @@ static expression_t *parse_compare_builtin(void)
                expression = allocate_expression_zero(EXPR_BINARY_ISUNORDERED);
                break;
        default:
-               panic("invalid compare builtin found");
+               internal_errorf(HERE, "invalid compare builtin found");
                break;
        }
        expression->base.source_position = HERE;
@@ -5755,7 +5766,7 @@ static bool expression_has_effect(const expression_t *const expr)
                case EXPR_BINARY_ISUNORDERED:        return false;
        }
 
-       panic("unexpected expression");
+       internal_errorf(HERE, "unexpected expression");
 }
 
 static void semantic_comma(binary_expression_t *expression)
@@ -7052,6 +7063,8 @@ void init_parser(void)
                sym_thread     = symbol_table_insert("thread");
                sym_uuid       = symbol_table_insert("uuid");
                sym_deprecated = symbol_table_insert("deprecated");
+               sym_restrict   = symbol_table_insert("restrict");
+               sym_noalias    = symbol_table_insert("noalias");
        }
        memset(token_anchor_set, 0, sizeof(token_anchor_set));
 
index b4ec98a..910ea6e 100644 (file)
@@ -8,3 +8,6 @@ int __declspec(noinline, naked, deprecated("Mist"))func(void);
 struct x {
        int __declspec(property(get=get_a, put=put_a)) a;
 };
+
+__declspec(restrict) char * malloc_like();
+int __declspec(noalias) test1(void *a, void *b);