From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1130) id 8AAD63853555; Thu, 16 Jun 2022 13:45:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8AAD63853555 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Richard Sandiford To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/vendors/ARM/heads/morello)] Handle INTCAP_TYPEs in conversion warnings X-Act-Checkin: gcc X-Git-Author: Richard Sandiford X-Git-Refname: refs/vendors/ARM/heads/morello X-Git-Oldrev: f943dc5219f965d5263c920ddc3d51b5feaa5116 X-Git-Newrev: b27ecfa2999280d3e87bdac3cefa3811a8646a7d Message-Id: <20220616134554.8AAD63853555@sourceware.org> Date: Thu, 16 Jun 2022 13:45:54 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 16 Jun 2022 13:45:54 -0000 https://gcc.gnu.org/g:b27ecfa2999280d3e87bdac3cefa3811a8646a7d commit b27ecfa2999280d3e87bdac3cefa3811a8646a7d Author: Richard Sandiford Date: Thu Jun 16 14:42:39 2022 +0100 Handle INTCAP_TYPEs in conversion warnings -Wconversion emits warnings for things like: uint64_t f1() { return -1; } // changes value int64_t f2(uint64_t x) { return x; } // might change sign uint64_t f3(float x) { return x; } // might change value int32_t f4(int64_t x) { return x; } // might change value However, it wasn't emitting the corresponding warnings with int64_t replaced by intcap_t and uint64_t replaced by uintcap_t. Also (unrelated to capabilities), -Wconversion wouldn't diagnose cases in which a scalar integer was converted to a complex integer (although it did handle the reverse, which if nothing else can change the value by dropping the imaginary component). Diff: --- gcc/c-family/c-common.c | 15 +++++ gcc/c-family/c-warn.c | 10 +++- .../aarch64/morello/conversion-warnings-1.c | 66 ++++++++++++++++++++++ gcc/tree.c | 9 ++- 4 files changed, 96 insertions(+), 4 deletions(-) diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index fed39e74f11..20030960b33 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -1331,8 +1331,17 @@ enum conversion_safety unsafe_conversion_p (tree type, tree expr, tree result, bool check_sign) { enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */ + + /* Converting an intcap_t or uintcap_t is unsafe iff the same conversion + would be unsafe for the integer capability value. */ + if (TREE_CODE (TREE_TYPE (expr)) == INTCAP_TYPE) + expr = fold_drop_capability (expr); tree expr_type = TREE_TYPE (expr); + /* Likewise converting to an intcap_t or uintcap_t. */ + if (TREE_CODE (type) == INTCAP_TYPE) + type = TREE_TYPE (type); + expr = fold_for_warn (expr); if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST) @@ -1439,6 +1448,12 @@ unsafe_conversion_p (tree type, tree expr, tree result, bool check_sign) /* Checks for remaining case: EXPR is not constant. */ else { + /* Treat a conversion from a scalar to a complex in the same way + as a conversion from the scalar to the real component. */ + if (TREE_CODE (type) == COMPLEX_TYPE + && TREE_CODE (expr_type) != COMPLEX_TYPE) + type = TREE_TYPE (type); + /* Warn for real types converted to integer types. */ if (TREE_CODE (expr_type) == REAL_TYPE && TREE_CODE (type) == INTEGER_TYPE) diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 1963847ff33..b98bb59087b 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -1193,7 +1193,7 @@ conversion_warning (location_t loc, tree type, tree expr, tree result) /* Conversion from boolean to a signed:1 bit-field (which only can hold the values 0 and -1) doesn't lose information - but it does change the value. */ - if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)) + if (TYPE_NONCAP_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)) warning_at (loc, OPT_Wconversion, "conversion to %qT from boolean expression", type); return true; @@ -1293,6 +1293,11 @@ conversion_warning (location_t loc, tree type, tree expr, tree result) || conversion_warning (loc, type, op2, result)); } + case CALL_EXPR: + if (CALL_EXPR_IFN (expr) == IFN_REPLACE_ADDRESS_VALUE) + return conversion_warning (loc, type, CALL_EXPR_ARG (expr, 1), result); + goto default_; + default_: default: conversion_kind = unsafe_conversion_p (type, expr, result, true); @@ -1370,7 +1375,8 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr, if (TREE_CODE (expr) == INTEGER_CST && (TREE_CODE (type) == INTEGER_TYPE - || TREE_CODE (type) == ENUMERAL_TYPE) + || TREE_CODE (type) == ENUMERAL_TYPE + || TREE_CODE (type) == INTCAP_TYPE) && !int_fits_type_p (expr, type)) { /* Do not diagnose overflow in a constant expression merely diff --git a/gcc/testsuite/gcc.target/aarch64/morello/conversion-warnings-1.c b/gcc/testsuite/gcc.target/aarch64/morello/conversion-warnings-1.c new file mode 100644 index 00000000000..78d94a5659e --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/morello/conversion-warnings-1.c @@ -0,0 +1,66 @@ +/* { dg-additional-options "-W -Wall -Wconversion" } */ + +#include + +__intcap_t overflow_intcap() { return 1ULL << 63; } /* { dg-warning "overflow in conversion" } */ +__uintcap_t overflow_uintcap() { return -1; } /* { dg-warning "unsigned conversion" } */ + +__intcap_t compare_to_intcap(int x) { return x == 0; } +__intcap_t short_to_intcap(short x) { return x; } +__intcap_t ushort_to_intcap(unsigned short x) { return x; } +__intcap_t int_to_intcap(int x) { return x; } +__intcap_t uint_to_intcap(unsigned int x) { return x; } +__intcap_t int64_to_intcap(int64_t x) { return x; } +__intcap_t uint64_to_intcap(uint64_t x) { return x; } /* { dg-warning "may change the sign of the result" } */ +__intcap_t uintcap_to_intcap(__uintcap_t x) { return x; } /* { dg-warning "may change the sign of the result" } */ +__intcap_t float_to_intcap(float x) { return x; } /* { dg-warning "may change value" } */ +__intcap_t complex_uint_to_intcap(_Complex unsigned int x) { return x; } /* { dg-warning "discards imaginary component" } */ + +__uintcap_t compare_to_uintcap(int x) { return x == 0; } +__uintcap_t short_to_uintcap(short x) { return x; } /* { dg-warning "may change the sign of the result" } */ +__uintcap_t ushort_to_uintcap(unsigned short x) { return x; } +__uintcap_t int_to_uintcap(int x) { return x; } /* { dg-warning "may change the sign of the result" } */ +__uintcap_t uint_to_uintcap(unsigned int x) { return x; } +__uintcap_t int64_to_uintcap(int64_t x) { return x; } /* { dg-warning "may change the sign of the result" } */ +__uintcap_t uint64_to_uintcap(uint64_t x) { return x; } +__uintcap_t intcap_to_uintcap(__intcap_t x) { return x; } /* { dg-warning "may change the sign of the result" } */ +__uintcap_t float_to_uintcap(float x) { return x; } /* { dg-warning "may change value" } */ +__uintcap_t complex_uint_to_uintcap(_Complex unsigned int x) { return x; } /* { dg-warning "discards imaginary component" } */ + +short intcap_to_short(__intcap_t x) { return x; } /* { dg-warning "may change value" } */ +unsigned short intcap_to_ushort(__intcap_t x) { return x; } /* { dg-warning "may change value" } */ +int intcap_to_int(__intcap_t x) { return x; } /* { dg-warning "may change value" } */ +unsigned int intcap_to_uint(__intcap_t x) { return x; } /* { dg-warning "may change value" } */ +int64_t intcap_to_int64(__intcap_t x) { return x; } +uint64_t intcap_to_uint64(__intcap_t x) { return x; } /* { dg-warning "may change the sign of the result" } */ +float intcap_to_float(__intcap_t x) { return x; } /* { dg-warning "may change value" } */ +_Complex unsigned int intcap_to_complex_uint(__intcap_t x) { return x; } /* { dg-warning "may change value" } */ +_Complex long intcap_to_complex_long(__intcap_t x) { return x; } +_Complex unsigned long intcap_to_complex_ulong(__intcap_t x) { return x; } /* { dg-warning "may change the sign of the result" } */ + +short uintcap_to_short(__uintcap_t x) { return x; } /* { dg-warning "may change value" } */ +unsigned short uintcap_to_ushort(__uintcap_t x) { return x; } /* { dg-warning "may change value" } */ +int uintcap_to_int(__uintcap_t x) { return x; } /* { dg-warning "may change value" } */ +unsigned int uintcap_to_uint(__uintcap_t x) { return x; } /* { dg-warning "may change value" } */ +int64_t uintcap_to_int64(__uintcap_t x) { return x; } /* { dg-warning "may change the sign of the result" } */ +uint64_t uintcap_to_uint64(__uintcap_t x) { return x; } +float uintcap_to_float(__uintcap_t x) { return x; } /* { dg-warning "may change value" } */ +_Complex unsigned int uintcap_to_complex_uint(__uintcap_t x) { return x; } /* { dg-warning "may change value" } */ +_Complex long uintcap_to_complex_long(__uintcap_t x) { return x; } /* { dg-warning "may change the sign of the result" } */ +_Complex unsigned long uintcap_to_complex_ulong(__uintcap_t x) { return x; } + +__intcap_t precise_intcap() { return 1.0; } +__intcap_t imprecise_intcap() { return 1.2; } /* { dg-warning "changes value" } */ + +__intcap_t masked_uintcap_to_intcap(__uintcap_t x) { return x & 0xff; } +__uintcap_t masked_intcap_to_uintcap(__intcap_t x) { return x & 0xff; } + +__intcap_t ptr_to_intcap(void *__capability x) { return x; } /* { dg-warning {integer from pointer without a cast} } */ +__uintcap_t ptr_to_uintcap(void *__capability x) { return x; } /* { dg-warning {integer from pointer without a cast} } */ +int64_t ptr_to_int64(void *__capability x) { return x; } /* { dg-warning {integer from pointer without a cast} } */ +uint64_t ptr_to_uint64(void *__capability x) { return x; } /* { dg-warning {integer from pointer without a cast} } */ + +__intcap_t explicit_ptr_to_intcap(void *__capability x) { return (__intcap_t)x; } +__uintcap_t explicit_ptr_to_uintcap(void *__capability x) { return (__uintcap_t)x; } +int64_t explicit_ptr_to_int64(void *__capability x) { return (int64_t)x; } +uint64_t explicit_ptr_to_uint64(void *__capability x) { return (uint64_t)x; } diff --git a/gcc/tree.c b/gcc/tree.c index 055a446b5e6..67349b66914 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -9033,10 +9033,15 @@ excess_precision_type (tree type) tree get_unwidened (tree op, tree for_type) { - /* Set UNS initially if converting OP to FOR_TYPE is a zero-extension. */ tree type = TREE_TYPE (op); + + /* Capability values have a fixed size, so we can't drop their precision. */ + if (TREE_CODE (type) == INTCAP_TYPE) + return op; + unsigned final_prec - = TYPE_PRECISION (for_type != 0 ? for_type : type); + = TYPE_NONCAP_PRECISION (for_type != 0 ? for_type : type); + /* Set UNS initially if converting OP to FOR_TYPE is a zero-extension. */ int uns = (for_type != 0 && for_type != type && final_prec > TYPE_PRECISION (type)