ast2firm: Implement casting from complex to real types.
[cparser] / parser.c
index 830d08f..19e165e 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1,21 +1,6 @@
 /*
  * This file is part of cparser.
- * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
  */
 #include <config.h>
 
@@ -173,7 +158,8 @@ typedef enum declarator_flags_t {
 static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                                   declarator_flags_t flags);
 
-static void semantic_comparison(binary_expression_t *expression);
+static void semantic_comparison(binary_expression_t *expression,
+                                bool is_relational);
 
 #define STORAGE_CLASSES       \
        STORAGE_CLASSES_NO_EXTERN \
@@ -1534,7 +1520,13 @@ static designator_t *parse_designation(void)
                        designator->pos = *HERE;
                        eat('[');
                        add_anchor_token(']');
+                       add_anchor_token(T_DOTDOTDOT);
                        designator->array_index = parse_constant_expression();
+                       if (accept(T_DOTDOTDOT)) {
+                               designator->range_last = parse_constant_expression();
+                               errorf(&designator->pos, "range initializer not supported");
+                       }
+                       rem_anchor_token(T_DOTDOTDOT);
                        rem_anchor_token(']');
                        expect(']');
                        break;
@@ -4079,9 +4071,7 @@ warn_redundant_declaration: ;
                                                                     decl->attributes);
                                        if (has_new_attrs) {
                                                merge_in_attributes(decl, prev_decl->attributes);
-                                       } else if (!is_definition        &&
-                                                       is_type_valid(prev_type) &&
-                                                       !pos->is_system_header) {
+                                       } else if (!is_definition && is_type_valid(prev_type)) {
                                                warningf(WARN_REDUNDANT_DECLS, pos, "redundant declaration for '%N' (declared %P)", entity, ppos);
                                        }
                                } else if (current_function == NULL) {
@@ -5396,6 +5386,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;
 
@@ -5446,7 +5437,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);
@@ -6305,17 +6295,9 @@ static expression_t *parse_cast(void)
        return cast;
 }
 
-static expression_t *parse_complex_extract_expression(void)
+static expression_t *parse_complex_extract_expression(expression_kind_t const kind)
 {
-       expression_kind_t kind;
-       if (token.kind == T___imag__) {
-               kind = EXPR_UNARY_IMAG;
-       } else {
-               assert(token.kind == T___real__);
-               kind = EXPR_UNARY_REAL;
-       }
        expression_t *extract = allocate_expression_zero(kind);
-       extract->base.pos = *HERE;
        next_token();
 
        extract->unary.value = parse_subexpression(PREC_CAST);
@@ -6427,9 +6409,6 @@ static designator_t *parse_designator(void)
                        designator->array_index  = parse_expression();
                        rem_anchor_token(']');
                        expect(']');
-                       if (designator->array_index == NULL) {
-                               return NULL;
-                       }
 
                        last_designator->next = designator;
                        last_designator       = designator;
@@ -6596,7 +6575,7 @@ static expression_t *parse_builtin_constant(void)
 
        add_anchor_token(')');
        expect('(');
-       expression->builtin_constant.value = parse_assignment_expression();
+       expression->builtin_constant.value = parse_expression();
        rem_anchor_token(')');
        expect(')');
        expression->base.type = type_int;
@@ -6666,7 +6645,7 @@ static expression_t *parse_compare_builtin(void)
                                &expression->base.pos, orig_type_left, orig_type_right);
                }
        } else {
-               semantic_comparison(&expression->binary);
+               semantic_comparison(&expression->binary, true);
        }
 
        return expression;
@@ -6683,7 +6662,7 @@ static expression_t *parse_assume(void)
 
        add_anchor_token(')');
        expect('(');
-       expression->unary.value = parse_assignment_expression();
+       expression->unary.value = parse_expression();
        rem_anchor_token(')');
        expect(')');
 
@@ -6809,8 +6788,8 @@ static expression_t *parse_primary_expression(void)
 
        case '(':                            return parse_parenthesized_expression();
        case T___noop:                       return parse_noop_expression();
-       case T___real__:
-       case T___imag__:                     return parse_complex_extract_expression();
+       case T___imag__:                     return parse_complex_extract_expression(EXPR_UNARY_IMAG);
+       case T___real__:                     return parse_complex_extract_expression(EXPR_UNARY_REAL);
 
        /* Gracefully handle type names while parsing expressions. */
        case T_COLONCOLON:
