add an is_constant_expression, only try to fold expressions that are really constant...
authorMatthias Braun <matze@braunis.de>
Wed, 5 Dec 2007 16:21:14 +0000 (16:21 +0000)
committerMatthias Braun <matze@braunis.de>
Wed, 5 Dec 2007 16:21:14 +0000 (16:21 +0000)
[r18610]

ast.c
ast.h
ast2firm.c
parser.c

diff --git a/ast.c b/ast.c
index 08dd23b..d25a63e 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -746,6 +746,102 @@ void print_ast(const translation_unit_t *unit)
        }
 }
 
+bool is_constant_expression(const expression_t *expression)
+{
+       switch(expression->type) {
+
+       case EXPR_CONST:
+       case EXPR_STRING_LITERAL:
+       case EXPR_WIDE_STRING_LITERAL:
+       case EXPR_SIZEOF:
+       case EXPR_CLASSIFY_TYPE:
+       case EXPR_FUNCTION:
+       case EXPR_PRETTY_FUNCTION:
+       case EXPR_OFFSETOF:
+               return true;
+
+       case EXPR_BUILTIN_SYMBOL:
+       case EXPR_CALL:
+       case EXPR_REFERENCE:
+       case EXPR_SELECT:
+       case EXPR_VA_START:
+       case EXPR_VA_ARG:
+       case EXPR_STATEMENT:
+       case EXPR_UNARY_POSTFIX_INCREMENT:
+       case EXPR_UNARY_POSTFIX_DECREMENT:
+       case EXPR_UNARY_PREFIX_INCREMENT:
+       case EXPR_UNARY_PREFIX_DECREMENT:
+       case EXPR_BINARY_ASSIGN:
+       case EXPR_BINARY_MUL_ASSIGN:
+       case EXPR_BINARY_DIV_ASSIGN:
+       case EXPR_BINARY_MOD_ASSIGN:
+       case EXPR_BINARY_ADD_ASSIGN:
+       case EXPR_BINARY_SUB_ASSIGN:
+       case EXPR_BINARY_SHIFTLEFT_ASSIGN:
+       case EXPR_BINARY_SHIFTRIGHT_ASSIGN:
+       case EXPR_BINARY_BITWISE_AND_ASSIGN:
+       case EXPR_BINARY_BITWISE_XOR_ASSIGN:
+       case EXPR_BINARY_BITWISE_OR_ASSIGN:
+       case EXPR_BINARY_COMMA:
+               return false;
+
+       case EXPR_UNARY_NEGATE:
+       case EXPR_UNARY_PLUS:
+       case EXPR_UNARY_BITWISE_NEGATE:
+       case EXPR_UNARY_NOT:
+       case EXPR_UNARY_DEREFERENCE:
+       case EXPR_UNARY_TAKE_ADDRESS:
+       case EXPR_UNARY_CAST:
+       case EXPR_UNARY_CAST_IMPLICIT:
+               return is_constant_expression(expression->unary.value);
+
+       case EXPR_BINARY_ADD:
+       case EXPR_BINARY_SUB:
+       case EXPR_BINARY_MUL:
+       case EXPR_BINARY_DIV:
+       case EXPR_BINARY_MOD:
+       case EXPR_BINARY_EQUAL:
+       case EXPR_BINARY_NOTEQUAL:
+       case EXPR_BINARY_LESS:
+       case EXPR_BINARY_LESSEQUAL:
+       case EXPR_BINARY_GREATER:
+       case EXPR_BINARY_GREATEREQUAL:
+       case EXPR_BINARY_BITWISE_AND:
+       case EXPR_BINARY_BITWISE_OR:
+       case EXPR_BINARY_BITWISE_XOR:
+       case EXPR_BINARY_LOGICAL_AND:
+       case EXPR_BINARY_LOGICAL_OR:
+       case EXPR_BINARY_SHIFTLEFT:
+       case EXPR_BINARY_SHIFTRIGHT:
+       case EXPR_BINARY_ISGREATER:
+       case EXPR_BINARY_ISGREATEREQUAL:
+       case EXPR_BINARY_ISLESS:
+       case EXPR_BINARY_ISLESSEQUAL:
+       case EXPR_BINARY_ISLESSGREATER:
+       case EXPR_BINARY_ISUNORDERED:
+               return is_constant_expression(expression->binary.left)
+                       && is_constant_expression(expression->binary.right);
+
+       case EXPR_CONDITIONAL:
+               /* TODO: not correct, we only have to test expressions which are
+                * evaluated, which means either the true or false part might be not
+                * constant */
+               return is_constant_expression(expression->conditional.condition)
+                       && is_constant_expression(expression->conditional.true_expression)
+                       && is_constant_expression(expression->conditional.false_expression);
+
+       case EXPR_ARRAY_ACCESS:
+               return is_constant_expression(expression->array_access.array_ref)
+                       && is_constant_expression(expression->array_access.index);
+
+       case EXPR_UNKNOWN:
+       case EXPR_INVALID:
+               break;
+       }
+       panic("invalid expression found (is constant expression)");
+}
+
+
 void init_ast(void)
 {
        obstack_init(&ast_obstack);
diff --git a/ast.h b/ast.h
index 479c184..2fa7c4c 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -2,6 +2,7 @@
 #define AST_H
 
 #include <stdio.h>
+#include <stdbool.h>
 
 typedef struct context_t                    context_t;
 
@@ -72,4 +73,6 @@ void  print_declaration(const declaration_t *declaration);
 void  change_indent(int delta);
 void *allocate_ast(size_t size);
 
+bool is_constant_expression(const expression_t *expression);
+
 #endif
index ec6afd7..56757d2 100644 (file)
@@ -1643,8 +1643,10 @@ static ir_node *sizeof_to_firm(const sizeof_expression_t *expression)
        return size_node;
 }
 
