[gcc(refs/vendors/ARM/heads/morello)] [morello, testsuite] Resolve some further front-end edge-cases and some tests

Matthew Malcomson matmal01@gcc.gnu.org
Tue Sep 21 09:13:40 GMT 2021


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

commit c5526519cfd1e5edabaded84aebfc239ffd6a862
Author: Stam Markianos-Wright <stam.markianos-wright@arm.com>
Date:   Mon Sep 20 16:35:56 2021 +0100

    [morello, testsuite] Resolve some further front-end edge-cases and some tests
    
    This includes the fix to the last testsuite ICE, an optimisation for
    folding of REPLACE_ADDRESS_VALUE, a fix in tree-ssa-ifcombine for invalid
    use of TYPE_PRECISION and a number of other fixes that I've had locally
    for tests that fell through the cracks of the testsuite analysis.
    
    Changes are as follows:
     - A few tests that either were forgotten or the fix added to them had
       been inadequate.
     - Re-instate the use of VIEW_CONVERT_EXPR for atomic return values, but
       convert to __intcap instead of not converting at this stage. This has the
       benefit of converting these to a "base type" with no type qualifiers,
       (this would happen anyway with the old convert-to-integer method) which
       means we avoid emitting spurious warnings about loss of type qualifiers
       when the standard convert_arguments, convert_for_assignment functions act
       on the same values.
     - A slightly trickier fix for a front-end ICE with reproducers like:
    
         static char commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
    
         int a  = {(__intcap_t) 0 * 3};
         int b  = {(__intcap_t) 2 * 3};
         int c  = {(__intcap_t) 0 * sizeof(int)};
         int d  = {(__intcap_t) 2 * sizeof(int)};
         int e  = {(__intcap_t) strlen(commonNameW) * sizeof(int)};
         int f  = {(__intcap_t) strlen(commonNameW) * sizeof(f)};
    
       that would happen at varasm.c:4569:
       (gcc_assert (TREE_CODE (ptr) == INTEGER_CST && tree_to_uhwi (ptr) == 0);)
       This has been resolved by improving the folding of REPLACE_ADDRESS_VALUE
       when it is wrapped in a NOP type conversion.
     - A piece of fallout from the above change was uncovering a possible ICE in
       tree-ssa-ifcombine, due to the use of TYPE_PRECISION with SSA_NAME_DEF_STMT
       when stripping away type conversion. This is resolved by not stripping away
       conversions from Capabilities to Integers and instead use the resulting
       integer in the pass logic, rather than the raw capability.

