differentiate between EXPR_INVALID and EXPR_ERROR
authorMatthias Braun <matze@braunis.de>
Fri, 12 Aug 2011 10:36:03 +0000 (12:36 +0200)
committerMatthias Braun <matze@braunis.de>
Fri, 12 Aug 2011 18:59:20 +0000 (20:59 +0200)
EXPR_INVALID should never happen can be considered a compiler bug
EXPR_ERROR represents parsing errors in a subexpression. This commit
should fix a few panics because of parsing errors.

ast.c
ast2firm.c
ast_t.h
parser.c
walk.c

diff --git a/ast.c b/ast.c
index f44284c..1aa9254 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -677,8 +677,8 @@ static void print_expression_prec(const expression_t *expression, unsigned top_p
        if (parenthesized)
                print_string("(");
        switch (expression->kind) {
-       case EXPR_INVALID:
-               print_string("$invalid expression$");
+       case EXPR_ERROR:
+               print_string("$error$");
                break;
        case EXPR_WIDE_STRING_LITERAL:
        case EXPR_STRING_LITERAL:
@@ -746,6 +746,8 @@ static void print_expression_prec(const expression_t *expression, unsigned top_p
        case EXPR_STATEMENT:
                print_statement_expression(&expression->statement);
                break;
+       case EXPR_INVALID:
+               panic("invalid expression found");
 
 #if 0
        default:
@@ -1610,8 +1612,10 @@ static expression_classification_t is_object_with_linker_constant_address(
                return EXPR_CLASS_VARIABLE;
        }
 
-       case EXPR_INVALID:
+       case EXPR_ERROR:
                return EXPR_CLASS_ERROR;
+       case EXPR_INVALID:
+               panic("invalid expression found");
 
        default:
                return EXPR_CLASS_VARIABLE;
@@ -1736,8 +1740,10 @@ expression_classification_t is_linker_constant(const expression_t *expression)
                return EXPR_CLASS_VARIABLE;
        }
 
-       case EXPR_INVALID:
+       case EXPR_ERROR:
                return EXPR_CLASS_ERROR;
+       case EXPR_INVALID:
+               panic("invalid expression found");
 
        default:
                return EXPR_CLASS_VARIABLE;
@@ -1816,8 +1822,10 @@ static expression_classification_t is_object_with_constant_address(const express
        case EXPR_UNARY_DEREFERENCE:
                return is_constant_pointer(expression->unary.value);
 
-       case EXPR_INVALID:
+       case EXPR_ERROR:
                return EXPR_CLASS_ERROR;
+       case EXPR_INVALID:
+               panic("invalid expression found");
 
        default:
                return EXPR_CLASS_VARIABLE;
@@ -1966,8 +1974,10 @@ expression_classification_t is_constant_expression(const expression_t *expressio
                }
        }
 
-       case EXPR_INVALID:
+       case EXPR_ERROR:
                return EXPR_CLASS_ERROR;
+       case EXPR_INVALID:
+               break;
        }
        panic("invalid expression found (is constant expression)");
 }