-static tarval *try_fold_constant(const expression_t *expression)
+static long fold_constant(const expression_t *expression)
 {
+       assert(is_constant_expression(expression));
+
        ir_graph *old_current_ir_graph = current_ir_graph;
        if(current_ir_graph == NULL) {
                current_ir_graph = get_const_code_irg();
@@ -1654,22 +1656,12 @@ static tarval *try_fold_constant(const expression_t *expression)
        current_ir_graph = old_current_ir_graph;
 
        if(!is_Const(cnst)) {
-               return NULL;
+               panic("couldn't fold constant\n");
        }
 
        tarval *tv = get_Const_tarval(cnst);
        if(!tarval_is_long(tv)) {
-               return NULL;
-       }
-
-       return tv;
-}
-
-static long fold_constant(const expression_t *expression)
-{
-       tarval *tv = try_fold_constant(expression);
-       if(tv == NULL) {
-               panic("couldn't fold constantl");
+               panic("result of constant folding is not integer\n");
        }
 
        return get_tarval_long(tv);
@@ -1680,9 +1672,8 @@ static ir_node *conditional_to_firm(const conditional_expression_t *expression)
        dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
 
        /* first try to fold a constant condition */
-       tarval *tv = try_fold_constant(expression->condition);
-       if(tv != NULL) {
-               long val = get_tarval_long(tv);
+       if(is_constant_expression(expression->condition)) {
+               long val = fold_constant(expression->condition);
                if(val) {
                        return expression_to_firm(expression->true_expression);
                } else {
index 33d7873..48ca810 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -954,7 +954,16 @@ incompatible_assign_types:
 static expression_t *parse_constant_expression(void)
 {
        /* start parsing at precedence 7 (conditional expression) */
-       return parse_sub_expression(7);
+       expression_t *result = parse_sub_expression(7);
+
+       if(!is_constant_expression(result)) {
+               parser_print_error_prefix_pos(result->base.source_position);
+               fprintf(stderr, "expression '");
+               print_expression(result);
+               fprintf(stderr, "' is not constant\n");
+       }
+
+       return result;
 }
 
 static expression_t *parse_assignment_expression(void)