change NEWS file to use markdown syntax
[cparser] / parser.c
index aea8ecf..795d755 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -4000,7 +4000,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                storage_class_t storage_class = specifiers->storage_class;
                entity->declaration.declared_storage_class = storage_class;
 
-               if (storage_class == STORAGE_CLASS_NONE && current_function != NULL)
+               if (storage_class == STORAGE_CLASS_NONE && current_function != NULL)
                        storage_class = STORAGE_CLASS_AUTO;
                entity->declaration.storage_class = storage_class;
        }
@@ -4264,7 +4264,7 @@ entity_t *record_entity(entity_t *entity, const bool is_definition)
                        } else {
                                unsigned old_storage_class = prev_decl->storage_class;
 
-                               if (warning.redundant_decls               &&
+                               if (warning.redundant_decls               &&
                                                is_definition                     &&
                                                !prev_decl->used                  &&
                                                !(prev_decl->modifiers & DM_USED) &&
@@ -4432,19 +4432,26 @@ static bool is_declaration_specifier(const token_t *token,
 
 static void parse_init_declarator_rest(entity_t *entity)
 {
-       assert(is_declaration(entity));
-       declaration_t *const declaration = &entity->declaration;
+       type_t *orig_type = type_error_type;
 
+       if (entity->base.kind == ENTITY_TYPEDEF) {
+               errorf(&entity->base.source_position,
+                      "typedef '%Y' is initialized (use __typeof__ instead)",
+                      entity->base.symbol);
+       } else {
+               assert(is_declaration(entity));
+               orig_type = entity->declaration.type;
+       }
        eat('=');
 
-       type_t *orig_type = declaration->type;
-       type_t *type      = skip_typeref(orig_type);
+       type_t *type = skip_typeref(orig_type);
 
        if (entity->kind == ENTITY_VARIABLE
                        && entity->variable.initializer != NULL) {
                parser_error_multiple_definition(entity, HERE);
        }
 
+       declaration_t *const declaration = &entity->declaration;
        bool must_be_constant = false;
        if (declaration->storage_class == STORAGE_CLASS_STATIC ||
            entity->base.parent_scope  == file_scope) {
@@ -7424,8 +7431,8 @@ static void check_call_argument(type_t          *expected_type,
                /* report exact scope in error messages (like "in argument 3") */
                char buf[64];
                snprintf(buf, sizeof(buf), "call argument %u", pos);
-               report_assign_error(error, expected_type, arg_expr,     buf,
-                                                       &arg_expr->base.source_position);
+               report_assign_error(error, expected_type, arg_expr, buf,
+                                   &arg_expr->base.source_position);
        } else if (warning.traditional || warning.conversion) {
                type_t *const promoted_type = get_default_promoted_type(arg_type);
                if (!types_compatible(expected_type_skip, promoted_type) &&
@@ -8076,8 +8083,8 @@ static void set_address_taken(expression_t *expression, bool may_be_register)
        if (entity->declaration.storage_class == STORAGE_CLASS_REGISTER
                        && !may_be_register) {
                errorf(&expression->base.source_position,
-                               "address of register %s '%Y' requested",
-                               get_entity_kind_name(entity->kind),     entity->base.symbol);
+                      "address of register %s '%Y' requested",
+                      get_entity_kind_name(entity->kind), entity->base.symbol);
        }
 
        if (entity->kind == ENTITY_VARIABLE) {
@@ -8258,6 +8265,30 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression)
        expression->base.type = arithmetic_type;
 }
 
+static void semantic_binexpr_integer(binary_expression_t *const expression)
+{
+       expression_t *const left            = expression->left;
+       expression_t *const right           = expression->right;
+       type_t       *const orig_type_left  = left->base.type;
+       type_t       *const orig_type_right = right->base.type;
+       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)) {
+               /* TODO: improve error message */
+               if (is_type_valid(type_left) && is_type_valid(type_right)) {
+                       errorf(&expression->base.source_position,
+                              "operation needs integer types");
+               }
+               return;
+       }
+
+       type_t *const result_type = semantic_arithmetic(type_left, type_right);
+       expression->left      = create_implicit_cast(left, result_type);
+       expression->right     = create_implicit_cast(right, result_type);
+       expression->base.type = result_type;
+}
+
 static void warn_div_by_zero(binary_expression_t const *const expression)
 {
        if (!warning.div_by_zero ||
@@ -8959,9 +8990,9 @@ CREATE_BINEXPR_PARSER(T_LESSEQUAL,            EXPR_BINARY_LESSEQUAL,          PR
 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_BITWISE_AND,        PREC_EQUALITY,       semantic_binexpr_arithmetic)
-CREATE_BINEXPR_PARSER('^',                    EXPR_BINARY_BITWISE_XOR,        PREC_AND,            semantic_binexpr_arithmetic)
-CREATE_BINEXPR_PARSER('|',                    EXPR_BINARY_BITWISE_OR,         PREC_XOR,            semantic_binexpr_arithmetic)
+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)
 CREATE_BINEXPR_PARSER(T_ANDAND,               EXPR_BINARY_LOGICAL_AND,        PREC_OR,             semantic_logical_op)
 CREATE_BINEXPR_PARSER(T_PIPEPIPE,             EXPR_BINARY_LOGICAL_OR,         PREC_LOGICAL_AND,    semantic_logical_op)
 CREATE_BINEXPR_PARSER('=',                    EXPR_BINARY_ASSIGN,             PREC_ASSIGNMENT,     semantic_binexpr_assign)
@@ -9052,7 +9083,7 @@ static void register_expression_parser(parse_expression_function parser,
  * @param precedence  the precedence of the operator
  */
 static void register_infix_parser(parse_expression_infix_function parser,
-               int token_type, precedence_t precedence)
+                                  int token_type, precedence_t precedence)
 {
        expression_parser_function_t *entry = &expression_parsers[token_type];
 
@@ -9308,17 +9339,17 @@ end_error:
        return create_invalid_statement();
 }
 
-static statement_t *parse_label_inner_statement(char const *const label, bool const eat_empty_stmt)
+static statement_t *parse_label_inner_statement(statement_t const *const label, char const *const label_kind)
 {
        statement_t *inner_stmt;
        switch (token.type) {
                case '}':
-                       errorf(HERE, "%s at end of compound statement", label);
+                       errorf(&label->base.source_position, "%s at end of compound statement", label_kind);
                        inner_stmt = create_invalid_statement();
                        break;
 
                case ';':
-                       if (eat_empty_stmt) {
+                       if (label->kind == STATEMENT_LABEL) {
                                /* Eat an empty statement here, to avoid the warning about an empty
                                 * statement after a label.  label:; is commonly used to have a label
                                 * before a closing brace. */
@@ -9330,8 +9361,9 @@ static statement_t *parse_label_inner_statement(char const *const label, bool co
 
                default:
                        inner_stmt = parse_statement();
-                       if (inner_stmt->kind == STATEMENT_DECLARATION) {
-                               errorf(&inner_stmt->base.source_position, "declaration after %s", label);
+                       /* ISO/IEC 14882:1998(E) §6:1/§6.7  Declarations are statements */
+                       if (inner_stmt->kind == STATEMENT_DECLARATION && !(c_mode & _CXX)) {
+                               errorf(&inner_stmt->base.source_position, "declaration after %s", label_kind);
                        }
                        break;
        }
@@ -9416,7 +9448,7 @@ end_error:
                errorf(pos, "case label not within a switch statement");
        }
 
-       statement->case_label.statement = parse_label_inner_statement("case label", false);
+       statement->case_label.statement = parse_label_inner_statement(statement, "case label");
 
        POP_PARENT;
        return statement;
@@ -9457,7 +9489,7 @@ end_error:
                        "'default' label not within a switch statement");
        }
 
-       statement->case_label.statement = parse_label_inner_statement("default label", false);
+       statement->case_label.statement = parse_label_inner_statement(statement, "default label");
 
        POP_PARENT;
        return statement;
@@ -9492,7 +9524,7 @@ static statement_t *parse_label_statement(void)
 
        eat(':');
 
-       statement->label.statement = parse_label_inner_statement("label", true);
+       statement->label.statement = parse_label_inner_statement(statement, "label");
 
        /* remember the labels in a list for later checking */
        *label_anchor = &statement->label;
@@ -10003,13 +10035,13 @@ static statement_t *parse_return(void)
                        }
                } else {
                        assign_error_t error = semantic_assign(return_type, return_value);
-                       report_assign_error(error, return_type, return_value, "'return'",
-                                       pos);
+                       report_assign_error(error, return_type, return_value, "'return'",
+                                           pos);
                }
                return_value = create_implicit_cast(return_value, return_type);
                /* check for returning address of a local var */
                if (warning.other && return_value != NULL
-                               && return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) {
+                   && return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) {
                        const expression_t *expression = return_value->unary.value;
                        if (expression_is_local_variable(expression)) {
                                warningf(pos, "function returns address of local variable");
@@ -10019,10 +10051,10 @@ static statement_t *parse_return(void)
                /* ISO/IEC 14882:1998(E) §6.6.3:3 */
                if (c_mode & _CXX || strict_mode) {
                        errorf(pos,
-                                       "'return' without value, in function returning non-void");
+                              "'return' without value, in function returning non-void");
                } else {
                        warningf(pos,
-                                       "'return' without value, in function returning non-void");
+                                "'return' without value, in function returning non-void");
                }
        }
        statement->returns.value = return_value;
@@ -10653,7 +10685,6 @@ end_error:;
 static void parse_linkage_specification(void)
 {
        eat(T_extern);
-       assert(token.type == T_STRING_LITERAL);
 
        const char *linkage = parse_string_literals().begin;
 
@@ -10735,6 +10766,7 @@ static void parse_externals(void)
        add_anchor_token(T_EOF);
 
 #ifndef NDEBUG
+       /* make a copy of the anchor set, so we can check if it is restored after parsing */
        unsigned char token_anchor_copy[T_LAST_TOKEN];
        memcpy(token_anchor_copy, token_anchor_set, sizeof(token_anchor_copy));
 #endif
@@ -10742,14 +10774,16 @@ static void parse_externals(void)
        while (token.type != T_EOF && token.type != '}') {
 #ifndef NDEBUG
                bool anchor_leak = false;
-               for (int i = 0; i != T_LAST_TOKEN; ++i) {
+               for (int i = 0; i < T_LAST_TOKEN; ++i) {
                        unsigned char count = token_anchor_set[i] - token_anchor_copy[i];
                        if (count != 0) {
+                               /* the anchor set and its copy differs */
                                errorf(HERE, "Leaked anchor token %k %d times", i, count);
                                anchor_leak = true;
                        }
                }
                if (in_gcc_extension) {
+                       /* an gcc extension scope was not closed */
                        errorf(HERE, "Leaked __extension__");
                        anchor_leak = true;
                }