Simplify do_while_statement_to_firm() a bit, which can be done since new_immBlock...
[cparser] / parser.c
index 7becd99..8b14bbf 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -130,7 +130,7 @@ static unsigned char token_anchor_set[T_LAST_TOKEN];
 static statement_t *parse_compound_statement(bool inside_expression_statement);
 static statement_t *parse_statement(void);
 
-static expression_t *parse_sub_expression(precedence_t);
+static expression_t *parse_subexpression(precedence_t);
 static expression_t *parse_expression(void);
 static type_t       *parse_typename(void);
 static void          parse_externals(void);
@@ -658,7 +658,7 @@ static void type_error_incompatible(const char *msg,
 /**
  * Expect the current token is the expected token.
  * If not, generate an error, eat the current statement,
- * and goto the end_error label.
+ * and goto the error_label label.
  */
 #define expect(expected, error_label)                     \
        do {                                                  \
@@ -823,7 +823,7 @@ static void stack_pop_to(stack_entry_t **stack_ptr, size_t new_top)
                }
        }
 
-       ARR_SHRINKLEN(*stack_ptr, (int) new_top);
+       ARR_SHRINKLEN(*stack_ptr, new_top);
 }
 
 /**
@@ -1055,8 +1055,8 @@ static assign_error_t semantic_assign(type_t *orig_type_left,
                        return ASSIGN_WARNING_POINTER_FROM_INT;
                }
        } else if ((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) ||
-           (is_type_atomic(type_left, ATOMIC_TYPE_BOOL)
-               && is_type_pointer(type_right))) {
+                       (is_type_atomic(type_left, ATOMIC_TYPE_BOOL)
+                               && is_type_pointer(type_right))) {
                return ASSIGN_SUCCESS;
        } else if ((is_type_compound(type_left)  && is_type_compound(type_right))
                        || (is_type_builtin(type_left) && is_type_builtin(type_right))) {
@@ -1077,7 +1077,7 @@ static assign_error_t semantic_assign(type_t *orig_type_left,
 
 static expression_t *parse_constant_expression(void)
 {
-       expression_t *result = parse_sub_expression(PREC_CONDITIONAL);
+       expression_t *result = parse_subexpression(PREC_CONDITIONAL);
 
        if (!is_constant_expression(result)) {
                errorf(&result->base.source_position,
@@ -1089,7 +1089,7 @@ static expression_t *parse_constant_expression(void)
 
 static expression_t *parse_assignment_expression(void)
 {
-       return parse_sub_expression(PREC_ASSIGNMENT);
+       return parse_subexpression(PREC_ASSIGNMENT);
 }
 
 static void warn_string_concat(const source_position_t *pos)
@@ -1967,7 +1967,7 @@ static bool walk_designator(type_path_t *path, const designator_t *designator,
                                        type_t *real_type = skip_typeref(iter->declaration.type);
                                        if (real_type->kind == TYPE_BITFIELD) {
                                                errorf(&designator->source_position,
-                                                      "offsetof designator '%Y' may not specify bitfield",
+                                                      "offsetof designator '%Y' must not specify bitfield",
                                                       symbol);
                                                goto failed;
                                        }
@@ -1999,8 +1999,8 @@ static bool walk_designator(type_path_t *path, const designator_t *designator,
                                        long array_size = type->array.size;
                                        if (index >= array_size) {
                                                errorf(&designator->source_position,
-                                                      "designator [%E] (%d) exceeds array size %d",
-                                                      array_index, index, array_size);
+                                                      "designator [%E] (%d) exceeds array size %d",
+                                                      array_index, index, array_size);
                                        }
                                }
                        }
@@ -2634,21 +2634,14 @@ static type_t *parse_typeof(void)
        switch (token.type) {
        case T_IDENTIFIER:
                if (is_typedef_symbol(token.symbol)) {
+       TYPENAME_START
                        type = parse_typename();
                } else {
+       default:
                        expression = parse_expression();
                        type       = revert_automatic_type_conversion(expression);
                }
                break;
-
-       TYPENAME_START
-               type = parse_typename();
-               break;
-
-       default:
-               expression = parse_expression();
-               type       = expression->base.type;
-               break;
        }
        in_type_prop     = old_type_prop;
        in_gcc_extension = old_gcc_extension;
@@ -3494,54 +3487,64 @@ union construct_type_t {
        parsed_array_t            array;
 };
 
+static construct_type_t *allocate_declarator_zero(construct_type_kind_t const kind, size_t const size)
+{
+       construct_type_t *const cons = obstack_alloc(&temp_obst, size);
+       memset(cons, 0, size);
+       cons->kind = kind;
+       return cons;
+}
+
+/* §6.7.5.1 */
 static construct_type_t *parse_pointer_declarator(void)
 {
        eat('*');
 
-       parsed_pointer_t *pointer = obstack_alloc(&temp_obst, sizeof(pointer[0]));
-       memset(pointer, 0, sizeof(pointer[0]));
-       pointer->base.kind       = CONSTRUCT_POINTER;
-       pointer->type_qualifiers = parse_type_qualifiers();
-       //pointer->base_variable       = base_variable;
+       construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_POINTER, sizeof(parsed_pointer_t));
+       cons->pointer.type_qualifiers = parse_type_qualifiers();
+       //cons->pointer.base_variable   = base_variable;
 
