more on MS __declspec
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 7 Mar 2008 14:50:27 +0000 (14:50 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 7 Mar 2008 14:50:27 +0000 (14:50 +0000)
[r18921]

ast.c
ast_t.h
parser.c
parsetest/MS/declspec.c

diff --git a/ast.c b/ast.c
index d2de04e..af5ae48 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1206,6 +1206,48 @@ void print_initializer(const initializer_t *initializer)
        panic("invalid initializer kind found");
 }
 
+/**
+ * Print microsoft extended declaration modifiers.
+ */
+static void print_ms_modifiers(const declaration_t *declaration) {
+       decl_modifiers_t modifiers = declaration->modifiers;
+
+       /* DM_FORCEINLINE handled outside. */
+       if((modifiers & ~DM_FORCEINLINE) != 0) {
+               char next = '(';
+
+               fputs("__declspec", out);
+               if(modifiers & DM_DLLIMPORT) {
+                       fputc(next, out); next = ' '; fputs("dllimport", out);
+               }
+               if(modifiers & DM_DLLEXPORT) {
+                       fputc(next, out); next = ' '; fputs("dllexport", out);
+               }
+               if(modifiers & DM_THREAD) {
+                       fputc(next, out); next = ' '; fputs("thread", out);
+               }
+               if(modifiers & DM_NAKED) {
+                       fputc(next, out); next = ' '; fputs("naked", out);
+               }
+               if(modifiers & DM_THREAD) {
+                       fputc(next, out); next = ' '; fputs("thread", out);
+               }
+               if(modifiers & DM_SELECTANY) {
+                       fputc(next, out); next = ' '; fputs("selectany", out);
+               }
+               if(modifiers & DM_NOTHROW) {
+                       fputc(next, out); next = ' '; fputs("nothrow", out);
+               }
+               if(modifiers & DM_NORETURN) {
+                       fputc(next, out); next = ' '; fputs("noreturn", out);
+               }
+               if(modifiers & DM_NOINLINE) {
+                       fputc(next, out); next = ' '; fputs("noinline", out);
+               }
+               fputs(") ", out);
+       }
+}
+
 /**
  * Print a declaration in the NORMAL namespace.
  *
@@ -1215,11 +1257,16 @@ static void print_normal_declaration(const declaration_t *declaration)
 {
        print_storage_class((storage_class_tag_t) declaration->declared_storage_class);
        if(declaration->is_inline) {
-               if (declaration->modifiers & DM_FORCEINLINE)
+               if(declaration->modifiers & DM_FORCEINLINE)
                        fputs("__forceinline ", out);
-               else
-                       fputs("inline ", out);
+               else {
+                       if(declaration->modifiers & DM_MICROSOFT_INLINE)
+                               fputs("__inline ", out);
+                       else
+                               fputs("inline ", out);
+               }
        }
+       print_ms_modifiers(declaration);
        print_type_ext(declaration->type, declaration->symbol,
                       &declaration->scope);
 
diff --git a/ast_t.h b/ast_t.h
index e6b71e6..cbe83ce 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -415,15 +415,21 @@ union initializer_t {
        initializer_designator_t  designator;
 };
 
+/**
+ * Extended microsoft modifier.
+ */
 typedef enum {
-       DM_DLLIMPORT   = (1 << 0),
-       DM_DLLEXPORT   = (1 << 1),
-       DM_THREAD      = (1 << 2),
-       DM_NAKED       = (1 << 3),
-       DM_FORCEINLINE = (1 << 4),
-       DM_NOTHROW     = (1 << 5),
-       DM_NORETURN    = (1 << 6),
-       DM_NOINLINE    = (1 << 7)
+       DM_DLLIMPORT        = (1 <<  0),
+       DM_DLLEXPORT        = (1 <<  1),
+       DM_THREAD           = (1 <<  2),
+       DM_NAKED            = (1 <<  3),
+       DM_MICROSOFT_INLINE = (1 <<  4),
+       DM_FORCEINLINE      = (1 <<  5),
+       DM_SELECTANY        = (1 <<  6),
+       DM_NOTHROW          = (1 <<  7),
+       DM_NOVTABLE         = (1 <<  8),
+       DM_NORETURN         = (1 <<  9),
+       DM_NOINLINE         = (1 << 10)
 } decl_modifier_t;
 
 typedef unsigned short decl_modifiers_t;
index e85b10d..02bc78a 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1949,9 +1949,9 @@ static type_t *get_typedef_type(symbol_t *symbol)
        return type;
 }
 
-static void parse_microsoft_extended_decl_modifier(void)
+static void parse_microsoft_extended_decl_modifier(decl_modifiers_t *modifiers)
 {
-       symbol_t *symbol;
+       symbol_t         *symbol;
 
        while(true) {
                switch(token.type) {
@@ -1974,20 +1974,28 @@ static void parse_microsoft_extended_decl_modifier(void)
                                expect(')');
                        } else if(symbol == sym_dllimport) {
                                next_token();
-                       } else if(symbol == sym_dllimport) {
-                               next_token();
+                               *modifiers |= DM_DLLIMPORT;
                        } else if(symbol == sym_dllexport) {
                                next_token();
+                               *modifiers |= DM_DLLEXPORT;
+                       } else if(symbol == sym_thread) {
+                               next_token();
+                               *modifiers |= DM_THREAD;
                        } else if(symbol == sym_naked) {
                                next_token();
+                               *modifiers |= DM_NAKED;
                        } else if(symbol == sym_noinline) {
                                next_token();
+                               *modifiers |= DM_NOINLINE;
                        } else if(symbol == sym_noreturn) {
                                next_token();
+                               *modifiers |= DM_NORETURN;
                        } else if(symbol == sym_nothrow) {
                                next_token();
+                               *modifiers |= DM_NOTHROW;
                        } else if(symbol == sym_novtable) {
                                next_token();
+                               *modifiers |= DM_NOVTABLE;
                        } else if(symbol == sym_property) {
                                next_token();
                                expect('(');
@@ -2006,8 +2014,6 @@ static void parse_microsoft_extended_decl_modifier(void)
                                expect(')');
                        } else if(symbol == sym_selectany) {
                                next_token();
-                       } else if(symbol == sym_thread) {
-                               next_token();
                        } else if(symbol == sym_uuid) {
                                next_token();
                                expect('(');
@@ -2022,7 +2028,7 @@ static void parse_microsoft_extended_decl_modifier(void)
                }
        }
 end_error:
-       ;
+       return;
 }
 
 static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
@@ -2056,7 +2062,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                case T_declspec:
                        next_token();
                        expect('(');
-                       parse_microsoft_extended_decl_modifier();
+                       parse_microsoft_extended_decl_modifier(&specifiers->decl_modifiers);
                        expect(')');
                        break;
 
@@ -3126,6 +3132,7 @@ static void parse_anonymous_declaration_rest(
        declaration->type                   = specifiers->type;
        declaration->declared_storage_class = specifiers->declared_storage_class;
        declaration->source_position        = specifiers->source_position;
+       declaration->modifiers              = specifiers->decl_modifiers;
 
        if (declaration->declared_storage_class != STORAGE_CLASS_NONE) {
                warningf(declaration->source_position, "useless storage class in empty declaration");
index 7af4da1..cdf21cc 100644 (file)
@@ -1 +1,6 @@
 int __declspec(align(4)) x;
+
+int __declspec(dllimport) y;
+int __declspec(dllexport) z;
+
+int __declspec(noinline naked)func(void);