parser: Remove the unused attribute alignment from struct declaration_specifiers_t.
[cparser] / parser.c
index 4be846a..b95b756 100644 (file)
--- a/parser.c
+++ b/parser.c
 #include <stdbool.h>
 
 #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"
 
@@ -44,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 */
@@ -856,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");
 }
 
 /**
@@ -1838,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)) {
@@ -3558,7 +3556,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;
@@ -3574,6 +3572,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;
@@ -4145,13 +4144,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;
@@ -4587,8 +4586,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;
 }
 
@@ -4796,7 +4795,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) {
@@ -5213,42 +5212,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);
@@ -5307,8 +5306,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);
                        }
                }
 
@@ -5386,6 +5384,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;
 
@@ -5436,7 +5435,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);
@@ -5464,7 +5462,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 {
@@ -5499,73 +5497,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(';');
@@ -5672,112 +5645,77 @@ static expression_t *parse_boolean_literal(bool value)
        return literal;
 }
 
-static void warn_traditional_suffix(char const *const suffix)
-{
-       warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%s' suffix", suffix);
-}
-
-static void check_integer_suffix(expression_t *const expr, char const *const suffix)
+static void check_number_suffix(expression_t *const expr, char const *const suffix, bool const is_float)
 {
-       unsigned     spec = SPECIFIER_NONE;
-       char const  *c    = suffix;
-       while (*c != '\0') {
+       unsigned spec = SPECIFIER_NONE;
+       for (char const *c = suffix; *c != '\0'; ++c) {
                specifiers_t add;
                switch (*c) {
-               case 'L':
-               case 'l':
+               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;
                        }
                        break;
-               case 'u':
-               case 'U':
+
+               case 'U': case 'u':
                        add = SPECIFIER_UNSIGNED;
                        break;
-               case 'i':
-               case 'I':
-               case 'j':
-               case 'J':
-                       if (!GNU_MODE)
-                               goto error;
+
+               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 & ~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;
-               default: panic("inconsistent suffix");
-               }
-               if (spec != SPECIFIER_NONE && spec != SPECIFIER_LONG) {
-                       warn_traditional_suffix(suffix);
-               }
-               if (spec & SPECIFIER_COMPLEX) {
-                       assert(type->kind == TYPE_ATOMIC);
-                       type = make_complex_type(type->atomic.akind, TYPE_QUALIFIER_NONE);
-               }
-               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);
-       }
-}
-
-static void check_floatingpoint_suffix(expression_t *const expr, char const *const suffix)
-{
-       type_t     *type;
-       char const *c          = suffix;
-       bool        is_complex = false;
-next:
-       switch (*c) {
-       case 'F':
-       case 'f': type = type_float;       ++c; break;
-       case 'L':
-       case 'l': type = type_long_double; ++c; break;
-       case 'i':
-       case 'I':
-       case 'j':
-       case 'J':
-               if (!GNU_MODE)
-                       break;
-               is_complex = true;
-               ++c;
-               goto next;
-       default:  type = type_double;           break;
+               errorf(HERE, "invalid suffix '%s' on %s constant", suffix, is_float ? "floatingpoint" : "integer");
+               return;
        }
 
-       if (*c == '\0') {
-               if (is_complex) {
-                       assert(type->kind == TYPE_ATOMIC);
-                       type = make_complex_type(type->atomic.akind, TYPE_QUALIFIER_NONE);
-               }
+       if (spec != SPECIFIER_NONE && spec != SPECIFIER_LONG && spec != SPECIFIER_DOUBLE)
+               warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%s' suffix", suffix);
 
-               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);
        }
 }
 
@@ -5894,11 +5832,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);
                }
        }
 
@@ -7914,7 +7848,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");
@@ -7974,7 +7908,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) {
@@ -8100,10 +8034,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)
@@ -8987,7 +8923,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");
                }
@@ -9011,7 +8947,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");
                                }