Hi! I'm not aware of any target that would support sign extension of something that can't be folded in the compiler into some type larger than word/pointer. Zero extension is doable and assemble_variable is able to deal with it by emitting low/high subregs of it (where the low one will contain some expression that needs to be computed by assembler or even have relocation and upper part will be all zeros), but for sign extension we'd need assembler support that would for some asm expression shift it arithmetically right.
So, this patch just rejects it in initializers (in C++ handles through dynamic initialization) in that case. clang also rejects it, ICC silently miscompiles (performs zero extension). Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-03-24 Jakub Jelinek <ja...@redhat.com> PR middle-end/80163 * varasm.c (initializer_constant_valid_p_1): Disallow sign-extending conversions to integer types wider than word and pointer. * gcc.dg/pr80163.c: New test. --- gcc/varasm.c.jj 2017-01-01 12:45:37.000000000 +0100 +++ gcc/varasm.c 2017-03-24 13:03:37.489529361 +0100 @@ -4472,8 +4472,15 @@ initializer_constant_valid_p_1 (tree val return initializer_constant_valid_p_1 (src, endtype, cache); /* Allow conversions between other integer types only if - explicit value. */ - if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type)) + explicit value. Don't allow sign-extension to a type larger + than word and pointer, there aren't relocations that would + allow to sign extend it to a wider type. */ + if (INTEGRAL_TYPE_P (dest_type) + && INTEGRAL_TYPE_P (src_type) + && (TYPE_UNSIGNED (src_type) + || TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type) + || TYPE_PRECISION (dest_type) <= BITS_PER_WORD + || TYPE_PRECISION (dest_type) <= POINTER_SIZE)) { tree inner = initializer_constant_valid_p_1 (src, endtype, cache); if (inner == null_pointer_node) --- gcc/testsuite/gcc.dg/pr80163.c.jj 2017-03-24 13:02:37.827295587 +0100 +++ gcc/testsuite/gcc.dg/pr80163.c 2017-03-24 13:05:12.465309614 +0100 @@ -0,0 +1,22 @@ +/* PR middle-end/80163 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O0" } */ + +void bar (void); + +__int128_t * +foo (void) +{ +a: + bar (); +b:; + static __int128_t d = (long) &&a - (long) &&b; /* { dg-error "initializer element is not computable at load time" } */ + return &d; +} + +__int128_t * +baz (void) +{ + static __int128_t d = (long) (3 * 4); + return &d; +} Jakub