- change enum to have an underlying atomic type
[cparser] / ast.c
diff --git a/ast.c b/ast.c
index 4478caa..36338a6 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -304,10 +304,10 @@ static void print_quoted_wide_string(const wide_string_t *const wstr,
                        default: {
                                const unsigned tc = *c;
                                if (tc < 0x80U) {
-                                       if (!isprint(*c)) {
-                                               fprintf(out, "\\%03o", (char)*c);
-                                       } else {
+                                       if (isprint(*c)) {
                                                fputc(*c, out);
+                                       } else {
+                                               fprintf(out, "\\%03o", tc);
                                        }
                                } else if (tc < 0x800) {
                                        fputc(0xC0 | (tc >> 6),   out);
@@ -879,7 +879,7 @@ static void print_compound_statement(const compound_statement_t *block)
        }
        --indent;
        print_indent();
-       fputs("}\n", out);
+       fputs(block->stmt_expr ? "}" : "}\n", out);
 }
 
 /**
@@ -999,25 +999,6 @@ static void print_case_label(const case_label_statement_t *statement)
        }
 }
 
-static void print_local_label(const local_label_statement_t *statement)
-{
-       fputs("__label__ ", out);
-
-       bool      first  = true;
-       entity_t *entity = statement->labels_begin;
-       for (;
-               entity != statement->labels_end->base.next;
-               entity = entity->base.next) {
-               if (!first) {
-                       fputs(", ", out);
-               } else {
-                       first = false;
-               }
-               fputs(entity->base.symbol->string, out);
-       }
-       fputs(";\n", out);
-}
-
 static void print_typedef(const entity_t *entity)
 {
        fputs("typedef ", out);
@@ -1057,7 +1038,7 @@ static void print_declaration_statement(
 
        entity_t *const end = statement->declarations_end->base.next;
        for (; entity != end; entity = entity->base.next) {
-               if (!is_declaration(entity) && entity->kind != ENTITY_TYPEDEF)
+               if (entity->kind == ENTITY_ENUM_VALUE)
                        continue;
                if (is_generated_entity(entity))
                        continue;
@@ -1068,13 +1049,7 @@ static void print_declaration_statement(
                        first = false;
                }
 
-               if (entity->kind == ENTITY_TYPEDEF) {
-                       print_typedef(entity);
-               } else {
-                       assert(is_declaration(entity));
-                       print_declaration(entity);
-               }
-
+               print_entity(entity);
                fputc('\n', out);
        }
 }
@@ -1272,9 +1247,6 @@ void print_statement(const statement_t *statement)
        case STATEMENT_LABEL:
                print_label_statement(&statement->label);
                break;
-       case STATEMENT_LOCAL_LABEL:
-               print_local_label(&statement->local_label);
-               break;
        case STATEMENT_GOTO:
                print_goto_statement(&statement->gotos);
                break;
@@ -1327,17 +1299,15 @@ void print_statement(const statement_t *statement)
  */
 static void print_storage_class(storage_class_tag_t storage_class)
 {
-       const char *text;
        switch (storage_class) {
        case STORAGE_CLASS_NONE:     return;
-       case STORAGE_CLASS_TYPEDEF:  text = "typedef ";  break;
-       case STORAGE_CLASS_EXTERN:   text = "extern ";   break;
-       case STORAGE_CLASS_STATIC:   text = "static ";   break;
-       case STORAGE_CLASS_AUTO:     text = "auto ";     break;
-       case STORAGE_CLASS_REGISTER: text = "register "; break;
-       default:                     panic("invalid storage class");
+       case STORAGE_CLASS_TYPEDEF:  fputs("typedef ",  out); return;
+       case STORAGE_CLASS_EXTERN:   fputs("extern ",   out); return;
+       case STORAGE_CLASS_STATIC:   fputs("static ",   out); return;
+       case STORAGE_CLASS_AUTO:     fputs("auto ",     out); return;
+       case STORAGE_CLASS_REGISTER: fputs("register ", out); return;
        }
-       fputs(text, out);
+       panic("invalid storage class");
 }
 
 /**
@@ -1621,9 +1591,11 @@ void print_entity(const entity_t *entity)
        case ENTITY_NAMESPACE:
                print_namespace(&entity->namespacee);
                return;
+       case ENTITY_LOCAL_LABEL:
+               fprintf(out, "__label__ %s;", entity->base.symbol->string);
+               return;
        case ENTITY_LABEL:
        case ENTITY_ENUM_VALUE:
-       case ENTITY_LOCAL_LABEL:
                panic("print_entity used on unexpected entity type");
        case ENTITY_INVALID:
                break;
@@ -1955,8 +1927,6 @@ bool is_constant_expression(const expression_t *expression)
        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:
@@ -1968,6 +1938,24 @@ bool is_constant_expression(const expression_t *expression)
                return is_constant_expression(expression->binary.left)
                        && is_constant_expression(expression->binary.right);
 
+       case EXPR_BINARY_LOGICAL_AND: {
+               expression_t const *const left = expression->binary.left;
+               if (!is_constant_expression(left))
+                       return false;
+               if (fold_constant(left) == 0)
+                       return true;
+               return is_constant_expression(expression->binary.right);
+       }
+
+       case EXPR_BINARY_LOGICAL_OR: {
+               expression_t const *const left = expression->binary.left;
+               if (!is_constant_expression(left))
+                       return false;
+               if (fold_constant(left) != 0)
+                       return true;
+               return is_constant_expression(expression->binary.right);
+       }
+
        case EXPR_COMPOUND_LITERAL:
                return is_constant_initializer(expression->compound_literal.initializer);