Diff:
---
 gcc/c-family/c-common.c                            | 98 ++++++++++++----------
 gcc/c/c-typeck.c                                   |  6 +-
 gcc/fold-const.c                                   | 21 +++++
 .../gcc.dg/Wbuiltin-declaration-mismatch-3.c       |  4 +-
 gcc/testsuite/gcc.dg/Wreturn-local-addr-10.c       |  1 +
 gcc/testsuite/gcc.dg/noncompile/20020213-1.c       | 12 +--
 gcc/testsuite/gcc.dg/pr56724-2.c                   |  4 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c         | 51 ++++++++---
 .../aarch64/morello/intcap-ptr-init-const.c        | 22 +++++
 gcc/tree-ssa-ifcombine.c                           | 17 ++--
 gcc/tree.h                                         |  9 ++
 gcc/varasm.c                                       |  3 +-
 12 files changed, 174 insertions(+), 74 deletions(-)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 6e241245eb7..d02d944b879 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -7370,9 +7370,9 @@ resolve_overloaded_atomic_exchange (location_t loc, tree function,
   p2 = (*params)[2];
   p3 = (*params)[3];
 
-  /* For capability types we do not want to do any conversions, so simply
-     dereference p1.  We also assume that the types are supported and do not
-     need to be changed to the library generic format.  */
+  /* For capability types we also assume that the types are supported by the
+     underlying architecture and the call does not need to be changed to their
+     library generic format. We only convert them to intcap_type_node.  */
   if (!capability_type_p (TREE_TYPE (TREE_TYPE (p0))))
     {
       /* If not a lock-free size, change to the library generic format.  */
@@ -7389,16 +7389,17 @@ resolve_overloaded_atomic_exchange (location_t loc, tree function,
 
       /* Create pointer to appropriate size.  */
       I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
-      I_type_ptr = build_pointer_type (I_type);
-
-      /* Convert object pointer to required type.  */
-      p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
-      /* Convert new value to required type, and dereference it.  */
-      p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
-      p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
     }
   else
-    p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
+    I_type = intcap_type_node;
+
+  I_type_ptr = build_pointer_type (I_type);
+
+  /* Convert object pointer to required type.  */
+  p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
+  /* Convert new value to required type, and dereference it.  */
+  p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
+  p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
 
   (*params)[0] = p0;
   (*params)[1] = p1;
@@ -7443,9 +7444,9 @@ resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
   p1 = (*params)[1];
   p2 = (*params)[2];
 
-  /* For capability types we do not want to do any conversions, so simply
-     dereference p2.  We also assume that the types are supported and do not
-     need to be changed to the library generic format.  */
+  /* For capability types we also assume that the types are supported by the
+     underlying architecture and the call does not need to be changed to their
+     library generic format. We only convert them to intcap_type_node.  */
   if (!capability_type_p (TREE_TYPE (TREE_TYPE (p0))))
     {
       /* If not a lock-free size, change to the library generic format.  */
@@ -7473,20 +7474,22 @@ resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
 
       /* Create pointer to appropriate size.  */
       I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
-      I_type_ptr = build_pointer_type (I_type);
-
-      /* Convert object pointer to required type.  */
-      p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
-
-      /* Convert expected pointer to required type.  */
-      p1 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1);
 
-      /* Convert desired value to required type, and dereference it.  */
-      p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR);
-      p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2);
     }
   else
-    p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR);
+    I_type = intcap_type_node;
+
+  I_type_ptr = build_pointer_type (I_type);
+
+  /* Convert object pointer to required type.  */
+  p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
+
+  /* Convert expected pointer to required type.  */
+  p1 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1);
+
+  /* Convert desired value to required type, and dereference it.  */
+  p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR);
+  p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2);
 
   (*params)[0] = p0;
   (*params)[1] = p1;
