Do not crash if the expression of an array designator is not constant.
[cparser] / ast.c
diff --git a/ast.c b/ast.c
index e7ab2cf..c0e6b1d 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -101,91 +101,88 @@ static int right_to_left(unsigned precedence)
 static unsigned get_expression_precedence(expression_kind_t kind)
 {
        static const unsigned prec[] = {
-               [EXPR_ERROR]                             = PREC_PRIMARY,
-               [EXPR_REFERENCE]                         = PREC_PRIMARY,
-               [EXPR_REFERENCE_ENUM_VALUE]              = PREC_PRIMARY,
-               [EXPR_LITERAL_INTEGER]                   = PREC_PRIMARY,
-               [EXPR_LITERAL_INTEGER_OCTAL]             = PREC_PRIMARY,
-               [EXPR_LITERAL_INTEGER_HEXADECIMAL]       = PREC_PRIMARY,
-               [EXPR_LITERAL_FLOATINGPOINT]             = PREC_PRIMARY,
-               [EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL] = PREC_PRIMARY,
-               [EXPR_LITERAL_CHARACTER]                 = PREC_PRIMARY,
-               [EXPR_LITERAL_WIDE_CHARACTER]            = PREC_PRIMARY,
-               [EXPR_LITERAL_MS_NOOP]                   = PREC_PRIMARY,
-               [EXPR_STRING_LITERAL]                    = PREC_PRIMARY,
-               [EXPR_WIDE_STRING_LITERAL]               = PREC_PRIMARY,
-               [EXPR_COMPOUND_LITERAL]                  = PREC_UNARY,
-               [EXPR_CALL]                              = PREC_POSTFIX,
-               [EXPR_CONDITIONAL]                       = PREC_CONDITIONAL,
-               [EXPR_SELECT]                            = PREC_POSTFIX,
-               [EXPR_ARRAY_ACCESS]                      = PREC_POSTFIX,
-               [EXPR_SIZEOF]                            = PREC_UNARY,
-               [EXPR_CLASSIFY_TYPE]                     = PREC_UNARY,
-               [EXPR_ALIGNOF]                           = PREC_UNARY,
-
-               [EXPR_FUNCNAME]                          = PREC_PRIMARY,
-               [EXPR_BUILTIN_CONSTANT_P]                = PREC_PRIMARY,
-               [EXPR_BUILTIN_TYPES_COMPATIBLE_P]        = PREC_PRIMARY,
-               [EXPR_OFFSETOF]                          = PREC_PRIMARY,
-               [EXPR_VA_START]                          = PREC_PRIMARY,
-               [EXPR_VA_ARG]                            = PREC_PRIMARY,
-               [EXPR_VA_COPY]                           = PREC_PRIMARY,
-               [EXPR_STATEMENT]                         = PREC_PRIMARY,
-               [EXPR_LABEL_ADDRESS]                     = PREC_PRIMARY,
-
-               [EXPR_UNARY_NEGATE]                      = PREC_UNARY,
-               [EXPR_UNARY_PLUS]                        = PREC_UNARY,
-               [EXPR_UNARY_BITWISE_NEGATE]              = PREC_UNARY,
-               [EXPR_UNARY_NOT]                         = PREC_UNARY,
-               [EXPR_UNARY_DEREFERENCE]                 = PREC_UNARY,
-               [EXPR_UNARY_TAKE_ADDRESS]                = PREC_UNARY,
-               [EXPR_UNARY_POSTFIX_INCREMENT]           = PREC_POSTFIX,
-               [EXPR_UNARY_POSTFIX_DECREMENT]           = PREC_POSTFIX,
-               [EXPR_UNARY_PREFIX_INCREMENT]            = PREC_UNARY,
-               [EXPR_UNARY_PREFIX_DECREMENT]            = PREC_UNARY,
-               [EXPR_UNARY_CAST]                        = PREC_UNARY,
-               [EXPR_UNARY_ASSUME]                      = PREC_PRIMARY,
-               [EXPR_UNARY_DELETE]                      = PREC_UNARY,
-               [EXPR_UNARY_DELETE_ARRAY]                = PREC_UNARY,
-               [EXPR_UNARY_THROW]                       = PREC_ASSIGNMENT,
-
-               [EXPR_BINARY_ADD]                        = PREC_ADDITIVE,
-               [EXPR_BINARY_SUB]                        = PREC_ADDITIVE,
-               [EXPR_BINARY_MUL]                        = PREC_MULTIPLICATIVE,
-               [EXPR_BINARY_DIV]                        = PREC_MULTIPLICATIVE,
-               [EXPR_BINARY_MOD]                        = PREC_MULTIPLICATIVE,
-               [EXPR_BINARY_EQUAL]                      = PREC_EQUALITY,
-               [EXPR_BINARY_NOTEQUAL]                   = PREC_EQUALITY,
-               [EXPR_BINARY_LESS]                       = PREC_RELATIONAL,
-               [EXPR_BINARY_LESSEQUAL]                  = PREC_RELATIONAL,
-               [EXPR_BINARY_GREATER]                    = PREC_RELATIONAL,
-               [EXPR_BINARY_GREATEREQUAL]               = PREC_RELATIONAL,
-               [EXPR_BINARY_BITWISE_AND]                = PREC_AND,
-               [EXPR_BINARY_BITWISE_OR]                 = PREC_OR,
-               [EXPR_BINARY_BITWISE_XOR]                = PREC_XOR,
-               [EXPR_BINARY_LOGICAL_AND]                = PREC_LOGICAL_AND,
-               [EXPR_BINARY_LOGICAL_OR]                 = PREC_LOGICAL_OR,
-               [EXPR_BINARY_SHIFTLEFT]                  = PREC_SHIFT,
-               [EXPR_BINARY_SHIFTRIGHT]                 = PREC_SHIFT,
-               [EXPR_BINARY_ASSIGN]                     = PREC_ASSIGNMENT,
-               [EXPR_BINARY_MUL_ASSIGN]                 = PREC_ASSIGNMENT,
-               [EXPR_BINARY_DIV_ASSIGN]                 = PREC_ASSIGNMENT,
-               [EXPR_BINARY_MOD_ASSIGN]                 = PREC_ASSIGNMENT,
-               [EXPR_BINARY_ADD_ASSIGN]                 = PREC_ASSIGNMENT,
-               [EXPR_BINARY_SUB_ASSIGN]                 = PREC_ASSIGNMENT,
-               [EXPR_BINARY_SHIFTLEFT_ASSIGN]           = PREC_ASSIGNMENT,
-               [EXPR_BINARY_SHIFTRIGHT_ASSIGN]          = PREC_ASSIGNMENT,
-               [EXPR_BINARY_BITWISE_AND_ASSIGN]         = PREC_ASSIGNMENT,
-               [EXPR_BINARY_BITWISE_XOR_ASSIGN]         = PREC_ASSIGNMENT,
-               [EXPR_BINARY_BITWISE_OR_ASSIGN]          = PREC_ASSIGNMENT,
-               [EXPR_BINARY_COMMA]                      = PREC_EXPRESSION,
-
-               [EXPR_BINARY_ISGREATER]                  = PREC_PRIMARY,
-               [EXPR_BINARY_ISGREATEREQUAL]             = PREC_PRIMARY,
-               [EXPR_BINARY_ISLESS]                     = PREC_PRIMARY,
-               [EXPR_BINARY_ISLESSEQUAL]                = PREC_PRIMARY,
-               [EXPR_BINARY_ISLESSGREATER]              = PREC_PRIMARY,
-               [EXPR_BINARY_ISUNORDERED]                = PREC_PRIMARY
+               [EXPR_ERROR]                      = PREC_PRIMARY,
+               [EXPR_REFERENCE]                  = PREC_PRIMARY,
+               [EXPR_ENUM_CONSTANT]              = PREC_PRIMARY,
+               [EXPR_LITERAL_INTEGER]            = PREC_PRIMARY,
+               [EXPR_LITERAL_FLOATINGPOINT]      = PREC_PRIMARY,
+               [EXPR_LITERAL_CHARACTER]          = PREC_PRIMARY,
+               [EXPR_LITERAL_WIDE_CHARACTER]     = PREC_PRIMARY,
+               [EXPR_LITERAL_MS_NOOP]            = PREC_PRIMARY,
+               [EXPR_STRING_LITERAL]             = PREC_PRIMARY,
+               [EXPR_WIDE_STRING_LITERAL]        = PREC_PRIMARY,
+               [EXPR_COMPOUND_LITERAL]           = PREC_UNARY,
+               [EXPR_CALL]                       = PREC_POSTFIX,
+               [EXPR_CONDITIONAL]                = PREC_CONDITIONAL,
+               [EXPR_SELECT]                     = PREC_POSTFIX,
+               [EXPR_ARRAY_ACCESS]               = PREC_POSTFIX,
+               [EXPR_SIZEOF]                     = PREC_UNARY,
+               [EXPR_CLASSIFY_TYPE]              = PREC_UNARY,
+               [EXPR_ALIGNOF]                    = PREC_UNARY,
+
+               [EXPR_FUNCNAME]                   = PREC_PRIMARY,
+               [EXPR_BUILTIN_CONSTANT_P]         = PREC_PRIMARY,
+               [EXPR_BUILTIN_TYPES_COMPATIBLE_P] = PREC_PRIMARY,
+               [EXPR_OFFSETOF]                   = PREC_PRIMARY,
+               [EXPR_VA_START]                   = PREC_PRIMARY,
+               [EXPR_VA_ARG]                     = PREC_PRIMARY,
+               [EXPR_VA_COPY]                    = PREC_PRIMARY,
+               [EXPR_STATEMENT]                  = PREC_PRIMARY,
+               [EXPR_LABEL_ADDRESS]              = PREC_PRIMARY,
+
+               [EXPR_UNARY_NEGATE]               = PREC_UNARY,
+               [EXPR_UNARY_PLUS]                 = PREC_UNARY,
+               [EXPR_UNARY_BITWISE_NEGATE]       = PREC_UNARY,
+               [EXPR_UNARY_NOT]                  = PREC_UNARY,
+               [EXPR_UNARY_DEREFERENCE]          = PREC_UNARY,
+               [EXPR_UNARY_TAKE_ADDRESS]         = PREC_UNARY,
+               [EXPR_UNARY_POSTFIX_INCREMENT]    = PREC_POSTFIX,
+               [EXPR_UNARY_POSTFIX_DECREMENT]    = PREC_POSTFIX,
+               [EXPR_UNARY_PREFIX_INCREMENT]     = PREC_UNARY,
+               [EXPR_UNARY_PREFIX_DECREMENT]     = PREC_UNARY,
+               [EXPR_UNARY_CAST]                 = PREC_UNARY,
+               [EXPR_UNARY_ASSUME]               = PREC_PRIMARY,
+               [EXPR_UNARY_DELETE]               = PREC_UNARY,
+               [EXPR_UNARY_DELETE_ARRAY]         = PREC_UNARY,
+               [EXPR_UNARY_THROW]                = PREC_ASSIGNMENT,
+
+               [EXPR_BINARY_ADD]                 = PREC_ADDITIVE,
+               [EXPR_BINARY_SUB]                 = PREC_ADDITIVE,
+               [EXPR_BINARY_MUL]                 = PREC_MULTIPLICATIVE,
+               [EXPR_BINARY_DIV]                 = PREC_MULTIPLICATIVE,
+               [EXPR_BINARY_MOD]                 = PREC_MULTIPLICATIVE,
+               [EXPR_BINARY_EQUAL]               = PREC_EQUALITY,
+               [EXPR_BINARY_NOTEQUAL]            = PREC_EQUALITY,
+               [EXPR_BINARY_LESS]                = PREC_RELATIONAL,
+               [EXPR_BINARY_LESSEQUAL]           = PREC_RELATIONAL,
+               [EXPR_BINARY_GREATER]             = PREC_RELATIONAL,
+               [EXPR_BINARY_GREATEREQUAL]        = PREC_RELATIONAL,
+               [EXPR_BINARY_BITWISE_AND]         = PREC_AND,
+               [EXPR_BINARY_BITWISE_OR]          = PREC_OR,
+               [EXPR_BINARY_BITWISE_XOR]         = PREC_XOR,
+               [EXPR_BINARY_LOGICAL_AND]         = PREC_LOGICAL_AND,
+               [EXPR_BINARY_LOGICAL_OR]          = PREC_LOGICAL_OR,
+               [EXPR_BINARY_SHIFTLEFT]           = PREC_SHIFT,
+               [EXPR_BINARY_SHIFTRIGHT]          = PREC_SHIFT,
+               [EXPR_BINARY_ASSIGN]              = PREC_ASSIGNMENT,
+               [EXPR_BINARY_MUL_ASSIGN]          = PREC_ASSIGNMENT,
+               [EXPR_BINARY_DIV_ASSIGN]          = PREC_ASSIGNMENT,
+               [EXPR_BINARY_MOD_ASSIGN]          = PREC_ASSIGNMENT,
+               [EXPR_BINARY_ADD_ASSIGN]          = PREC_ASSIGNMENT,
+               [EXPR_BINARY_SUB_ASSIGN]          = PREC_ASSIGNMENT,
+               [EXPR_BINARY_SHIFTLEFT_ASSIGN]    = PREC_ASSIGNMENT,
+               [EXPR_BINARY_SHIFTRIGHT_ASSIGN]   = PREC_ASSIGNMENT,
+               [EXPR_BINARY_BITWISE_AND_ASSIGN]  = PREC_ASSIGNMENT,
+               [EXPR_BINARY_BITWISE_XOR_ASSIGN]  = PREC_ASSIGNMENT,
+               [EXPR_BINARY_BITWISE_OR_ASSIGN]   = PREC_ASSIGNMENT,
+               [EXPR_BINARY_COMMA]               = PREC_EXPRESSION,
+
+               [EXPR_BINARY_ISGREATER]           = PREC_PRIMARY,
+               [EXPR_BINARY_ISGREATEREQUAL]      = PREC_PRIMARY,
+               [EXPR_BINARY_ISLESS]              = PREC_PRIMARY,
+               [EXPR_BINARY_ISLESSEQUAL]         = PREC_PRIMARY,
+               [EXPR_BINARY_ISLESSGREATER]       = PREC_PRIMARY,
+               [EXPR_BINARY_ISUNORDERED]         = PREC_PRIMARY
        };
        assert((size_t)kind < lengthof(prec));
        unsigned res = prec[kind];
@@ -252,18 +249,14 @@ static void print_literal(const literal_expression_t *literal)
        case EXPR_LITERAL_MS_NOOP:
                print_string("__noop");
                return;
-       case EXPR_LITERAL_INTEGER_HEXADECIMAL:
-       case EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL:
-               print_string("0x");
-               /* FALLTHROUGH */
+
        case EXPR_LITERAL_BOOLEAN:
-       case EXPR_LITERAL_INTEGER:
-       case EXPR_LITERAL_INTEGER_OCTAL:
        case EXPR_LITERAL_FLOATINGPOINT:
+       case EXPR_LITERAL_INTEGER:
                print_stringrep(&literal->value);
-               if (literal->suffix.size > 0)
-                       print_stringrep(&literal->suffix);
+               print_stringrep(&literal->suffix);
                return;
+
        case EXPR_LITERAL_WIDE_CHARACTER:
                print_char('L');
                /* FALLTHROUGH */
@@ -545,7 +538,7 @@ static void print_va_start(const va_start_expression_t *const expression)
        print_string("__builtin_va_start(");
        print_assignment_expression(expression->ap);
        print_string(", ");
-       print_string(expression->parameter->base.base.symbol->string);
+       print_assignment_expression(expression->parameter);
        print_char(')');
 }
 