-       return (construct_type_t*) pointer;
+       return cons;
 }
 
+/* ISO/IEC 14882:1998(E) §8.3.2 */
 static construct_type_t *parse_reference_declarator(void)
 {
        eat('&');
 
-       construct_type_t   *cons      = obstack_alloc(&temp_obst, sizeof(cons->reference));
-       parsed_reference_t *reference = &cons->reference;
-       memset(reference, 0, sizeof(*reference));
-       cons->kind = CONSTRUCT_REFERENCE;
+       if (!(c_mode & _CXX))
+               errorf(HERE, "references are only available for C++");
+
+       construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_REFERENCE, sizeof(parsed_reference_t));
 
        return cons;
 }
 
+/* §6.7.5.2 */
 static construct_type_t *parse_array_declarator(void)
 {
        eat('[');
        add_anchor_token(']');
 
-       construct_type_t *cons  = obstack_alloc(&temp_obst, sizeof(cons->array));
-       parsed_array_t   *array = &cons->array;
-       memset(array, 0, sizeof(*array));
-       cons->kind = CONSTRUCT_ARRAY;
+       construct_type_t *const cons  = allocate_declarator_zero(CONSTRUCT_ARRAY, sizeof(parsed_array_t));
+       parsed_array_t   *const array = &cons->array;
 
-       if (next_if(T_static))
-               array->is_static = true;
+       bool is_static = next_if(T_static);
 
        type_qualifiers_t type_qualifiers = parse_type_qualifiers();
-       if (type_qualifiers != 0 && next_if(T_static))
-                       array->is_static = true;
+
+       if (!is_static)
+               is_static = next_if(T_static);
+
        array->type_qualifiers = type_qualifiers;
+       array->is_static       = is_static;
 
+       expression_t *size = NULL;
        if (token.type == '*' && look_ahead(1)->type == ']') {
                array->is_variable = true;
                next_token();
        } else if (token.type != ']') {
-               expression_t *const size = parse_assignment_expression();
+               size = parse_assignment_expression();
 
                /* §6.7.5.2:1  Array size must have integer type */
                type_t *const orig_type = size->base.type;
@@ -3556,6 +3559,9 @@ static construct_type_t *parse_array_declarator(void)
                mark_vars_read(size, NULL);
        }
 
+       if (is_static && size == NULL)
+               errorf(HERE, "static array parameters require a size");
+
        rem_anchor_token(']');
        expect(']', end_error);
 
@@ -3563,6 +3569,7 @@ end_error:
        return cons;
 }
 
