Correct logic in is_error_entity().
[cparser] / parser.c
index ce7ce2f..7e44886 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -702,6 +702,7 @@ static void scope_pop(scope_t *old_scope)
 static entity_t *get_entity(const symbol_t *const symbol,
                             namespace_tag_t namespc)
 {
+       assert(namespc != NAMESPACE_INVALID);
        entity_t *entity = symbol->entity;
        for (; entity != NULL; entity = entity->base.symbol_next) {
                if (entity->base.namespc == namespc)
@@ -916,10 +917,13 @@ static bool is_null_pointer_constant(const expression_t *expression)
        }
 
        type_t *const type = skip_typeref(expression->base.type);
-       return
-               is_type_integer(type)              &&
-               is_constant_expression(expression) &&
-               !fold_constant_to_bool(expression);
+       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;
+       }
 }
 
 /**
@@ -1079,7 +1083,7 @@ static expression_t *parse_constant_expression(void)
 {
        expression_t *result = parse_subexpression(PREC_CONDITIONAL);
 
-       if (!is_constant_expression(result)) {
+       if (is_constant_expression(result) == EXPR_CLASS_VARIABLE) {
                errorf(&result->base.source_position,
                       "expression '%E' is not constant", result);
        }
@@ -1732,8 +1736,9 @@ static initializer_t *initializer_from_expression(type_t *orig_type,
  */
 static bool is_initializer_constant(const expression_t *expression)
 {
-       return is_constant_expression(expression)
-               || is_address_constant(expression);
+       return
+               is_constant_expression(expression) != EXPR_CLASS_VARIABLE ||
+               is_address_constant(expression)    != EXPR_CLASS_VARIABLE;
 }
 
 /**
@@ -2506,6 +2511,7 @@ static void parse_enum_entries(type_t *const enum_type)
 
                entity_t *entity             = allocate_entity_zero(ENTITY_ENUM_VALUE);
                entity->enum_value.enum_type = enum_type;
+               entity->base.namespc         = NAMESPACE_NORMAL;
                entity->base.symbol          = token.symbol;
                entity->base.source_position = token.source_position;
                next_token();
@@ -2820,6 +2826,7 @@ end_error:
 static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind)
 {
        entity_t *entity             = allocate_entity_zero(kind);
+       entity->base.namespc         = NAMESPACE_NORMAL;
        entity->base.source_position = *HERE;
        entity->base.symbol          = symbol;
        if (is_declaration(entity)) {
@@ -3658,12 +3665,16 @@ ptr_operator_end: ;
                        }
                        rem_anchor_token(')');
                        expect(')', end_error);
+               } else if (!env->may_be_abstract) {
+                       errorf(HERE, "declarator must have a name");
+                       goto error_out;
                }
                break;
        default:
                if (env->may_be_abstract)
                        break;
                parse_error_expected("while parsing declarator", T_IDENTIFIER, '(', NULL);
+error_out:
                eat_until_anchor();
                return NULL;
        }
@@ -3775,24 +3786,31 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
                        array_type->array.size_expression = size_expression;
 
                        if (size_expression != NULL) {
-                               if (is_constant_expression(size_expression)) {
-                                       long const size
-                                               = fold_constant_to_int(size_expression);
-                                       array_type->array.size          = size;
-                                       array_type->array.size_constant = true;
-                                       /* §6.7.5.2:1  If the expression is a constant expression, it shall
-                                        * have a value greater than zero. */
-                                       if (size <= 0) {
-                                               if (size < 0 || !GNU_MODE) {
-                                                       errorf(&size_expression->base.source_position,
-                                                                       "size of array must be greater than zero");
-                                               } else if (warning.other) {
-                                                       warningf(&size_expression->base.source_position,
-                                                                       "zero length arrays are a GCC extension");
+                               switch (is_constant_expression(size_expression)) {
+                                       case EXPR_CLASS_CONSTANT: {
+                                               long const size = fold_constant_to_int(size_expression);
+                                               array_type->array.size          = size;
+                                               array_type->array.size_constant = true;
+                                               /* §6.7.5.2:1  If the expression is a constant expression, it shall
+                                                * have a value greater than zero. */
+                                               if (size <= 0) {
+                                                       if (size < 0 || !GNU_MODE) {
+                                                               errorf(&size_expression->base.source_position,
+                                                                               "size of array must be greater than zero");
+                                                       } else if (warning.other) {
+                                                               warningf(&size_expression->base.source_position,
+                                                                               "zero length arrays are a GCC extension");
+                                                       }
                                                }
+                                               break;
                                        }
-                               } else {
-                                       array_type->array.is_vla = true;
+
+                                       case EXPR_CLASS_VARIABLE:
+                                               array_type->array.is_vla = true;
+                                               break;
+
+                                       case EXPR_CLASS_ERROR:
+                                               break;
                                }
                        }
 
@@ -3875,6 +3893,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
        entity_t *entity;
        if (specifiers->storage_class == STORAGE_CLASS_TYPEDEF) {
                entity                       = allocate_entity_zero(ENTITY_TYPEDEF);
+               entity->base.namespc         = NAMESPACE_NORMAL;
                entity->base.symbol          = env.symbol;
                entity->base.source_position = env.source_position;
                entity->typedefe.type        = orig_type;
@@ -4091,9 +4110,9 @@ static void error_redefined_as_different_kind(const source_position_t *pos,
 static bool is_error_entity(entity_t *const ent)
 {
        if (is_declaration(ent)) {
-               return is_type_valid(skip_typeref(ent->declaration.type));
+               return !is_type_valid(skip_typeref(ent->declaration.type));
        } else if (ent->kind == ENTITY_TYPEDEF) {
-               return is_type_valid(skip_typeref(ent->typedefe.type));
+               return !is_type_valid(skip_typeref(ent->typedefe.type));
        }
        return false;
 }
@@ -4879,8 +4898,8 @@ static void check_declarations(void)
 static int determine_truth(expression_t const* const cond)
 {
        return
-               !is_constant_expression(cond) ? 0 :
-               fold_constant_to_bool(cond)   ? 1 :
+               is_constant_expression(cond) != EXPR_CLASS_CONSTANT ? 0 :
+               fold_constant_to_bool(cond)                         ? 1 :
                -1;
 }
 
@@ -5090,7 +5109,7 @@ static void check_reachable(statement_t *const stmt)
                        if (!expression_returns(expr))
                                return;
 
-                       if (is_constant_expression(expr)) {
+                       if (is_constant_expression(expr) == EXPR_CLASS_CONSTANT) {
                                long                    const val      = fold_constant_to_int(expr);
                                case_label_statement_t *      defaults = NULL;
                                for (case_label_statement_t *i = switchs->first_case; i != NULL; i = i->next) {
@@ -5676,7 +5695,7 @@ static type_t *make_bitfield_type(type_t *base_type, expression_t *size,
                bit_size = get_type_size(base_type) * 8;
        }
 
-       if (is_constant_expression(size)) {
+       if (is_constant_expression(size) == EXPR_CLASS_CONSTANT) {
                long v = fold_constant_to_int(size);
                const symbol_t *user_symbol = symbol == NULL ? sym_anonymous : symbol;
 
@@ -6215,6 +6234,7 @@ static entity_t *create_implicit_function(symbol_t *symbol,
        entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
        entity->declaration.type                   = type;
        entity->declaration.implicit               = true;
+       entity->base.namespc                       = NAMESPACE_NORMAL;
        entity->base.symbol                        = symbol;
        entity->base.source_position               = *source_position;
 
@@ -7150,6 +7170,7 @@ static expression_t *parse_primary_expression(void)
        }
 
        errorf(HERE, "unexpected token %K, expected an expression", &token);
+       eat_until_anchor();
        return create_invalid_expression();
 }
 
@@ -7253,12 +7274,28 @@ typeprop_expression:
 
        tp_expression->typeprop.type   = orig_type;
        type_t const* const type       = skip_typeref(orig_type);
-       char   const* const wrong_type =
-               GNU_MODE && is_type_atomic(type, ATOMIC_TYPE_VOID) ? NULL                  :
-               is_type_incomplete(type)                           ? "incomplete"          :
-               type->kind == TYPE_FUNCTION                        ? "function designator" :
-               type->kind == TYPE_BITFIELD                        ? "bitfield"            :
-               NULL;
+       char   const*       wrong_type = NULL;
+       if (is_type_incomplete(type)) {
+               if (!is_type_atomic(type, ATOMIC_TYPE_VOID) || !GNU_MODE)
+                       wrong_type = "incomplete";
+       } else if (type->kind == TYPE_FUNCTION) {
+               if (GNU_MODE) {
+                       /* function types are allowed (and return 1) */
+                       if (warning.other) {
+                               char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
+                               warningf(&tp_expression->base.source_position,
+                                        "%s expression with function argument returns invalid result", what);
+                       }
+               } else {
+                       wrong_type = "function";
+               }
+       } else {
+               if (is_type_incomplete(type))
+                       wrong_type = "incomplete";
+       }
+       if (type->kind == TYPE_BITFIELD)
+               wrong_type = "bitfield";
+
        if (wrong_type != NULL) {
                char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
                errorf(&tp_expression->base.source_position,
@@ -7285,6 +7322,7 @@ static expression_t *parse_select_expression(expression_t *addr)
 {
        assert(token.type == '.' || token.type == T_MINUSGREATER);
        bool select_left_arrow = (token.type == T_MINUSGREATER);
+       source_position_t const pos = *HERE;
        next_token();
 
        if (token.type != T_IDENTIFIER) {
@@ -7301,7 +7339,7 @@ static expression_t *parse_select_expression(expression_t *addr)
        bool    saw_error = false;
        if (is_type_pointer(type)) {
                if (!select_left_arrow) {
-                       errorf(HERE,
+                       errorf(&pos,
                               "request for member '%Y' in something not a struct or union, but '%T'",
                               symbol, orig_type);
                        saw_error = true;
@@ -7309,7 +7347,7 @@ static expression_t *parse_select_expression(expression_t *addr)
                type_left = skip_typeref(type->pointer.points_to);
        } else {
                if (select_left_arrow && is_type_valid(type)) {
-                       errorf(HERE, "left hand side of '->' is not a pointer, but '%T'", orig_type);
+                       errorf(&pos, "left hand side of '->' is not a pointer, but '%T'", orig_type);
                        saw_error = true;
                }
                type_left = type;
@@ -7319,7 +7357,7 @@ static expression_t *parse_select_expression(expression_t *addr)
            type_left->kind != TYPE_COMPOUND_UNION) {
 
                if (is_type_valid(type_left) && !saw_error) {
-                       errorf(HERE,
+                       errorf(&pos,
                               "request for member '%Y' in something not a struct or union, but '%T'",
                               symbol, type_left);
                }
@@ -7328,17 +7366,17 @@ static expression_t *parse_select_expression(expression_t *addr)
 
        compound_t *compound = type_left->compound.compound;
        if (!compound->complete) {
-               errorf(HERE, "request for member '%Y' in incomplete type '%T'",
+               errorf(&pos, "request for member '%Y' in incomplete type '%T'",
                       symbol, type_left);
                return create_invalid_expression();
        }
 
        type_qualifiers_t  qualifiers = type_left->base.qualifiers;
-       expression_t      *result
-               = find_create_select(HERE, addr, qualifiers, compound, symbol);
+       expression_t      *result     =
+               find_create_select(&pos, addr, qualifiers, compound, symbol);
 
        if (result == NULL) {
-               errorf(HERE, "'%T' has no member named '%Y'", orig_type, symbol);
+               errorf(&pos, "'%T' has no member named '%Y'", orig_type, symbol);
                return create_invalid_expression();
        }
 
@@ -7411,7 +7449,7 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) {
                        /* argument must be constant */
                        call_argument_t *argument = call->arguments;
 
-                       if (! is_constant_expression(argument->expression)) {
+                       if (is_constant_expression(argument->expression) == EXPR_CLASS_VARIABLE) {
                                errorf(&call->base.source_position,
                                       "argument of '%Y' must be a constant expression",
                                       call->function->reference.entity->base.symbol);
@@ -7423,7 +7461,7 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) {
                                break;
 
                        call_argument_t *arg = call->arguments->next;
-                       if (arg != NULL && ! is_constant_expression(arg->expression)) {
+                       if (arg != NULL && is_constant_expression(arg->expression) == EXPR_CLASS_VARIABLE) {
                                errorf(&call->base.source_position,
                                           "second argument of '%Y' must be a constant expression",
                                           call->function->reference.entity->base.symbol);
@@ -7437,7 +7475,7 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) {
                        call_argument_t *locality = NULL;
 
                        if (rw != NULL) {
-                               if (! is_constant_expression(rw->expression)) {
+                               if (is_constant_expression(rw->expression) == EXPR_CLASS_VARIABLE) {
                                        errorf(&call->base.source_position,
                                               "second argument of '%Y' must be a constant expression",
                                               call->function->reference.entity->base.symbol);
@@ -7445,7 +7483,7 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) {
                                locality = rw->next;
                        }
                        if (locality != NULL) {
-                               if (! is_constant_expression(locality->expression)) {
+                               if (is_constant_expression(locality->expression) == EXPR_CLASS_VARIABLE) {
                                        errorf(&call->base.source_position,
                                               "third argument of '%Y' must be a constant expression",
                                               call->function->reference.entity->base.symbol);
@@ -8228,8 +8266,8 @@ 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(right->base.type) &&
-           is_constant_expression(right)     &&
+       if (is_type_integer(right->base.type)                    &&
+           is_constant_expression(right) == EXPR_CLASS_CONSTANT &&
            !fold_constant_to_bool(right)) {
                warningf(&expression->base.source_position, "division by zero");
        }
@@ -8280,7 +8318,7 @@ static bool semantic_shift(binary_expression_t *expression)
 
        type_left = promote_integer(type_left);
 
-       if (is_constant_expression(right)) {
+       if (is_constant_expression(right) == EXPR_CLASS_CONSTANT) {
                long count = fold_constant_to_int(right);
                if (count < 0) {
                        warningf(&right->base.source_position,
@@ -8428,9 +8466,11 @@ static void warn_comparison_in_comparison(const expression_t *const expr)
 
 static bool maybe_negative(expression_t const *const expr)
 {
-       return
-               !is_constant_expression(expr) ||
-               fold_constant_to_int(expr) < 0;
+       switch (is_constant_expression(expr)) {
+               case EXPR_CLASS_ERROR:    return false;
+               case EXPR_CLASS_CONSTANT: return fold_constant_to_int(expr) < 0;
+               default:                  return true;
+       }
 }
 
 /**
@@ -9310,11 +9350,9 @@ static statement_t *parse_case_statement(void)
 
        expression_t *const expression   = parse_expression();
        statement->case_label.expression = expression;
-       if (!is_constant_expression(expression)) {
-               /* This check does not prevent the error message in all cases of an
-                * prior error while parsing the expression.  At least it catches the
-                * common case of a mistyped enum entry. */
-               if (is_type_valid(skip_typeref(expression->base.type))) {
+       expression_classification_t const expr_class = is_constant_expression(expression);
+       if (expr_class != EXPR_CLASS_CONSTANT) {
+               if (expr_class != EXPR_CLASS_ERROR) {
                        errorf(pos, "case label does not reduce to an integer constant");
                }
                statement->case_label.is_bad = true;
@@ -9328,11 +9366,9 @@ static statement_t *parse_case_statement(void)
                if (next_if(T_DOTDOTDOT)) {
                        expression_t *const end_range   = parse_expression();
                        statement->case_label.end_range = end_range;
-                       if (!is_constant_expression(end_range)) {
-                               /* This check does not prevent the error message in all cases of an
-                                * prior error while parsing the expression.  At least it catches the
-                                * common case of a mistyped enum entry. */
-                               if (is_type_valid(skip_typeref(end_range->base.type))) {
+                       expression_classification_t const end_class = is_constant_expression(end_range);
+                       if (end_class != EXPR_CLASS_CONSTANT) {
+                               if (end_class != EXPR_CLASS_ERROR) {
                                        errorf(pos, "case range does not reduce to an integer constant");
                                }
                                statement->case_label.is_bad = true;
@@ -10099,8 +10135,9 @@ static statement_t *parse_local_label_declaration(void)
 
        eat(T___label__);
 
-       entity_t *begin = NULL, *end = NULL;
-
+       entity_t *begin   = NULL;
+       entity_t *end     = NULL;
+       entity_t **anchor = &begin;
        do {
                if (token.type != T_IDENTIFIER) {
                        parse_error_expected("while parsing local label declaration",
@@ -10120,11 +10157,9 @@ static statement_t *parse_local_label_declaration(void)
                        entity->base.source_position = token.source_position;
                        entity->base.symbol          = symbol;
 
-                       if (end != NULL)
-                               end->base.next = entity;
-                       end = entity;
-                       if (begin == NULL)
-                               begin = entity;
+                       *anchor = entity;
+                       anchor  = &entity->base.next;
+                       end     = entity;
 
                        environment_push(entity);
                }