fix cases where compoundlits are constant/get an entity
authorMatthias Braun <matze@braunis.de>
Wed, 28 Nov 2012 12:29:38 +0000 (13:29 +0100)
committerMatthias Braun <matze@braunis.de>
Wed, 28 Nov 2012 12:34:16 +0000 (13:34 +0100)
This is possible when they are in global scope (and have a constant
initializers anyway) or when they have a const type and constant
initializers.

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

diff --git a/ast.c b/ast.c
index da758db..d08da8c 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1498,6 +1498,14 @@ static expression_classification_t is_object_with_linker_constant_address(
        case EXPR_UNARY_DEREFERENCE:
                return is_linker_constant(expression->unary.value);
 
+       case EXPR_COMPOUND_LITERAL: {
+               const compound_literal_expression_t *literal
+                       = &expression->compound_literal;
+               return literal->global_scope ||
+                      ((literal->type->base.qualifiers & TYPE_QUALIFIER_CONST)
+                       && is_constant_initializer(literal->initializer));
+       }
+
        case EXPR_SELECT: {
                type_t *base_type = skip_typeref(expression->select.compound->base.type);
                if (is_type_pointer(base_type)) {
index 1755af2..f0043c5 100644 (file)
@@ -2759,7 +2759,9 @@ static ir_node *compound_literal_addr(compound_literal_expression_t const *const
        type_t        *type        = expression->type;
        initializer_t *initializer = expression->initializer;
 
-       if (is_constant_initializer(initializer) == EXPR_CLASS_CONSTANT) {
+       if (expression->global_scope ||
+               ((type->base.qualifiers & TYPE_QUALIFIER_CONST)
+           && is_constant_initializer(initializer) == EXPR_CLASS_CONSTANT)) {
                ir_entity *entity = create_initializer_entity(dbgi, initializer, type);
                return create_symconst(dbgi, entity);
        } else {
diff --git a/ast_t.h b/ast_t.h
index 7e72895..e1c365a 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -277,6 +277,7 @@ struct compound_literal_expression_t {
        expression_base_t  base;
        type_t            *type;
        initializer_t     *initializer;
+       bool               global_scope;
 };
 
 struct builtin_constant_expression_t {
index c888119..a9a4041 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -6187,21 +6187,24 @@ static bool semantic_cast(expression_t *cast)
        return true;
 }
 
-static expression_t *parse_compound_literal(source_position_t const *const pos, type_t *type)
+static expression_t *parse_compound_literal(source_position_t const *const pos,
+                                            type_t *type)
 {
        expression_t *expression = allocate_expression_zero(EXPR_COMPOUND_LITERAL);
        expression->base.source_position = *pos;
+       bool global_scope = current_scope == file_scope;
 
        parse_initializer_env_t env;
        env.type             = type;
        env.entity           = NULL;
-       env.must_be_constant = false;
+       env.must_be_constant = global_scope;
        initializer_t *initializer = parse_initializer(&env);
        type = env.type;
 
-       expression->compound_literal.initializer = initializer;
-       expression->compound_literal.type        = type;
-       expression->base.type                    = automatic_type_conversion(type);
+       expression->base.type                     = automatic_type_conversion(type);
+       expression->compound_literal.initializer  = initializer;
+       expression->compound_literal.type         = type;
+       expression->compound_literal.global_scope = global_scope;
 
        return expression;
 }