+/* §6.7.5.3 */
 static construct_type_t *parse_function_declarator(scope_t *scope)
 {
        type_t          *type  = allocate_type_zero(TYPE_FUNCTION);
@@ -3573,11 +3580,8 @@ static construct_type_t *parse_function_declarator(scope_t *scope)
 
        parse_parameters(ftype, scope);
 
-       construct_type_t          *cons     = obstack_alloc(&temp_obst, sizeof(cons->function));
-       construct_function_type_t *function = &cons->function;
-       memset(function, 0, sizeof(*function));
-       cons->kind              = CONSTRUCT_FUNCTION;
-       function->function_type = type;
+       construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_FUNCTION, sizeof(construct_function_type_t));
+       cons->function.function_type = type;
 
        return cons;
 }
@@ -3592,6 +3596,7 @@ typedef struct parse_declarator_env_t {
        attribute_t       *attributes;
 } parse_declarator_env_t;
 
+/* §6.7.5 */
 static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env)
 {
        /* construct a single linked list of construct_type_t's which describe
@@ -3606,8 +3611,6 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env)
                //variable_t       *based = NULL; /* MS __based extension */
                switch (token.type) {
                        case '&':
-                               if (!(c_mode & _CXX))
-                                       errorf(HERE, "references are only available for C++");
                                type = parse_reference_declarator();
                                break;
 
@@ -3927,10 +3930,10 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                                bool in_function_scope = current_function != NULL;
 
                                if (specifiers->thread_local || (
-                                     specifiers->storage_class != STORAGE_CLASS_EXTERN &&
-                                         specifiers->storage_class != STORAGE_CLASS_NONE   &&
-                                         (in_function_scope || specifiers->storage_class != STORAGE_CLASS_STATIC)
-                                  )) {
+                                                       specifiers->storage_class != STORAGE_CLASS_EXTERN &&
+                                                       specifiers->storage_class != STORAGE_CLASS_NONE   &&
+                                                       (in_function_scope || specifiers->storage_class != STORAGE_CLASS_STATIC)
+                                               )) {
                                        errorf(&env.source_position,
                                                        "invalid storage class for function '%Y'", env.symbol);
                                }
@@ -5941,7 +5944,7 @@ static type_t *parse_typename(void)
                /* TODO: improve error message, user does probably not know what a
                 * storage class is...
                 */
-               errorf(HERE, "typename may not have a storage class");
+               errorf(HERE, "typename must not have a storage class");
        }
 
        type_t *result = parse_abstract_declarator(specifiers.type);
@@ -6119,14 +6122,17 @@ static expression_t *parse_number_literal(void)
        case T_INTEGER:
                kind = EXPR_LITERAL_INTEGER;
                check_integer_suffix();
+               type = type_int;
                break;
        case T_INTEGER_OCTAL:
                kind = EXPR_LITERAL_INTEGER_OCTAL;
                check_integer_suffix();
+               type = type_int;
                break;
        case T_INTEGER_HEXADECIMAL:
                kind = EXPR_LITERAL_INTEGER_HEXADECIMAL;
                check_integer_suffix();
+               type = type_int;
                break;
        case T_FLOATINGPOINT:
                kind = EXPR_LITERAL_FLOATINGPOINT;
@@ -6540,7 +6546,7 @@ static expression_t *parse_cast(void)
        expression_t *cast = allocate_expression_zero(EXPR_UNARY_CAST);
        cast->base.source_position = source_position;
 
-       expression_t *value = parse_sub_expression(PREC_CAST);
+       expression_t *value = parse_subexpression(PREC_CAST);
        cast->base.type   = type;
        cast->unary.value = value;
 
@@ -7239,7 +7245,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind)
                        goto typeprop_expression;
                }
        } else {
-               expression = parse_sub_expression(PREC_UNARY);
+               expression = parse_subexpression(PREC_UNARY);
 
 typeprop_expression:
                tp_expression->typeprop.tp_expression = expression;
@@ -7415,8 +7421,21 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) {
                        }
                        break;
                }
