diff options
-rw-r--r-- | eval.c | 11 | ||||
-rw-r--r-- | test/initializer-pointer-int-cast.c | 2 | ||||
-rw-r--r-- | test/initializer-pointer-int-cast.qbe | 2 |
3 files changed, 13 insertions, 2 deletions
@@ -137,8 +137,15 @@ eval(struct expr *expr, enum evalkind kind) else expr->constant = l->constant; cast(expr); - } else if (l->type->kind == TYPEPOINTER && expr->type->kind == TYPEPOINTER) { - expr = l; + } else if (l->type->kind == TYPEPOINTER) { + /* + A cast from a pointer to integer is not a valid constant + expression, but C11 allows implementations to recognize + other forms of constant expressions (6.6p10), and some + programs expect this functionality. + */ + if (expr->type->kind == TYPEPOINTER || expr->type->prop & PROPINT && expr->type->size == typelong.size) + expr = l; } break; case EXPRBINARY: diff --git a/test/initializer-pointer-int-cast.c b/test/initializer-pointer-int-cast.c new file mode 100644 index 0000000..75963b2 --- /dev/null +++ b/test/initializer-pointer-int-cast.c @@ -0,0 +1,2 @@ +int x; +long p = (long)&x; diff --git a/test/initializer-pointer-int-cast.qbe b/test/initializer-pointer-int-cast.qbe new file mode 100644 index 0000000..a996882 --- /dev/null +++ b/test/initializer-pointer-int-cast.qbe @@ -0,0 +1,2 @@ +export data $p = align 8 { l $x, } +export data $x = align 4 { z 4 } |