}
-static int current_token_spells_identifier_now (const char *name) {
-
- const char *p;
- size_t len;
-
- if (!name || !*name) {
- return 0;
- }
-
- if (tok.ident && strcmp (tok.ident, name) == 0) {
- return 1;
- }
-
- /*
- * Some declaration modifiers are real tokens rather than TOK_IDENT.
- * Use the original source spelling as a generic fallback so the
- * declaration parser can accept them in either specifier position:
- *
- * __dllexport void f(void);
- * void __dllexport f(void);
- */
- p = tok.caret ? tok.caret : tok.start;
-
- if (!p) {
- return 0;
- }
-
- while (*p == ' ' || *p == '\t') {
- p++;
- }
-
- len = strlen (name);
-
- if (strncmp (p, name, len) != 0) {
- return 0;
- }
-
- if ((p[len] >= 'A' && p[len] <= 'Z') ||
- (p[len] >= 'a' && p[len] <= 'z') ||
- (p[len] >= '0' && p[len] <= '9') ||
- p[len] == '_') {
- return 0;
- }
-
- return 1;
-
-}
-
-static void consume_post_type_declaration_modifiers_now (int *out_dllimport, int *out_dllexport) {
-
- for (;;) {
-
- if (current_token_spells_identifier_now ("__dllimport")) {
-
- if (out_dllimport) {
- *out_dllimport = 1;
- }
-
- parsed_dllimport = 1;
- get_token ();
-
- continue;
-
- }
-
- if (current_token_spells_identifier_now ("__dllexport")) {
-
- if (out_dllexport) {
- *out_dllexport = 1;
- }
-
- parsed_dllexport = 1;
- get_token ();
-
- continue;
-
- }
-
- break;
-
- }
-
-}
-
static int last_deref_cast_type_is_floating = 0;
static int parse_deref_cast_type_name (int *out_size) {
if (emit_body) {
if (parsed_dllimport) {
- report_line_at (get_filename (), last_declarator_name_line, REPORT_ERROR, last_declarator_name_start, last_declarator_name_caret, "function '%s' cannot be defined with '__dllimport'", name);
+ report_line_at (get_filename (), last_declarator_name_line, REPORT_ERROR, last_declarator_name_start, last_declarator_name_caret, "function '%s' cannot be defined with '__declspec(dllimport)'", name);
}
should_emit = add_global_symbol (name, GLOBAL_SYMBOL_FUNCTION, 0, last_declarator_name_start, last_declarator_name_caret, last_declarator_name_line);
declaration_dllimport = parsed_dllimport;
declaration_dllexport = parsed_dllexport;
- consume_post_type_declaration_modifiers_now (&declaration_dllimport, &declaration_dllexport);
parse_declarator (&name);
declaration_dllimport = declaration_dllimport || parsed_dllimport || declarator_dllimport;
#include "vector.h"
struct typedef_entry typedef_names[MAX_TYPEDEF_NAMES];
+
int typedef_name_count = 0;
int anonymous_aggregate_owner_id = 1;
if (parsed_calling_convention == TOK_EOF && declarator_calling_convention == TOK_EOF) {
parsed_calling_convention = TOK_STDCALL;
}
+
+ get_token ();
+ return;
- } else if (tok.kind == TOK_DLLEXPORT) {
+ }
- if (parsed_dllexport) {
- report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "duplicate '__dllexport'");
- } else if (parsed_dllimport) {
- report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "'__dllexport' and '__dllimport' cannot both be specified");
- } else {
+ if (tok.kind == TOK_DECLSPEC) {
+
+ const char *declspec_start = tok.report_start;
+ const char *declspec_caret = tok.report_caret;
- declarator_dllexport = 1;
- parsed_dllexport = 1;
+ get_token ();
+
+ if (!_accept (TOK_LPAREN)) {
+
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, declspec_start, declspec_caret, "expected '(' after '__declspec'");
+ return;
}
-
- } else if (tok.kind == TOK_DLLIMPORT) {
-
- if (parsed_dllimport) {
- report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "duplicate '__dllimport'");
- } else if (parsed_dllexport) {
- report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "'__dllexport' and '__dllimport' cannot both be specified");
+
+ if (tok.kind != TOK_IDENT || !tok.ident) {
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "expected attribute in '__declspec'");
+ } else if (strcmp (tok.ident, "dllexport") == 0) {
+
+ if (parsed_dllexport) {
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "duplicate '__declspec(dllexport)'");
+ } else if (parsed_dllimport) {
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "'__declspec(dllexport)' and '__declspec(dllimport)' cannot both be specified");
+ } else {
+
+ declarator_dllexport = 1;
+ parsed_dllexport = 1;
+
+ }
+
+ get_token ();
+
+ } else if (strcmp (tok.ident, "dllimport") == 0) {
+
+ if (parsed_dllimport) {
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "duplicate '__declspec(dllimport)'");
+ } else if (parsed_dllexport) {
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "'__declspec(dllexport)' and '__declspec(dllimport)' cannot both be specified");
+ } else {
+
+ declarator_dllimport = 1;
+ parsed_dllimport = 1;
+
+ }
+
+ get_token ();
+
+ } else if (strcmp (tok.ident, "packed") == 0) {
+
+ if (parsed_type_is_packed) {
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "duplicate '__declspec(packed)'");
+ } else {
+ parsed_type_is_packed = 1;
+ }
+
+ get_token ();
+
} else {
- declarator_dllimport = 1;
- parsed_dllimport = 1;
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "unsupported '__declspec' attribute '%s'", tok.ident);
+ get_token ();
}
+
+ expect (TOK_RPAREN, ")");
+ return;
}
-
- get_token ();
}
void parse_declarator_inner (char **out_name) {
- while (tok.kind == TOK_STDCALL || tok.kind == TOK_DLLEXPORT || tok.kind == TOK_DLLIMPORT) {
+ while (tok.kind == TOK_STDCALL || tok.kind == TOK_DECLSPEC) {
if (tok.kind == TOK_STDCALL) {
get_token ();
- while (tok.kind == TOK_CONST || tok.kind == TOK_VOLATILE || tok.kind == TOK_RESTRICT || tok.kind == TOK_STDCALL || tok.kind == TOK_DLLEXPORT || tok.kind == TOK_DLLIMPORT) {
+ while (tok.kind == TOK_CONST || tok.kind == TOK_VOLATILE || tok.kind == TOK_RESTRICT || tok.kind == TOK_STDCALL || tok.kind == TOK_DECLSPEC) {
if (tok.kind == TOK_STDCALL) {
get_token ();
- } else if (tok.kind == TOK_DLLEXPORT || tok.kind == TOK_DLLIMPORT) {
+ } else if (tok.kind == TOK_DECLSPEC) {
parse_decl_modifier ();
} else {
get_token ();
return 0;
case TOK_AUTO: case TOK_REGISTER: case TOK_STATIC:
- case TOK_DLLEXPORT: case TOK_DLLIMPORT: case TOK_PACKED:
+ case TOK_DECLSPEC: case TOK_STDCALL:
case TOK_EXTERN: case TOK_TYPEDEF: case TOK_INLINE:
case TOK_CONST: case TOK_VOLATILE: case TOK_RESTRICT:
case TOK_SIGNED: case TOK_UNSIGNED:
while (tok.kind == TOK_AUTO || tok.kind == TOK_REGISTER || tok.kind == TOK_STATIC ||
tok.kind == TOK_EXTERN || tok.kind == TOK_TYPEDEF || tok.kind == TOK_CONST ||
- tok.kind == TOK_PACKED || tok.kind == TOK_VOLATILE || tok.kind == TOK_SIGNED || tok.kind == TOK_UNSIGNED ||
+ tok.kind == TOK_VOLATILE || tok.kind == TOK_SIGNED || tok.kind == TOK_UNSIGNED ||
tok.kind == TOK_SHORT || tok.kind == TOK_LONG || tok.kind == TOK_CHAR ||
tok.kind == TOK_INT || tok.kind == TOK_VOID || tok.kind == TOK_FLOAT ||
tok.kind == TOK_DOUBLE || tok.kind == TOK_INLINE || tok.kind == TOK_RESTRICT ||
- tok.kind == TOK_DLLEXPORT || tok.kind == TOK_DLLIMPORT || tok.kind == TOK_STDCALL || token_is_ms_int_type_name ()) {
+ tok.kind == TOK_DECLSPEC || tok.kind == TOK_STDCALL || token_is_ms_int_type_name ()) {
saw = 1;
saw_real_type = 1;
}
- if (tok.kind == TOK_STDCALL || tok.kind == TOK_DLLEXPORT || tok.kind == TOK_DLLIMPORT) {
+ if (tok.kind == TOK_STDCALL || tok.kind == TOK_DECLSPEC) {
parse_decl_modifier ();
continue;
} else if (tok.kind == TOK_INLINE) {
parsed_type_is_inline = 1;
- } else if (tok.kind == TOK_PACKED) {
- parsed_type_is_packed = 1;
} else if (tok.kind == TOK_CHAR) {
if (parsed_type_size == DATA_CHAR) {
clear_parsed_fields ();
get_token ();
- if (tok.kind == TOK_PACKED) {
+ while (tok.kind == TOK_DECLSPEC) {
- aggregate_is_packed = 1;
- get_token ();
+ parse_decl_modifier ();
+
+ if (parsed_type_is_packed) {
+ aggregate_is_packed = 1;
+ }
}
}
- if (tok.kind == TOK_PACKED) {
+ while (tok.kind == TOK_DECLSPEC) {
- aggregate_is_packed = 1;
- get_token ();
+ parse_decl_modifier ();
+
+ if (parsed_type_is_packed) {
+ aggregate_is_packed = 1;
+ }
}