string literals as array intiailizers are supported now
authorMatthias Braun <matze@braunis.de>
Fri, 23 Nov 2007 15:36:41 +0000 (15:36 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 23 Nov 2007 15:36:41 +0000 (15:36 +0000)
[r18523]

ast.h
ast2firm.c
ast_t.h
parser.c
parsetest/shouldfail/const.c [new file with mode: 0644]
type.c

diff --git a/ast.h b/ast.h
index ef9ae43..bc93e16 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -31,6 +31,7 @@ typedef struct classify_type_expression_t   classify_type_expression_t;
 typedef struct initializer_t                initializer_t;
 typedef struct initializer_list_t           initializer_list_t;
 typedef struct initializer_value_t          initializer_value_t;
+typedef struct initializer_string_t         initializer_string_t;
 typedef struct declaration_t                declaration_t;
 
 typedef struct statement_t                  statement_t;
index f21e197..1da9bf6 100644 (file)
@@ -2020,19 +2020,12 @@ struct compound_graph_path_entry_t {
        compound_graph_path_entry_t *prev;
 };
 
-static void create_initializer_list(initializer_list_t *initializer,
-                                    type_t *type, ir_entity *entity,
-                                    compound_graph_path_entry_t *entry,
-                                    int len);
+static void create_initializer_object(initializer_t *initializer, type_t *type,
+               ir_entity *entity, compound_graph_path_entry_t *entry, int len);
 
-static void create_initializer_value(initializer_value_t *initializer,
-                                     ir_entity *entity,
-                                     compound_graph_path_entry_t *entry,
-                                     int len)
+static compound_graph_path *create_compound_path(ir_type *type,
+               compound_graph_path_entry_t *entry, int len)
 {
-       ir_node *node = expression_to_firm(initializer->value);
-
-       ir_type *type = get_entity_type(entity);
        compound_graph_path *path = new_compound_graph_path(type, len);
 
        int i = len - 1;
@@ -2047,6 +2040,17 @@ static void create_initializer_value(initializer_value_t *initializer,
        }
        assert(i == -1);
 
+       return path;
+}
+
+static void create_initializer_value(initializer_value_t *initializer,
+                                     ir_entity *entity,
+                                     compound_graph_path_entry_t *entry,
+                                     int len)
+{
+       ir_node             *node = expression_to_firm(initializer->value);
+       ir_type             *type = get_entity_type(entity);
+       compound_graph_path *path = create_compound_path(type, entry, len);
        add_compound_ent_value_w_path(entity, node, path);
 }
 
@@ -2087,10 +2091,9 @@ static void create_initializer_compound(initializer_list_t *initializer,
                        create_initializer_value((initializer_value_t*) sub_initializer,
                                                 entity, &entry, len);
                } else {
-                       assert(sub_initializer->type == INITIALIZER_LIST);
                        type_t *type = skip_typeref(compound_entry->type);
-                       create_initializer_list((initializer_list_t*) sub_initializer,
-                                               type, entity, &entry, len);
+                       create_initializer_object(sub_initializer, type, entity, &entry,
+                                                 len);
                }
 
                ++i;
@@ -2120,24 +2123,63 @@ static void create_initializer_array(initializer_list_t *initializer,
                                                 entity, &entry, len);
                } else {
                        assert(sub_initializer->type == INITIALIZER_LIST);
-                       create_initializer_list((initializer_list_t*) sub_initializer,
-                                               element_type, entity, &entry, len);
+                       create_initializer_object(sub_initializer, element_type, entity,
+                                                 &entry, len);
                }
        }
 }
 