@@ -657,6 +650,33 @@ static void print_statement_expression(const statement_expression_t *expression)
        print_char(')');
 }
 
+static bool needs_parentheses(expression_t const *const expr, unsigned const top_prec)
+{
+       if (expr->base.parenthesized)
+               return true;
+
+       if (top_prec > get_expression_precedence(expr->base.kind))
+               return true;
+
+       if (print_parenthesis && top_prec != PREC_BOTTOM) {
+               switch (expr->kind) {
+               case EXPR_ENUM_CONSTANT:
+               case EXPR_FUNCNAME:
+               case EXPR_LITERAL_CASES:
+               case EXPR_REFERENCE:
+               case EXPR_STRING_LITERAL:
+               case EXPR_WIDE_STRING_LITERAL:
+                       /* Do not print () around subexpressions consisting of a single token. */
+                       return false;
+
+               default:
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 /**
  * Prints an expression with parenthesis if needed.
  *
@@ -669,10 +689,7 @@ static void print_expression_prec(expression_t const *expr, unsigned const top_p
                expr = expr->unary.value;
        }
 
-       bool parenthesized =
-               expr->base.parenthesized                       ||
-               (print_parenthesis && top_prec != PREC_BOTTOM) ||
-               top_prec > get_expression_precedence(expr->base.kind);
+       bool const parenthesized = needs_parentheses(expr, top_prec);
 
        if (parenthesized)
                print_char('(');
@@ -693,7 +710,7 @@ static void print_expression_prec(expression_t const *expr, unsigned const top_p
        case EXPR_LITERAL_CASES:              print_literal(                 &expr->literal);                  break;
        case EXPR_OFFSETOF:                   print_offsetof_expression(     &expr->offsetofe);                break;
        case EXPR_REFERENCE:
-       case EXPR_REFERENCE_ENUM_VALUE:       print_reference_expression(    &expr->reference);                break;
+       case EXPR_ENUM_CONSTANT:              print_reference_expression(    &expr->reference);                break;
        case EXPR_SELECT:                     print_select(                  &expr->select);                   break;
        case EXPR_STATEMENT:                  print_statement_expression(    &expr->statement);                break;
        case EXPR_STRING_LITERAL:
@@ -773,6 +790,18 @@ static void print_expression_statement(const expression_statement_t *statement)
        print_char(';');
 }
 
+/**
+ * Print a computed goto statement.
+ *
+ * @param statement  the computed goto statement
+ */
+static void print_computed_goto_statement(computed_goto_statement_t const *const stmt)
+{
+       print_string("goto *");
+       print_expression(stmt->expression);
+       print_char(';');
+}
+
 /**
  * Print a goto statement.
  *
@@ -781,12 +810,7 @@ static void print_expression_statement(const expression_statement_t *statement)
 static void print_goto_statement(const goto_statement_t *statement)
 {
        print_string("goto ");
-       if (statement->expression != NULL) {
-               print_char('*');
-               print_expression(statement->expression);
-       } else {
-               print_string(statement->label->base.symbol->string);
-       }
+       print_string(statement->label->base.symbol->string);
        print_char(';');
 }
 
@@ -1116,25 +1140,26 @@ static void print_leave_statement(const leave_statement_t *statement)
 void print_statement(statement_t const *const stmt)
 {
        switch (stmt->kind) {
-       case STATEMENT_ASM:         print_asm_statement(        &stmt->asms);        break;
-       case STATEMENT_BREAK:       print_string("break;");                          break;
-       case STATEMENT_CASE_LABEL:  print_case_label(           &stmt->case_label);  break;
-       case STATEMENT_COMPOUND:    print_compound_statement(   &stmt->compound);    break;
-       case STATEMENT_CONTINUE:    print_string("continue;");                       break;
-       case STATEMENT_DECLARATION: print_declaration_statement(&stmt->declaration); break;
-       case STATEMENT_DO_WHILE:    print_do_while_statement(   &stmt->do_while);    break;
-       case STATEMENT_EMPTY:       print_char(';');                                 break;
-       case STATEMENT_ERROR:       print_string("$error statement$");               break;
-       case STATEMENT_EXPRESSION:  print_expression_statement( &stmt->expression);  break;
-       case STATEMENT_FOR:         print_for_statement(        &stmt->fors);        break;
-       case STATEMENT_GOTO:        print_goto_statement(       &stmt->gotos);       break;
-       case STATEMENT_IF:          print_if_statement(         &stmt->ifs);         break;
-       case STATEMENT_LABEL:       print_label_statement(      &stmt->label);       break;
-       case STATEMENT_LEAVE:       print_leave_statement(      &stmt->leave);       break;
-       case STATEMENT_MS_TRY:      print_ms_try_statement(     &stmt->ms_try);      break;
-       case STATEMENT_RETURN:      print_return_statement(     &stmt->returns);     break;
-       case STATEMENT_SWITCH:      print_switch_statement(     &stmt->switchs);     break;
-       case STATEMENT_WHILE:       print_while_statement(      &stmt->whiles);      break;
+       case STATEMENT_ASM:           print_asm_statement(          &stmt->asms);          break;
+       case STATEMENT_BREAK:         print_string("break;");                              break;
+       case STATEMENT_CASE_LABEL:    print_case_label(             &stmt->case_label);    break;
+       case STATEMENT_COMPOUND:      print_compound_statement(     &stmt->compound);      break;
+       case STATEMENT_COMPUTED_GOTO: print_computed_goto_statement(&stmt->computed_goto); break;
+       case STATEMENT_CONTINUE:      print_string("continue;");                           break;
+       case STATEMENT_DECLARATION:   print_declaration_statement(  &stmt->declaration);   break;
+       case STATEMENT_DO_WHILE:      print_do_while_statement(     &stmt->do_while);      break;
+       case STATEMENT_EMPTY:         print_char(';');                                     break;
+       case STATEMENT_ERROR:         print_string("$error statement$");                   break;
+       case STATEMENT_EXPRESSION:    print_expression_statement(   &stmt->expression);    break;
+       case STATEMENT_FOR:           print_for_statement(          &stmt->fors);          break;
+       case STATEMENT_GOTO:          print_goto_statement(         &stmt->gotos);         break;
+       case STATEMENT_IF:            print_if_statement(           &stmt->ifs);           break;
+       case STATEMENT_LABEL:         print_label_statement(        &stmt->label);         break;
+       case STATEMENT_LEAVE:         print_leave_statement(        &stmt->leave);         break;
+       case STATEMENT_MS_TRY:        print_ms_try_statement(       &stmt->ms_try);        break;
+       case STATEMENT_RETURN:        print_return_statement(       &stmt->returns);       break;
+       case STATEMENT_SWITCH:        print_switch_statement(       &stmt->switchs);       break;
+       case STATEMENT_WHILE:         print_while_statement(        &stmt->whiles);        break;
        }
 }
 
@@ -1770,7 +1795,7 @@ expression_classification_t is_constant_expression(const expression_t *expressio
        case EXPR_ALIGNOF:
        case EXPR_BUILTIN_CONSTANT_P:
        case EXPR_BUILTIN_TYPES_COMPATIBLE_P:
-       case EXPR_REFERENCE_ENUM_VALUE:
+       case EXPR_ENUM_CONSTANT:
                return EXPR_CLASS_CONSTANT;
 
        case EXPR_SIZEOF: {