@@ -8155,10 +8134,9 @@ static void warn_comparison(position_t const *const pos, expression_t const *con
 
 /**
  * Check the semantics of comparison expressions.
- *
- * @param expression   The expression to check.
  */
-static void semantic_comparison(binary_expression_t *expression)
+static void semantic_comparison(binary_expression_t *expression,
+                                bool is_relational)
 {
        position_t const *const pos   = &expression->base.pos;
        expression_t     *const left  = expression->left;
@@ -8190,14 +8168,17 @@ static void semantic_comparison(binary_expression_t *expression)
                        }
                }
 
-               expression->left        = create_implicit_cast(left, arithmetic_type);
-               expression->right       = create_implicit_cast(right, arithmetic_type);
-               expression->base.type   = arithmetic_type;
-               if ((expression->base.kind == EXPR_BINARY_EQUAL ||
-                    expression->base.kind == EXPR_BINARY_NOTEQUAL) &&
-                   is_type_float(arithmetic_type)) {
+               expression->left      = create_implicit_cast(left, arithmetic_type);
+               expression->right     = create_implicit_cast(right, arithmetic_type);
+               expression->base.type = arithmetic_type;
+               if (!is_relational && is_type_float(arithmetic_type)) {
                        warningf(WARN_FLOAT_EQUAL, pos, "comparing floating point with == or != is unsafe");
                }
+               /* for relational ops we need real types, not just arithmetic */
+               if (is_relational
+                   && (!is_type_real(type_left) || !is_type_real(type_right))) {
+                       type_error_incompatible("invalid operands for relational operator", pos, type_left, type_right);
+               }
        } else if (is_type_pointer(type_left) && is_type_pointer(type_right)) {
                /* TODO check compatibility */
        } else if (is_type_pointer(type_left)) {
@@ -8210,6 +8191,16 @@ static void semantic_comparison(binary_expression_t *expression)
        expression->base.type = c_mode & _CXX ? type_bool : type_int;
 }
 
+static void semantic_relational(binary_expression_t *expression)
+{
+       semantic_comparison(expression, true);
+}
+
+static void semantic_equality(binary_expression_t *expression)
+{
+       semantic_comparison(expression, false);
+}
+
 /**
  * Checks if a compound type has constant fields.
  */
@@ -8599,12 +8590,12 @@ CREATE_BINEXPR_PARSER('+',                    EXPR_BINARY_ADD,                PR
 CREATE_BINEXPR_PARSER('-',                    EXPR_BINARY_SUB,                PREC_MULTIPLICATIVE, semantic_sub)
 CREATE_BINEXPR_PARSER(T_LESSLESS,             EXPR_BINARY_SHIFTLEFT,          PREC_ADDITIVE,       semantic_shift_op)
 CREATE_BINEXPR_PARSER(T_GREATERGREATER,       EXPR_BINARY_SHIFTRIGHT,         PREC_ADDITIVE,       semantic_shift_op)
-CREATE_BINEXPR_PARSER('<',                    EXPR_BINARY_LESS,               PREC_SHIFT,          semantic_comparison)
-CREATE_BINEXPR_PARSER('>',                    EXPR_BINARY_GREATER,            PREC_SHIFT,          semantic_comparison)
-CREATE_BINEXPR_PARSER(T_LESSEQUAL,            EXPR_BINARY_LESSEQUAL,          PREC_SHIFT,          semantic_comparison)
-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_LESS,               PREC_SHIFT,          semantic_relational)
+CREATE_BINEXPR_PARSER('>',                    EXPR_BINARY_GREATER,            PREC_SHIFT,          semantic_relational)
+CREATE_BINEXPR_PARSER(T_LESSEQUAL,            EXPR_BINARY_LESSEQUAL,          PREC_SHIFT,          semantic_relational)
+CREATE_BINEXPR_PARSER(T_GREATEREQUAL,         EXPR_BINARY_GREATEREQUAL,       PREC_SHIFT,          semantic_relational)
+CREATE_BINEXPR_PARSER(T_EXCLAMATIONMARKEQUAL, EXPR_BINARY_NOTEQUAL,           PREC_RELATIONAL,     semantic_equality)
+CREATE_BINEXPR_PARSER(T_EQUALEQUAL,           EXPR_BINARY_EQUAL,              PREC_RELATIONAL,     semantic_equality)
 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)