-static void create_initializer_list(initializer_list_t *initializer,
-                                    type_t *type, ir_entity *entity,
-                                    compound_graph_path_entry_t *entry, int len)
+static void create_initializer_string(initializer_string_t *initializer,
+                                      array_type_t *type, ir_entity *entity,
+                                      compound_graph_path_entry_t *last_entry,
+                                      int len)
+{
+       type_t *element_type = type->element_type;
+       element_type         = skip_typeref(element_type);
+
+       compound_graph_path_entry_t entry;
+       entry.type = COMPOUND_GRAPH_ENTRY_ARRAY;
+       entry.prev = last_entry;
+       ++len;
+
+       ir_type    *irtype  = get_entity_type(entity);
+       size_t      arr_len = get_array_type_size(type);
+       const char *p       = initializer->string;
+       size_t      i       = 0;
+       for(i = 0; i < arr_len; ++i, ++p) {
+               entry.v.array_index = i;
+
+               ir_node             *node = new_Const_long(mode_Bs, *p);
+               compound_graph_path *path = create_compound_path(irtype, &entry, len);
+               add_compound_ent_value_w_path(entity, node, path);
+
+               if(*p == '\0')
+                       break;
+       }
+}
+
+static void create_initializer_object(initializer_t *initializer, type_t *type,
+               ir_entity *entity, compound_graph_path_entry_t *entry, int len)
 {
        if(type->type == TYPE_ARRAY) {
-               create_initializer_array(initializer, (array_type_t*) type,
-                                        entity, entry, len);
+               array_type_t *array_type = (array_type_t*) type;
+
+               if(initializer->type == INITIALIZER_STRING) {
+                       initializer_string_t *string = (initializer_string_t*) initializer;
+                       create_initializer_string(string, array_type, entity, entry, len);
+               } else {
+                       assert(initializer->type == INITIALIZER_LIST);
+                       initializer_list_t *list = (initializer_list_t*) initializer;
+                       create_initializer_array(list, array_type, entity, entry, len);
+               }
        } else {
+               assert(initializer->type == INITIALIZER_LIST);
+               initializer_list_t *list = (initializer_list_t*) initializer;
+
                assert(type->type == TYPE_COMPOUND_STRUCT
                                || type->type == TYPE_COMPOUND_UNION);
-               create_initializer_compound(initializer, (compound_type_t*) type,
-                                           entity, entry, len);
+               compound_type_t *compound_type = (compound_type_t*) type;
+               create_initializer_compound(list, compound_type, entity, entry, len);
        }
 }
 
@@ -2173,14 +2215,11 @@ static void create_initializer_local_variable_entity(declaration_t *declaration)
        set_entity_variability(init_entity, variability_initialized);
        set_entity_visibility(init_entity, visibility_local);
 
-       assert(initializer->type == INITIALIZER_LIST);
-       initializer_list_t *list = (initializer_list_t*) initializer;
-
        ir_graph *old_current_ir_graph = current_ir_graph;
        current_ir_graph = get_const_code_irg();
 
        type_t *type = skip_typeref(declaration->type);
-       create_initializer_list(list, type, init_entity, NULL, 0);
+       create_initializer_object(initializer, type, init_entity, NULL, 0);
 
        assert(current_ir_graph == get_const_code_irg());
        current_ir_graph = old_current_ir_graph;
@@ -2220,9 +2259,6 @@ static void create_initializer(declaration_t *declaration)
                        set_atomic_ent_value(entity, value);
                }
        } else {
-               assert(initializer->type == INITIALIZER_LIST);
-               initializer_list_t *list = (initializer_list_t*) initializer;
-
                declaration_type_t declaration_type = declaration->declaration_type;
                assert(declaration_type == DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY
                                || declaration_type == DECLARATION_TYPE_GLOBAL_VARIABLE);
@@ -2231,7 +2267,7 @@ static void create_initializer(declaration_t *declaration)
                set_entity_variability(entity, variability_initialized);
 
                type_t *type = skip_typeref(declaration->type);
-               create_initializer_list(list, type, entity, NULL, 0);
+               create_initializer_object(initializer, type, entity, NULL, 0);
        }
 }
 
@@ -2278,7 +2314,13 @@ static void create_local_static_variable(declaration_t *declaration)
        set_entity_variability(entity, variability_uninitialized);
        set_entity_visibility(entity, visibility_local);
 
+       ir_graph *old_current_ir_graph = current_ir_graph;
+       current_ir_graph = get_const_code_irg();
+
        create_initializer(declaration);
+
+       assert(current_ir_graph == get_const_code_irg());
+       current_ir_graph = old_current_ir_graph;
 }
 
 static void declaration_statement_to_firm(declaration_statement_t *statement)
