public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/ARM/heads/morello)] Handle INTCAP_TYPEs in conversion warnings
@ 2022-06-16 13:45 Richard Sandiford
  0 siblings, 0 replies; only message in thread
From: Richard Sandiford @ 2022-06-16 13:45 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:b27ecfa2999280d3e87bdac3cefa3811a8646a7d

commit b27ecfa2999280d3e87bdac3cefa3811a8646a7d
Author: Richard Sandiford <richard.sandiford@arm.com>
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 <stdint.h>
+
+__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)


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-16 13:45 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-16 13:45 [gcc(refs/vendors/ARM/heads/morello)] Handle INTCAP_TYPEs in conversion warnings Richard Sandiford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).