-               case bk_gnu_builtin_prefetch: {
+               case bk_gnu_builtin_object_size:
+                       if (call->arguments == NULL)
+                               break;
+
+                       call_argument_t *arg = call->arguments->next;
+                       if (arg != NULL && ! is_constant_expression(arg->expression)) {
+                               errorf(&call->base.source_position,
+                                          "second argument of '%Y' must be a constant expression",
+                                          call->function->reference.entity->base.symbol);
+                       }
+                       break;
+               case bk_gnu_builtin_prefetch:
                        /* second and third argument must be constant if existent */
+                       if (call->arguments == NULL)
+                               break;
                        call_argument_t *rw = call->arguments->next;
                        call_argument_t *locality = NULL;
 
@@ -7437,7 +7456,6 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) {
                                locality = rw->next;
                        }
                        break;
-               }
                default:
                        break;
        }
@@ -7514,6 +7532,10 @@ static expression_t *parse_call_expression(expression_t *expression)
        /* do default promotion for other arguments */
        for (; argument != NULL; argument = argument->next) {
                type_t *type = argument->expression->base.type;
+               if (!is_type_object(skip_typeref(type))) {
+                       errorf(&argument->expression->base.source_position,
+                              "call argument '%E' must not be void", argument->expression);
+               }
 
                type = get_default_promoted_type(type);
 
@@ -7646,7 +7668,7 @@ static expression_t *parse_conditional_expression(expression_t *expression)
        expect(':', end_error);
 end_error:;
        expression_t *false_expression =
-               parse_sub_expression(c_mode & _CXX ? PREC_ASSIGNMENT : PREC_CONDITIONAL);
+               parse_subexpression(c_mode & _CXX ? PREC_ASSIGNMENT : PREC_CONDITIONAL);
 
        type_t *const orig_true_type  = true_expression->base.type;
        type_t *const orig_false_type = false_expression->base.type;
@@ -7675,13 +7697,6 @@ end_error:;
        } else if (is_type_arithmetic(true_type)
                   && is_type_arithmetic(false_type)) {
                result_type = semantic_arithmetic(true_type, false_type);
-
-               true_expression  = create_implicit_cast(true_expression, result_type);
-               false_expression = create_implicit_cast(false_expression, result_type);
-
-               conditional->true_expression  = true_expression;
-               conditional->false_expression = false_expression;
-               conditional->base.type        = result_type;
        } else if (same_compound_type(true_type, false_type)) {
                /* just take 1 of the 2 types */
                result_type = true_type;
@@ -7733,7 +7748,7 @@ end_error:;
                        result_type = pointer_type;
                } else {
                        if (is_type_valid(other_type)) {
-                               type_error_incompatible("while parsing conditional",
+                               type_error_incompatible("while parsing conditional",
                                                &expression->base.source_position, true_type, false_type);
                        }
                        result_type = type_error_type;
@@ -7764,7 +7779,7 @@ static expression_t *parse_extension(void)
 
        bool old_gcc_extension   = in_gcc_extension;
        in_gcc_extension         = true;
-       expression_t *expression = parse_sub_expression(PREC_UNARY);
+       expression_t *expression = parse_subexpression(PREC_UNARY);
        in_gcc_extension         = old_gcc_extension;
        return expression;
 }
@@ -7808,7 +7823,7 @@ static expression_t *parse_delete(void)
 end_error:;
        }
 
-       expression_t *const value = parse_sub_expression(PREC_CAST);
+       expression_t *const value = parse_subexpression(PREC_CAST);
        result->unary.value = value;
 
        type_t *const type = skip_typeref(value->base.type);
@@ -8072,7 +8087,7 @@ static expression_t *parse_##unexpression_type(void)                         \
        expression_t *unary_expression                                           \
                = allocate_expression_zero(unexpression_type);                       \
        eat(token_type);                                                         \