@@ -7529,9 +7532,9 @@ resolve_overloaded_atomic_load (location_t loc, tree function,
   p1 = (*params)[1];
   p2 = (*params)[2];
 
-  /* For capability types we do not want to do any conversions.
-     We also assume that the types are supported and do not
-     need to be changed to the library generic format.  */
+  /* For capability types we also assume that the types are supported by the
+     underlying architecture and the call does not need to be changed to their
+     library generic format. We only convert them to intcap_type_node.  */
   if (!capability_type_p (TREE_TYPE (TREE_TYPE (p0))))
     {
       /* If not a lock-free size, change to the library generic format.  */
@@ -7548,11 +7551,14 @@ resolve_overloaded_atomic_load (location_t loc, tree function,
 
       /* Create pointer to appropriate size.  */
       I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
-      I_type_ptr = build_pointer_type (I_type);
-
-      /* Convert object pointer to required type.  */
-      p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
     }
+  else
+    I_type = intcap_type_node;
+
+  I_type_ptr = build_pointer_type (I_type);
+
+  /* Convert object pointer to required type.  */
+  p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
 
   (*params)[0] = p0;
   /* Move memory model to the 2nd position, and end param list.  */
@@ -7595,9 +7601,9 @@ resolve_overloaded_atomic_store (location_t loc, tree function,
   p0 = (*params)[0];
   p1 = (*params)[1];
 
-  /* For capability types we do not want to do any conversions, so simply
-     dereference p1.  We also assume that the types are supported and do not
-     need to be changed to the library generic format.  */
+  /* For capability types we also assume that the types are supported by the
+     underlying architecture and the call does not need to be changed to their
+     library generic format. We only convert them to intcap_type_node.  */
   if (!capability_type_p (TREE_TYPE (TREE_TYPE (p0))))
     {
       /* If not a lock-free size, change to the library generic format.  */
@@ -7614,17 +7620,18 @@ resolve_overloaded_atomic_store (location_t loc, tree function,
 
       /* Create pointer to appropriate size.  */
       I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
-      I_type_ptr = build_pointer_type (I_type);
-
-      /* Convert object pointer to required type.  */
-      p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
-
-      /* Convert new value to required type, and dereference it.  */
-      p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
-      p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
     }
   else
-    p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
+    I_type = intcap_type_node;
+
+  I_type_ptr = build_pointer_type (I_type);
+
+  /* Convert object pointer to required type.  */
+  p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
+
+  /* Convert new value to required type, and dereference it.  */
+  p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
+  p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
 
   (*params)[0] = p0;
   (*params)[1] = p1;
@@ -7635,7 +7642,8 @@ resolve_overloaded_atomic_store (location_t loc, tree function,
   return false;
 }
 
-tree resolve_atomic_fncode_n (tree function, vec<tree, va_gc> *params,
+static tree
+resolve_atomic_fncode_n (tree function, vec<tree, va_gc> *params,
 				  built_in_function orig_code, bool fetch_op)
 {
   enum built_in_function new_code_bt;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 94879118902..5b6c6e186af 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -12926,7 +12926,7 @@ build_binary_op (location_t location, enum tree_code code,
 
   /* For INTCAP_TYPEs, we dropped the capabilities early on and now need
      to work out where the provenance (if any) should come from.  */
-  if (!capability_type_p (result_type)
+  if (!capability_type_p (TREE_TYPE (ret))
       && TREE_CODE_CLASS (code) != tcc_comparison
       && !boolean_op)
     {
@@ -12957,8 +12957,8 @@ build_binary_op (location_t location, enum tree_code code,
 
       if (intcap)
 	{
-	  tree ic_type = c_common_type (TREE_TYPE (intcap), result_type);
-	  gcc_assert (noncapability_type (ic_type) == result_type);
+	  tree ic_type = c_common_type (TREE_TYPE (intcap), TREE_TYPE (ret));
+	  gcc_assert (TREE_TYPE (ret) == noncapability_type (ic_type));
 	  intcap = convert (ic_type, intcap);
 
 	  /* We can't fold inside REPLACE_ADDRESS_VALUE calls, so ensure
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index d85d6cf25b3..08d54b98d05 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8885,6 +8885,17 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
       return NULL_TREE;
 
     CASE_CONVERT:
+      /*  If we plan to convert to an INTEGER_TYPE and we are given a call to
+	  IFN_REPLACE_ADDRESS_VALUE with an INTEGER_CST on the left hand side,
+	  extract the second operand and recursively call fold_unary_loc to
+	  allow for further folding inside the conversion.  */
+      if (TREE_CODE (type) == INTEGER_TYPE
+	  && TREE_CODE (arg0) == CALL_EXPR
+	  && CALL_EXPR_IFN (arg0) == IFN_REPLACE_ADDRESS_VALUE
+	  && !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (arg0, 0)))
+	return fold_unary_loc (loc, code, type, CALL_EXPR_ARG (arg0, 1));
+      /* Fall through */
+
     case FLOAT_EXPR:
     case FIX_TRUNC_EXPR:
       if (COMPARISON_CLASS_P (op0))
@@ -13574,6 +13585,16 @@ fold_build_replace_address_value_loc (location_t loc, tree c, tree cv)
       && CALL_EXPR_IFN (c) == IFN_REPLACE_ADDRESS_VALUE)
     return fold_build_replace_address_value_loc (loc,
 						 CALL_EXPR_ARG (c, 0), cv);
+  /* If the capability C is an INTEGER_CST or a REPLACE_ADDRESS_VALUE inside
+     a NOP conversion, allow this function to recurse and re-apply the
+     conversion on the result.  */
+  if (TREE_CODE (c) == NOP_EXPR
+      && ((TREE_CODE (TREE_OPERAND (c, 0)) == CALL_EXPR
+	   && CALL_EXPR_IFN (TREE_OPERAND (c, 0)) == IFN_REPLACE_ADDRESS_VALUE
+	   && CALL_EXPR_FN (TREE_OPERAND (c, 0)) == NULL_TREE)
+	 ||  TREE_CODE (TREE_OPERAND (c, 0)) == INTEGER_CST))
+    return convert (TREE_TYPE (c), fold_build_replace_address_value_loc (loc,
+						    TREE_OPERAND (c, 0), cv));
 
   return build_replace_address_value_loc (loc, c, cv);
 }
diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-3.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-3.c
index 1f6cca096be..923d2f40ac0 100644
--- a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-3.c
+++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-3.c
@@ -66,9 +66,9 @@ void test_call_memcpy (void *p, const void *q, size_t n)
   memcpy (q, p, n); /* { dg-warning "\\\[-Wdiscarded-qualifiers]" } */
 
 #ifdef __GCC_ARM_CAPABILITY_ANY
-  memcpy (p, (__intcap_t) n, q); /* { dg-warning "\\\[-Wint-conversion]" } */
+  memcpy (p, (__intcap_t) n, q); /* { dg-warning "\\\[-Wint-conversion]" "" { target { aarch64_capability_any } } } */
 #else
-  memcpy (p, n, q); /* { dg-warning "\\\[-Wint-conversion]" } */
+  memcpy (p, n, q); /* { dg-warning "\\\[-Wint-conversion]" "" { target { ! aarch64_capability_any } } } */
 #endif
   memcpy (p, q, n, 0); /* { dg-warning "too many arguments to built-in function 'memcpy' expecting 3" } */
 }
diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-10.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-10.c
index 859a8cb4fa2..b1242829ef3 100644
--- a/gcc/testsuite/gcc.dg/Wreturn-local-addr-10.c
+++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-10.c
@@ -39,6 +39,7 @@ static inline void set (struct P *p, struct A* q)
     p->d = 1;
   else
     p->d = (uintptr_t)(q) - (uintptr_t)(p);
+    /* { dg-warning "binary expression on capability types" "" { target { aarch64_capability_any } } .-1 } */
 }
 
 void f (void)
diff --git a/gcc/testsuite/gcc.dg/noncompile/20020213-1.c b/gcc/testsuite/gcc.dg/noncompile/20020213-1.c
index 5618df521e7..2ad32baebfe 100644
--- a/gcc/testsuite/gcc.dg/noncompile/20020213-1.c
+++ b/gcc/testsuite/gcc.dg/noncompile/20020213-1.c
@@ -23,21 +23,21 @@ int main ()
   /* { dg-warning "passing argument 2 of" "2nd incompatible" { target *-*-* } .-1 } */
 
   fputs (21, 43);
-  /* { dg-warning "passing argument 1 of" "1st incompatible" { target ! aarch64_capability_any } .-1 } */
-  /* { dg-warning "passing argument 2 of" "2nd incompatible" { target ! aarch64_capability_any } .-2 } */
-  /* { dg-error "passing 'int' to parameter of incompatible type capability" "" { target { aarch64_capability_any } } .-3 } */
-  /* { dg-error "passing 'int' to parameter of incompatible type capability" "" { target { aarch64_capability_any } } .-4 } */
+  /* { dg-warning "passing argument 1 of" "1st incompatible" { target { ! aarch64_capability_any } } .-1 } */
+  /* { dg-warning "passing argument 2 of" "2nd incompatible" { target { ! aarch64_capability_any } } .-2 } */
+  /* { dg-error "passing 'int' to parameter of incompatible type capability.*for argument 1 of 'fputs'" "1st incompatible" { target { aarch64_capability_any } } .-3 } */
+  /* { dg-error "passing 'int' to parameter of incompatible type capability.*for argument 2 of 'fputs'" "2nd incompatible" { target { aarch64_capability_any } } .-4 } */
 
   bzero (buf);			/* { dg-error "too few" } */
 
   bzero (21);			/* { dg-error "too few" } */
-  /* { dg-warning "passing argument 1 of" "1st incompatible" { target ! aarch64_capability_any } .-1 } */
+  /* { dg-warning "passing argument 1 of" "1st incompatible" { target { ! aarch64_capability_any } } .-1 } */
   /* { dg-error "passing 'int' to parameter of incompatible type capability" "" { target { aarch64_capability_any } } .-2 } */
 
   bcmp (buf, buf + 16);		/* { dg-error "too few" } */
 
   bcmp (21);			/* { dg-error "too few" } */
-  /* { dg-warning "passing argument 1 of" "1st incompatible" { target ! aarch64_capability_any } .-1 } */
+  /* { dg-warning "passing argument 1 of" "1st incompatible" { target { ! aarch64_capability_any } } .-1 } */
   /* { dg-error "passing 'int' to parameter of incompatible type capability" "" { target { aarch64_capability_any } } .-2 } */
 
   fputs ("foo", f);
diff --git a/gcc/testsuite/gcc.dg/pr56724-2.c b/gcc/testsuite/gcc.dg/pr56724-2.c
index d4c96a3f7ed..1e999d7897d 100644
--- a/gcc/testsuite/gcc.dg/pr56724-2.c
+++ b/gcc/testsuite/gcc.dg/pr56724-2.c
@@ -22,9 +22,9 @@ foo (void)
   foo_sc (1, 2, uc); /* { dg-warning "17:pointer targets in passing argument" } */
   foo_sc (1, 2, f); /* { dg-warning "17:passing argument" } */
 #ifdef __GCC_ARM_CAPABILITY_ANY
-  foo_sc (1, 2, (__intcap_t) sc); /* { dg-warning "17:passing argument" } */
+  foo_sc (1, 2, (__intcap_t) sc); /* { dg-warning "17:passing argument" "" { target { aarch64_capability_any } } } */
 #else
-  foo_sc (1, 2, sc); /* { dg-warning "17:passing argument" } */
+  foo_sc (1, 2, sc); /* { dg-warning "17:passing argument" "" { target { ! aarch64_capability_any } } } */
 #endif
   foo_sc (uc, 2, &sc); /* { dg-warning "11:passing argument" } */
   foo_sc (1, 2, csc); /* { dg-warning "17:passing argument" } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c
index f97c57503ce..bac4636557f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c
@@ -765,8 +765,13 @@ static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
 static CHAR oid_us[] = "2.5.4.6",
             oid_aric[] = "1.2.840.113549.1.9.1";
-static CERT_RDN_ATTR rdnAttrs[] = { { oid_us, 4, { sizeof(us), (LPBYTE)us } },
-                                           { oid_aric, 7, { sizeof(aric), (LPBYTE)aric } } };
+#ifdef __GCC_ARM_CAPABILITY_ANY
+static CERT_RDN_ATTR rdnAttrs[] = { { oid_us, 4, { (__intcap_t) sizeof(us), (LPBYTE)us } },
+                                           { oid_aric, 7, { (__intcap_t) sizeof(aric), (LPBYTE)aric } } };
+#else
+static CERT_RDN_ATTR rdnAttrs[] = { { oid_us, 4, {  sizeof(us), (LPBYTE)us } },
+                                           { oid_aric, 7, {  sizeof(aric), (LPBYTE)aric } } };
+#endif
 static const BYTE encodedRDNAttrs[] = {
 };
 static void test_encodeName(DWORD dwEncoding)
@@ -846,7 +851,11 @@ static void test_decodeName(DWORD dwEncoding)
         static CHAR oid_sur_name[] = "2.5.4.4",
                     oid_common_name[] = "2.5.4.3";
         CERT_RDN_ATTR attrs[] = {
-         { oid_sur_name, 4, { sizeof(surName),
+#ifdef __GCC_ARM_CAPABILITY_ANY
+         { oid_sur_name, 4, { (__intcap_t) sizeof(surName),
+#else
+         { oid_sur_name, 4, {  sizeof(surName),
+#endif
           (BYTE *)commonName } },
         };
     }
@@ -873,7 +882,11 @@ static void test_decodeUnicodeName(DWORD dwEncoding)
                     oid_common_name[] = "2.5.4.3";
         CERT_RDN_ATTR attrs[] = {
          { oid_sur_name, 4,
-         { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
+#ifdef __GCC_ARM_CAPABILITY_ANY
+         { (__intcap_t) lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
+#else
+         {  lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
+#endif
         };
     }
 }
@@ -1030,7 +1043,11 @@ static void test_decodeBasicConstraints(DWORD dwEncoding)
          0x08000, ((void *)0), (BYTE *)&buf, &bufSize);
         {
             CERT_BASIC_CONSTRAINTS2_INFO *info =
-            (winetest_set_location("encode.c", 1984), 0) ? 0 : winetest_ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
+#ifdef __GCC_ARM_CAPABILITY_ANY
+            (winetest_set_location("encode.c", 1984), 0) ? (__intcap_t) 0 : (__intcap_t) winetest_ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
+#else
+            (winetest_set_location("encode.c", 1984), 0) ?  0 :  winetest_ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
+#endif
              "Unexpected value for item %d\n", i);
         }
     }
@@ -1115,8 +1132,13 @@ struct encodedExtensions
 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
 static CHAR oid_basic_constraints2[] = "2.5.29.19";
 static CERT_EXTENSION nonCriticalExt =
- { oid_basic_constraints2, 0, { 8, noncrit_ext_data } };
-static const struct encodedExtensions exts[] = {
+ { oid_basic_constraints2, 0,
+#ifdef __GCC_ARM_CAPABILITY_ANY
+ { (__intcap_t) 8, noncrit_ext_data } };
+#else
+ {  8, noncrit_ext_data } };
+#endif
+ static const struct encodedExtensions exts[] = {
 };
 static void test_encodeExtensions(DWORD dwEncoding)
 {
@@ -1140,7 +1162,11 @@ static void test_encodeExtensions(DWORD dwEncoding)
                 (winetest_set_location("encode.c", 2410), 0) ? 0 : winetest_ok(!__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (ext->rgExtension[j].pszObjId) && __builtin_constant_p (exts[i].exts.rgExtension[j].pszObjId) && (__s1_len = strlen (ext->rgExtension[j].pszObjId), __s2_len = strlen (exts[i].exts.rgExtension[j].pszObjId), (!((size_t)(const void *)((ext->rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(ext->rgExtension[j].pszObjId) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((exts[i].exts.rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(exts[i].exts.rgExtension[j].pszObjId) == 1) || __s2_len >= 4)) ? __builtin_strcmp (ext->rgExtension[j].pszObjId, exts[i].exts.rgExtension[j].pszObjId) : (__builtin_constant_p (ext->rgExtension[j].pszObjId) && ((size_t)(const void *)((ext->rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(ext->rgExtension[j].pszObjId) == 1) && (__s1_len = strlen (ext->rgExtension[j].pszObjId), __s1_len < 4) ? (__builtin_constant_p (exts[i].exts.rgExtension[j].pszObjId) && ((size_t)(const void *)((exts[i].exts.rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(exts[i].exts.rgExtension[j].pszObjId) == 1) ? __builtin_strcmp (ext->rgExtension[j].pszObjId, exts[i].exts.rgExtension[j].pszObjId) : (__extension__ ({ __const unsigned char *__s2 = (__const unsigned char *) (__const char *) (exts[i].exts.rgExtension[j].pszObjId); register int __result = (((__const unsigned char *) (__const char *) (ext->rgExtension[j].pszObjId))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (ext->rgExtension[j].pszObjId))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (ext->rgExtension[j].pszObjId))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((__const unsigned char *) (__const char *) (ext->rgExtension[j].pszObjId))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (exts[i].exts.rgExtension[j].pszObjId) && ((size_t)(const void *)((exts[i].exts.rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(exts[i].exts.rgExtension[j].pszObjId) == 1) && (__s2_len = strlen (exts[i].exts.rgExtension[j].pszObjId), __s2_len < 4) ? (__builtin_constant_p (ext->rgExtension[j].pszObjId) && ((size_t)(const void *)((ext->rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(ext->rgExtension[j].pszObjId) == 1) ? __builtin_strcmp (ext->rgExtension[j].pszObjId, exts[i].exts.rgExtension[j].pszObjId) : (__extension__ ({ __const unsigned char *__s1 = (__const unsigned char *) (__const char *) (ext->rgExtension[j].pszObjId); register int __result = __s1[0] - ((__const unsigned char *) (__const char *) (exts[i].exts.rgExtension[j].pszObjId))[0]; if (__s2_len > 0 && __result == 0) { __result = (__s1[1] - ((__const unsigned char *) (__const char *) (exts[i].exts.rgExtension[j].pszObjId))[1]); if (__s2_len > 1 && __result == 0) { __result = (__s1[2] - ((__const unsigned char *) (__const char *) (exts[i].exts.rgExtension[j].pszObjId))[2]); if (__s2_len > 2 && __result == 0) __result = (__s1[3] - ((__const unsigned char *) (__const char *) (exts[i].exts.rgExtension[j].pszObjId))[3]); } } __result; }))) : __builtin_strcmp (ext->rgExtension[j].pszObjId, exts[i].exts.rgExtension[j].pszObjId)))); }),
                  ext->rgExtension[j].pszObjId);
                 (winetest_set_location("encode.c", 2415), 0) ? 0 : winetest_ok(!memcmp(ext->rgExtension[j].Value.pbData,
-                 exts[i].exts.rgExtension[j].Value.cbData),
+#ifdef __GCC_ARM_CAPABILITY_ANY
+                 (__intcap_t) exts[i].exts.rgExtension[j].Value.cbData),
+#else
+                  exts[i].exts.rgExtension[j].Value.cbData),
+#endif
                  "Unexpected value\n");
             }
         }
@@ -1165,8 +1191,13 @@ static CHAR oid_bogus[] = "1.2.3",
             oid_rsa[] = "1.2.840.113549";
 static const struct encodedPublicKey pubKeys[] = {
  { { { oid_rsa, { 0, ((void *)0) } }, { 0, ((void *)0), 0} },
-  { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
- { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
+#ifdef __GCC_ARM_CAPABILITY_ANY
+  { { oid_rsa, { (__intcap_t) 2, bin72 } }, { (__intcap_t) sizeof(aKey), (BYTE *)aKey, 0} } },
+ { { { oid_rsa, { (__intcap_t) sizeof(params), (BYTE *)params } }, { (__intcap_t) sizeof(aKey),
+#else
+  { { oid_rsa, {  2, bin72 } }, {  sizeof(aKey), (BYTE *)aKey, 0} } },
+ { { { oid_rsa, {  sizeof(params), (BYTE *)params } }, {  sizeof(aKey),
+#endif
   (BYTE *)aKey, 0 } } },
 };
 static void test_encodePublicKeyInfo(DWORD dwEncoding)
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/intcap-ptr-init-const.c b/gcc/testsuite/gcc.target/aarch64/morello/intcap-ptr-init-const.c
new file mode 100644
index 00000000000..a488e443167
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/intcap-ptr-init-const.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Werror" } */
+
+#include <string.h>
+
+static char commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
+
+void func(int z)
+{
+     int a  = {(__intcap_t) 0 * 3};
+     int b  = {(__intcap_t) 2 * 3};
+     int c  = {(__intcap_t) 0 * sizeof(int)};
+     int d  = {(__intcap_t) 2 * sizeof(d)};
+     int e  = {(__intcap_t) 0 * z};
+     int f  = {(__intcap_t) 2 * z};
+     int g  = {(__intcap_t) strlen(commonNameW) * 3};
+     int h  = {(__intcap_t) strlen(commonNameW) * 3};
+     int i  = {(__intcap_t) strlen(commonNameW) * sizeof(int)};
+     int j  = {(__intcap_t) strlen(commonNameW) * sizeof(f)};
+     int k  = {(__intcap_t) strlen(commonNameW) * z};
+     int l  = {(__intcap_t) strlen(commonNameW) * z};
+}
\ No newline at end of file
diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c
index 21a70f4386d..d11eb783321 100644
--- a/gcc/tree-ssa-ifcombine.c
+++ b/gcc/tree-ssa-ifcombine.c
@@ -180,7 +180,8 @@ static tree
 get_name_for_bit_test (tree candidate)
 {
   /* Skip single-use names in favor of using the name from a
-     non-widening conversion definition.  */
+     non-widening conversion definition. Do not look through
+     conversions from capability types into integers.  */
   if (TREE_CODE (candidate) == SSA_NAME
       && has_single_use (candidate))
     {
@@ -189,7 +190,11 @@ get_name_for_bit_test (tree candidate)
 	  && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
 	{
 	  if (TYPE_PRECISION (TREE_TYPE (candidate))
-	      <= TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
+	      <= TYPE_CAP_PRECISION (TREE_TYPE
+				      (gimple_assign_rhs1 (def_stmt)))
+	      && !(capability_type_p (TREE_TYPE
+				       (gimple_assign_rhs1 (def_stmt))))
+)
 	    return gimple_assign_rhs1 (def_stmt);
 	}
     }
@@ -228,13 +233,15 @@ recognize_single_bit_test (gcond *cond, tree *name, tree *bit, bool inv)
       tree orig_name = gimple_assign_rhs1 (stmt);
 
       /* Look through copies and conversions to eventually
-	 find the stmt that computes the shift.  */
+	 find the stmt that computes the shift. Do not look through
+	 conversions from capability types into integers.  */
       stmt = SSA_NAME_DEF_STMT (orig_name);
 
       while (is_gimple_assign (stmt)
 	     && ((CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
-		  && (TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (stmt)))
-		      <= TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (stmt))))
+		  && TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (stmt)))
+		      <= TYPE_CAP_PRECISION (TREE_TYPE (gimple_assign_rhs1 (stmt)))
+		  && !capability_type_p (TREE_TYPE (gimple_assign_rhs1 (stmt)))
 		  && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
 		 || gimple_assign_ssa_name_copy_p (stmt)))
 	stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
diff --git a/gcc/tree.h b/gcc/tree.h
index 5b88db8bafd..111687d5430 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -6365,6 +6365,15 @@ tree_is_capability_value (const_tree t)
   return t && t != error_mark_node && capability_type_p (TREE_TYPE (t));
 }
 
+inline wide_int
+tree_constant_capability_metadata (const_tree t)
+{
+  gcc_assert (TREE_CODE (t) == INTEGER_CST);
+  return wi::bit_and (wi::to_wide (t, TYPE_CAP_PRECISION (TREE_TYPE(t))),
+		      wi::mask (TYPE_NONCAP_PRECISION (TREE_TYPE(t)), 1,
+				TYPE_CAP_PRECISION (TREE_TYPE(t))));
+}
+
 static inline bool
 capability_args_valid (const_tree type,
 		       tree_code code, const_tree op0)
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 0eda56fcda5..96fa820c3c7 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -4566,7 +4566,8 @@ initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache)
 	/* MORELLO TODO Just adding this assert in temporarily.  I would be
 	   interested to see any time that this is not the case and hence want
 	   to get alerted.  */
-	gcc_assert (TREE_CODE (ptr) == INTEGER_CST && tree_to_uhwi (ptr) == 0);
+	gcc_assert (TREE_CODE (ptr) == INTEGER_CST
+		    && tree_constant_capability_metadata (ptr) == 0);
 	tree ptr_ret = initializer_constant_valid_p_1 (ptr, endtype, cache);
 	tree addrval_ret = initializer_constant_valid_p_1
 		(addr_value, noncapability_type (endtype), cache);


More information about the Gcc-cvs mailing list