diff --git a/ast_t.h b/ast_t.h
index 7d078ec..e342788 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -217,6 +217,7 @@ typedef enum {
 typedef enum {
        INITIALIZER_VALUE,
        INITIALIZER_LIST,
+       INITIALIZER_STRING
 } initializer_type_t;
 
 struct initializer_t {
@@ -234,6 +235,11 @@ struct initializer_list_t {
        initializer_t *initializers[];
 };
 
+struct initializer_string_t {
+       initializer_t  initializer;
+       const char    *string;
+};
+
 struct declaration_t {
        unsigned char       namespc;
        unsigned char       storage_class;
index 2e698fa..7ea8225 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -716,7 +716,7 @@ static void semantic_assign(type_t *orig_type_left, expression_t **right,
        type_t *const type_left  = skip_typeref(orig_type_left);
        type_t *const type_right = skip_typeref(orig_type_right);
 
-       if (type_left == type_right) {
+       if (types_compatible(type_left, type_right)) {
                return;
        }
 
@@ -894,10 +894,24 @@ static designator_t *parse_designation(void)
 }
 #endif
 
+static initializer_t *initializer_from_string(array_type_t *type,
+                                              const char *string)
+{
+       /* TODO: check len vs. size of array type */
+       (void) type;
+
+       initializer_string_t *initializer
+               = allocate_ast_zero(sizeof(initializer[0]));
+
+       initializer->initializer.type = INITIALIZER_STRING;
+       initializer->string           = string;
+
+       return (initializer_t*) initializer;
+}
+
 static initializer_t *initializer_from_expression(type_t *type,
                                                   expression_t *expression)
 {
-       initializer_value_t *result = allocate_ast_zero(sizeof(result[0]));
 
        /* TODO check that expression is a constant expression */
 
@@ -914,15 +928,16 @@ static initializer_t *initializer_from_expression(type_t *type,
                        if(atype == ATOMIC_TYPE_CHAR
                                        || atype == ATOMIC_TYPE_SCHAR
                                        || atype == ATOMIC_TYPE_UCHAR) {
-                               /* it's fine TODO: check for length of string array... */
-                               goto initializer_from_expression_finished;
+
+                               string_literal_t *literal = (string_literal_t*) expression;
+                               return initializer_from_string(array_type, literal->value);
                        }
                }
        }
 
        semantic_assign(type, &expression, "initializer");
 
-initializer_from_expression_finished:
+       initializer_value_t *result = allocate_ast_zero(sizeof(result[0]));
        result->initializer.type = INITIALIZER_VALUE;
        result->value            = expression;
 
@@ -2164,9 +2179,6 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers)
                        initializer_t *initializer = parse_initializer(type);
 
                        if(type->type == TYPE_ARRAY && initializer != NULL) {
-                               assert(initializer->type == INITIALIZER_LIST);
-
-                               initializer_list_t *list = (initializer_list_t*) initializer;
                                array_type_t       *array_type = (array_type_t*) type;
 
                                if(array_type->size == NULL) {
@@ -2174,7 +2186,17 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers)
 
                                        cnst->expression.type     = EXPR_CONST;
                                        cnst->expression.datatype = type_size_t;
-                                       cnst->v.int_value         = list->len;
+
+                                       if(initializer->type == INITIALIZER_LIST) {
+                                               initializer_list_t *list
+                                                       = (initializer_list_t*) initializer;
+                                               cnst->v.int_value = list->len;
+                                       } else {
+                                               assert(initializer->type == INITIALIZER_STRING);
+                                               initializer_string_t *string
+                                                       = (initializer_string_t*) initializer;
+                                               cnst->v.int_value = strlen(string->string) + 1;
+                                       }
 
                                        array_type->size = (expression_t*) cnst;
                                }
@@ -3607,19 +3629,31 @@ static void semantic_logical_op(binary_expression_t *expression)
 
 static void semantic_binexpr_assign(binary_expression_t *expression)
 {
-       expression_t *left       = expression->left;
-       type_t       *type_left  = left->datatype;
+       expression_t *left           = expression->left;
+       type_t       *orig_type_left = left->datatype;
 
-       if(type_left == NULL)
+       if(orig_type_left == NULL)
                return;
 
+       type_t *type_left = skip_typeref(orig_type_left);
+
        if (type_left->type == TYPE_ARRAY) {
                parse_error("Cannot assign to arrays.");
-       } else if (type_left != NULL) {
-               semantic_assign(type_left, &expression->right, "assignment");
+               return;
        }
 
-       expression->expression.datatype = type_left;
+       if(type_left->qualifiers & TYPE_QUALIFIER_CONST) {
+               parser_print_error_prefix();
+               fprintf(stderr, "assignment to readonly location '");
+               print_expression(left);
+               fprintf(stderr, "' (type ");
+               print_type_quoted(orig_type_left);
+               fprintf(stderr, ")\n");
+       }
+
+       semantic_assign(orig_type_left, &expression->right, "assignment");
+
+       expression->expression.datatype = orig_type_left;
 }
 
 static void semantic_comma(binary_expression_t *expression)
diff --git a/parsetest/shouldfail/const.c b/parsetest/shouldfail/const.c
new file mode 100644 (file)
index 0000000..fa549b6
--- /dev/null
@@ -0,0 +1,11 @@
+
+void t(void)
+{
+       typedef int       Int;
+       typedef const Int CInt;
+       typedef CInt      MyCInt;
+
+       MyCInt k;
+
+       k = 5; /* should fail, assignment to const */
+}
diff --git a/type.c b/type.c
index 1a204e8..6653c3f 100644 (file)
--- a/type.c
+++ b/type.c
@@ -500,8 +500,9 @@ bool is_type_incomplete(const type_t *type)
 
 bool types_compatible(const type_t *type1, const type_t *type2)
 {
-       (void) type1;
-       (void) type2;
+       if(type1 == type2)
+               return true;
+
        return true;
 }