-       unary_expression->unary.value = parse_sub_expression(PREC_UNARY);        \
+       unary_expression->unary.value = parse_subexpression(PREC_UNARY);         \
                                                                                 \
        sfunc(&unary_expression->unary);                                         \
                                                                                 \
@@ -8886,7 +8901,7 @@ static expression_t *parse_##binexpression_type(expression_t *left)          \
        binexpr->binary.left  = left;                                            \
        eat(token_type);                                                         \
                                                                              \
-       expression_t *right = parse_sub_expression(prec_r);                      \
+       expression_t *right = parse_subexpression(prec_r);                       \
                                                                              \
        binexpr->binary.right = right;                                           \
        sfunc(&binexpr->binary);                                                 \
@@ -8926,7 +8941,7 @@ CREATE_BINEXPR_PARSER(T_CARETEQUAL,           EXPR_BINARY_BITWISE_XOR_ASSIGN, PR
 CREATE_BINEXPR_PARSER(',',                    EXPR_BINARY_COMMA,              PREC_ASSIGNMENT,     semantic_comma)
 
 
-static expression_t *parse_sub_expression(precedence_t precedence)
+static expression_t *parse_subexpression(precedence_t precedence)
 {
        if (token.type < 0) {
                return expected_expression_error();
@@ -8971,7 +8986,7 @@ static expression_t *parse_sub_expression(precedence_t precedence)
  */
 static expression_t *parse_expression(void)
 {
-       return parse_sub_expression(PREC_EXPRESSION);
+       return parse_subexpression(PREC_EXPRESSION);
 }
 
 /**
@@ -9152,7 +9167,9 @@ static asm_argument_t *parse_asm_arguments(bool is_out)
                                       "asm output argument is not an lvalue");
                        }
 
-                       if (argument->constraints.begin[0] == '+')
+                       if (argument->constraints.begin[0] == '=')
+                               determine_lhs_ent(expression, NULL);
+                       else
                                mark_vars_read(expression, NULL);
                } else {
                        mark_vars_read(expression, NULL);
@@ -9211,9 +9228,13 @@ static statement_t *parse_asm_statement(void)
 
        expect('(', end_error);
        add_anchor_token(')');
-       add_anchor_token(':');
+       if (token.type != T_STRING_LITERAL) {
+               parse_error_expected("after asm(", T_STRING_LITERAL, NULL);
+               goto end_of_asm;
+       }
        asm_statement->asm_text = parse_string_literals();
 
+       add_anchor_token(':');
        if (!next_if(':')) {
                rem_anchor_token(':');
                goto end_of_asm;
@@ -9354,6 +9375,8 @@ static statement_t *parse_default_statement(void)
        PUSH_PARENT(statement);
 
        expect(':', end_error);
+end_error:
+
        if (current_switch != NULL) {
                const case_label_statement_t *def_label = current_switch->default_label;
                if (def_label != NULL) {
@@ -9383,9 +9406,6 @@ static statement_t *parse_default_statement(void)
 
        POP_PARENT;
        return statement;
-end_error:
-       POP_PARENT;
-       return create_invalid_statement();
 }
 
 /**
@@ -9418,14 +9438,8 @@ static statement_t *parse_label_statement(void)
        eat(':');
 
        if (token.type == '}') {
-               /* TODO only warn? */
-               if (warning.other && false) {
-                       warningf(HERE, "label at end of compound statement");
-                       statement->label.statement = create_empty_statement();
-               } else {
-                       errorf(HERE, "label at end of compound statement");
-                       statement->label.statement = create_invalid_statement();
-               }
+               errorf(HERE, "label at end of compound statement");
+               statement->label.statement = create_invalid_statement();
        } else if (token.type == ';') {
                /* Eat an empty statement here, to avoid the warning about an empty
                 * statement after a label.  label:; is commonly used to have a label