compound literals are linker_constants
authorMatthias Braun <matze@braunis.de>
Thu, 24 Nov 2011 20:13:20 +0000 (21:13 +0100)
committerMatthias Braun <matze@braunis.de>
Thu, 24 Nov 2011 22:11:12 +0000 (23:11 +0100)
ast.c
ast.h
parser.c

diff --git a/ast.c b/ast.c
index 3944ade..0fb422b 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1537,7 +1537,7 @@ expression_classification_t is_constant_initializer(const initializer_t *initial
                return EXPR_CLASS_CONSTANT;
 
        case INITIALIZER_VALUE:
-               return is_constant_expression(initializer->value.value);
+               return is_linker_constant(initializer->value.value);
 
        case INITIALIZER_LIST: {
                expression_classification_t all = EXPR_CLASS_CONSTANT;
@@ -1623,6 +1623,9 @@ expression_classification_t is_linker_constant(const expression_t *expression)
        case EXPR_LABEL_ADDRESS:
                return EXPR_CLASS_CONSTANT;
 
+       case EXPR_COMPOUND_LITERAL:
+               return is_constant_initializer(expression->compound_literal.initializer);
+
        case EXPR_UNARY_TAKE_ADDRESS:
                return is_object_with_linker_constant_address(expression->unary.value);
 
@@ -1643,11 +1646,9 @@ expression_classification_t is_linker_constant(const expression_t *expression)
                                !(get_atomic_type_flags(dest->atomic.akind) & ATOMIC_TYPE_FLAG_INTEGER) ||
                                get_atomic_type_size(dest->atomic.akind) < get_type_size(type_void_ptr)
                    ))
-                       return EXPR_CLASS_VARIABLE;
+                       return is_constant_expression(expression);
 
-               expression_classification_t const expr = is_constant_expression(expression->unary.value);
-               expression_classification_t const addr = is_linker_constant(expression->unary.value);
-               return expr > addr ? expr : addr;
+               return is_linker_constant(expression->unary.value);
        }
 
        case EXPR_BINARY_ADD:
@@ -1668,7 +1669,7 @@ expression_classification_t is_linker_constant(const expression_t *expression)
                } else if (!is_type_valid(ltype) || !is_type_valid(rtype)) {
                        return EXPR_CLASS_ERROR;
                } else {
-                       return EXPR_CLASS_VARIABLE;
+                       return is_constant_expression(expression);
                }
        }
 
@@ -1694,9 +1695,7 @@ expression_classification_t is_linker_constant(const expression_t *expression)
                        skip_typeref(revert_automatic_type_conversion(expression));
                if (!is_type_array(type))
                        return EXPR_CLASS_VARIABLE;
-               expression_classification_t const ref = is_linker_constant(expression->array_access.array_ref);
-               expression_classification_t const idx = is_constant_expression(expression->array_access.index);
-               return ref < idx ? ref : idx;
+               return is_linker_constant(expression->array_access.array_ref);
        }
 
        case EXPR_CONDITIONAL: {
@@ -1732,11 +1731,8 @@ expression_classification_t is_linker_constant(const expression_t *expression)
                return EXPR_CLASS_VARIABLE;
        }
 
-       case EXPR_ERROR:
-               return EXPR_CLASS_ERROR;
-
        default:
-               return EXPR_CLASS_VARIABLE;
+               return is_constant_expression(expression);
        }
 }
 
diff --git a/ast.h b/ast.h
index cd00cdc..9e1dee0 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -112,10 +112,8 @@ typedef enum expression_classification_t {
 } expression_classification_t;
 
 /**
- * Returns true if a given expression is a compile time
- * constant. ยง6.6
- *
- * @param expression  the expression to check
+ * Returns true when an initializer contains only constants/linker_constant
+ * values.
  */
 expression_classification_t is_constant_initializer(const initializer_t *initializer);
 
@@ -129,7 +127,7 @@ expression_classification_t is_constant_expression(const expression_t *expressio
 
 /**
  * Checks if an expression is a constant/known value to the linker. Examples:
- *  - all constant expression casted to a pointer type
+ *  - all constant/linker constant expression casted to a pointer type
  *  - "&x", with x being a global variable.
  *  - "array" or "a.array" in case array is an array and array and a,
  *  respectively is an object with link time constant address
index 8986376..1469800 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1665,15 +1665,6 @@ static initializer_t *initializer_from_expression(type_t *orig_type,
        return result;
 }
 
-/**
- * Checks if a given expression can be used as a constant initializer.
- */
-static bool is_initializer_constant(const expression_t *expression)
-{
-       return is_constant_expression(expression) != EXPR_CLASS_VARIABLE ||
-              is_linker_constant(expression)     != EXPR_CLASS_VARIABLE;
-}
-
 /**
  * Parses an scalar initializer.
  *
@@ -1694,7 +1685,7 @@ static initializer_t *parse_scalar_initializer(type_t *type,
 
        expression_t *expression = parse_assignment_expression();
        mark_vars_read(expression, NULL);
-       if (must_be_constant && !is_initializer_constant(expression)) {
+       if (must_be_constant && !is_linker_constant(expression)) {
                errorf(&expression->base.source_position,
                       "initialisation expression '%E' is not constant",
                       expression);
@@ -2114,7 +2105,7 @@ finish_designator:
                        expression_t *expression = parse_assignment_expression();
                        mark_vars_read(expression, NULL);
 
-                       if (env->must_be_constant && !is_initializer_constant(expression)) {
+                       if (env->must_be_constant && !is_linker_constant(expression)) {
                                errorf(&expression->base.source_position,
                                       "Initialisation expression '%E' is not constant",
                                       expression);