This makes us use build_nonstandard_integer_type in signed_or_unsigned_type_for and adjusts the function to return NULL_TREE for non-sensical inputs (only allowing pointer and integeral types). This way we make sure that the precision of the result type matches that of the input - something which fold-const.c definitely expects for example (it uses type_for_size itself if it doesn't).
In the long run type_for_size should go - or it should be a wrapper that calls type_for_mode (int_mode_for_size ()) instead. I'm working towards that. Bootstrapped and tested on x86_64-unknown-linux-gnu for all languages. I get FAIL: gcc.dg/tree-ssa/pr31261.c scan-tree-dump-times original "return \\(char\\) -\\(unsigned char\\) c & 31;" 1 FAIL: gcc.dg/tree-ssa/pr31261.c scan-tree-dump-times original "return \\(int\\) \\(12 - \\(unsigned int\\) d\\) & 7;" 1 because we dump the unsigned type variant differently now. What do people think - adjust the testcase? Adjust how we pretty-print these non-standard integer types? Thanks, Richard. 2012-03-07 Richard Guenther <rguent...@suse.de> * tree.c (signed_or_unsigned_type_for): Use build_nonstandard_integer_type. (signed_type_for): Adjust documentation. (unsigned_type_for): Likewise. Index: gcc/tree.c =================================================================== *** gcc/tree.c (revision 185029) --- gcc/tree.c (working copy) *************** widest_int_cst_value (const_tree x) *** 10197,10228 **** return val; } ! /* If TYPE is an integral type, return an equivalent type which is ! unsigned iff UNSIGNEDP is true. If TYPE is not an integral type, ! return TYPE itself. */ tree signed_or_unsigned_type_for (int unsignedp, tree type) { ! tree t = type; ! if (POINTER_TYPE_P (type)) ! { ! /* If the pointer points to the normal address space, use the ! size_type_node. Otherwise use an appropriate size for the pointer ! based on the named address space it points to. */ ! if (!TYPE_ADDR_SPACE (TREE_TYPE (t))) ! t = size_type_node; ! else ! return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp); ! } ! if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp) ! return t; ! return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp); } ! /* Returns unsigned variant of TYPE. */ tree unsigned_type_for (tree type) --- 10197,10222 ---- return val; } ! /* If TYPE is an integral or pointer type, return an integer type with ! the same precision which is unsigned iff UNSIGNEDP is true, or itself ! if TYPE is already an integer type of signedness UNSIGNEDP. */ tree signed_or_unsigned_type_for (int unsignedp, tree type) { ! if (TREE_CODE (type) == INTEGER_TYPE && TYPE_UNSIGNED (type) == unsignedp) ! return type; ! if (!INTEGRAL_TYPE_P (type) ! && !POINTER_TYPE_P (type)) ! return NULL_TREE; ! return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp); } ! /* If TYPE is an integral or pointer type, return an integer type with ! the same precision which is unsigned, or itself if TYPE is already an ! unsigned integer type. */ tree unsigned_type_for (tree type) *************** unsigned_type_for (tree type) *** 10230,10236 **** return signed_or_unsigned_type_for (1, type); } ! /* Returns signed variant of TYPE. */ tree signed_type_for (tree type) --- 10224,10232 ---- return signed_or_unsigned_type_for (1, type); } ! /* If TYPE is an integral or pointer type, return an integer type with ! the same precision which is signed, or itself if TYPE is already a ! signed integer type. */ tree signed_type_for (tree type)