index d1cf59a..cc5d6a0 100644 (file)
@@ -3115,7 +3115,7 @@ bool constant_is_negative(const expression_t *expression)
 
 long fold_constant_to_int(const expression_t *expression)
 {
-       if (expression->kind == EXPR_INVALID)
+       if (expression->kind == EXPR_ERROR)
                return 0;
 
        ir_tarval *tv = fold_constant_to_tarval(expression);
@@ -3128,7 +3128,7 @@ long fold_constant_to_int(const expression_t *expression)
 
 bool fold_constant_to_bool(const expression_t *expression)
 {
-       if (expression->kind == EXPR_INVALID)
+       if (expression->kind == EXPR_ERROR)
                return false;
        ir_tarval *tv = fold_constant_to_tarval(expression);
        return !tarval_is_null(tv);
@@ -3524,6 +3524,12 @@ static ir_node *label_address_to_firm(const label_address_expression_t *label)
        return new_d_SymConst(dbgi, mode_P_code, value, symconst_addr_ent);
 }
 
+static ir_node *error_to_firm(const expression_t *expression)
+{
+       ir_mode *mode = get_ir_mode_arithmetic(expression->base.type);
+       return new_Bad(mode);
+}
+
 /**
  * creates firm nodes for an expression. The difference between this function
  * and expression_to_firm is, that this version might produce mode_b nodes
@@ -3589,6 +3595,8 @@ static ir_node *_expression_to_firm(const expression_t *expression)
        case EXPR_LABEL_ADDRESS:
                return label_address_to_firm(&expression->label_address);
 
+       case EXPR_ERROR:
+               return error_to_firm(expression);
        case EXPR_INVALID:
                break;
        }
diff --git a/ast_t.h b/ast_t.h
index 5fe2735..e7a95c1 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -63,6 +63,7 @@ typedef enum precedence_t {
  */
 typedef enum expression_kind_t {
        EXPR_INVALID = 0,
+       EXPR_ERROR,
        EXPR_REFERENCE,
        EXPR_REFERENCE_ENUM_VALUE,
        EXPR_LITERAL_BOOLEAN,
index e0e2503..2fbb6cb 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -317,6 +317,7 @@ static size_t get_expression_struct_size(expression_kind_t kind)
 {
        static const size_t sizes[] = {
                [EXPR_INVALID]                    = sizeof(expression_base_t),
+               [EXPR_ERROR]                      = sizeof(expression_base_t),
                [EXPR_REFERENCE]                  = sizeof(reference_expression_t),
                [EXPR_REFERENCE_ENUM_VALUE]       = sizeof(reference_expression_t),
                [EXPR_LITERAL_BOOLEAN]            = sizeof(literal_expression_t),
@@ -397,9 +398,11 @@ static expression_t *allocate_expression_zero(expression_kind_t kind)
  * Creates a new invalid expression at the source position
  * of the current token.
  */
-static expression_t *create_invalid_expression(void)
+static expression_t *create_error_expression(void)
 {
-       return allocate_expression_zero(EXPR_INVALID);
+       expression_t *expression = allocate_expression_zero(EXPR_ERROR);
+       expression->base.type = type_error_type;
+       return expression;
 }
 
 /**
@@ -1548,6 +1551,7 @@ unary:
 
                EXPR_LITERAL_CASES
                case EXPR_INVALID:
+               case EXPR_ERROR:
                case EXPR_STRING_LITERAL:
                case EXPR_WIDE_STRING_LITERAL:
                case EXPR_COMPOUND_LITERAL: // TODO init?
@@ -4778,6 +4782,7 @@ static bool expression_returns(expression_t const *const expr)
                case EXPR_BUILTIN_TYPES_COMPATIBLE_P:
                case EXPR_OFFSETOF:
                case EXPR_INVALID:
+               case EXPR_ERROR:
                        return true;
 
                case EXPR_STATEMENT: {
@@ -5804,7 +5809,7 @@ static expression_t *expected_expression_error(void)
        }
        next_token();
 
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 static type_t *get_string_type(void)
@@ -6357,7 +6362,7 @@ static expression_t *parse_cast(void)
 
        return cast;
 end_error:
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 /**
@@ -6572,14 +6577,14 @@ static expression_t *parse_offsetof(void)
        descend_into_subtype(&path);
 
        if (!walk_designator(&path, designator, true)) {
-               return create_invalid_expression();
+               return create_error_expression();
        }
 
        DEL_ARR_F(path.path);
 
        return expression;
 end_error:
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 /**
@@ -6615,7 +6620,7 @@ static expression_t *parse_va_start(void)
        }
        expect(')', end_error);
 end_error:
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 /**
@@ -6639,7 +6644,7 @@ static expression_t *parse_va_arg(void)
 
        return expression;
 end_error:
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 /**
@@ -6668,7 +6673,7 @@ static expression_t *parse_va_copy(void)
 
        return expression;
 end_error:
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 /**
@@ -6689,7 +6694,7 @@ static expression_t *parse_builtin_constant(void)
 
        return expression;
 end_error:
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 /**
@@ -6714,7 +6719,7 @@ static expression_t *parse_builtin_types_compatible(void)
 
        return expression;
 end_error:
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 /**
@@ -6771,7 +6776,7 @@ static expression_t *parse_compare_builtin(void)
 
        return expression;
 end_error:
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 /**
@@ -6792,7 +6797,7 @@ static expression_t *parse_assume(void)
        expression->base.type = type_void;
        return expression;
 end_error:
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 /**
@@ -6829,7 +6834,7 @@ static expression_t *parse_label_address(void)
        eat(T_ANDAND);
        if (token.kind != T_IDENTIFIER) {
                parse_error_expected("while parsing label address", T_IDENTIFIER, NULL);
-               return create_invalid_expression();
+               return create_error_expression();
        }
 
        label_t *const label = get_label();
@@ -6933,13 +6938,13 @@ static expression_t *parse_primary_expression(void)
                parse_declaration_specifiers(&specifiers);
                type_t const *const type = parse_abstract_declarator(specifiers.type);
                errorf(&pos, "encountered type '%T' while parsing expression", type);
-               return create_invalid_expression();
+               return create_error_expression();
        }
        }
 
        errorf(HERE, "unexpected token %K, expected an expression", &token);
        eat_until_anchor();
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 static expression_t *parse_array_expression(expression_t *left)
@@ -7093,7 +7098,7 @@ static expression_t *parse_select_expression(expression_t *addr)
 
        if (token.kind != T_IDENTIFIER) {
                parse_error_expected("while parsing select", T_IDENTIFIER, NULL);
-               return create_invalid_expression();
+               return create_error_expression();
        }
        symbol_t *symbol = token.identifier.symbol;
        next_token();
@@ -7127,14 +7132,14 @@ static expression_t *parse_select_expression(expression_t *addr)
                               "request for member '%Y' in something not a struct or union, but '%T'",
                               symbol, type_left);
                }
-               return create_invalid_expression();
+               return create_error_expression();
        }
 
        compound_t *compound = type_left->compound.compound;
        if (!compound->complete) {
                errorf(&pos, "request for member '%Y' in incomplete type '%T'",
                       symbol, type_left);
-               return create_invalid_expression();
+               return create_error_expression();
        }
 
        type_qualifiers_t  qualifiers = type_left->base.qualifiers;
@@ -7143,7 +7148,7 @@ static expression_t *parse_select_expression(expression_t *addr)
 
        if (result == NULL) {
                errorf(&pos, "'%T' has no member named '%Y'", orig_type, symbol);
-               return create_invalid_expression();
+               return create_error_expression();
        }
 
        return result;
@@ -7580,7 +7585,7 @@ static expression_t *parse_builtin_classify_type(void)
 
        return result;
 end_error:
-       return create_invalid_expression();
+       return create_error_expression();
 }
 
 /**
@@ -8523,6 +8528,7 @@ static void semantic_binexpr_assign(binary_expression_t *expression)
 static bool expression_has_effect(const expression_t *const expr)
 {
        switch (expr->kind) {
+               case EXPR_ERROR:
                case EXPR_INVALID:                    return true; /* do NOT warn */
                case EXPR_REFERENCE:                  return false;
                case EXPR_REFERENCE_ENUM_VALUE:       return false;
diff --git a/walk.c b/walk.c
index 4ed3156..6724872 100644 (file)
--- a/walk.c
+++ b/walk.c
@@ -185,6 +185,7 @@ static void walk_expression(expression_t *const expr,
        case EXPR_WIDE_STRING_LITERAL:
        case EXPR_FUNCNAME:
        case EXPR_LABEL_ADDRESS:
+       case EXPR_ERROR:
                return;
        case EXPR_INVALID:
                break;