X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=b637dd25e556220b5ed97be847590d566012c401;hb=779610287a11b207e958e31a29f0dd9ea5459e39;hp=d3f650eaed1d48c698efd4e5c057efbc7391e1ce;hpb=ce3658440838ab4d730c4c9461705283b887cb1a;p=cparser diff --git a/parser.c b/parser.c index d3f650e..b637dd2 100644 --- a/parser.c +++ b/parser.c @@ -1,21 +1,6 @@ /* * This file is part of cparser. - * Copyright (C) 2007-2009 Matthias Braun - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * Copyright (C) 2012 Matthias Braun */ #include @@ -25,24 +10,24 @@ #include #include "adt/strutil.h" +#include "adt/util.h" #include "parser.h" #include "diagnostic.h" #include "format_check.h" #include "preprocessor.h" #include "symbol_t.h" +#include "symbol_table.h" #include "token_t.h" #include "types.h" #include "type_t.h" #include "type_hash.h" #include "ast_t.h" -#include "entity_t.h" #include "attribute_t.h" #include "lang_features.h" #include "walk.h" #include "warning.h" #include "printer.h" #include "ast2firm.h" -#include "adt/bitfiddle.h" #include "adt/error.h" #include "adt/array.h" @@ -59,7 +44,6 @@ typedef struct declaration_specifiers_t declaration_specifiers_t; struct declaration_specifiers_t { position_t pos; storage_class_t storage_class; - unsigned char alignment; /**< Alignment, 0 if not set. */ bool is_inline : 1; bool thread_local : 1; attribute_t *attributes; /**< list of attributes */ @@ -173,7 +157,8 @@ typedef enum declarator_flags_t { static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, declarator_flags_t flags); -static void semantic_comparison(binary_expression_t *expression); +static void semantic_comparison(binary_expression_t *expression, + bool is_relational); #define STORAGE_CLASSES \ STORAGE_CLASSES_NO_EXTERN \ @@ -273,7 +258,9 @@ static void semantic_comparison(binary_expression_t *expression); case T_false: \ case T_sizeof: \ case T_throw: \ - case T_true: + case T_true: \ + case T___imag__: \ + case T___real__: /** * Returns the size of a statement node. @@ -843,13 +830,6 @@ static void label_pop_to(size_t new_top) stack_pop_to(&label_stack, new_top); } -static atomic_type_kind_t get_akind(const type_t *type) -{ - assert(type->kind == TYPE_ATOMIC || type->kind == TYPE_COMPLEX - || type->kind == TYPE_IMAGINARY || type->kind == TYPE_ENUM); - return type->atomic.akind; -} - /** * §6.3.1.1:2 Do integer promotion for a given type. * @@ -858,7 +838,8 @@ static atomic_type_kind_t get_akind(const type_t *type) */ static type_t *promote_integer(type_t *type) { - if (get_akind_rank(get_akind(type)) < get_akind_rank(ATOMIC_TYPE_INT)) + atomic_type_kind_t akind = get_arithmetic_akind(type); + if (get_akind_rank(akind) < get_akind_rank(ATOMIC_TYPE_INT)) type = type_int; return type; @@ -874,18 +855,17 @@ static bool is_null_pointer_constant(const expression_t *expression) /* skip void* cast */ if (expression->kind == EXPR_UNARY_CAST) { type_t *const type = skip_typeref(expression->base.type); - if (types_compatible(type, type_void_ptr)) + if (type == type_void_ptr) expression = expression->unary.value; } - type_t *const type = skip_typeref(expression->base.type); - if (!is_type_integer(type)) - return false; switch (is_constant_expression(expression)) { - case EXPR_CLASS_ERROR: return true; - case EXPR_CLASS_CONSTANT: return !fold_constant_to_bool(expression); - default: return false; + case EXPR_CLASS_VARIABLE: return false; + case EXPR_CLASS_ERROR: return true; + case EXPR_CLASS_CONSTANT: return false; + case EXPR_CLASS_INTEGER_CONSTANT: return !fold_constant_to_bool(expression); } + panic("invalid expression classification"); } /** @@ -1447,6 +1427,8 @@ static void mark_vars_read(expression_t *const expr, entity_t *lhs_ent) case EXPR_UNARY_PREFIX_INCREMENT: case EXPR_UNARY_PREFIX_DECREMENT: case EXPR_UNARY_ASSUME: + case EXPR_UNARY_IMAG: + case EXPR_UNARY_REAL: unary: mark_vars_read(expr->unary.value, lhs_ent); return; @@ -1536,7 +1518,13 @@ static designator_t *parse_designation(void) designator->pos = *HERE; eat('['); add_anchor_token(']'); + add_anchor_token(T_DOTDOTDOT); designator->array_index = parse_constant_expression(); + if (accept(T_DOTDOTDOT)) { + designator->range_last = parse_constant_expression(); + errorf(&designator->pos, "range initializer not supported"); + } + rem_anchor_token(T_DOTDOTDOT); rem_anchor_token(']'); expect(']'); break; @@ -1848,7 +1836,7 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, } } else { expression_t *array_index = designator->array_index; - if (is_constant_expression(array_index) != EXPR_CLASS_CONSTANT) + if (is_constant_expression(array_index) < EXPR_CLASS_CONSTANT) return true; if (!is_type_array(type)) { @@ -2118,9 +2106,7 @@ finish_designator: type_t *first_type = first->type; first_type = skip_typeref(first_type); if (is_type_array(first_type)) { - size_t index = first->v.index; - if (index > path->max_index) - path->max_index = index; + path->max_index = MAX(path->max_index, first->v.index); } /* append to initializers list */ @@ -2861,11 +2847,19 @@ finish_specifiers: specifiers->attributes = parse_attributes(specifiers->attributes); if (type == NULL || (saw_error && type_specifiers != 0)) { + position_t const* const pos = &specifiers->pos; atomic_type_kind_t atomic_type; /* match valid basic types */ - switch (type_specifiers) { + switch (type_specifiers & ~(SPECIFIER_COMPLEX|SPECIFIER_IMAGINARY)) { case SPECIFIER_VOID: + if (type_specifiers & (SPECIFIER_COMPLEX|SPECIFIER_IMAGINARY)) { + if (type_specifiers & SPECIFIER_COMPLEX) + errorf(pos, "_Complex specifier is invalid for void"); + if (type_specifiers & SPECIFIER_IMAGINARY) + errorf(pos, "_Imaginary specifier is invalid for void"); + type_specifiers &= ~(SPECIFIER_COMPLEX|SPECIFIER_IMAGINARY); + } atomic_type = ATOMIC_TYPE_VOID; break; case SPECIFIER_WCHAR_T: @@ -2981,23 +2975,17 @@ warn_about_long_long: atomic_type = ATOMIC_TYPE_LONG_DOUBLE; break; case SPECIFIER_BOOL: + if (type_specifiers & (SPECIFIER_COMPLEX|SPECIFIER_IMAGINARY)) { + if (type_specifiers & SPECIFIER_COMPLEX) + errorf(pos, "_Complex specifier is invalid for _Bool"); + if (type_specifiers & SPECIFIER_IMAGINARY) + errorf(pos, "_Imaginary specifier is invalid for _Bool"); + type_specifiers &= ~(SPECIFIER_COMPLEX|SPECIFIER_IMAGINARY); + } atomic_type = ATOMIC_TYPE_BOOL; break; - case SPECIFIER_FLOAT | SPECIFIER_COMPLEX: - case SPECIFIER_FLOAT | SPECIFIER_IMAGINARY: - atomic_type = ATOMIC_TYPE_FLOAT; - break; - case SPECIFIER_DOUBLE | SPECIFIER_COMPLEX: - case SPECIFIER_DOUBLE | SPECIFIER_IMAGINARY: - atomic_type = ATOMIC_TYPE_DOUBLE; - break; - case SPECIFIER_LONG | SPECIFIER_DOUBLE | SPECIFIER_COMPLEX: - case SPECIFIER_LONG | SPECIFIER_DOUBLE | SPECIFIER_IMAGINARY: - atomic_type = ATOMIC_TYPE_LONG_DOUBLE; - break; default: { /* invalid specifier combination, give an error message */ - position_t const* const pos = &specifiers->pos; if (type_specifiers == 0) { if (!saw_error) { /* ISO/IEC 14882:1998(E) §C.1.5:4 */ @@ -3009,6 +2997,10 @@ warn_about_long_long: errorf(pos, "no type specifiers given in declaration"); } } + } else if (type_specifiers == SPECIFIER_COMPLEX) { + warningf(WARN_OTHER, pos, "_Complex requires a type specifier; assuming '_Complex double'"); + atomic_type = ATOMIC_TYPE_DOUBLE; + break; } else if ((type_specifiers & SPECIFIER_SIGNED) && (type_specifiers & SPECIFIER_UNSIGNED)) { errorf(pos, "signed and unsigned specifiers given"); @@ -3562,7 +3554,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, if (size_expression != NULL) { switch (is_constant_expression(size_expression)) { - case EXPR_CLASS_CONSTANT: { + case EXPR_CLASS_INTEGER_CONSTANT: { long const size = fold_constant_to_int(size_expression); array_type->array.size = size; array_type->array.size_constant = true; @@ -3578,6 +3570,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, break; } + case EXPR_CLASS_CONSTANT: case EXPR_CLASS_VARIABLE: array_type->array.is_vla = true; break; @@ -4075,9 +4068,7 @@ warn_redundant_declaration: ; decl->attributes); if (has_new_attrs) { merge_in_attributes(decl, prev_decl->attributes); - } else if (!is_definition && - is_type_valid(prev_type) && - !pos->is_system_header) { + } else if (!is_definition && is_type_valid(prev_type)) { warningf(WARN_REDUNDANT_DECLS, pos, "redundant declaration for '%N' (declared %P)", entity, ppos); } } else if (current_function == NULL) { @@ -4130,10 +4121,11 @@ error_redeclaration: } } else if (entity->kind == ENTITY_VARIABLE) { if (current_scope == file_scope && - entity->declaration.storage_class == STORAGE_CLASS_NONE && - !entity->declaration.implicit) { + entity->declaration.storage_class == STORAGE_CLASS_NONE && + !entity->declaration.implicit) { warn_missing_declaration: - warningf(WARN_MISSING_DECLARATIONS, pos, "no previous declaration for '%#N'", entity); + if (is_type_valid(skip_typeref(entity->declaration.type))) + warningf(WARN_MISSING_DECLARATIONS, pos, "no previous declaration for '%#N'", entity); } } @@ -4150,13 +4142,13 @@ static void parser_error_multiple_definition(entity_t *entity, errorf(pos, "redefinition of '%N' (declared %P)", entity, &entity->base.pos); } -static bool is_declaration_specifier(const token_t *token) +static bool is_declaration_specifier(token_t const *const tk) { - switch (token->kind) { + switch (tk->kind) { DECLARATION_START return true; case T_IDENTIFIER: - return is_typedef_symbol(token->base.symbol); + return is_typedef_symbol(tk->base.symbol); default: return false; @@ -4592,8 +4584,8 @@ static void check_declarations(void) static int determine_truth(expression_t const* const cond) { return - is_constant_expression(cond) != EXPR_CLASS_CONSTANT ? 0 : - fold_constant_to_bool(cond) ? 1 : + is_constant_expression(cond) < EXPR_CLASS_CONSTANT ? 0 : + fold_constant_to_bool(cond) ? 1 : -1; } @@ -4801,7 +4793,7 @@ static void check_reachable(statement_t *const stmt) if (!expression_returns(expr)) return; - if (is_constant_expression(expr) == EXPR_CLASS_CONSTANT) { + if (is_constant_expression(expr) >= EXPR_CLASS_CONSTANT) { ir_tarval *const val = fold_constant_to_tarval(expr); case_label_statement_t * defaults = NULL; for (case_label_statement_t *i = switchs->first_case; i != NULL; i = i->next) { @@ -5218,42 +5210,42 @@ static void parse_external_declaration(void) return; } - assert(is_declaration(ndeclaration)); - type_t *const orig_type = ndeclaration->declaration.type; - type_t * type = skip_typeref(orig_type); + { + assert(is_declaration(ndeclaration)); + type_t *const orig_type = ndeclaration->declaration.type; + type_t *const type = skip_typeref(orig_type); - if (!is_type_function(type)) { - if (is_type_valid(type)) { - errorf(HERE, "declarator '%#N' has a body but is not a function type", ndeclaration); + if (!is_type_function(type)) { + if (is_type_valid(type)) { + errorf(HERE, "declarator '%#N' has a body but is not a function type", ndeclaration); + } + eat_block(); + return; } - eat_block(); - return; - } - - position_t const *const pos = &ndeclaration->base.pos; - if (is_typeref(orig_type)) { - /* §6.9.1:2 */ - errorf(pos, "type of function definition '%#N' is a typedef", ndeclaration); - } - if (is_type_compound(skip_typeref(type->function.return_type))) { - warningf(WARN_AGGREGATE_RETURN, pos, "'%N' returns an aggregate", ndeclaration); - } - if (type->function.unspecified_parameters) { - warningf(WARN_OLD_STYLE_DEFINITION, pos, "old-style definition of '%N'", ndeclaration); - } else { - warningf(WARN_TRADITIONAL, pos, "traditional C rejects ISO C style definition of '%N'", ndeclaration); - } + position_t const *const pos = &ndeclaration->base.pos; + if (is_typeref(orig_type)) { + /* §6.9.1:2 */ + errorf(pos, "type of function definition '%#N' is a typedef", ndeclaration); + } - /* §6.7.5.3:14 a function definition with () means no - * parameters (and not unspecified parameters) */ - if (type->function.unspecified_parameters && - type->function.parameters == NULL) { - type_t *copy = duplicate_type(type); - copy->function.unspecified_parameters = false; - type = identify_new_type(copy); + if (is_type_compound(skip_typeref(type->function.return_type))) { + warningf(WARN_AGGREGATE_RETURN, pos, "'%N' returns an aggregate", ndeclaration); + } + if (type->function.unspecified_parameters) { + warningf(WARN_OLD_STYLE_DEFINITION, pos, "old-style definition of '%N'", ndeclaration); + } else { + warningf(WARN_TRADITIONAL, pos, "traditional C rejects ISO C style definition of '%N'", ndeclaration); + } - ndeclaration->declaration.type = type; + /* §6.7.5.3:14 a function definition with () means no + * parameters (and not unspecified parameters) */ + if (type->function.unspecified_parameters && + type->function.parameters == NULL) { + type_t *copy = duplicate_type(type); + copy->function.unspecified_parameters = false; + ndeclaration->declaration.type = identify_new_type(copy); + } } entity_t *const entity = record_entity(ndeclaration, true); @@ -5312,8 +5304,7 @@ static void parse_external_declaration(void) walk_statements(body, check_unreachable, NULL); if (noreturn_candidate && !(function->base.modifiers & DM_NORETURN)) { - position_t const *const pos = &body->base.pos; - warningf(WARN_MISSING_NORETURN, pos, "function '%#N' is candidate for attribute 'noreturn'", entity); + warningf(WARN_MISSING_NORETURN, &body->base.pos, "function '%#N' is candidate for attribute 'noreturn'", entity); } } @@ -5391,6 +5382,7 @@ static expression_t *create_select(const position_t *pos, expression_t *addr, check_deprecated(pos, entry); expression_t *select = allocate_expression_zero(EXPR_SELECT); + select->base.pos = *pos; select->select.compound = addr; select->select.compound_entry = entry; @@ -5441,7 +5433,6 @@ static expression_t *find_create_select(const position_t *pos, continue; expression_t *sub_addr = create_select(pos, addr, qualifiers, iter); - sub_addr->base.pos = *pos; sub_addr->base.implicit = true; return find_create_select(pos, sub_addr, qualifiers, sub_compound, symbol); @@ -5469,7 +5460,7 @@ static void parse_bitfield_member(entity_t *entity) type); } - if (is_constant_expression(size) != EXPR_CLASS_CONSTANT) { + if (is_constant_expression(size) < EXPR_CLASS_CONSTANT) { /* error already reported by parse_constant_expression */ size_long = get_type_size(type) * 8; } else { @@ -5504,73 +5495,48 @@ static void parse_compound_declarators(compound_t *compound, add_anchor_token(';'); add_anchor_token(','); do { - entity_t *entity; - - if (token.kind == ':') { - /* anonymous bitfield */ - type_t *type = specifiers->type; - entity_t *const entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, NULL, HERE); - entity->declaration.declared_storage_class = STORAGE_CLASS_NONE; - entity->declaration.storage_class = STORAGE_CLASS_NONE; - entity->declaration.type = type; + entity_t *const entity = parse_declarator(specifiers, DECL_MAY_BE_ABSTRACT | DECL_CREATE_COMPOUND_MEMBER); + position_t const *const pos = &entity->base.pos; + if (entity->kind == ENTITY_TYPEDEF) { + errorf(pos, "typedef not allowed as compound member"); + continue; + } - parse_bitfield_member(entity); + assert(entity->kind == ENTITY_COMPOUND_MEMBER); - attribute_t *attributes = parse_attributes(NULL); - attribute_t **anchor = &attributes; - while (*anchor != NULL) - anchor = &(*anchor)->next; - *anchor = specifiers->attributes; - if (attributes != NULL) { - handle_entity_attributes(attributes, entity); + /* make sure we don't define a symbol multiple times */ + symbol_t *symbol = entity->base.symbol; + if (symbol != NULL) { + entity_t *prev = find_compound_entry(compound, symbol); + if (prev != NULL) { + position_t const *const ppos = &prev->base.pos; + errorf(pos, "multiple declarations of '%N' (declared %P)", entity, ppos); } - entity->declaration.attributes = attributes; - - append_entity(&compound->members, entity); - } else { - entity = parse_declarator(specifiers, - DECL_MAY_BE_ABSTRACT | DECL_CREATE_COMPOUND_MEMBER); - position_t const *const pos = &entity->base.pos; - if (entity->kind == ENTITY_TYPEDEF) { - errorf(pos, "typedef not allowed as compound member"); - } else { - assert(entity->kind == ENTITY_COMPOUND_MEMBER); - - /* make sure we don't define a symbol multiple times */ - symbol_t *symbol = entity->base.symbol; - if (symbol != NULL) { - entity_t *prev = find_compound_entry(compound, symbol); - if (prev != NULL) { - position_t const *const ppos = &prev->base.pos; - errorf(pos, "multiple declarations of '%N' (declared %P)", entity, ppos); - } - } + } - if (token.kind == ':') { - parse_bitfield_member(entity); + if (token.kind == ':') { + parse_bitfield_member(entity); - attribute_t *attributes = parse_attributes(NULL); - handle_entity_attributes(attributes, entity); - } else { - type_t *orig_type = entity->declaration.type; - type_t *type = skip_typeref(orig_type); - if (is_type_function(type)) { - errorf(pos, "'%N' must not have function type '%T'", entity, orig_type); - } else if (is_type_incomplete(type)) { - /* §6.7.2.1:16 flexible array member */ - if (!is_type_array(type) || - token.kind != ';' || - look_ahead(1)->kind != '}') { - errorf(pos, "'%N' has incomplete type '%T'", entity, orig_type); - } else if (compound->members.entities == NULL) { - errorf(pos, "flexible array member in otherwise empty struct"); - } - } + attribute_t *attributes = parse_attributes(NULL); + handle_entity_attributes(attributes, entity); + } else { + type_t *orig_type = entity->declaration.type; + type_t *type = skip_typeref(orig_type); + if (is_type_function(type)) { + errorf(pos, "'%N' must not have function type '%T'", entity, orig_type); + } else if (is_type_incomplete(type)) { + /* §6.7.2.1:16 flexible array member */ + if (!is_type_array(type) || + token.kind != ';' || + look_ahead(1)->kind != '}') { + errorf(pos, "'%N' has incomplete type '%T'", entity, orig_type); + } else if (compound->members.entities == NULL) { + errorf(pos, "flexible array member in otherwise empty struct"); } - - append_entity(&compound->members, entity); } } + + append_entity(&compound->members, entity); } while (accept(',')); rem_anchor_token(','); rem_anchor_token(';'); @@ -5677,78 +5643,77 @@ static expression_t *parse_boolean_literal(bool value) return literal; } -static void warn_traditional_suffix(char const *const suffix) +static void check_number_suffix(expression_t *const expr, char const *const suffix, bool const is_float) { - warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%s' suffix", suffix); -} - -static void check_integer_suffix(expression_t *const expr, char const *const suffix) -{ - unsigned spec = SPECIFIER_NONE; - char const *c = suffix; - for (;;) { + unsigned spec = SPECIFIER_NONE; + for (char const *c = suffix; *c != '\0'; ++c) { specifiers_t add; - if (*c == 'L' || *c == 'l') { + switch (*c) { + case 'F': case 'f': + add = SPECIFIER_FLOAT; + break; + + case 'L': case 'l': add = SPECIFIER_LONG; - if (*c == c[1]) { + if (*c == c[1] && !is_float) { add |= SPECIFIER_LONG_LONG; ++c; } - } else if (*c == 'U' || *c == 'u') { + break; + + case 'U': case 'u': add = SPECIFIER_UNSIGNED; - } else { break; + + case 'I': case 'i': + case 'J': case 'j': + add = SPECIFIER_COMPLEX; + break; + + default: + goto error; } - ++c; if (spec & add) goto error; spec |= add; } - if (*c == '\0') { - type_t *type; - switch (spec) { - case SPECIFIER_NONE: type = type_int; break; - case SPECIFIER_LONG: type = type_long; break; - case SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_long_long; break; - case SPECIFIER_UNSIGNED: type = type_unsigned_int; break; - case SPECIFIER_UNSIGNED | SPECIFIER_LONG: type = type_unsigned_long; break; - case SPECIFIER_UNSIGNED | SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_unsigned_long_long; break; - default: panic("inconsistent suffix"); - } - if (spec != SPECIFIER_NONE && spec != SPECIFIER_LONG) { - warn_traditional_suffix(suffix); - } - expr->base.type = type; - /* Integer type depends on the size of the number and the size - * representable by the types. The backend/codegeneration has to - * determine that. */ - determine_literal_type(&expr->literal); - } else { + if (!(spec & SPECIFIER_FLOAT) && is_float) + spec |= SPECIFIER_DOUBLE; + + if (!(spec & (SPECIFIER_FLOAT | SPECIFIER_DOUBLE)) == is_float) + goto error; + + type_t *type; + switch (spec & ~SPECIFIER_COMPLEX) { + case SPECIFIER_NONE: type = type_int; break; + case SPECIFIER_LONG: type = type_long; break; + case SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_long_long; break; + case SPECIFIER_UNSIGNED: type = type_unsigned_int; break; + case SPECIFIER_UNSIGNED | SPECIFIER_LONG: type = type_unsigned_long; break; + case SPECIFIER_UNSIGNED | SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_unsigned_long_long; break; + case SPECIFIER_FLOAT: type = type_float; break; + case SPECIFIER_DOUBLE: type = type_double; break; + case SPECIFIER_DOUBLE | SPECIFIER_LONG: type = type_long_double; break; + + default: error: - errorf(HERE, "invalid suffix '%s' on integer constant", suffix); + errorf(HERE, "invalid suffix '%s' on %s constant", suffix, is_float ? "floatingpoint" : "integer"); + return; } -} -static void check_floatingpoint_suffix(expression_t *const expr, char const *const suffix) -{ - type_t *type; - char const *c = suffix; - switch (*c) { - case 'F': - case 'f': type = type_float; ++c; break; - case 'L': - case 'l': type = type_long_double; ++c; break; - default: type = type_double; break; - } + if (spec != SPECIFIER_NONE && spec != SPECIFIER_LONG && spec != SPECIFIER_DOUBLE) + warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%s' suffix", suffix); - if (*c == '\0') { - expr->base.type = type; - if (suffix[0] != '\0') { - warn_traditional_suffix(suffix); - } - } else { - errorf(HERE, "invalid suffix '%s' on floatingpoint constant", suffix); + if (spec & SPECIFIER_COMPLEX) + type = make_complex_type(get_arithmetic_akind(type), TYPE_QUALIFIER_NONE); + + expr->base.type = type; + if (!is_float) { + /* Integer type depends on the size of the number and the size + * representable by the types. The backend/codegeneration has to + * determine that. */ + determine_literal_type(&expr->literal); } } @@ -5865,11 +5830,7 @@ done:; errorf(HERE, "invalid digit in %K", &token); } else { expr->literal.suffix = i; - if (is_float) { - check_floatingpoint_suffix(expr, i); - } else { - check_integer_suffix(expr, i); - } + check_number_suffix(expr, i, is_float); } } @@ -6147,7 +6108,8 @@ static bool semantic_cast(expression_t *cast) type_t const *src_type = skip_typeref(orig_type_right); position_t const *pos = &cast->base.pos; - /* §6.5.4 A (void) cast is explicitly permitted, more for documentation than for utility. */ + /* §6.5.4 A (void) cast is explicitly permitted, more for documentation + * than for utility. */ if (is_type_void(dst_type)) return true; @@ -6182,6 +6144,34 @@ static bool semantic_cast(expression_t *cast) return true; } +static void semantic_complex_extract(unary_expression_t *extract) +{ + type_t *orig_value_type = extract->value->base.type; + type_t *value_type = skip_typeref(orig_value_type); + if (!is_type_valid(value_type)) { + extract->base.type = type_error_type; + return; + } + + type_t *type = value_type; + if (!is_type_complex(type)) { + if (!is_type_arithmetic(type)) { + errorf(&extract->base.pos, + "%s requires an argument with complex or arithmetic type, got '%T'", + extract->base.kind == EXPR_UNARY_IMAG ? "__imag__" : "__real__", + orig_value_type); + extract->base.type = type_error_type; + return; + } + atomic_type_kind_t const akind = get_arithmetic_akind(type); + type = make_complex_type(akind, TYPE_QUALIFIER_NONE); + extract->value = create_implicit_cast(extract->value, type); + } + assert(type->kind == TYPE_COMPLEX); + type = make_atomic_type(type->atomic.akind, TYPE_QUALIFIER_NONE); + extract->base.type = type; +} + static expression_t *parse_compound_literal(position_t const *const pos, type_t *type) { @@ -6230,13 +6220,23 @@ static expression_t *parse_cast(void) cast->base.type = type; cast->unary.value = value; - if (! semantic_cast(cast)) { - /* TODO: record the error in the AST. else it is impossible to detect it */ + if (!semantic_cast(cast)) { + cast->base.type = type_error_type; } return cast; } +static expression_t *parse_complex_extract_expression(expression_kind_t const kind) +{ + expression_t *extract = allocate_expression_zero(kind); + next_token(); + + extract->unary.value = parse_subexpression(PREC_CAST); + semantic_complex_extract(&extract->unary); + return extract; +} + /** * Parse a statement expression. */ @@ -6341,9 +6341,6 @@ static designator_t *parse_designator(void) designator->array_index = parse_expression(); rem_anchor_token(']'); expect(']'); - if (designator->array_index == NULL) { - return NULL; - } last_designator->next = designator; last_designator = designator; @@ -6510,7 +6507,7 @@ static expression_t *parse_builtin_constant(void) add_anchor_token(')'); expect('('); - expression->builtin_constant.value = parse_assignment_expression(); + expression->builtin_constant.value = parse_expression(); rem_anchor_token(')'); expect(')'); expression->base.type = type_int; @@ -6580,7 +6577,7 @@ static expression_t *parse_compare_builtin(void) &expression->base.pos, orig_type_left, orig_type_right); } } else { - semantic_comparison(&expression->binary); + semantic_comparison(&expression->binary, true); } return expression; @@ -6597,7 +6594,7 @@ static expression_t *parse_assume(void) add_anchor_token(')'); expect('('); - expression->unary.value = parse_assignment_expression(); + expression->unary.value = parse_expression(); rem_anchor_token(')'); expect(')'); @@ -6723,6 +6720,8 @@ static expression_t *parse_primary_expression(void) case '(': return parse_parenthesized_expression(); case T___noop: return parse_noop_expression(); + case T___imag__: return parse_complex_extract_expression(EXPR_UNARY_IMAG); + case T___real__: return parse_complex_extract_expression(EXPR_UNARY_REAL); /* Gracefully handle type names while parsing expressions. */ case T_COLONCOLON: @@ -7511,17 +7510,18 @@ static bool is_lvalue(const expression_t *expression) static void semantic_incdec(unary_expression_t *expression) { - type_t *const orig_type = expression->value->base.type; - type_t *const type = skip_typeref(orig_type); + type_t *orig_type = expression->value->base.type; + type_t *type = skip_typeref(orig_type); if (is_type_pointer(type)) { if (!check_pointer_arithmetic(&expression->base.pos, type, orig_type)) { return; } - } else if (!is_type_real(type) && is_type_valid(type)) { + } else if (!is_type_real(type) && + (!GNU_MODE || !is_type_complex(type)) && is_type_valid(type)) { /* TODO: improve error message */ errorf(&expression->base.pos, "operation needs an arithmetic or pointer type"); - return; + orig_type = type = type_error_type; } if (!is_lvalue(expression->value)) { /* TODO: improve error message */ @@ -7532,7 +7532,16 @@ static void semantic_incdec(unary_expression_t *expression) static void promote_unary_int_expr(unary_expression_t *const expr, type_t *const type) { - type_t *const res_type = promote_integer(type); + atomic_type_kind_t akind = get_arithmetic_akind(type); + type_t *res_type; + if (get_akind_rank(akind) < get_akind_rank(ATOMIC_TYPE_INT)) { + if (type->kind == TYPE_COMPLEX) + res_type = make_complex_type(ATOMIC_TYPE_INT, TYPE_QUALIFIER_NONE); + else + res_type = type_int; + } else { + res_type = type; + } expr->base.type = res_type; expr->value = create_implicit_cast(expr->value, res_type); } @@ -7572,14 +7581,18 @@ static void semantic_complement(unary_expression_t *expression) { type_t *const orig_type = expression->value->base.type; type_t *const type = skip_typeref(orig_type); - if (!is_type_integer(type)) { + if (!is_type_integer(type) && (!GNU_MODE || !is_type_complex(type))) { if (is_type_valid(type)) { errorf(&expression->base.pos, "operand of ~ must be of integer type"); } return; } - promote_unary_int_expr(expression, type); + if (is_type_integer(type)) { + promote_unary_int_expr(expression, type); + } else { + expression->base.type = orig_type; + } } static void semantic_dereference(unary_expression_t *expression) @@ -7701,67 +7714,78 @@ CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(T_MINUSMINUS, EXPR_UNARY_POSTFIX_DECREMENT, semantic_incdec) -static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right) +static atomic_type_kind_t semantic_arithmetic_(atomic_type_kind_t kind_left, + atomic_type_kind_t kind_right) { - /* TODO: handle complex + imaginary types */ - - type_left = get_unqualified_type(type_left); - type_right = get_unqualified_type(type_right); - /* §6.3.1.8 Usual arithmetic conversions */ - if (type_left == type_long_double || type_right == type_long_double) { - return type_long_double; - } else if (type_left == type_double || type_right == type_double) { - return type_double; - } else if (type_left == type_float || type_right == type_float) { - return type_float; - } - - type_left = promote_integer(type_left); - type_right = promote_integer(type_right); - - if (type_left == type_right) - return type_left; - - bool const signed_left = is_type_signed(type_left); - bool const signed_right = is_type_signed(type_right); - unsigned const rank_left = get_akind_rank(get_akind(type_left)); - unsigned const rank_right = get_akind_rank(get_akind(type_right)); - + if (kind_left == ATOMIC_TYPE_LONG_DOUBLE + || kind_right == ATOMIC_TYPE_LONG_DOUBLE) { + return ATOMIC_TYPE_LONG_DOUBLE; + } else if (kind_left == ATOMIC_TYPE_DOUBLE + || kind_right == ATOMIC_TYPE_DOUBLE) { + return ATOMIC_TYPE_DOUBLE; + } else if (kind_left == ATOMIC_TYPE_FLOAT + || kind_right == ATOMIC_TYPE_FLOAT) { + return ATOMIC_TYPE_FLOAT; + } + + unsigned rank_left = get_akind_rank(kind_left); + unsigned rank_right = get_akind_rank(kind_right); + unsigned const rank_int = get_akind_rank(ATOMIC_TYPE_INT); + if (rank_left < rank_int) { + kind_left = ATOMIC_TYPE_INT; + rank_left = rank_int; + } + if (rank_right < rank_int) { + kind_right = ATOMIC_TYPE_INT; + rank_right = rank_int; + } + if (kind_left == kind_right) + return kind_left; + + bool const signed_left = is_akind_signed(kind_left); + bool const signed_right = is_akind_signed(kind_right); if (signed_left == signed_right) - return rank_left >= rank_right ? type_left : type_right; + return rank_left >= rank_right ? kind_left : kind_right; unsigned s_rank; unsigned u_rank; - atomic_type_kind_t s_akind; - atomic_type_kind_t u_akind; - type_t *s_type; - type_t *u_type; + atomic_type_kind_t s_kind; + atomic_type_kind_t u_kind; if (signed_left) { - s_type = type_left; - u_type = type_right; + s_kind = kind_left; + s_rank = rank_left; + u_kind = kind_right; + u_rank = rank_right; } else { - s_type = type_right; - u_type = type_left; + s_kind = kind_right; + s_rank = rank_right; + u_kind = kind_left; + u_rank = rank_left; } - s_akind = get_akind(s_type); - u_akind = get_akind(u_type); - s_rank = get_akind_rank(s_akind); - u_rank = get_akind_rank(u_akind); - if (u_rank >= s_rank) - return u_type; - - if (get_atomic_type_size(s_akind) > get_atomic_type_size(u_akind)) - return s_type; + return u_kind; + if (get_atomic_type_size(s_kind) > get_atomic_type_size(u_kind)) + return s_kind; + + switch (s_kind) { + case ATOMIC_TYPE_INT: return ATOMIC_TYPE_UINT; + case ATOMIC_TYPE_LONG: return ATOMIC_TYPE_ULONG; + case ATOMIC_TYPE_LONGLONG: return ATOMIC_TYPE_ULONGLONG; + default: panic("invalid atomic type"); + } +} - switch (s_akind) { - case ATOMIC_TYPE_INT: return type_unsigned_int; - case ATOMIC_TYPE_LONG: return type_unsigned_long; - case ATOMIC_TYPE_LONGLONG: return type_unsigned_long_long; +static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right) +{ + atomic_type_kind_t kind_left = get_arithmetic_akind(type_left); + atomic_type_kind_t kind_right = get_arithmetic_akind(type_right); + atomic_type_kind_t kind_res = semantic_arithmetic_(kind_left, kind_right); - default: panic("invalid atomic type"); + if (type_left->kind == TYPE_COMPLEX || type_right->kind == TYPE_COMPLEX) { + return make_complex_type(kind_res, TYPE_QUALIFIER_NONE); } + return make_atomic_type(kind_res, TYPE_QUALIFIER_NONE); } /** @@ -7799,7 +7823,8 @@ static void semantic_binexpr_integer(binary_expression_t *const expression) type_t *const type_left = skip_typeref(orig_type_left); type_t *const type_right = skip_typeref(orig_type_right); - if (!is_type_integer(type_left) || !is_type_integer(type_right)) { + if (!is_type_integer(type_left) || !is_type_integer(type_right) + || is_type_complex(type_left) || is_type_complex(type_right)) { if (is_type_valid(type_left) && is_type_valid(type_right)) { position_t const *const pos = &expression->base.pos; errorf(pos, "operands of binary expression must have integer types, but are '%T' and '%T'", orig_type_left, orig_type_right); @@ -7821,7 +7846,7 @@ static void warn_div_by_zero(binary_expression_t const *const expression) expression_t const *const right = expression->right; /* The type of the right operand can be different for /= */ if (is_type_integer(skip_typeref(right->base.type)) && - is_constant_expression(right) == EXPR_CLASS_CONSTANT && + is_constant_expression(right) >= EXPR_CLASS_CONSTANT && !fold_constant_to_bool(right)) { position_t const *const pos = &expression->base.pos; warningf(WARN_DIV_BY_ZERO, pos, "division by zero"); @@ -7881,7 +7906,7 @@ static bool semantic_shift(binary_expression_t *expression) type_left = promote_integer(type_left); - if (is_constant_expression(right) == EXPR_CLASS_CONSTANT) { + if (is_constant_expression(right) >= EXPR_CLASS_CONSTANT) { position_t const *const pos = &right->base.pos; long const count = fold_constant_to_int(right); if (count < 0) { @@ -8007,10 +8032,12 @@ static void warn_string_literal_address(expression_t const* expr) static bool maybe_negative(expression_t const *const expr) { switch (is_constant_expression(expr)) { - case EXPR_CLASS_ERROR: return false; - case EXPR_CLASS_CONSTANT: return constant_is_negative(expr); - default: return true; + case EXPR_CLASS_VARIABLE: return true; + case EXPR_CLASS_ERROR: return false; + case EXPR_CLASS_CONSTANT: + case EXPR_CLASS_INTEGER_CONSTANT: return constant_is_negative(expr); } + panic("invalid expression classification"); } static void warn_comparison(position_t const *const pos, expression_t const *const expr, expression_t const *const other) @@ -8041,10 +8068,9 @@ static void warn_comparison(position_t const *const pos, expression_t const *con /** * Check the semantics of comparison expressions. - * - * @param expression The expression to check. */ -static void semantic_comparison(binary_expression_t *expression) +static void semantic_comparison(binary_expression_t *expression, + bool is_relational) { position_t const *const pos = &expression->base.pos; expression_t *const left = expression->left; @@ -8076,14 +8102,17 @@ static void semantic_comparison(binary_expression_t *expression) } } - expression->left = create_implicit_cast(left, arithmetic_type); - expression->right = create_implicit_cast(right, arithmetic_type); - expression->base.type = arithmetic_type; - if ((expression->base.kind == EXPR_BINARY_EQUAL || - expression->base.kind == EXPR_BINARY_NOTEQUAL) && - is_type_float(arithmetic_type)) { + expression->left = create_implicit_cast(left, arithmetic_type); + expression->right = create_implicit_cast(right, arithmetic_type); + expression->base.type = arithmetic_type; + if (!is_relational && is_type_float(arithmetic_type)) { warningf(WARN_FLOAT_EQUAL, pos, "comparing floating point with == or != is unsafe"); } + /* for relational ops we need real types, not just arithmetic */ + if (is_relational + && (!is_type_real(type_left) || !is_type_real(type_right))) { + type_error_incompatible("invalid operands for relational operator", pos, type_left, type_right); + } } else if (is_type_pointer(type_left) && is_type_pointer(type_right)) { /* TODO check compatibility */ } else if (is_type_pointer(type_left)) { @@ -8096,6 +8125,16 @@ static void semantic_comparison(binary_expression_t *expression) expression->base.type = c_mode & _CXX ? type_bool : type_int; } +static void semantic_relational(binary_expression_t *expression) +{ + semantic_comparison(expression, true); +} + +static void semantic_equality(binary_expression_t *expression) +{ + semantic_comparison(expression, false); +} + /** * Checks if a compound type has constant fields. */ @@ -8382,6 +8421,8 @@ static bool expression_has_effect(const expression_t *const expr) case EXPR_UNARY_NOT: return false; case EXPR_UNARY_DEREFERENCE: return false; case EXPR_UNARY_TAKE_ADDRESS: return false; + case EXPR_UNARY_REAL: return false; + case EXPR_UNARY_IMAG: return false; case EXPR_UNARY_POSTFIX_INCREMENT: return true; case EXPR_UNARY_POSTFIX_DECREMENT: return true; case EXPR_UNARY_PREFIX_INCREMENT: return true; @@ -8483,12 +8524,12 @@ CREATE_BINEXPR_PARSER('+', EXPR_BINARY_ADD, PR CREATE_BINEXPR_PARSER('-', EXPR_BINARY_SUB, PREC_MULTIPLICATIVE, semantic_sub) CREATE_BINEXPR_PARSER(T_LESSLESS, EXPR_BINARY_SHIFTLEFT, PREC_ADDITIVE, semantic_shift_op) CREATE_BINEXPR_PARSER(T_GREATERGREATER, EXPR_BINARY_SHIFTRIGHT, PREC_ADDITIVE, semantic_shift_op) -CREATE_BINEXPR_PARSER('<', EXPR_BINARY_LESS, PREC_SHIFT, semantic_comparison) -CREATE_BINEXPR_PARSER('>', EXPR_BINARY_GREATER, PREC_SHIFT, semantic_comparison) -CREATE_BINEXPR_PARSER(T_LESSEQUAL, EXPR_BINARY_LESSEQUAL, PREC_SHIFT, semantic_comparison) -CREATE_BINEXPR_PARSER(T_GREATEREQUAL, EXPR_BINARY_GREATEREQUAL, PREC_SHIFT, semantic_comparison) -CREATE_BINEXPR_PARSER(T_EXCLAMATIONMARKEQUAL, EXPR_BINARY_NOTEQUAL, PREC_RELATIONAL, semantic_comparison) -CREATE_BINEXPR_PARSER(T_EQUALEQUAL, EXPR_BINARY_EQUAL, PREC_RELATIONAL, semantic_comparison) +CREATE_BINEXPR_PARSER('<', EXPR_BINARY_LESS, PREC_SHIFT, semantic_relational) +CREATE_BINEXPR_PARSER('>', EXPR_BINARY_GREATER, PREC_SHIFT, semantic_relational) +CREATE_BINEXPR_PARSER(T_LESSEQUAL, EXPR_BINARY_LESSEQUAL, PREC_SHIFT, semantic_relational) +CREATE_BINEXPR_PARSER(T_GREATEREQUAL, EXPR_BINARY_GREATEREQUAL, PREC_SHIFT, semantic_relational) +CREATE_BINEXPR_PARSER(T_EXCLAMATIONMARKEQUAL, EXPR_BINARY_NOTEQUAL, PREC_RELATIONAL, semantic_equality) +CREATE_BINEXPR_PARSER(T_EQUALEQUAL, EXPR_BINARY_EQUAL, PREC_RELATIONAL, semantic_equality) CREATE_BINEXPR_PARSER('&', EXPR_BINARY_BITWISE_AND, PREC_EQUALITY, semantic_binexpr_integer) CREATE_BINEXPR_PARSER('^', EXPR_BINARY_BITWISE_XOR, PREC_AND, semantic_binexpr_integer) CREATE_BINEXPR_PARSER('|', EXPR_BINARY_BITWISE_OR, PREC_XOR, semantic_binexpr_integer) @@ -8880,7 +8921,7 @@ static statement_t *parse_case_statement(void) statement->case_label.expression = expression; expression_classification_t const expr_class = is_constant_expression(expression); - if (expr_class != EXPR_CLASS_CONSTANT) { + if (expr_class < EXPR_CLASS_CONSTANT) { if (expr_class != EXPR_CLASS_ERROR) { errorf(pos, "case label does not reduce to an integer constant"); } @@ -8904,7 +8945,7 @@ static statement_t *parse_case_statement(void) end_range = create_implicit_cast(end_range, type); statement->case_label.end_range = end_range; expression_classification_t const end_class = is_constant_expression(end_range); - if (end_class != EXPR_CLASS_CONSTANT) { + if (end_class < EXPR_CLASS_CONSTANT) { if (end_class != EXPR_CLASS_ERROR) { errorf(pos, "case range does not reduce to an integer constant"); } @@ -9172,7 +9213,7 @@ static statement_t *parse_switch(void) type_t * type = skip_typeref(expr->base.type); if (is_type_integer(type)) { type = promote_integer(type); - if (get_akind_rank(get_akind(type)) >= get_akind_rank(ATOMIC_TYPE_LONG)) { + if (get_akind_rank(get_arithmetic_akind(type)) >= get_akind_rank(ATOMIC_TYPE_LONG)) { warningf(WARN_TRADITIONAL, &expr->base.pos, "'%T' switch expression not converted to '%T' in ISO C", type, type_int);