Print this page
11972 resync smatch

*** 56,65 **** --- 56,67 ---- struct_specifier, union_specifier, enum_specifier, attribute_specifier, typeof_specifier, parse_asm_declarator, typedef_specifier, inline_specifier, auto_specifier, register_specifier, static_specifier, extern_specifier, thread_specifier, const_qualifier, volatile_qualifier; + static declarator_t restrict_qualifier; + static declarator_t atomic_qualifier; static struct token *parse_if_statement(struct token *token, struct statement *stmt); static struct token *parse_return_statement(struct token *token, struct statement *stmt); static struct token *parse_loop_iterator(struct token *token, struct statement *stmt); static struct token *parse_default_statement(struct token *token, struct statement *stmt);
*** 78,97 **** typedef struct token *attr_t(struct token *, struct symbol *, struct decl_state *); static attr_t attribute_packed, attribute_aligned, attribute_modifier, attribute_bitwise, attribute_address_space, attribute_context, attribute_designated_init, attribute_transparent_union, ignore_attribute, attribute_mode, attribute_force; typedef struct symbol *to_mode_t(struct symbol *); static to_mode_t ! to_QI_mode, to_HI_mode, to_SI_mode, to_DI_mode, to_TI_mode, to_word_mode; enum { Set_T = 1, Set_S = 2, Set_Char = 4, --- 80,101 ---- typedef struct token *attr_t(struct token *, struct symbol *, struct decl_state *); static attr_t attribute_packed, attribute_aligned, attribute_modifier, + attribute_ext_visible, attribute_bitwise, attribute_address_space, attribute_context, attribute_designated_init, attribute_transparent_union, ignore_attribute, attribute_mode, attribute_force; typedef struct symbol *to_mode_t(struct symbol *); static to_mode_t ! to_QI_mode, to_HI_mode, to_SI_mode, to_DI_mode, to_TI_mode; ! static to_mode_t to_pointer_mode, to_word_mode; enum { Set_T = 1, Set_S = 2, Set_Char = 4,
*** 113,130 **** --- 117,152 ---- enum { SNone = 0, STypedef, SAuto, SRegister, SExtern, SStatic, SForced, SMax, }; + static void asm_modifier(struct token *token, unsigned long *mods, unsigned long mod) + { + if (*mods & mod) + warning(token->pos, "duplicated asm modifier"); + *mods |= mod; + } + + static void asm_modifier_volatile(struct token *token, unsigned long *mods) + { + asm_modifier(token, mods, MOD_VOLATILE); + } + + static void asm_modifier_inline(struct token *token, unsigned long *mods) + { + asm_modifier(token, mods, MOD_INLINE); + } + static struct symbol_op typedef_op = { .type = KW_MODIFIER, .declarator = typedef_specifier, }; static struct symbol_op inline_op = { .type = KW_MODIFIER, .declarator = inline_specifier, + .asm_modifier = asm_modifier_inline, }; static declarator_t noreturn_specifier; static struct symbol_op noreturn_op = { .type = KW_MODIFIER,
*** 168,183 **** --- 190,212 ---- }; static struct symbol_op volatile_op = { .type = KW_QUALIFIER, .declarator = volatile_qualifier, + .asm_modifier = asm_modifier_volatile, }; static struct symbol_op restrict_op = { .type = KW_QUALIFIER, + .declarator = restrict_qualifier, }; + static struct symbol_op atomic_op = { + .type = KW_QUALIFIER, + .declarator = atomic_qualifier, + }; + static struct symbol_op typeof_op = { .type = KW_SPECIFIER, .declarator = typeof_specifier, .test = Set_Any, .set = Set_S|Set_T,
*** 233,250 **** .test = Set_T|Set_Signed|Set_Unsigned|Set_Short|Set_Vlong, .set = Set_T|Set_Double, .class = CReal, }; - /* FIXME: this is not even slightly right. */ - static struct symbol_op complex_op = { - .type = KW_SPECIFIER, - .test = 0, //Set_T|Set_Signed|Set_Unsigned|Set_Short|Set_Vlong, - .set = 0, //Set_Double, //Set_T,Set_Double, - .class = CReal, - }; - static struct symbol_op float_op = { .type = KW_SPECIFIER | KW_SHORT, .test = Set_T|Set_Signed|Set_Unsigned|Set_Short|Set_Long, .set = Set_T|Set_Float, .class = CReal, --- 262,271 ----
*** 351,360 **** --- 372,385 ---- static struct symbol_op attr_mod_op = { .attribute = attribute_modifier, }; + static struct symbol_op ext_visible_op = { + .attribute = attribute_ext_visible, + }; + static struct symbol_op attr_bitwise_op = { .attribute = attribute_bitwise, }; static struct symbol_op attr_force_op = {
*** 408,417 **** --- 433,447 ---- static struct symbol_op mode_TI_op = { .type = KW_MODE, .to_mode = to_TI_mode }; + static struct symbol_op mode_pointer_op = { + .type = KW_MODE, + .to_mode = to_pointer_mode + }; + static struct symbol_op mode_word_op = { .type = KW_MODE, .to_mode = to_word_mode };
*** 428,437 **** --- 458,471 ---- { "__const", NS_TYPEDEF, .op = &const_op }, { "__const__", NS_TYPEDEF, .op = &const_op }, { "volatile", NS_TYPEDEF, .op = &volatile_op }, { "__volatile", NS_TYPEDEF, .op = &volatile_op }, { "__volatile__", NS_TYPEDEF, .op = &volatile_op }, + { "restrict", NS_TYPEDEF, .op = &restrict_op}, + { "__restrict", NS_TYPEDEF, .op = &restrict_op}, + { "__restrict__", NS_TYPEDEF, .op = &restrict_op}, + { "_Atomic", NS_TYPEDEF, .op = &atomic_op}, /* Typedef.. */ { "typedef", NS_TYPEDEF, .op = &typedef_op }, /* Type specifiers */
*** 446,462 **** { "__signed", NS_TYPEDEF, .op = &signed_op }, { "__signed__", NS_TYPEDEF, .op = &signed_op }, { "unsigned", NS_TYPEDEF, .op = &unsigned_op }, { "__int128", NS_TYPEDEF, .op = &int128_op }, { "_Bool", NS_TYPEDEF, .type = &bool_ctype, .op = &spec_op }, - { "_Complex", NS_TYPEDEF, .op = &complex_op }, /* Predeclared types */ { "__builtin_va_list", NS_TYPEDEF, .type = &ptr_ctype, .op = &spec_op }, { "__builtin_ms_va_list", NS_TYPEDEF, .type = &ptr_ctype, .op = &spec_op }, { "__int128_t", NS_TYPEDEF, .type = &lllong_ctype, .op = &spec_op }, { "__uint128_t",NS_TYPEDEF, .type = &ulllong_ctype, .op = &spec_op }, /* Extended types */ { "typeof", NS_TYPEDEF, .op = &typeof_op }, { "__typeof", NS_TYPEDEF, .op = &typeof_op }, { "__typeof__", NS_TYPEDEF, .op = &typeof_op }, --- 480,500 ---- { "__signed", NS_TYPEDEF, .op = &signed_op }, { "__signed__", NS_TYPEDEF, .op = &signed_op }, { "unsigned", NS_TYPEDEF, .op = &unsigned_op }, { "__int128", NS_TYPEDEF, .op = &int128_op }, { "_Bool", NS_TYPEDEF, .type = &bool_ctype, .op = &spec_op }, /* Predeclared types */ { "__builtin_va_list", NS_TYPEDEF, .type = &ptr_ctype, .op = &spec_op }, { "__builtin_ms_va_list", NS_TYPEDEF, .type = &ptr_ctype, .op = &spec_op }, { "__int128_t", NS_TYPEDEF, .type = &lllong_ctype, .op = &spec_op }, { "__uint128_t",NS_TYPEDEF, .type = &ulllong_ctype, .op = &spec_op }, + { "_Float32", NS_TYPEDEF, .type = &float32_ctype, .op = &spec_op }, + { "_Float32x", NS_TYPEDEF, .type = &float32x_ctype, .op = &spec_op }, + { "_Float64", NS_TYPEDEF, .type = &float64_ctype, .op = &spec_op }, + { "_Float64x", NS_TYPEDEF, .type = &float64x_ctype, .op = &spec_op }, + { "_Float128", NS_TYPEDEF, .type = &float128_ctype, .op = &spec_op }, /* Extended types */ { "typeof", NS_TYPEDEF, .op = &typeof_op }, { "__typeof", NS_TYPEDEF, .op = &typeof_op }, { "__typeof__", NS_TYPEDEF, .op = &typeof_op },
*** 474,488 **** { "_Noreturn", NS_TYPEDEF, .op = &noreturn_op }, { "_Alignas", NS_TYPEDEF, .op = &alignas_op }, - /* Ignored for now.. */ - { "restrict", NS_TYPEDEF, .op = &restrict_op}, - { "__restrict", NS_TYPEDEF, .op = &restrict_op}, - { "__restrict__", NS_TYPEDEF, .op = &restrict_op}, - /* Static assertion */ { "_Static_assert", NS_KEYWORD, .op = &static_assert_op }, /* Storage class */ { "auto", NS_TYPEDEF, .op = &auto_op }, --- 512,521 ----
*** 520,554 **** { "safe", NS_KEYWORD, MOD_SAFE, .op = &attr_mod_op }, { "force", NS_KEYWORD, .op = &attr_force_op }, { "bitwise", NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op }, { "__bitwise__",NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op }, { "address_space",NS_KEYWORD, .op = &address_space_op }, - { "mode", NS_KEYWORD, .op = &mode_op }, { "context", NS_KEYWORD, .op = &context_op }, { "designated_init", NS_KEYWORD, .op = &designated_init_op }, { "__transparent_union__", NS_KEYWORD, .op = &transparent_union_op }, { "noreturn", NS_KEYWORD, MOD_NORETURN, .op = &attr_mod_op }, { "__noreturn__", NS_KEYWORD, MOD_NORETURN, .op = &attr_mod_op }, { "pure", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"__pure__", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"const", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"__const", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"__const__", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, { "__mode__", NS_KEYWORD, .op = &mode_op }, ! { "QI", NS_KEYWORD, MOD_CHAR, .op = &mode_QI_op }, ! { "__QI__", NS_KEYWORD, MOD_CHAR, .op = &mode_QI_op }, ! { "HI", NS_KEYWORD, MOD_SHORT, .op = &mode_HI_op }, ! { "__HI__", NS_KEYWORD, MOD_SHORT, .op = &mode_HI_op }, { "SI", NS_KEYWORD, .op = &mode_SI_op }, { "__SI__", NS_KEYWORD, .op = &mode_SI_op }, ! { "DI", NS_KEYWORD, MOD_LONGLONG, .op = &mode_DI_op }, ! { "__DI__", NS_KEYWORD, MOD_LONGLONG, .op = &mode_DI_op }, ! { "TI", NS_KEYWORD, MOD_LONGLONGLONG, .op = &mode_TI_op }, ! { "__TI__", NS_KEYWORD, MOD_LONGLONGLONG, .op = &mode_TI_op }, ! { "word", NS_KEYWORD, MOD_LONG, .op = &mode_word_op }, ! { "__word__", NS_KEYWORD, MOD_LONG, .op = &mode_word_op }, }; static const char *ignored_attributes[] = { --- 553,595 ---- { "safe", NS_KEYWORD, MOD_SAFE, .op = &attr_mod_op }, { "force", NS_KEYWORD, .op = &attr_force_op }, { "bitwise", NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op }, { "__bitwise__",NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op }, { "address_space",NS_KEYWORD, .op = &address_space_op }, { "context", NS_KEYWORD, .op = &context_op }, { "designated_init", NS_KEYWORD, .op = &designated_init_op }, + { "__designated_init__", NS_KEYWORD, .op = &designated_init_op }, + { "transparent_union", NS_KEYWORD, .op = &transparent_union_op }, { "__transparent_union__", NS_KEYWORD, .op = &transparent_union_op }, { "noreturn", NS_KEYWORD, MOD_NORETURN, .op = &attr_mod_op }, { "__noreturn__", NS_KEYWORD, MOD_NORETURN, .op = &attr_mod_op }, { "pure", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"__pure__", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"const", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"__const", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"__const__", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, + {"externally_visible", NS_KEYWORD, .op = &ext_visible_op }, + {"__externally_visible__", NS_KEYWORD, .op = &ext_visible_op }, + { "mode", NS_KEYWORD, .op = &mode_op }, { "__mode__", NS_KEYWORD, .op = &mode_op }, ! { "QI", NS_KEYWORD, .op = &mode_QI_op }, ! { "__QI__", NS_KEYWORD, .op = &mode_QI_op }, ! { "HI", NS_KEYWORD, .op = &mode_HI_op }, ! { "__HI__", NS_KEYWORD, .op = &mode_HI_op }, { "SI", NS_KEYWORD, .op = &mode_SI_op }, { "__SI__", NS_KEYWORD, .op = &mode_SI_op }, ! { "DI", NS_KEYWORD, .op = &mode_DI_op }, ! { "__DI__", NS_KEYWORD, .op = &mode_DI_op }, ! { "TI", NS_KEYWORD, .op = &mode_TI_op }, ! { "__TI__", NS_KEYWORD, .op = &mode_TI_op }, ! { "byte", NS_KEYWORD, .op = &mode_QI_op }, ! { "__byte__", NS_KEYWORD, .op = &mode_QI_op }, ! { "pointer", NS_KEYWORD, .op = &mode_pointer_op }, ! { "__pointer__",NS_KEYWORD, .op = &mode_pointer_op }, ! { "word", NS_KEYWORD, .op = &mode_word_op }, ! { "__word__", NS_KEYWORD, .op = &mode_word_op }, }; static const char *ignored_attributes[] = {
*** 765,852 **** static struct token *union_specifier(struct token *token, struct decl_state *ctx) { return struct_union_enum_specifier(SYM_UNION, token, ctx, parse_union_declaration); } ! ! typedef struct { ! int x; ! unsigned long long y; ! } Num; ! ! static void upper_boundary(Num *n, Num *v) { ! if (n->x > v->x) ! return; ! if (n->x < v->x) { ! *n = *v; ! return; ! } ! if (n->y < v->y) ! n->y = v->y; } ! static void lower_boundary(Num *n, Num *v) { ! if (n->x < v->x) ! return; ! if (n->x > v->x) { ! *n = *v; ! return; } - if (n->y > v->y) - n->y = v->y; } ! static int type_is_ok(struct symbol *type, Num *upper, Num *lower) { int shift = type->bit_size; int is_unsigned = type->ctype.modifiers & MOD_UNSIGNED; if (!is_unsigned) shift--; ! if (upper->x == 0 && upper->y >> shift) return 0; ! if (lower->x == 0 || (!is_unsigned && (~lower->y >> shift) == 0)) return 1; return 0; } ! static struct symbol *bigger_enum_type(struct symbol *s1, struct symbol *s2) { ! if (s1->bit_size < s2->bit_size) { ! s1 = s2; ! } else if (s1->bit_size == s2->bit_size) { ! if (s2->ctype.modifiers & MOD_UNSIGNED) ! s1 = s2; } ! if (s1->bit_size < bits_in_int) ! return &int_ctype; ! return s1; } static void cast_enum_list(struct symbol_list *list, struct symbol *base_type) { struct symbol *sym; FOR_EACH_PTR(list, sym) { struct expression *expr = sym->initializer; struct symbol *ctype; if (expr->type != EXPR_VALUE) continue; ctype = expr->ctype; ! if (ctype->bit_size == base_type->bit_size) continue; cast_value(expr, base_type, expr, ctype); } END_FOR_EACH_PTR(sym); } static struct token *parse_enum_declaration(struct token *token, struct symbol *parent) { unsigned long long lastval = 0; struct symbol *ctype = NULL, *base_type = NULL; ! Num upper = {-1, 0}, lower = {1, 0}; parent->examined = 1; parent->ctype.base_type = &int_ctype; while (token_type(token) == TOKEN_IDENT) { struct expression *expr = NULL; --- 806,926 ---- static struct token *union_specifier(struct token *token, struct decl_state *ctx) { return struct_union_enum_specifier(SYM_UNION, token, ctx, parse_union_declaration); } ! /// ! // safe right shift ! // ! // This allow to use a shift amount as big (or bigger) ! // than the width of the value to be shifted, in which case ! // the result is, of course, 0. ! static unsigned long long rshift(unsigned long long val, unsigned int n) { ! if (n >= (sizeof(val) * 8)) ! return 0; ! return val >> n; } ! struct range { ! long long neg; ! unsigned long long pos; ! }; ! ! static void update_range(struct range *range, unsigned long long uval, struct symbol *vtype) { ! long long sval = uval; ! ! if (is_signed_type(vtype) && (sval < 0)) { ! if (sval < range->neg) ! range->neg = sval; ! } else { ! if (uval > range->pos) ! range->pos = uval; } } ! static int type_is_ok(struct symbol *type, struct range range) { int shift = type->bit_size; int is_unsigned = type->ctype.modifiers & MOD_UNSIGNED; if (!is_unsigned) shift--; ! if (rshift(range.pos, shift)) return 0; ! if (range.neg == 0) return 1; + if (is_unsigned) return 0; + if (rshift(~range.neg, shift)) + return 0; + return 1; } ! static struct range type_range(struct symbol *type) { ! struct range range; ! unsigned int size = type->bit_size; ! unsigned long long max; ! long long min; ! ! if (is_signed_type(type)) { ! min = sign_bit(size); ! max = min - 1; ! } else { ! min = 0; ! max = bits_mask(size); } ! ! range.pos = max; ! range.neg = min; ! return range; } + static int val_in_range(struct range *range, long long sval, struct symbol *vtype) + { + unsigned long long uval = sval; + + if (is_signed_type(vtype) && (sval < 0)) + return range->neg <= sval; + else + return uval <= range->pos; + } + static void cast_enum_list(struct symbol_list *list, struct symbol *base_type) { + struct range irange = type_range(&int_ctype); struct symbol *sym; FOR_EACH_PTR(list, sym) { struct expression *expr = sym->initializer; struct symbol *ctype; + long long val; if (expr->type != EXPR_VALUE) continue; ctype = expr->ctype; ! val = get_expression_value(expr); ! if (is_int_type(ctype) && val_in_range(&irange, val, ctype)) { ! expr->ctype = &int_ctype; continue; + } + if (ctype->bit_size == base_type->bit_size) { + expr->ctype = base_type; + continue; + } cast_value(expr, base_type, expr, ctype); + expr->ctype = base_type; } END_FOR_EACH_PTR(sym); } static struct token *parse_enum_declaration(struct token *token, struct symbol *parent) { unsigned long long lastval = 0; struct symbol *ctype = NULL, *base_type = NULL; ! struct range range = { }; ! int mix_bitwise = 0; parent->examined = 1; parent->ctype.base_type = &int_ctype; while (token_type(token) == TOKEN_IDENT) { struct expression *expr = NULL;
*** 898,927 **** * - if enums are of different types, they * all have to be integer types, and the * base type is at least "int_ctype". * - otherwise the base_type is "bad_ctype". */ ! if (!base_type) { base_type = ctype; } else if (ctype == base_type) { /* nothing */ } else if (is_int_type(base_type) && is_int_type(ctype)) { ! base_type = bigger_enum_type(base_type, ctype); ! } else base_type = &bad_ctype; parent->ctype.base_type = base_type; } if (is_int_type(base_type)) { ! Num v = {.y = lastval}; ! if (ctype->ctype.modifiers & MOD_UNSIGNED) ! v.x = 0; ! else if ((long long)lastval >= 0) ! v.x = 0; ! else ! v.x = -1; ! upper_boundary(&upper, &v); ! lower_boundary(&lower, &v); } token = next; sym->endpos = token->pos; --- 972,1004 ---- * - if enums are of different types, they * all have to be integer types, and the * base type is at least "int_ctype". * - otherwise the base_type is "bad_ctype". */ ! if (!base_type || ctype == &bad_ctype) { base_type = ctype; } else if (ctype == base_type) { /* nothing */ } else if (is_int_type(base_type) && is_int_type(ctype)) { ! base_type = &int_ctype; ! } else if (is_restricted_type(base_type) != is_restricted_type(ctype)) { ! if (!mix_bitwise++) { ! warning(expr->pos, "mixed bitwiseness"); ! } ! } else if (is_restricted_type(base_type) && base_type != ctype) { ! sparse_error(expr->pos, "incompatible restricted type"); ! info(expr->pos, " expected: %s", show_typename(base_type)); ! info(expr->pos, " got: %s", show_typename(ctype)); base_type = &bad_ctype; + } else if (base_type != &bad_ctype) { + sparse_error(token->pos, "bad enum definition"); + base_type = &bad_ctype; + } parent->ctype.base_type = base_type; } if (is_int_type(base_type)) { ! update_range(&range, lastval, ctype); } token = next; sym->endpos = token->pos;
*** 928,962 **** if (!match_op(token, ',')) break; token = token->next; } if (!base_type) { ! sparse_error(token->pos, "bad enum definition"); base_type = &bad_ctype; } else if (!is_int_type(base_type)) ! base_type = base_type; ! else if (type_is_ok(base_type, &upper, &lower)) ! base_type = base_type; ! else if (type_is_ok(&int_ctype, &upper, &lower)) ! base_type = &int_ctype; ! else if (type_is_ok(&uint_ctype, &upper, &lower)) base_type = &uint_ctype; ! else if (type_is_ok(&long_ctype, &upper, &lower)) ! base_type = &long_ctype; ! else if (type_is_ok(&ulong_ctype, &upper, &lower)) base_type = &ulong_ctype; ! else if (type_is_ok(&llong_ctype, &upper, &lower)) ! base_type = &llong_ctype; ! else if (type_is_ok(&ullong_ctype, &upper, &lower)) base_type = &ullong_ctype; else base_type = &bad_ctype; parent->ctype.base_type = base_type; parent->ctype.modifiers |= (base_type->ctype.modifiers & MOD_UNSIGNED); parent->examined = 0; cast_enum_list(parent->symbol_list, base_type); return token; } --- 1005,1039 ---- if (!match_op(token, ',')) break; token = token->next; } if (!base_type) { ! sparse_error(token->pos, "empty enum definition"); base_type = &bad_ctype; } else if (!is_int_type(base_type)) ! ; ! else if (type_is_ok(&uint_ctype, range)) base_type = &uint_ctype; ! else if (type_is_ok(&int_ctype, range)) ! base_type = &int_ctype; ! else if (type_is_ok(&ulong_ctype, range)) base_type = &ulong_ctype; ! else if (type_is_ok(&long_ctype, range)) ! base_type = &long_ctype; ! else if (type_is_ok(&ullong_ctype, range)) base_type = &ullong_ctype; + else if (type_is_ok(&llong_ctype, range)) + base_type = &llong_ctype; else base_type = &bad_ctype; parent->ctype.base_type = base_type; parent->ctype.modifiers |= (base_type->ctype.modifiers & MOD_UNSIGNED); parent->examined = 0; + if (mix_bitwise) + return token; cast_enum_list(parent->symbol_list, base_type); return token; }
*** 1041,1069 **** { apply_qualifier(&token->pos, &ctx->ctype, attr->ctype.modifiers); return token; } static struct token *attribute_bitwise(struct token *token, struct symbol *attr, struct decl_state *ctx) { if (Wbitwise) attribute_modifier(token, attr, ctx); return token; } static struct token *attribute_address_space(struct token *token, struct symbol *attr, struct decl_state *ctx) { struct expression *expr = NULL; ! int as; token = expect(token, '(', "after address_space attribute"); ! token = conditional_expression(token, &expr); ! if (expr) { ! as = const_expression_value(expr); ! if (Waddress_space && as) ctx->ctype.as = as; } ! token = expect(token, ')', "after address_space attribute"); return token; } static struct symbol *to_QI_mode(struct symbol *ctype) { --- 1118,1183 ---- { apply_qualifier(&token->pos, &ctx->ctype, attr->ctype.modifiers); return token; } + static struct token *attribute_ext_visible(struct token *token, struct symbol *attr, struct decl_state *ctx) + { + ctx->is_ext_visible = 1; + return token; + } + static struct token *attribute_bitwise(struct token *token, struct symbol *attr, struct decl_state *ctx) { if (Wbitwise) attribute_modifier(token, attr, ctx); return token; } + static struct ident *numerical_address_space(int asn) + { + char buff[32]; + + if (!asn) + return NULL; + sprintf(buff, "<asn:%d>", asn); + return built_in_ident(buff); + } + static struct token *attribute_address_space(struct token *token, struct symbol *attr, struct decl_state *ctx) { struct expression *expr = NULL; ! struct ident *as = NULL; ! struct token *next; ! token = expect(token, '(', "after address_space attribute"); ! switch (token_type(token)) { ! case TOKEN_NUMBER: ! next = primary_expression(token, &expr); ! if (expr->type != EXPR_VALUE) ! goto invalid; ! as = numerical_address_space(expr->value); ! break; ! case TOKEN_IDENT: ! next = token->next; ! as = token->ident; ! break; ! default: ! next = token->next; ! invalid: ! as = NULL; ! warning(token->pos, "invalid address space name"); ! } ! ! if (Waddress_space && as) { ! if (ctx->ctype.as) ! sparse_error(token->pos, ! "multiple address space given: %s & %s", ! show_as(ctx->ctype.as), show_as(as)); ctx->ctype.as = as; } ! token = expect(next, ')', "after address_space attribute"); return token; } static struct symbol *to_QI_mode(struct symbol *ctype) {
*** 1105,1114 **** --- 1219,1236 ---- return NULL; return ctype->ctype.modifiers & MOD_UNSIGNED ? &ulllong_ctype : &slllong_ctype; } + static struct symbol *to_pointer_mode(struct symbol *ctype) + { + if (ctype->ctype.base_type != &int_type) + return NULL; + return ctype->ctype.modifiers & MOD_UNSIGNED ? uintptr_ctype + : intptr_ctype; + } + static struct symbol *to_word_mode(struct symbol *ctype) { if (ctype->ctype.base_type != &int_type) return NULL; return ctype->ctype.modifiers & MOD_UNSIGNED ? &ulong_ctype
*** 1121,1131 **** if (token_type(token) == TOKEN_IDENT) { struct symbol *mode = lookup_keyword(token->ident, NS_KEYWORD); if (mode && mode->op->type == KW_MODE) ctx->mode = mode->op; else ! sparse_error(token->pos, "unknown mode attribute %s\n", show_ident(token->ident)); token = token->next; } else sparse_error(token->pos, "expect attribute mode symbol\n"); token = expect(token, ')', "after mode attribute"); return token; --- 1243,1253 ---- if (token_type(token) == TOKEN_IDENT) { struct symbol *mode = lookup_keyword(token->ident, NS_KEYWORD); if (mode && mode->op->type == KW_MODE) ctx->mode = mode->op; else ! sparse_error(token->pos, "unknown mode attribute %s", show_ident(token->ident)); token = token->next; } else sparse_error(token->pos, "expect attribute mode symbol\n"); token = expect(token, ')', "after mode attribute"); return token;
*** 1133,1179 **** static struct token *attribute_context(struct token *token, struct symbol *attr, struct decl_state *ctx) { struct context *context = alloc_context(); struct expression *args[3]; ! int argc = 0; token = expect(token, '(', "after context attribute"); ! while (!match_op(token, ')')) { ! struct expression *expr = NULL; ! token = conditional_expression(token, &expr); ! if (!expr) ! break; ! if (argc < 3) ! args[argc++] = expr; ! if (!match_op(token, ',')) ! break; token = token->next; ! } ! ! switch(argc) { ! case 0: ! sparse_error(token->pos, "expected context input/output values"); ! break; ! case 1: ! context->in = get_expression_value(args[0]); ! break; ! case 2: ! context->in = get_expression_value(args[0]); ! context->out = get_expression_value(args[1]); ! break; ! case 3: context->context = args[0]; ! context->in = get_expression_value(args[1]); ! context->out = get_expression_value(args[2]); ! break; } ! ! if (argc) add_ptr_list(&ctx->ctype.contexts, context); - - token = expect(token, ')', "after context attribute"); return token; } static struct token *attribute_designated_init(struct token *token, struct symbol *attr, struct decl_state *ctx) { --- 1255,1282 ---- static struct token *attribute_context(struct token *token, struct symbol *attr, struct decl_state *ctx) { struct context *context = alloc_context(); struct expression *args[3]; ! int idx = 0; token = expect(token, '(', "after context attribute"); ! token = conditional_expression(token, &args[0]); ! token = expect(token, ',', "after context 1st argument"); ! token = conditional_expression(token, &args[1]); ! if (match_op(token, ',')) { token = token->next; ! token = conditional_expression(token, &args[2]); ! token = expect(token, ')', "after context 3rd argument"); context->context = args[0]; ! idx++; ! } else { ! token = expect(token, ')', "after context 2nd argument"); } ! context->in = get_expression_value(args[idx++]); ! context->out = get_expression_value(args[idx++]); add_ptr_list(&ctx->ctype.contexts, context); return token; } static struct token *attribute_designated_init(struct token *token, struct symbol *attr, struct decl_state *ctx) {
*** 1199,1209 **** static struct token *recover_unknown_attribute(struct token *token) { struct expression *expr = NULL; if (Wunknown_attribute) ! warning(token->pos, "attribute '%s': unknown attribute", show_ident(token->ident)); token = token->next; if (match_op(token, '(')) token = parens_expression(token, &expr, "in attribute"); return token; } --- 1302,1312 ---- static struct token *recover_unknown_attribute(struct token *token) { struct expression *expr = NULL; if (Wunknown_attribute) ! warning(token->pos, "unknown attribute '%s'", show_ident(token->ident)); token = token->next; if (match_op(token, '(')) token = parens_expression(token, &expr, "in attribute"); return token; }
*** 1258,1268 **** [SExtern] = MOD_EXTERN, [SStatic] = MOD_STATIC, [SRegister] = MOD_REGISTER }; return mod[ctx->storage_class] | (ctx->is_inline ? MOD_INLINE : 0) ! | (ctx->is_tls ? MOD_TLS : 0); } static void set_storage_class(struct position *pos, struct decl_state *ctx, int class) { /* __thread can be used alone, or with extern or static */ --- 1361,1372 ---- [SExtern] = MOD_EXTERN, [SStatic] = MOD_STATIC, [SRegister] = MOD_REGISTER }; return mod[ctx->storage_class] | (ctx->is_inline ? MOD_INLINE : 0) ! | (ctx->is_tls ? MOD_TLS : 0) ! | (ctx->is_ext_visible ? MOD_EXT_VISIBLE : 0); } static void set_storage_class(struct position *pos, struct decl_state *ctx, int class) { /* __thread can be used alone, or with extern or static */
*** 1389,1398 **** --- 1493,1514 ---- { apply_qualifier(&next->pos, &ctx->ctype, MOD_VOLATILE); return next; } + static struct token *restrict_qualifier(struct token *next, struct decl_state *ctx) + { + apply_qualifier(&next->pos, &ctx->ctype, MOD_RESTRICT); + return next; + } + + static struct token *atomic_qualifier(struct token *next, struct decl_state *ctx) + { + apply_qualifier(&next->pos, &ctx->ctype, MOD_ATOMIC); + return next; + } + static void apply_ctype(struct position pos, struct ctype *thistype, struct ctype *ctype) { unsigned long mod = thistype->modifiers; if (mod)
*** 1703,1713 **** if (token_type(next) != TOKEN_SPECIAL) return Bad_Func; if (next->special == ')') { /* don't complain about those */ - if (!n || match_op(next->next, ';')) if (!n || match_op(next->next, ';') || match_op(next->next, ',')) return Empty; if (Wstrict_prototypes) warning(next->pos, "non-ANSI function declaration of function '%s'", --- 1819,1828 ----
*** 1779,1789 **** ptr->ctype.base_type = ctx->ctype.base_type; ptr->ctype.as = ctx->ctype.as; ptr->ctype.contexts = ctx->ctype.contexts; ctx->ctype.modifiers = 0; ctx->ctype.base_type = ptr; ! ctx->ctype.as = 0; ctx->ctype.contexts = NULL; ctx->ctype.alignment = 0; token = handle_qualifiers(token->next, ctx); ctx->ctype.base_type->endpos = token->pos; --- 1894,1904 ---- ptr->ctype.base_type = ctx->ctype.base_type; ptr->ctype.as = ctx->ctype.as; ptr->ctype.contexts = ctx->ctype.contexts; ctx->ctype.modifiers = 0; ctx->ctype.base_type = ptr; ! ctx->ctype.as = NULL; ctx->ctype.contexts = NULL; ctx->ctype.alignment = 0; token = handle_qualifiers(token->next, ctx); ctx->ctype.base_type->endpos = token->pos;
*** 1962,1989 **** } static struct token *parse_asm_operands(struct token *token, struct statement *stmt, struct expression_list **inout) { - struct expression *expr; - /* Allow empty operands */ if (match_op(token->next, ':') || match_op(token->next, ')')) return token->next; do { ! struct ident *ident = NULL; if (match_op(token->next, '[') && token_type(token->next->next) == TOKEN_IDENT && match_op(token->next->next->next, ']')) { ! ident = token->next->next->ident; token = token->next->next->next; } ! add_expression(inout, (struct expression *)ident); /* UGGLEE!!! */ ! token = primary_expression(token->next, &expr); ! add_expression(inout, expr); ! token = parens_expression(token, &expr, "in asm parameter"); ! add_expression(inout, expr); } while (match_op(token, ',')); return token; } static struct token *parse_asm_clobbers(struct token *token, struct statement *stmt, --- 2077,2100 ---- } static struct token *parse_asm_operands(struct token *token, struct statement *stmt, struct expression_list **inout) { /* Allow empty operands */ if (match_op(token->next, ':') || match_op(token->next, ')')) return token->next; do { ! struct expression *op = alloc_expression(token->pos, EXPR_ASM_OPERAND); if (match_op(token->next, '[') && token_type(token->next->next) == TOKEN_IDENT && match_op(token->next->next->next, ']')) { ! op->name = token->next->next->ident; token = token->next->next->next; } ! token = primary_expression(token->next, &op->constraint); ! token = parens_expression(token, &op->expr, "in asm parameter"); ! add_expression(inout, op); } while (match_op(token, ',')); return token; } static struct token *parse_asm_clobbers(struct token *token, struct statement *stmt,
*** 2015,2044 **** return token; } static struct token *parse_asm_statement(struct token *token, struct statement *stmt) { ! int is_goto = 0; token = token->next; stmt->type = STMT_ASM; ! if (match_idents(token, &__volatile___ident, &__volatile_ident, &volatile_ident, NULL)) { token = token->next; } - if (token_type(token) == TOKEN_IDENT && token->ident == &goto_ident) { - is_goto = 1; - token = token->next; - } token = expect(token, '(', "after asm"); token = parse_expression(token, &stmt->asm_string); if (match_op(token, ':')) token = parse_asm_operands(token, stmt, &stmt->asm_outputs); if (match_op(token, ':')) token = parse_asm_operands(token, stmt, &stmt->asm_inputs); if (match_op(token, ':')) token = parse_asm_clobbers(token, stmt, &stmt->asm_clobbers); ! if (is_goto && match_op(token, ':')) token = parse_asm_labels(token, stmt, &stmt->asm_labels); token = expect(token, ')', "after asm"); return expect(token, ';', "at end of asm-statement"); } --- 2126,2156 ---- return token; } static struct token *parse_asm_statement(struct token *token, struct statement *stmt) { ! unsigned long mods = 0; token = token->next; stmt->type = STMT_ASM; ! while (token_type(token) == TOKEN_IDENT) { ! struct symbol *s = lookup_keyword(token->ident, NS_TYPEDEF); ! if (s && s->op && s->op->asm_modifier) ! s->op->asm_modifier(token, &mods); ! else if (token->ident == &goto_ident) ! asm_modifier(token, &mods, MOD_ASM_GOTO); token = token->next; } token = expect(token, '(', "after asm"); token = parse_expression(token, &stmt->asm_string); if (match_op(token, ':')) token = parse_asm_operands(token, stmt, &stmt->asm_outputs); if (match_op(token, ':')) token = parse_asm_operands(token, stmt, &stmt->asm_inputs); if (match_op(token, ':')) token = parse_asm_clobbers(token, stmt, &stmt->asm_clobbers); ! if (match_op(token, ':') && (mods & MOD_ASM_GOTO)) token = parse_asm_labels(token, stmt, &stmt->asm_labels); token = expect(token, ')', "after asm"); return expect(token, ';', "at end of asm-statement"); }
*** 2127,2137 **** struct statement *stmt = alloc_statement(sym->pos, STMT_COMPOUND); start_function_scope(sym->pos); ret = alloc_symbol(sym->pos, SYM_NODE); ret->ctype = sym->ctype.base_type->ctype; ! ret->ctype.modifiers &= ~(MOD_STORAGE | MOD_CONST | MOD_VOLATILE | MOD_TLS | MOD_INLINE | MOD_ADDRESSABLE | MOD_NOCAST | MOD_NODEREF | MOD_ACCESSED | MOD_TOPLEVEL); ret->ctype.modifiers |= (MOD_AUTO | MOD_REGISTER); bind_symbol(ret, &return_ident, NS_ITERATOR); stmt->ret = ret; fn_local_symbol(ret); --- 2239,2249 ---- struct statement *stmt = alloc_statement(sym->pos, STMT_COMPOUND); start_function_scope(sym->pos); ret = alloc_symbol(sym->pos, SYM_NODE); ret->ctype = sym->ctype.base_type->ctype; ! ret->ctype.modifiers &= ~(MOD_STORAGE | MOD_QUALIFIER | MOD_TLS | MOD_ACCESS | MOD_NOCAST | MOD_NODEREF); ret->ctype.modifiers |= (MOD_AUTO | MOD_REGISTER); bind_symbol(ret, &return_ident, NS_ITERATOR); stmt->ret = ret; fn_local_symbol(ret);
*** 2370,2399 **** } static struct token *parse_context_statement(struct token *token, struct statement *stmt) { stmt->type = STMT_CONTEXT; ! token = parse_expression(token->next, &stmt->expression); ! if (stmt->expression->type == EXPR_PREOP ! && stmt->expression->op == '(' ! && stmt->expression->unop->type == EXPR_COMMA) { ! struct expression *expr; ! expr = stmt->expression->unop; ! stmt->context = expr->left; ! stmt->expression = expr->right; } return expect(token, ';', "at end of statement"); } static struct token *parse_range_statement(struct token *token, struct statement *stmt) { stmt->type = STMT_RANGE; ! token = assignment_expression(token->next, &stmt->range_expression); token = expect(token, ',', "after range expression"); token = assignment_expression(token, &stmt->range_low); token = expect(token, ',', "after low range"); token = assignment_expression(token, &stmt->range_high); return expect(token, ';', "after range statement"); } static struct token *statement(struct token *token, struct statement **tree) { --- 2482,2518 ---- } static struct token *parse_context_statement(struct token *token, struct statement *stmt) { stmt->type = STMT_CONTEXT; ! token = token->next; ! token = expect(token, '(', "after __context__ statement"); ! token = assignment_expression(token, &stmt->expression); ! if (!stmt->expression) ! unexpected(token, "expression expected after '('"); ! if (match_op(token, ',')) { ! token = token->next; ! stmt->context = stmt->expression; ! token = assignment_expression(token, &stmt->expression); ! if (!stmt->expression) ! unexpected(token, "expression expected after ','"); } + token = expect(token, ')', "at end of __context__ statement"); return expect(token, ';', "at end of statement"); } static struct token *parse_range_statement(struct token *token, struct statement *stmt) { stmt->type = STMT_RANGE; ! token = token->next; ! token = expect(token, '(', "after __range__ statement"); ! token = assignment_expression(token, &stmt->range_expression); token = expect(token, ',', "after range expression"); token = assignment_expression(token, &stmt->range_low); token = expect(token, ',', "after low range"); token = assignment_expression(token, &stmt->range_high); + token = expect(token, ')', "after range statement"); return expect(token, ';', "after range statement"); } static struct token *statement(struct token *token, struct statement **tree) {
*** 2405,2420 **** if (s && s->op->statement) return s->op->statement(token, stmt); if (match_op(token->next, ':')) { struct symbol *s = label_symbol(token); stmt->type = STMT_LABEL; stmt->label_identifier = s; - if (s->stmt) - sparse_error(stmt->pos, "label '%s' redefined", show_ident(token->ident)); s->stmt = stmt; - token = skip_attributes(token->next->next); return statement(token, &stmt->label_statement); } } if (match_op(token, '{')) { --- 2524,2542 ---- if (s && s->op->statement) return s->op->statement(token, stmt); if (match_op(token->next, ':')) { struct symbol *s = label_symbol(token); + token = skip_attributes(token->next->next); + if (s->stmt) { + sparse_error(stmt->pos, "label '%s' redefined", show_ident(s->ident)); + // skip the label to avoid multiple definitions + return statement(token, tree); + } stmt->type = STMT_LABEL; stmt->label_identifier = s; s->stmt = stmt; return statement(token, &stmt->label_statement); } } if (match_op(token, '{')) {
*** 2695,2709 **** p = &base_type->stmt; } function_computed_target_list = NULL; function_computed_goto_list = NULL; ! if (decl->ctype.modifiers & MOD_EXTERN && ! !(decl->ctype.modifiers & MOD_INLINE) && ! Wexternal_function_has_definition) warning(decl->pos, "function '%s' with external linkage has definition", show_ident(decl->ident)); ! if (!(decl->ctype.modifiers & MOD_STATIC)) decl->ctype.modifiers |= MOD_EXTERN; stmt = start_function(decl); --- 2817,2830 ---- p = &base_type->stmt; } function_computed_target_list = NULL; function_computed_goto_list = NULL; ! if ((decl->ctype.modifiers & (MOD_EXTERN|MOD_INLINE)) == MOD_EXTERN) { ! if (Wexternal_function_has_definition) warning(decl->pos, "function '%s' with external linkage has definition", show_ident(decl->ident)); ! } if (!(decl->ctype.modifiers & MOD_STATIC)) decl->ctype.modifiers |= MOD_EXTERN; stmt = start_function(decl);
*** 2775,2785 **** } END_FOR_EACH_PTR(type); if (Wimplicit_int) { sparse_error(arg->pos, "missing type declaration for parameter '%s'", show_ident(arg->ident)); } ! continue; match: type->used = 1; /* "char" and "short" promote to "int" */ promote_k_r_types(type); --- 2896,2908 ---- } END_FOR_EACH_PTR(type); if (Wimplicit_int) { sparse_error(arg->pos, "missing type declaration for parameter '%s'", show_ident(arg->ident)); } ! type = alloc_symbol(arg->pos, SYM_NODE); ! type->ident = arg->ident; ! type->ctype.base_type = &int_ctype; match: type->used = 1; /* "char" and "short" promote to "int" */ promote_k_r_types(type);
*** 2948,2958 **** --- 3071,3085 ---- } check_declaration(decl); if (decl->same_symbol) { decl->definition = decl->same_symbol->definition; decl->op = decl->same_symbol->op; + if (is_typedef) { + // TODO: handle -std=c89 --pedantic + check_duplicates(decl); } + } if (!match_op(token, ',')) break; token = token->next;