From 39da8a7ba9a3a643e6318a5534d5d7c85a3bedfa Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 30 Jun 2021 09:48:37 +0200 Subject: tree-optimization/101264 - rework SLP "any" permute forward prop This integrates the forward propagation of SLP "any" permutes into the main propagation stage as a separate single-pass propagation didn't work out. 2021-06-30 Richard Biener PR tree-optimization/101264 * tree-vect-slp.c (vect_optimize_slp): Propagate the computed perm_in to all "any" permute successors we cannot de-duplicate immediately. * gfortran.dg/pr101264.f90: New testcase. --- gcc/testsuite/gfortran.dg/pr101264.f90 | 94 ++++++++++++++++++++++++++++++++++ gcc/tree-vect-slp.c | 79 ++++++++-------------------- 2 files changed, 115 insertions(+), 58 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/pr101264.f90 (limited to 'gcc') diff --git a/gcc/testsuite/gfortran.dg/pr101264.f90 b/gcc/testsuite/gfortran.dg/pr101264.f90 new file mode 100644 index 0000000..5602a70 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr101264.f90 @@ -0,0 +1,94 @@ +! { dg-do compile } +! { dg-options "-Ofast" } + SUBROUTINE foo (a,b,c,d,trigs,inc1,inc2,inc3,inc4,lot,n,la) + IMPLICIT NONE (type, external) + INTEGER, PARAMETER :: wp = 8 + INTEGER, PARAMETER :: iwp = 4 + INTEGER(iwp) :: inc1 + INTEGER(iwp) :: inc2 + INTEGER(iwp) :: inc3 + INTEGER(iwp) :: inc4 + INTEGER(iwp) :: la + INTEGER(iwp) :: lot + INTEGER(iwp) :: n + + REAL(wp) :: a(*) + REAL(wp) :: b(*) + REAL(wp) :: c(*) + REAL(wp) :: d(*) + REAL(wp) :: trigs(*) + + REAL(wp) :: c1 + REAL(wp) :: c2 + REAL(wp) :: s1 + REAL(wp) :: s2 + REAL(wp) :: sin60 + + INTEGER(iwp) :: i + INTEGER(iwp) :: ia + INTEGER(iwp) :: ib + INTEGER(iwp) :: ibase + INTEGER(iwp) :: ic + INTEGER(iwp) :: iink + INTEGER(iwp) :: ijk + INTEGER(iwp) :: j + INTEGER(iwp) :: ja + INTEGER(iwp) :: jb + INTEGER(iwp) :: jbase + INTEGER(iwp) :: jc + INTEGER(iwp) :: jink + INTEGER(iwp) :: jump + INTEGER(iwp) :: k + INTEGER(iwp) :: kb + INTEGER(iwp) :: kc + INTEGER(iwp) :: kstop + INTEGER(iwp) :: l + INTEGER(iwp) :: m + + sin60=0.866025403784437_wp + + ia = 1 + ib = ia + (2*m-la)*inc1 + ic = ib + ja = 1 + jb = ja + jink + jc = jb + jink + + DO k = la, kstop, la + kb = k + k + kc = kb + kb + c1 = trigs(kb+1) + s1 = trigs(kb+2) + c2 = trigs(kc+1) + s2 = trigs(kc+2) + ibase = 0 + DO l = 1, la + i = ibase + j = jbase + DO ijk = 1, lot + c(ja+j) = a(ia+i) + (a(ib+i)+a(ic+i)) + d(ja+j) = b(ia+i) + (b(ib+i)-b(ic+i)) + c(jb+j) = c1*((a(ia+i)-0.5_wp*(a(ib+i)+a(ic+i)))-(sin60*(b(ib+i)+ & + & b(ic+i)))) & + & - s1*((b(ia+i)-0.5_wp*(b(ib+i)-b(ic+i)))+(sin60*(a(ib+i)- & + & a(ic+i)))) + d(jb+j) = s1*((a(ia+i)-0.5_wp*(a(ib+i)+a(ic+i)))-(sin60*(b(ib+i)+ & + & b(ic+i)))) & + & + c1*((b(ia+i)-0.5_wp*(b(ib+i)-b(ic+i)))+(sin60*(a(ib+i)- & + & a(ic+i)))) + c(jc+j) = c2*((a(ia+i)-0.5_wp*(a(ib+i)+a(ic+i)))+(sin60*(b(ib+i)+ & + & b(ic+i)))) & + & - s2*((b(ia+i)-0.5_wp*(b(ib+i)-b(ic+i)))-(sin60*(a(ib+i)- & + & a(ic+i)))) + i = i + inc3 + j = j + inc4 + END DO + ibase = ibase + inc1 + jbase = jbase + inc2 + END DO + ia = ia + iink + ib = ib + iink + ic = ic - iink + jbase = jbase + jump + END DO + END diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 9155af4..10195d3 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -3729,6 +3729,7 @@ vect_optimize_slp (vec_info *vinfo) perm = vertices[idx].perm_out; else { + bool any_succ_perm_out_m1 = false; perm = vertices[idx].get_perm_in (); for (graph_edge *succ = slpg->vertices[idx].succ; succ; succ = succ->succ_next) @@ -3742,7 +3743,15 @@ vect_optimize_slp (vec_info *vinfo) For example see gcc.dg/vect/bb-slp-14.c for a case that would break. */ if (succ_perm == -1) - continue; + { + /* When we handled a non-leaf optimistically, note + that so we can adjust its outgoing permute below. */ + slp_tree succ_node = vertices[succ_idx].node; + if (SLP_TREE_DEF_TYPE (succ_node) != vect_external_def + && SLP_TREE_DEF_TYPE (succ_node) != vect_constant_def) + any_succ_perm_out_m1 = true; + continue; + } if (perm == -1) perm = succ_perm; else if (succ_perm == 0 @@ -3753,25 +3762,19 @@ vect_optimize_slp (vec_info *vinfo) } } - /* If this is a node we do not want to eventually unshare - but it can be permuted at will, verify all users have - the same permutations registered and otherwise drop to - zero. */ - if (perm == -1 - && SLP_TREE_DEF_TYPE (node) != vect_external_def - && SLP_TREE_DEF_TYPE (node) != vect_constant_def) + /* Adjust any incoming permutes we treated optimistically. */ + if (perm != -1 && any_succ_perm_out_m1) { - int preds_perm = -1; - for (graph_edge *pred = slpg->vertices[idx].pred; - pred; pred = pred->pred_next) + for (graph_edge *succ = slpg->vertices[idx].succ; + succ; succ = succ->succ_next) { - int pred_perm = vertices[pred->src].get_perm_in (); - if (preds_perm == -1) - preds_perm = pred_perm; - else if (!vect_slp_perms_eq (perms, - pred_perm, preds_perm)) - perm = 0; + slp_tree succ_node = vertices[succ->dest].node; + if (vertices[succ->dest].perm_out == -1 + && SLP_TREE_DEF_TYPE (succ_node) != vect_external_def + && SLP_TREE_DEF_TYPE (succ_node) != vect_constant_def) + vertices[succ->dest].perm_out = perm; } + changed = true; } if (!vect_slp_perms_eq (perms, perm, @@ -3840,47 +3843,7 @@ vect_optimize_slp (vec_info *vinfo) } } while (changed); - statistics_counter_event (cfun, "SLP optimize perm iterations", iteration); - - /* Compute pre-order. */ - auto_vec heads; - heads.reserve (vinfo->slp_instances.length ()); - for (slp_instance inst : vinfo->slp_instances) - heads.quick_push (SLP_INSTANCE_TREE (inst)->vertex); - auto_vec po; - graphds_dfs (slpg, &heads[0], heads.length (), &po, true, NULL, NULL); - - /* Propagate materialized permutes to "any" permute nodes. For heads - ending up as "any" (reductions with just invariants), set them to - no permute. */ - for (int idx : heads) - if (vertices[idx].perm_out == -1) - vertices[idx].perm_out = 0; - for (i = po.length (); i > 0; --i) - { - int idx = po[i-1]; - int perm_in = vertices[idx].get_perm_in (); - slp_tree node = vertices[idx].node; - if (SLP_TREE_DEF_TYPE (node) == vect_external_def - || SLP_TREE_DEF_TYPE (node) == vect_constant_def) - continue; - gcc_assert (perm_in != -1); - for (graph_edge *succ = slpg->vertices[idx].succ; - succ; succ = succ->succ_next) - { - slp_tree succ_node = vertices[succ->dest].node; - if (SLP_TREE_DEF_TYPE (succ_node) == vect_external_def - || SLP_TREE_DEF_TYPE (succ_node) == vect_constant_def) - continue; - if (vertices[succ->dest].perm_out == -1) - vertices[succ->dest].perm_out = perm_in; - else - /* Propagation should have ensured that all preds have the same - permutation. */ - gcc_assert (vect_slp_perms_eq (perms, perm_in, - vertices[succ->dest].perm_out)); - } - } + statistics_histogram_event (cfun, "SLP optimize perm iterations", iteration); /* Materialize. */ for (i = 0; i < vertices.length (); ++i) -- cgit v1.1 From 0a9d038ec10aa0d109ca965cc435934bfea92d14 Mon Sep 17 00:00:00 2001 From: "prathamesh.kulkarni" Date: Wed, 30 Jun 2021 15:12:06 +0530 Subject: arm/66791: Gate comparison in vca intrinsics on __FAST_MATH__. gcc/ChangeLog: PR target/66791 * config/arm/arm_neon.h: Move vabs intrinsics before vcage_f32. (vcage_f32): Gate comparison on __FAST_MATH__. (vcageq_f32): Likewise. (vcale_f32): Likewise. (vcaleq_f32): Likewise. (vcagt_f32): Likewise. (vcagtq_f32): Likewise. (vcalt_f32): Likewise. (vcaltq_f32): Likewise. (vcage_f16): Likewise. (vcageq_f16): Likewise. (vcale_f16): Likewise. (vcaleq_f16): Likewise. (vcagt_f16): Likewise. (vcagtq_f16): Likewise. (vcalt_f16): Likewise. (vcaltq_f16): Likewise. --- gcc/config/arm/arm_neon.h | 259 ++++++++++++++++++++++++++++------------------ 1 file changed, 161 insertions(+), 98 deletions(-) (limited to 'gcc') diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h index 7a800062..f42a15f 100644 --- a/gcc/config/arm/arm_neon.h +++ b/gcc/config/arm/arm_neon.h @@ -2867,60 +2867,189 @@ vcltq_u32 (uint32x4_t __a, uint32x4_t __b) return (__a < __b); } +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabs_s8 (int8x8_t __a) +{ + return (int8x8_t)__builtin_neon_vabsv8qi (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabs_s16 (int16x4_t __a) +{ + return (int16x4_t)__builtin_neon_vabsv4hi (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabs_s32 (int32x2_t __a) +{ + return (int32x2_t)__builtin_neon_vabsv2si (__a); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabs_f32 (float32x2_t __a) +{ + return (float32x2_t)__builtin_neon_vabsv2sf (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsq_s8 (int8x16_t __a) +{ + return (int8x16_t)__builtin_neon_vabsv16qi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsq_s16 (int16x8_t __a) +{ + return (int16x8_t)__builtin_neon_vabsv8hi (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsq_s32 (int32x4_t __a) +{ + return (int32x4_t)__builtin_neon_vabsv4si (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsq_f32 (float32x4_t __a) +{ + return (float32x4_t)__builtin_neon_vabsv4sf (__a); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabs_s8 (int8x8_t __a) +{ + return (int8x8_t)__builtin_neon_vqabsv8qi (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabs_s16 (int16x4_t __a) +{ + return (int16x4_t)__builtin_neon_vqabsv4hi (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabs_s32 (int32x2_t __a) +{ + return (int32x2_t)__builtin_neon_vqabsv2si (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabsq_s8 (int8x16_t __a) +{ + return (int8x16_t)__builtin_neon_vqabsv16qi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabsq_s16 (int16x8_t __a) +{ + return (int16x8_t)__builtin_neon_vqabsv8hi (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabsq_s32 (int32x4_t __a) +{ + return (int32x4_t)__builtin_neon_vqabsv4si (__a); +} __extension__ extern __inline uint32x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcage_f32 (float32x2_t __a, float32x2_t __b) { +#ifdef __FAST_MATH__ + return (uint32x2_t) (vabs_f32 (__a) >= vabs_f32 (__b)); +#else return (uint32x2_t)__builtin_neon_vcagev2sf (__a, __b); +#endif } __extension__ extern __inline uint32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcageq_f32 (float32x4_t __a, float32x4_t __b) { +#ifdef __FAST_MATH__ + return (uint32x4_t) (vabsq_f32 (__a) >= vabsq_f32 (__b)); +#else return (uint32x4_t)__builtin_neon_vcagev4sf (__a, __b); +#endif } __extension__ extern __inline uint32x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcale_f32 (float32x2_t __a, float32x2_t __b) { +#ifdef __FAST_MATH__ + return (uint32x2_t) (vabs_f32 (__a) <= vabs_f32 (__b)); +#else return (uint32x2_t)__builtin_neon_vcagev2sf (__b, __a); +#endif } __extension__ extern __inline uint32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcaleq_f32 (float32x4_t __a, float32x4_t __b) { +#ifdef __FAST_MATH__ + return (uint32x4_t) (vabsq_f32 (__a) <= vabsq_f32 (__b)); +#else return (uint32x4_t)__builtin_neon_vcagev4sf (__b, __a); +#endif } __extension__ extern __inline uint32x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcagt_f32 (float32x2_t __a, float32x2_t __b) { +#ifdef __FAST_MATH__ + return (uint32x2_t) (vabs_f32 (__a) > vabs_f32 (__b)); +#else return (uint32x2_t)__builtin_neon_vcagtv2sf (__a, __b); +#endif } __extension__ extern __inline uint32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcagtq_f32 (float32x4_t __a, float32x4_t __b) { +#ifdef __FAST_MATH__ + return (uint32x4_t) (vabsq_f32 (__a) > vabsq_f32 (__b)); +#else return (uint32x4_t)__builtin_neon_vcagtv4sf (__a, __b); +#endif } __extension__ extern __inline uint32x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcalt_f32 (float32x2_t __a, float32x2_t __b) { +#ifdef __FAST_MATH__ + return (uint32x2_t) (vabs_f32 (__a) < vabs_f32 (__b)); +#else return (uint32x2_t)__builtin_neon_vcagtv2sf (__b, __a); +#endif } __extension__ extern __inline uint32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcaltq_f32 (float32x4_t __a, float32x4_t __b) { +#ifdef __FAST_MATH__ + return (uint32x4_t) (vabsq_f32 (__a) < vabsq_f32 (__b)); +#else return (uint32x4_t)__builtin_neon_vcagtv4sf (__b, __a); +#endif } __extension__ extern __inline uint8x8_t @@ -5622,104 +5751,6 @@ vsliq_n_p16 (poly16x8_t __a, poly16x8_t __b, const int __c) __extension__ extern __inline int8x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vabs_s8 (int8x8_t __a) -{ - return (int8x8_t)__builtin_neon_vabsv8qi (__a); -} - -__extension__ extern __inline int16x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vabs_s16 (int16x4_t __a) -{ - return (int16x4_t)__builtin_neon_vabsv4hi (__a); -} - -__extension__ extern __inline int32x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vabs_s32 (int32x2_t __a) -{ - return (int32x2_t)__builtin_neon_vabsv2si (__a); -} - -__extension__ extern __inline float32x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vabs_f32 (float32x2_t __a) -{ - return (float32x2_t)__builtin_neon_vabsv2sf (__a); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vabsq_s8 (int8x16_t __a) -{ - return (int8x16_t)__builtin_neon_vabsv16qi (__a); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vabsq_s16 (int16x8_t __a) -{ - return (int16x8_t)__builtin_neon_vabsv8hi (__a); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vabsq_s32 (int32x4_t __a) -{ - return (int32x4_t)__builtin_neon_vabsv4si (__a); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vabsq_f32 (float32x4_t __a) -{ - return (float32x4_t)__builtin_neon_vabsv4sf (__a); -} - -__extension__ extern __inline int8x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vqabs_s8 (int8x8_t __a) -{ - return (int8x8_t)__builtin_neon_vqabsv8qi (__a); -} - -__extension__ extern __inline int16x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vqabs_s16 (int16x4_t __a) -{ - return (int16x4_t)__builtin_neon_vqabsv4hi (__a); -} - -__extension__ extern __inline int32x2_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vqabs_s32 (int32x2_t __a) -{ - return (int32x2_t)__builtin_neon_vqabsv2si (__a); -} - -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vqabsq_s8 (int8x16_t __a) -{ - return (int8x16_t)__builtin_neon_vqabsv16qi (__a); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vqabsq_s16 (int16x8_t __a) -{ - return (int16x8_t)__builtin_neon_vqabsv8hi (__a); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -vqabsq_s32 (int32x4_t __a) -{ - return (int32x4_t)__builtin_neon_vqabsv4si (__a); -} - -__extension__ extern __inline int8x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vneg_s8 (int8x8_t __a) { return -__a; @@ -17147,56 +17178,88 @@ __extension__ extern __inline uint16x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcage_f16 (float16x4_t __a, float16x4_t __b) { +#ifdef __FAST_MATH__ + return (uint16x4_t) (vabs_f16 (__a) >= vabs_f16 (__b)); +#else return (uint16x4_t)__builtin_neon_vcagev4hf (__a, __b); +#endif } __extension__ extern __inline uint16x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcageq_f16 (float16x8_t __a, float16x8_t __b) { +#ifdef __FAST_MATH__ + return (uint16x8_t) (vabsq_f16 (__a) >= vabsq_f16 (__b)); +#else return (uint16x8_t)__builtin_neon_vcagev8hf (__a, __b); +#endif } __extension__ extern __inline uint16x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcagt_f16 (float16x4_t __a, float16x4_t __b) { +#ifdef __FAST_MATH__ + return (uint16x4_t) (vabs_f16 (__a) > vabs_f16 (__b)); +#else return (uint16x4_t)__builtin_neon_vcagtv4hf (__a, __b); +#endif } __extension__ extern __inline uint16x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcagtq_f16 (float16x8_t __a, float16x8_t __b) { +#ifdef __FAST_MATH__ + return (uint16x8_t) (vabsq_f16 (__a) > vabsq_f16 (__b)); +#else return (uint16x8_t)__builtin_neon_vcagtv8hf (__a, __b); +#endif } __extension__ extern __inline uint16x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcale_f16 (float16x4_t __a, float16x4_t __b) { +#ifdef __FAST_MATH__ + return (uint16x4_t) (vabs_f16 (__a) <= vabs_f16 (__b)); +#else return (uint16x4_t)__builtin_neon_vcalev4hf (__a, __b); +#endif } __extension__ extern __inline uint16x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcaleq_f16 (float16x8_t __a, float16x8_t __b) { +#ifdef __FAST_MATH__ + return (uint16x8_t) (vabsq_f16 (__a) <= vabsq_f16 (__b)); +#else return (uint16x8_t)__builtin_neon_vcalev8hf (__a, __b); +#endif } __extension__ extern __inline uint16x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcalt_f16 (float16x4_t __a, float16x4_t __b) { +#ifdef __FAST_MATH__ + return (uint16x4_t) (vabs_f16 (__a) < vabs_f16 (__b)); +#else return (uint16x4_t)__builtin_neon_vcaltv4hf (__a, __b); +#endif } __extension__ extern __inline uint16x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vcaltq_f16 (float16x8_t __a, float16x8_t __b) { +#ifdef __FAST_MATH__ + return (uint16x8_t) (vabsq_f16 (__a) < vabsq_f16 (__b)); +#else return (uint16x8_t)__builtin_neon_vcaltv8hf (__a, __b); +#endif } __extension__ extern __inline uint16x4_t -- cgit v1.1 From a3ce7d75dd9c0308b8565669f31127436cb2ba9f Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Wed, 30 Jun 2021 13:17:54 +0200 Subject: gcc.c's check_offload_target_name: Fixes to inform hints gcc/ChangeLog: * gcc.c (close_at_file, execute): Replace alloca by XALLOCAVEC. (check_offload_target_name): Fix splitting OFFLOAD_TARGETS into a candidate list; better inform no offload target is configured and fix hint extraction when passed target is not '\0' at [len]. * common.opt (foffload): Add tailing '.'. (foffload-options): Likewise; fix flag name in the help string. --- gcc/common.opt | 4 ++-- gcc/gcc.c | 42 ++++++++++++++++++++---------------------- 2 files changed, 22 insertions(+), 24 deletions(-) (limited to 'gcc') diff --git a/gcc/common.opt b/gcc/common.opt index eaee74c..2f5ff9f 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2104,11 +2104,11 @@ Support synchronous non-call exceptions. ; -foffload== is supported for backward compatibility foffload= Driver Joined MissingArgError(targets missing after %qs) --foffload= Specify offloading targets +-foffload= Specify offloading targets. foffload-options= Common Driver Joined MissingArgError(options or targets=options missing after %qs) --foffload== Specify options for the offloading targets +-foffload-options== Specify options for the offloading targets. foffload-abi= Common Joined RejectNegative Enum(offload_abi) Var(flag_offload_abi) Init(OFFLOAD_ABI_UNSET) diff --git a/gcc/gcc.c b/gcc/gcc.c index 9baa7d6..f802148 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -2242,7 +2242,7 @@ close_at_file (void) if (n_args == 0) return; - char **argv = (char **) alloca (sizeof (char *) * (n_args + 1)); + char **argv = XALLOCAVEC (char *, n_args + 1); char *temp_file = make_at_file (); char *at_argument = concat ("@", temp_file, NULL); FILE *f = fopen (temp_file, "w"); @@ -3251,7 +3251,7 @@ execute (void) n_commands++; /* Get storage for each command. */ - commands = (struct command *) alloca (n_commands * sizeof (struct command)); + commands = XALLOCAVEC (struct command, n_commands); /* Split argbuf into its separate piped processes, and record info about each one. @@ -3430,13 +3430,13 @@ execute (void) struct pex_time *times = NULL; int ret_code = 0; - statuses = (int *) alloca (n_commands * sizeof (int)); + statuses = XALLOCAVEC (int, n_commands); if (!pex_get_status (pex, n_commands, statuses)) fatal_error (input_location, "failed to get exit status: %m"); if (report_times || report_times_to_file) { - times = (struct pex_time *) alloca (n_commands * sizeof (struct pex_time)); + times = XALLOCAVEC (struct pex_time, n_commands); if (!pex_get_times (pex, n_commands, times)) fatal_error (input_location, "failed to get process times: %m"); } @@ -3997,24 +3997,22 @@ check_offload_target_name (const char *target, ptrdiff_t len) { char *s; auto_vec candidates; - char *cand = (char *) alloca (strlen (OFFLOAD_TARGETS) + 1); - c = OFFLOAD_TARGETS; - while (c) - { - n = strchr (c, ','); - if (n == NULL) - n = strchr (c, '\0'); - if (n - c == 0) - break; - strncpy (cand, c, n - c); - cand[n - c] = '\0'; - candidates.safe_push (cand); - c = *n ? n + 1 : NULL; - } - error ("GCC is not configured to support %q.*s as offload target", - (int) len, target); - const char *hint = candidates_list_and_hint (target, s, candidates); - if (hint) + size_t olen = strlen (OFFLOAD_TARGETS) + 1; + char *cand = XALLOCAVEC (char, olen); + memcpy (cand, OFFLOAD_TARGETS, olen); + for (c = strtok (cand, ","); c; c = strtok (NULL, ",")) + candidates.safe_push (c); + + char *target2 = XALLOCAVEC (char, len + 1); + memcpy (target2, target, len); + target2[len] = '\0'; + + error ("GCC is not configured to support %qs as offload target", target2); + + const char *hint = candidates_list_and_hint (target2, s, candidates); + if (candidates.is_empty ()) + inform (UNKNOWN_LOCATION, "no offloading targets configured"); + else if (hint) inform (UNKNOWN_LOCATION, "valid offload targets are: %s; did you mean %qs?", s, hint); else -- cgit v1.1 From f6bc9d9bddad7f9e3aad939bb6750770ac67f003 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Wed, 30 Jun 2021 11:44:00 +0000 Subject: [testsuite]: Add missing dg-add-options float16 to gcc.dg/debug/ctf/ctf-skip-types-2.c The test already checks dg-require-effective-target float16, but this is not sufficient to use the flags needed, if any. This patch makes the test pass on arm. 2021-06-30 Christophe Lyon gcc/testsuite/ * gcc.dg/debug/ctf/ctf-skip-types-2.c: Add dg-add-options float16. --- gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-2.c index 7c8b17d..79d5cb2 100644 --- a/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-2.c +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-2.c @@ -13,5 +13,6 @@ /* { dg-options "-gctf" } */ /* { dg-require-effective-target float16 } */ +/* { dg-add-options float16 } */ _Float16 f16; -- cgit v1.1 From 63fe82d80dee997b25ca60fa7d1ed07e97930976 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Wed, 30 Jun 2021 14:49:48 +0200 Subject: gcc.c: Add -foffload= to display_help gcc/ChangeLog: * common.opt (foffload): Remove help as Driver only. * gcc.c (display_help): Add -foffload. --- gcc/common.opt | 3 --- gcc/gcc.c | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/common.opt b/gcc/common.opt index 2f5ff9f..5b03bbc 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2100,11 +2100,8 @@ fnon-call-exceptions Common Var(flag_non_call_exceptions) Optimization Support synchronous non-call exceptions. -; -foffload= is documented -; -foffload== is supported for backward compatibility foffload= Driver Joined MissingArgError(targets missing after %qs) --foffload= Specify offloading targets. foffload-options= Common Driver Joined MissingArgError(options or targets=options missing after %qs) diff --git a/gcc/gcc.c b/gcc/gcc.c index f802148..c8dbff6 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -3752,6 +3752,7 @@ display_help (void) fputs (_(" -dumpspecs Display all of the built in spec strings.\n"), stdout); fputs (_(" -dumpversion Display the version of the compiler.\n"), stdout); fputs (_(" -dumpmachine Display the compiler's target processor.\n"), stdout); + fputs (_(" -foffload= Specify offloading targets.\n"), stdout); fputs (_(" -print-search-dirs Display the directories in the compiler's search path.\n"), stdout); fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library.\n"), stdout); fputs (_(" -print-file-name= Display the full path to library .\n"), stdout); -- cgit v1.1 From e61ffa201403e3814a43b176883e176716b1492f Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 30 Jun 2021 09:39:04 -0400 Subject: analyzer: eliminate enum binding_key [PR95006] I rewrote the way the analyzer's region_model tracks the state of memory in GCC 11 (in 808f4dfeb3a95f50f15e71148e5c1067f90a126d), which introduced a store with a binding_map class, mapping binding keys to symbolic values. The GCC 11 implementation of binding keys has an enum binding_kind, which can be "default" vs "direct"; the idea being that direct bindings take priority over default bindings, where the latter could be used to represent e.g. a zero-fill of a buffer, and the former expresses those subregions that have since been touched. This doesn't work well: it doesn't express the idea of filling different subregions with different values, or a memset that only touches part of a buffer, leading to numerous XFAILs in the memset test cases (and elsewhere). As preparatory work towards tracking uninitialized values, this patch eliminates the enum binding_kind, so that all bindings have equal weight; the order in which they happen is all that matters. If a write happens which partially overwrites an existing binding, the new code can partially overwrite a binding, potentially punching a hole so that an existing binding is split into two parts. The patch adds some new classes: - a new "bits_within_svalue" symbolic value to support extracting parts of an existing value when its binding is partially clobbered - a new "repeated_svalue" symbolic value to better express filling a region with repeated copies of a symbolic value (e.g. constant zero) - a new "sized_region" region to express accessing a subregion with a symbolic size in bytes and it rewrites e.g. how memset is implemented, so that we can precisely track which bits in a region have not been touched. That said, the patch doesn't actually implement "uninitialized" values; I'm saving that for a followup. gcc/analyzer/ChangeLog: PR analyzer/95006 * analyzer.h (class repeated_svalue): New forward decl. (class bits_within_svalue): New forward decl. (class sized_region): New forward decl. (get_field_at_bit_offset): New forward decl. * engine.cc (exploded_graph::get_or_create_node): Validate the merged state. (exploded_graph::maybe_process_run_of_before_supernode_enodes): Validate the states at each stage. * program-state.cc (program_state::validate): Validate m_region_model. * region-model-impl-calls.cc (region_model::impl_call_memset): Replace special-case logic for handling constant sizes with a call to fill_region of a sized_region with the given fill value. * region-model-manager.cc (maybe_undo_optimize_bit_field_compare): Drop DK_direct. (region_model_manager::maybe_fold_sub_svalue): Fold element-based subregions of an initial value into initial values of an element. Fold subvalues of repeated svalues. (region_model_manager::maybe_fold_repeated_svalue): New. (region_model_manager::get_or_create_repeated_svalue): New. (get_bit_range_for_field): New. (get_byte_range_for_field): New. (get_field_at_byte_range): New. (region_model_manager::maybe_fold_bits_within_svalue): New. (region_model_manager::get_or_create_bits_within): New. (region_model_manager::get_sized_region): New. (region_model_manager::log_stats): Update for addition of m_repeated_values_map, m_bits_within_values_map, and m_sized_regions. * region-model.cc (region_model::validate): New. (region_model::on_assignment): Drop enum binding_kind. (region_model::get_initial_value_for_global): Likewise. (region_model::get_rvalue_for_bits): Replace body with call to get_or_create_bits_within. (region_model::get_capacity): Handle RK_SIZED. (region_model::set_value): Drop enum binding_kind. (region_model::fill_region): New. (region_model::get_representative_path_var_1): Handle RK_SIZED. * region-model.h (visitor::visit_repeated_svalue): New. (visitor::visit_bits_within_svalue): New. (region_model_manager::get_or_create_repeated_svalue): New decl. (region_model_manager::get_or_create_bits_within): New decl. (region_model_manager::get_sized_region): New decl. (region_model_manager::maybe_fold_repeated_svalue): New decl. (region_model_manager::maybe_fold_bits_within_svalue): New decl. (region_model_manager::repeated_values_map_t): New typedef. (region_model_manager::m_repeated_values_map): New field. (region_model_manager::bits_within_values_map_t): New typedef. (region_model_manager::m_bits_within_values_map): New field. (region_model_manager::m_sized_regions): New field. (region_model::fill_region): New decl. * region.cc (region::get_base_region): Handle RK_SIZED. (region::base_region_p): Likewise. (region::get_byte_size_sval): New. (get_field_at_bit_offset): Make non-static. (region::calc_offset): Move implementation of cases to get_relative_concrete_offset vfunc implementations. Handle RK_SIZED. (region::get_relative_concrete_offset): New. (decl_region::get_svalue_for_initializer): Drop enum binding_kind. (field_region::get_relative_concrete_offset): New, from region::calc_offset. (element_region::get_relative_concrete_offset): Likewise. (offset_region::get_relative_concrete_offset): Likewise. (sized_region::accept): New. (sized_region::dump_to_pp): New. (sized_region::get_byte_size): New. (sized_region::get_bit_size): New. * region.h (enum region_kind): Add RK_SIZED. (region::dyn_cast_sized_region): New. (region::get_byte_size): Make virtual. (region::get_bit_size): Likewise. (region::get_byte_size_sval): New decl. (region::get_relative_concrete_offset): New decl. (field_region::get_relative_concrete_offset): New decl. (element_region::get_relative_concrete_offset): Likewise. (offset_region::get_relative_concrete_offset): Likewise. (class sized_region): New. * store.cc (binding_kind_to_string): Delete. (binding_key::make): Drop enum binding_kind. (binding_key::dump_to_pp): Delete. (binding_key::cmp_ptrs): Drop enum binding_kind. (bit_range::contains_p): New. (byte_range::dump): New. (byte_range::contains_p): New. (byte_range::cmp): New. (concrete_binding::dump_to_pp): Drop enum binding_kind. (concrete_binding::cmp_ptr_ptr): Likewise. (symbolic_binding::dump_to_pp): Likewise. (symbolic_binding::cmp_ptr_ptr): Likewise. (binding_map::apply_ctor_val_to_range): Likewise. (binding_map::apply_ctor_pair_to_child_region): Likewise. (binding_map::get_overlapping_bindings): New. (binding_map::remove_overlapping_bindings): New. (binding_cluster::validate): New. (binding_cluster::bind): Drop enum binding_kind. (binding_cluster::bind_compound_sval): Likewise. (binding_cluster::purge_region): Likewise. (binding_cluster::zero_fill_region): Reimplement in terms of... (binding_cluster::fill_region): New. (binding_cluster::mark_region_as_unknown): Drop enum binding_kind. (binding_cluster::get_binding): Likewise. (binding_cluster::get_binding_recursive): Likewise. (binding_cluster::get_any_binding): Likewise. (binding_cluster::maybe_get_compound_binding): Reimplement. (binding_cluster::get_overlapping_bindings): Delete. (binding_cluster::remove_overlapping_bindings): Reimplement in terms of binding_map::remove_overlapping_bindings. (binding_cluster::can_merge_p): Update for removal of enum binding_kind. (binding_cluster::on_unknown_fncall): Drop enum binding_kind. (binding_cluster::maybe_get_simple_value): Likewise. (store_manager::get_concrete_binding): Likewise. (store_manager::get_symbolic_binding): Likewise. (store::validate): New. (store::set_value): Drop enum binding_kind. (store::zero_fill_region): Reimplement in terms of... (store::fill_region): New. (selftest::test_binding_key_overlap): Drop enum binding_kind. * store.h (enum binding_kind): Delete. (binding_kind_to_string): Delete decl. (binding_key::make): Drop enum binding_kind. (binding_key::dump_to_pp): Make pure virtual. (binding_key::get_kind): Delete. (binding_key::mark_deleted): Delete. (binding_key::mark_empty): Delete. (binding_key::is_deleted): Delete. (binding_key::is_empty): Delete. (binding_key::binding_key): Delete. (binding_key::impl_hash): Delete. (binding_key::impl_eq): Delete. (binding_key::m_kind): Delete. (bit_range::get_last_bit_offset): New. (bit_range::contains_p): New. (byte_range::contains_p): New. (byte_range::operator==): New. (byte_range::get_start_byte_offset): New. (byte_range::get_next_byte_offset): New. (byte_range::get_last_byte_offset): New. (byte_range::as_bit_range): New. (byte_range::cmp): New. (concrete_binding::concrete_binding): Drop enum binding_kind. (concrete_binding::hash): Likewise. (concrete_binding::operator==): Likewise. (concrete_binding::mark_deleted): New. (concrete_binding::mark_empty): New. (concrete_binding::is_deleted): New. (concrete_binding::is_empty): New. (default_hash_traits::empty_zero_p): Make false. (symbolic_binding::symbolic_binding): Drop enum binding_kind. (symbolic_binding::hash): Likewise. (symbolic_binding::operator==): Likewise. (symbolic_binding::mark_deleted): New. (symbolic_binding::mark_empty): New. (symbolic_binding::is_deleted): New. (symbolic_binding::is_empty): New. (binding_map::remove_overlapping_bindings): New decl. (binding_map::get_overlapping_bindings): New decl. (binding_cluster::validate): New decl. (binding_cluster::bind): Drop enum binding_kind. (binding_cluster::fill_region): New decl. (binding_cluster::get_binding): Drop enum binding_kind. (binding_cluster::get_binding_recursive): Likewise. (binding_cluster::get_overlapping_bindings): Delete. (store::validate): New decl. (store::set_value): Drop enum binding_kind. (store::fill_region): New decl. (store_manager::get_concrete_binding): Drop enum binding_kind. (store_manager::get_symbolic_binding): Likewise. * svalue.cc (svalue::cmp_ptr): Handle SK_REPEATED and SK_BITS_WITHIN. (svalue::extract_bit_range): New. (svalue::maybe_fold_bits_within): New. (constant_svalue::maybe_fold_bits_within): New. (unknown_svalue::maybe_fold_bits_within): New. (unaryop_svalue::maybe_fold_bits_within): New. (repeated_svalue::repeated_svalue): New. (repeated_svalue::dump_to_pp): New. (repeated_svalue::accept): New. (repeated_svalue::all_zeroes_p): New. (repeated_svalue::maybe_fold_bits_within): New. (bits_within_svalue::bits_within_svalue): New. (bits_within_svalue::dump_to_pp): New. (bits_within_svalue::maybe_fold_bits_within): New. (bits_within_svalue::accept): New. (bits_within_svalue::implicitly_live_p): New. (compound_svalue::maybe_fold_bits_within): New. * svalue.h (enum svalue_kind): Add SK_REPEATED and SK_BITS_WITHIN. (svalue::dyn_cast_repeated_svalue): New. (svalue::dyn_cast_bits_within_svalue): New. (svalue::extract_bit_range): New decl. (svalue::maybe_fold_bits_within): New vfunc decl. (region_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. (region_svalue::key_t::is_empty): Likewise. (default_hash_traits::empty_zero_p): Make false. (constant_svalue::maybe_fold_bits_within): New. (unknown_svalue::maybe_fold_bits_within): New. (poisoned_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. (poisoned_svalue::key_t::is_empty): Likewise. (default_hash_traits::empty_zero_p): Make false. (setjmp_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. (setjmp_svalue::key_t::is_empty): Likewise. (default_hash_traits::empty_zero_p): Make false. (unaryop_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. (unaryop_svalue::key_t::is_empty): Likewise. (unaryop_svalue::maybe_fold_bits_within): New. (default_hash_traits::empty_zero_p): Make false. (binop_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. (binop_svalue::key_t::is_empty): Likewise. (default_hash_traits::empty_zero_p): Make false. (sub_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. (sub_svalue::key_t::is_empty): Likewise. (default_hash_traits::empty_zero_p): Make false. (class repeated_svalue): New. (is_a_helper ::test): New. (struct default_hash_traits): New. (class bits_within_svalue): New. (is_a_helper ::test): New. (struct default_hash_traits): New. (widening_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. (widening_svalue::key_t::is_empty): Likewise. (default_hash_traits::empty_zero_p): Make false. (compound_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. (compound_svalue::key_t::is_empty): Likewise. (compound_svalue::maybe_fold_bits_within): New. (default_hash_traits::empty_zero_p): Make false. gcc/testsuite/ChangeLog: PR analyzer/95006 * gcc.dg/analyzer/clobbers-1.c: New test. * gcc.dg/analyzer/clobbers-2.c: New test. * gcc.dg/analyzer/data-model-1.c (test_26): Mark xfail as fixed. (test_28): Likewise. (test_52): Likewise. Add coverage for end of buffer. * gcc.dg/analyzer/explode-1.c: Add leak warning. * gcc.dg/analyzer/memset-1.c (test_3): Mark xfail as fixed. (test_4): Use char. Mark xfail as fixed. (test_6b): New. (test_7): Mark xfail as fixed. Add coverage for start of buffer. (test_8): New. (test_9): New. * gcc.dg/analyzer/memset-CVE-2017-18549-1.c: New test. * gcc.dg/analyzer/symbolic-8.c: New test. Signed-off-by: David Malcolm --- gcc/analyzer/analyzer.h | 5 + gcc/analyzer/engine.cc | 5 + gcc/analyzer/program-state.cc | 1 + gcc/analyzer/region-model-impl-calls.cc | 39 +- gcc/analyzer/region-model-manager.cc | 313 +++++++++- gcc/analyzer/region-model.cc | 72 +-- gcc/analyzer/region-model.h | 27 + gcc/analyzer/region.cc | 230 ++++++-- gcc/analyzer/region.h | 125 +++- gcc/analyzer/store.cc | 653 ++++++++++++++------- gcc/analyzer/store.h | 157 +++-- gcc/analyzer/svalue.cc | 381 ++++++++++++ gcc/analyzer/svalue.h | 262 ++++++++- gcc/testsuite/gcc.dg/analyzer/clobbers-1.c | 98 ++++ gcc/testsuite/gcc.dg/analyzer/clobbers-2.c | 72 +++ gcc/testsuite/gcc.dg/analyzer/data-model-1.c | 24 +- gcc/testsuite/gcc.dg/analyzer/explode-1.c | 2 +- gcc/testsuite/gcc.dg/analyzer/memset-1.c | 118 +++- .../gcc.dg/analyzer/memset-CVE-2017-18549-1.c | 107 ++++ gcc/testsuite/gcc.dg/analyzer/symbolic-8.c | 11 + 20 files changed, 2207 insertions(+), 495 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/clobbers-1.c create mode 100644 gcc/testsuite/gcc.dg/analyzer/clobbers-2.c create mode 100644 gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c create mode 100644 gcc/testsuite/gcc.dg/analyzer/symbolic-8.c (limited to 'gcc') diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h index f06b68c..02830e4 100644 --- a/gcc/analyzer/analyzer.h +++ b/gcc/analyzer/analyzer.h @@ -46,6 +46,8 @@ class svalue; class unaryop_svalue; class binop_svalue; class sub_svalue; + class repeated_svalue; + class bits_within_svalue; class unmergeable_svalue; class placeholder_svalue; class widening_svalue; @@ -60,6 +62,7 @@ class region; class symbolic_region; class element_region; class offset_region; + class sized_region; class cast_region; class field_region; class string_region; @@ -147,6 +150,8 @@ typedef offset_int byte_size_t; extern bool int_size_in_bits (const_tree type, bit_size_t *out); +extern tree get_field_at_bit_offset (tree record_type, bit_offset_t bit_offset); + /* The location of a region expressesd as an offset relative to a base region. */ diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index f322fdb..4456d9b 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -2275,6 +2275,7 @@ exploded_graph::get_or_create_node (const program_point &point, if (pruned_state.can_merge_with_p (existing_state, point, &merged_state)) { + merged_state.validate (m_ext_state); if (logger) logger->log ("merging new state with that of EN: %i", existing_enode->m_index); @@ -2794,6 +2795,7 @@ maybe_process_run_of_before_supernode_enodes (exploded_node *enode) items.quick_push (it); const program_state &state = iter_enode->get_state (); program_state *next_state = &it->m_processed_state; + next_state->validate (m_ext_state); const program_point &iter_point = iter_enode->get_point (); if (const superedge *iter_sedge = iter_point.get_from_edge ()) { @@ -2807,6 +2809,7 @@ maybe_process_run_of_before_supernode_enodes (exploded_node *enode) next_state->m_region_model->update_for_phis (snode, last_cfg_superedge, &ctxt); } + next_state->validate (m_ext_state); } /* Attempt to partition the items into a set of merged states. @@ -2823,10 +2826,12 @@ maybe_process_run_of_before_supernode_enodes (exploded_node *enode) unsigned iter_merger_idx; FOR_EACH_VEC_ELT (merged_states, iter_merger_idx, merged_state) { + merged_state->validate (m_ext_state); program_state merge (m_ext_state); if (it_state.can_merge_with_p (*merged_state, next_point, &merge)) { *merged_state = merge; + merged_state->validate (m_ext_state); it->m_merger_idx = iter_merger_idx; if (logger) logger->log ("reusing merger state %i for item %i (EN: %i)", diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index 67dd785..6d60c04 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -1142,6 +1142,7 @@ program_state::validate (const extrinsic_state &ext_state) const #endif gcc_assert (m_checker_states.length () == ext_state.get_num_checkers ()); + m_region_model->validate (); } static void diff --git a/gcc/analyzer/region-model-impl-calls.cc b/gcc/analyzer/region-model-impl-calls.cc index 099520a..466d397 100644 --- a/gcc/analyzer/region-model-impl-calls.cc +++ b/gcc/analyzer/region-model-impl-calls.cc @@ -389,36 +389,15 @@ region_model::impl_call_memset (const call_details &cd) const region *dest_reg = deref_rvalue (dest_sval, cd.get_arg_tree (0), cd.get_ctxt ()); - if (tree num_bytes = num_bytes_sval->maybe_get_constant ()) - { - /* "memset" of zero size is a no-op. */ - if (zerop (num_bytes)) - return true; - - /* Set with known amount. */ - byte_size_t reg_size; - if (dest_reg->get_byte_size (®_size)) - { - /* Check for an exact size match. */ - if (reg_size == wi::to_offset (num_bytes)) - { - if (tree cst = fill_value_sval->maybe_get_constant ()) - { - if (zerop (cst)) - { - zero_fill_region (dest_reg); - return true; - } - } - } - } - } - - check_for_writable_region (dest_reg, cd.get_ctxt ()); - - /* Otherwise, mark region's contents as unknown. */ - mark_region_as_unknown (dest_reg, cd.get_uncertainty ()); - return false; + const svalue *fill_value_u8 + = m_mgr->get_or_create_cast (unsigned_char_type_node, fill_value_sval); + + const region *sized_dest_reg = m_mgr->get_sized_region (dest_reg, + NULL_TREE, + num_bytes_sval); + check_for_writable_region (sized_dest_reg, cd.get_ctxt ()); + fill_region (sized_dest_reg, fill_value_u8); + return true; } /* Handle the on_call_pre part of "operator new". */ diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index 1ee6663..55acb90 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -477,7 +477,7 @@ maybe_undo_optimize_bit_field_compare (tree type, bound_bits = bit_range (BITS_PER_UNIT - bits.get_next_bit_offset (), bits.m_size_in_bits); const concrete_binding *conc - = get_store_manager ()->get_concrete_binding (bound_bits, BK_direct); + = get_store_manager ()->get_concrete_binding (bound_bits); const svalue *sval = map.get (conc); if (!sval) return NULL; @@ -686,13 +686,13 @@ region_model_manager::maybe_fold_sub_svalue (tree type, return get_or_create_cast (type, char_sval); } - /* SUB(INIT(r)).FIELD -> INIT(r.FIELD) - i.e. - Subvalue(InitialValue(R1), FieldRegion(R2, F)) - -> InitialValue(FieldRegion(R1, F)). */ if (const initial_svalue *init_sval - = parent_svalue->dyn_cast_initial_svalue ()) + = parent_svalue->dyn_cast_initial_svalue ()) { + /* SUB(INIT(r)).FIELD -> INIT(r.FIELD) + i.e. + Subvalue(InitialValue(R1), FieldRegion(R2, F)) + -> InitialValue(FieldRegion(R1, F)). */ if (const field_region *field_reg = subregion->dyn_cast_field_region ()) { const region *field_reg_new @@ -700,8 +700,24 @@ region_model_manager::maybe_fold_sub_svalue (tree type, field_reg->get_field ()); return get_or_create_initial_value (field_reg_new); } + /* SUB(INIT(r)[ELEMENT] -> INIT(e[ELEMENT]) + i.e. + Subvalue(InitialValue(R1), ElementRegion(R2, IDX)) + -> InitialValue(ElementRegion(R1, IDX)). */ + if (const element_region *element_reg = subregion->dyn_cast_element_region ()) + { + const region *element_reg_new + = get_element_region (init_sval->get_region (), + element_reg->get_type (), + element_reg->get_index ()); + return get_or_create_initial_value (element_reg_new); + } } + if (const repeated_svalue *repeated_sval + = parent_svalue->dyn_cast_repeated_svalue ()) + return get_or_create_cast (type, repeated_sval->get_inner_svalue ()); + return NULL; } @@ -727,6 +743,255 @@ region_model_manager::get_or_create_sub_svalue (tree type, return sub_sval; } +/* Subroutine of region_model_manager::get_or_create_repeated_svalue. + Return a folded svalue, or NULL. */ + +const svalue * +region_model_manager::maybe_fold_repeated_svalue (tree type, + const svalue *outer_size, + const svalue *inner_svalue) +{ + /* If INNER_SVALUE is the same size as OUTER_SIZE, + turn into simply a cast. */ + if (tree cst_outer_num_bytes = outer_size->maybe_get_constant ()) + { + HOST_WIDE_INT num_bytes_inner_svalue + = int_size_in_bytes (inner_svalue->get_type ()); + if (num_bytes_inner_svalue != -1) + if (num_bytes_inner_svalue + == (HOST_WIDE_INT)tree_to_uhwi (cst_outer_num_bytes)) + { + if (type) + return get_or_create_cast (type, inner_svalue); + else + return inner_svalue; + } + } + + /* Handle zero-fill of a specific type. */ + if (tree cst = inner_svalue->maybe_get_constant ()) + if (zerop (cst) && type) + return get_or_create_cast (type, inner_svalue); + + return NULL; +} + +/* Return the svalue * of type TYPE in which INNER_SVALUE is repeated + enough times to be of size OUTER_SIZE, creating it if necessary. + e.g. for filling buffers with a constant value. */ + +const svalue * +region_model_manager::get_or_create_repeated_svalue (tree type, + const svalue *outer_size, + const svalue *inner_svalue) +{ + if (const svalue *folded + = maybe_fold_repeated_svalue (type, outer_size, inner_svalue)) + return folded; + + repeated_svalue::key_t key (type, outer_size, inner_svalue); + if (repeated_svalue **slot = m_repeated_values_map.get (key)) + return *slot; + repeated_svalue *repeated_sval + = new repeated_svalue (type, outer_size, inner_svalue); + RETURN_UNKNOWN_IF_TOO_COMPLEX (repeated_sval); + m_repeated_values_map.put (key, repeated_sval); + return repeated_sval; +} + +/* Attempt to get the bit_range for FIELD within a RECORD_TYPE. + Return true and write the result to OUT if successful. + Return false otherwise. */ + +static bool +get_bit_range_for_field (tree field, bit_range *out) +{ + bit_size_t bit_size; + if (!int_size_in_bits (TREE_TYPE (field), &bit_size)) + return false; + int field_bit_offset = int_bit_position (field); + *out = bit_range (field_bit_offset, bit_size); + return true; +} + +/* Attempt to get the byte_range for FIELD within a RECORD_TYPE. + Return true and write the result to OUT if successful. + Return false otherwise. */ + +static bool +get_byte_range_for_field (tree field, byte_range *out) +{ + bit_range field_bits (0, 0); + if (!get_bit_range_for_field (field, &field_bits)) + return false; + return field_bits.as_byte_range (out); +} + +/* Attempt to determine if there is a specific field within RECORD_TYPE + at BYTES. If so, return it, and write the location of BYTES relative + to the field to *OUT_RANGE_WITHIN_FIELD. + Otherwise, return NULL_TREE. + For example, given: + struct foo { uint32 a; uint32; b}; + and + bytes = {bytes 6-7} (of foo) + we have bytes 3-4 of field b. */ + +static tree +get_field_at_byte_range (tree record_type, const byte_range &bytes, + byte_range *out_range_within_field) +{ + bit_offset_t bit_offset = bytes.m_start_byte_offset * BITS_PER_UNIT; + + tree field = get_field_at_bit_offset (record_type, bit_offset); + if (!field) + return NULL_TREE; + + byte_range field_bytes (0,0); + if (!get_byte_range_for_field (field, &field_bytes)) + return NULL_TREE; + + /* Is BYTES fully within field_bytes? */ + byte_range bytes_within_field (0,0); + if (!field_bytes.contains_p (bytes, &bytes_within_field)) + return NULL_TREE; + + *out_range_within_field = bytes_within_field; + return field; +} + +/* Subroutine of region_model_manager::get_or_create_bits_within. + Return a folded svalue, or NULL. */ + +const svalue * +region_model_manager::maybe_fold_bits_within_svalue (tree type, + const bit_range &bits, + const svalue *inner_svalue) +{ + tree inner_type = inner_svalue->get_type (); + /* Fold: + BITS_WITHIN ((0, sizeof (VAL), VAL)) + to: + CAST(TYPE, VAL). */ + if (bits.m_start_bit_offset == 0 && inner_type) + { + bit_size_t inner_type_size; + if (int_size_in_bits (inner_type, &inner_type_size)) + if (inner_type_size == bits.m_size_in_bits) + { + if (type) + return get_or_create_cast (type, inner_svalue); + else + return inner_svalue; + } + } + + /* Kind-specific folding. */ + if (const svalue *sval + = inner_svalue->maybe_fold_bits_within (type, bits, this)) + return sval; + + byte_range bytes (0,0); + if (bits.as_byte_range (&bytes) && inner_type) + switch (TREE_CODE (inner_type)) + { + default: + break; + case ARRAY_TYPE: + { + /* Fold: + BITS_WITHIN (range, KIND(REG)) + to: + BITS_WITHIN (range - offsetof(ELEMENT), KIND(REG.ELEMENT)) + if range1 is a byte-range fully within one ELEMENT. */ + tree element_type = TREE_TYPE (inner_type); + HOST_WIDE_INT element_byte_size + = int_size_in_bytes (element_type); + if (element_byte_size > 0) + { + HOST_WIDE_INT start_idx + = (bytes.get_start_byte_offset ().to_shwi () + / element_byte_size); + HOST_WIDE_INT last_idx + = (bytes.get_last_byte_offset ().to_shwi () + / element_byte_size); + if (start_idx == last_idx) + { + if (const initial_svalue *initial_sval + = inner_svalue->dyn_cast_initial_svalue ()) + { + bit_offset_t start_of_element + = start_idx * element_byte_size * BITS_PER_UNIT; + bit_range bits_within_element + (bits.m_start_bit_offset - start_of_element, + bits.m_size_in_bits); + const svalue *idx_sval + = get_or_create_int_cst (integer_type_node, start_idx); + const region *element_reg = + get_element_region (initial_sval->get_region (), + element_type, idx_sval); + const svalue *element_reg_sval + = get_or_create_initial_value (element_reg); + return get_or_create_bits_within (type, + bits_within_element, + element_reg_sval); + } + } + } + } + break; + case RECORD_TYPE: + { + /* Fold: + BYTES_WITHIN (range, KIND(REG)) + to: + BYTES_WITHIN (range - offsetof(FIELD), KIND(REG.FIELD)) + if range1 is fully within FIELD. */ + byte_range bytes_within_field (0, 0); + if (tree field = get_field_at_byte_range (inner_type, bytes, + &bytes_within_field)) + { + if (const initial_svalue *initial_sval + = inner_svalue->dyn_cast_initial_svalue ()) + { + const region *field_reg = + get_field_region (initial_sval->get_region (), field); + const svalue *initial_reg_sval + = get_or_create_initial_value (field_reg); + return get_or_create_bits_within + (type, + bytes_within_field.as_bit_range (), + initial_reg_sval); + } + } + } + break; + } + return NULL; +} + +/* Return the svalue * of type TYPE for extracting BITS from INNER_SVALUE, + creating it if necessary. */ + +const svalue * +region_model_manager::get_or_create_bits_within (tree type, + const bit_range &bits, + const svalue *inner_svalue) +{ + if (const svalue *folded + = maybe_fold_bits_within_svalue (type, bits, inner_svalue)) + return folded; + + bits_within_svalue::key_t key (type, bits, inner_svalue); + if (bits_within_svalue **slot = m_bits_within_values_map.get (key)) + return *slot; + bits_within_svalue *bits_within_sval + = new bits_within_svalue (type, bits, inner_svalue); + RETURN_UNKNOWN_IF_TOO_COMPLEX (bits_within_sval); + m_bits_within_values_map.put (key, bits_within_sval); + return bits_within_sval; +} + /* Return the svalue * that decorates ARG as being unmergeable, creating it if necessary. */ @@ -966,6 +1231,38 @@ region_model_manager::get_offset_region (const region *parent, return offset_reg; } +/* Return the region that describes accessing the subregion of type + TYPE of size BYTE_SIZE_SVAL within PARENT, creating it if necessary. */ + +const region * +region_model_manager::get_sized_region (const region *parent, + tree type, + const svalue *byte_size_sval) +{ + if (byte_size_sval->get_type () != size_type_node) + byte_size_sval = get_or_create_cast (size_type_node, byte_size_sval); + + /* If PARENT is already that size, return it. */ + const svalue *parent_byte_size_sval = parent->get_byte_size_sval (this); + if (tree parent_size_cst = parent_byte_size_sval->maybe_get_constant ()) + if (tree size_cst = byte_size_sval->maybe_get_constant ()) + { + tree comparison + = fold_binary (EQ_EXPR, boolean_type_node, parent_size_cst, size_cst); + if (comparison == boolean_true_node) + return parent; + } + + sized_region::key_t key (parent, type, byte_size_sval); + if (sized_region *reg = m_sized_regions.get (key)) + return reg; + + sized_region *sized_reg + = new sized_region (alloc_region_id (), parent, type, byte_size_sval); + m_sized_regions.put (key, sized_reg); + return sized_reg; +} + /* Return the region that describes accessing PARENT_REGION as if it were of type TYPE, creating it if necessary. */ @@ -1180,6 +1477,9 @@ region_model_manager::log_stats (logger *logger, bool show_objs) const log_uniq_map (logger, show_objs, "unaryop_svalue", m_unaryop_values_map); log_uniq_map (logger, show_objs, "binop_svalue", m_binop_values_map); log_uniq_map (logger, show_objs, "sub_svalue", m_sub_values_map); + log_uniq_map (logger, show_objs, "repeated_svalue", m_repeated_values_map); + log_uniq_map (logger, show_objs, "bits_within_svalue", + m_bits_within_values_map); log_uniq_map (logger, show_objs, "unmergeable_svalue", m_unmergeable_values_map); log_uniq_map (logger, show_objs, "widening_svalue", m_widening_values_map); @@ -1198,6 +1498,7 @@ region_model_manager::log_stats (logger *logger, bool show_objs) const log_uniq_map (logger, show_objs, "field_region", m_field_regions); log_uniq_map (logger, show_objs, "element_region", m_element_regions); log_uniq_map (logger, show_objs, "offset_region", m_offset_regions); + log_uniq_map (logger, show_objs, "sized_region", m_sized_regions); log_uniq_map (logger, show_objs, "cast_region", m_cast_regions); log_uniq_map (logger, show_objs, "frame_region", m_frame_regions); log_uniq_map (logger, show_objs, "symbolic_region", m_symbolic_regions); diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index ee11e82..4fb6bc9 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -393,6 +393,14 @@ region_model::debug () const dump (true); } +/* Assert that this object is valid. */ + +void +region_model::validate () const +{ + m_store.validate (); +} + /* Canonicalize the store and constraints, to maximize the chance of equality between region_model instances. */ @@ -847,11 +855,9 @@ region_model::on_assignment (const gassign *assign, region_model_context *ctxt) case STRING_CST: { /* e.g. "struct s2 x = {{'A', 'B', 'C', 'D'}};". */ - /* Add a default binding, rather than a direct one, so that array - access will "inherit" the individual chars. */ const svalue *rhs_sval = get_rvalue (rhs1, ctxt); m_store.set_value (m_mgr->get_store_manager(), lhs_reg, rhs_sval, - BK_default, ctxt ? ctxt->get_uncertainty () : NULL); + ctxt ? ctxt->get_uncertainty () : NULL); } break; } @@ -1662,8 +1668,7 @@ region_model::get_initial_value_for_global (const region *reg) const { /* Get the value for REG within base_reg_init. */ binding_cluster c (base_reg); - c.bind (m_mgr->get_store_manager (), base_reg, base_reg_init, - BK_direct); + c.bind (m_mgr->get_store_manager (), base_reg, base_reg_init); const svalue *sval = c.get_any_binding (m_mgr->get_store_manager (), reg); if (sval) @@ -1854,45 +1859,7 @@ region_model::get_rvalue_for_bits (tree type, const bit_range &bits) const { const svalue *sval = get_store_value (reg); - if (const compound_svalue *compound_sval = sval->dyn_cast_compound_svalue ()) - { - const binding_map &map = compound_sval->get_map (); - binding_map result_map; - for (auto iter : map) - { - const binding_key *key = iter.first; - if (const concrete_binding *conc_key - = key->dyn_cast_concrete_binding ()) - { - /* Ignore concrete bindings outside BITS. */ - if (!conc_key->get_bit_range ().intersects_p (bits)) - continue; - if ((conc_key->get_start_bit_offset () - < bits.get_start_bit_offset ()) - || (conc_key->get_next_bit_offset () - > bits.get_next_bit_offset ())) - { - /* If we have any concrete keys that aren't fully within BITS, - then bail out. */ - return m_mgr->get_or_create_unknown_svalue (type); - } - const concrete_binding *offset_conc_key - = m_mgr->get_store_manager ()->get_concrete_binding - (conc_key->get_start_bit_offset () - - bits.get_start_bit_offset (), - conc_key->get_size_in_bits (), - conc_key->get_kind ()); - const svalue *sval = iter.second; - result_map.put (offset_conc_key, sval); - } - else - /* If we have any symbolic keys we can't get it as bits. */ - return m_mgr->get_or_create_unknown_svalue (type); - } - return m_mgr->get_or_create_compound_svalue (type, result_map); - } - - return m_mgr->get_or_create_unknown_svalue (type); + return m_mgr->get_or_create_bits_within (type, bits, sval); } /* A subclass of pending_diagnostic for complaining about writes to @@ -2035,6 +2002,10 @@ region_model::get_capacity (const region *reg) const } } break; + case RK_SIZED: + /* Look through sized regions to get at the capacity + of the underlying regions. */ + return get_capacity (reg->get_parent_region ()); } if (const svalue *recorded = get_dynamic_extents (reg)) @@ -2056,7 +2027,7 @@ region_model::set_value (const region *lhs_reg, const svalue *rhs_sval, check_for_writable_region (lhs_reg, ctxt); m_store.set_value (m_mgr->get_store_manager(), lhs_reg, rhs_sval, - BK_direct, ctxt ? ctxt->get_uncertainty () : NULL); + ctxt ? ctxt->get_uncertainty () : NULL); } /* Set the value of the region given by LHS to the value given by RHS. */ @@ -2087,6 +2058,14 @@ region_model::purge_region (const region *reg) m_store.purge_region (m_mgr->get_store_manager(), reg); } +/* Fill REG with SVAL. */ + +void +region_model::fill_region (const region *reg, const svalue *sval) +{ + m_store.fill_region (m_mgr->get_store_manager(), reg, sval); +} + /* Zero-fill REG. */ void @@ -2711,6 +2690,9 @@ region_model::get_representative_path_var_1 (const region *reg, parent_pv.m_stack_depth); } + case RK_SIZED: + return path_var (NULL_TREE, 0); + case RK_CAST: { path_var parent_pv diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index a4b584d..b42852b 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -212,6 +212,8 @@ public: virtual void visit_unaryop_svalue (const unaryop_svalue *) {} virtual void visit_binop_svalue (const binop_svalue *) {} virtual void visit_sub_svalue (const sub_svalue *) {} + virtual void visit_repeated_svalue (const repeated_svalue *) {} + virtual void visit_bits_within_svalue (const bits_within_svalue *) {} virtual void visit_unmergeable_svalue (const unmergeable_svalue *) {} virtual void visit_placeholder_svalue (const placeholder_svalue *) {} virtual void visit_widening_svalue (const widening_svalue *) {} @@ -255,6 +257,12 @@ public: const svalue *get_or_create_sub_svalue (tree type, const svalue *parent_svalue, const region *subregion); + const svalue *get_or_create_repeated_svalue (tree type, + const svalue *outer_size, + const svalue *inner_svalue); + const svalue *get_or_create_bits_within (tree type, + const bit_range &bits, + const svalue *inner_svalue); const svalue *get_or_create_unmergeable (const svalue *arg); const svalue *get_or_create_widening_svalue (tree type, const program_point &point, @@ -286,6 +294,9 @@ public: const region *get_offset_region (const region *parent, tree type, const svalue *byte_offset); + const region *get_sized_region (const region *parent, + tree type, + const svalue *byte_size_sval); const region *get_cast_region (const region *original_region, tree type); const frame_region *get_frame_region (const frame_region *calling_frame, @@ -321,6 +332,12 @@ private: const svalue *maybe_fold_sub_svalue (tree type, const svalue *parent_svalue, const region *subregion); + const svalue *maybe_fold_repeated_svalue (tree type, + const svalue *outer_size, + const svalue *inner_svalue); + const svalue *maybe_fold_bits_within_svalue (tree type, + const bit_range &bits, + const svalue *inner_svalue); const svalue *maybe_undo_optimize_bit_field_compare (tree type, const compound_svalue *compound_sval, tree cst, const svalue *arg1); @@ -362,6 +379,14 @@ private: typedef hash_map sub_values_map_t; sub_values_map_t m_sub_values_map; + typedef hash_map repeated_values_map_t; + repeated_values_map_t m_repeated_values_map; + + typedef hash_map bits_within_values_map_t; + bits_within_values_map_t m_bits_within_values_map; + typedef hash_map unmergeable_values_map_t; unmergeable_values_map_t m_unmergeable_values_map; @@ -402,6 +427,7 @@ private: consolidation_map m_field_regions; consolidation_map m_element_regions; consolidation_map m_offset_regions; + consolidation_map m_sized_regions; consolidation_map m_cast_regions; consolidation_map m_frame_regions; consolidation_map m_symbolic_regions; @@ -575,6 +601,7 @@ class region_model void set_value (tree lhs, tree rhs, region_model_context *ctxt); void clobber_region (const region *reg); void purge_region (const region *reg); + void fill_region (const region *reg, const svalue *sval); void zero_fill_region (const region *reg); void mark_region_as_unknown (const region *reg, uncertainty_t *uncertainty); diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index 5f246df..4633717 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -98,6 +98,7 @@ region::get_base_region () const case RK_FIELD: case RK_ELEMENT: case RK_OFFSET: + case RK_SIZED: iter = iter->get_parent_region (); continue; case RK_CAST: @@ -121,6 +122,7 @@ region::base_region_p () const case RK_FIELD: case RK_ELEMENT: case RK_OFFSET: + case RK_SIZED: case RK_CAST: return false; @@ -188,7 +190,8 @@ region::get_offset () const return *m_cached_offset; } -/* If the size of this region (in bytes) is known statically, write it to *OUT +/* Base class implementation of region::get_byte_size vfunc. + If the size of this region (in bytes) is known statically, write it to *OUT and return true. Otherwise return false. */ @@ -208,8 +211,29 @@ region::get_byte_size (byte_size_t *out) const return true; } -/* If the size of TYPE (in bits) is constant, write it to *OUT - and return true. +/* Base implementation of region::get_byte_size_sval vfunc. */ + +const svalue * +region::get_byte_size_sval (region_model_manager *mgr) const +{ + tree type = get_type (); + + /* Bail out e.g. for heap-allocated regions. */ + if (!type) + return mgr->get_or_create_unknown_svalue (size_type_node); + + HOST_WIDE_INT bytes = int_size_in_bytes (type); + if (bytes == -1) + return mgr->get_or_create_unknown_svalue (size_type_node); + + tree byte_size = size_in_bytes (type); + if (TREE_TYPE (byte_size) != size_type_node) + byte_size = fold_build1 (NOP_EXPR, size_type_node, byte_size); + return mgr->get_or_create_constant_svalue (byte_size); +} + +/* Attempt to get the size of TYPE in bits. + If successful, return true and write the size to *OUT. Otherwise return false. */ bool @@ -249,7 +273,7 @@ region::get_bit_size (bit_size_t *out) const /* Get the field within RECORD_TYPE at BIT_OFFSET. */ -static tree +tree get_field_at_bit_offset (tree record_type, bit_offset_t bit_offset) { gcc_assert (TREE_CODE (record_type) == RECORD_TYPE); @@ -375,18 +399,10 @@ region::calc_offset () const = (const field_region *)iter_region; iter_region = iter_region->get_parent_region (); - /* Compare with e.g. gimple-fold.c's - fold_nonarray_ctor_reference. */ - tree field = field_reg->get_field (); - tree byte_offset = DECL_FIELD_OFFSET (field); - if (TREE_CODE (byte_offset) != INTEGER_CST) + bit_offset_t rel_bit_offset; + if (!field_reg->get_relative_concrete_offset (&rel_bit_offset)) return region_offset::make_symbolic (iter_region); - tree field_offset = DECL_FIELD_BIT_OFFSET (field); - /* Compute bit offset of the field. */ - offset_int bitoffset - = (wi::to_offset (field_offset) - + (wi::to_offset (byte_offset) << LOG2_BITS_PER_UNIT)); - accum_bit_offset += bitoffset; + accum_bit_offset += rel_bit_offset; } continue; @@ -396,28 +412,10 @@ region::calc_offset () const = (const element_region *)iter_region; iter_region = iter_region->get_parent_region (); - if (tree idx_cst - = element_reg->get_index ()->maybe_get_constant ()) - { - gcc_assert (TREE_CODE (idx_cst) == INTEGER_CST); - - tree elem_type = element_reg->get_type (); - offset_int element_idx = wi::to_offset (idx_cst); - - /* First, use int_size_in_bytes, to reject the case where we - have an incomplete type, or a non-constant value. */ - HOST_WIDE_INT hwi_byte_size = int_size_in_bytes (elem_type); - if (hwi_byte_size > 0) - { - offset_int element_bit_size - = hwi_byte_size << LOG2_BITS_PER_UNIT; - offset_int element_bit_offset - = element_idx * element_bit_size; - accum_bit_offset += element_bit_offset; - continue; - } - } - return region_offset::make_symbolic (iter_region); + bit_offset_t rel_bit_offset; + if (!element_reg->get_relative_concrete_offset (&rel_bit_offset)) + return region_offset::make_symbolic (iter_region); + accum_bit_offset += rel_bit_offset; } continue; @@ -427,22 +425,17 @@ region::calc_offset () const = (const offset_region *)iter_region; iter_region = iter_region->get_parent_region (); - if (tree byte_offset_cst - = offset_reg->get_byte_offset ()->maybe_get_constant ()) - { - gcc_assert (TREE_CODE (byte_offset_cst) == INTEGER_CST); - /* Use a signed value for the byte offset, to handle - negative offsets. */ - HOST_WIDE_INT byte_offset - = wi::to_offset (byte_offset_cst).to_shwi (); - HOST_WIDE_INT bit_offset = byte_offset * BITS_PER_UNIT; - accum_bit_offset += bit_offset; - } - else + bit_offset_t rel_bit_offset; + if (!offset_reg->get_relative_concrete_offset (&rel_bit_offset)) return region_offset::make_symbolic (iter_region); + accum_bit_offset += rel_bit_offset; } continue; + case RK_SIZED: + iter_region = iter_region->get_parent_region (); + continue; + case RK_CAST: { const cast_region *cast_reg @@ -458,6 +451,14 @@ region::calc_offset () const return region_offset::make_concrete (iter_region, accum_bit_offset); } +/* Base implementation of region::get_relative_concrete_offset vfunc. */ + +bool +region::get_relative_concrete_offset (bit_offset_t *) const +{ + return false; +} + /* Copy from SRC_REG to DST_REG, using CTXT for any issues that occur. */ void @@ -984,7 +985,7 @@ decl_region::get_svalue_for_initializer (region_model_manager *mgr) const which can fail if we have a region with unknown size (e.g. "extern const char arr[];"). */ const binding_key *binding - = binding_key::make (mgr->get_store_manager (), this, BK_direct); + = binding_key::make (mgr->get_store_manager (), this); if (binding->symbolic_p ()) return NULL; @@ -1030,6 +1031,26 @@ field_region::dump_to_pp (pretty_printer *pp, bool simple) const } } +/* Implementation of region::get_relative_concrete_offset vfunc + for field_region. */ + +bool +field_region::get_relative_concrete_offset (bit_offset_t *out) const +{ + /* Compare with e.g. gimple-fold.c's + fold_nonarray_ctor_reference. */ + tree byte_offset = DECL_FIELD_OFFSET (m_field); + if (TREE_CODE (byte_offset) != INTEGER_CST) + return false; + tree field_offset = DECL_FIELD_BIT_OFFSET (m_field); + /* Compute bit offset of the field. */ + offset_int bitoffset + = (wi::to_offset (field_offset) + + (wi::to_offset (byte_offset) << LOG2_BITS_PER_UNIT)); + *out = bitoffset; + return true; +} + /* class element_region : public region. */ /* Implementation of region::accept vfunc for element_region. */ @@ -1067,6 +1088,35 @@ element_region::dump_to_pp (pretty_printer *pp, bool simple) const } } +/* Implementation of region::get_relative_concrete_offset vfunc + for element_region. */ + +bool +element_region::get_relative_concrete_offset (bit_offset_t *out) const +{ + if (tree idx_cst = m_index->maybe_get_constant ()) + { + gcc_assert (TREE_CODE (idx_cst) == INTEGER_CST); + + tree elem_type = get_type (); + offset_int element_idx = wi::to_offset (idx_cst); + + /* First, use int_size_in_bytes, to reject the case where we + have an incomplete type, or a non-constant value. */ + HOST_WIDE_INT hwi_byte_size = int_size_in_bytes (elem_type); + if (hwi_byte_size > 0) + { + offset_int element_bit_size + = hwi_byte_size << LOG2_BITS_PER_UNIT; + offset_int element_bit_offset + = element_idx * element_bit_size; + *out = element_bit_offset; + return true; + } + } + return false; +} + /* class offset_region : public region. */ /* Implementation of region::accept vfunc for offset_region. */ @@ -1103,6 +1153,86 @@ offset_region::dump_to_pp (pretty_printer *pp, bool simple) const } } +/* Implementation of region::get_relative_concrete_offset vfunc + for offset_region. */ + +bool +offset_region::get_relative_concrete_offset (bit_offset_t *out) const +{ + if (tree byte_offset_cst = m_byte_offset->maybe_get_constant ()) + { + gcc_assert (TREE_CODE (byte_offset_cst) == INTEGER_CST); + /* Use a signed value for the byte offset, to handle + negative offsets. */ + HOST_WIDE_INT byte_offset + = wi::to_offset (byte_offset_cst).to_shwi (); + HOST_WIDE_INT bit_offset = byte_offset * BITS_PER_UNIT; + *out = bit_offset; + return true; + } + return false; +} + +/* class sized_region : public region. */ + +/* Implementation of region::accept vfunc for sized_region. */ + +void +sized_region::accept (visitor *v) const +{ + region::accept (v); + m_byte_size_sval->accept (v); +} + +/* Implementation of region::dump_to_pp vfunc for sized_region. */ + +void +sized_region::dump_to_pp (pretty_printer *pp, bool simple) const +{ + if (simple) + { + pp_string (pp, "SIZED_REG("); + get_parent_region ()->dump_to_pp (pp, simple); + pp_string (pp, ", "); + m_byte_size_sval->dump_to_pp (pp, simple); + pp_string (pp, ")"); + } + else + { + pp_string (pp, "sized_region("); + get_parent_region ()->dump_to_pp (pp, simple); + pp_string (pp, ", "); + m_byte_size_sval->dump_to_pp (pp, simple); + pp_printf (pp, ")"); + } +} + +/* Implementation of region::get_byte_size vfunc for sized_region. */ + +bool +sized_region::get_byte_size (byte_size_t *out) const +{ + if (tree cst = m_byte_size_sval->maybe_get_constant ()) + { + gcc_assert (TREE_CODE (cst) == INTEGER_CST); + *out = tree_to_uhwi (cst); + return true; + } + return false; +} + +/* Implementation of region::get_bit_size vfunc for sized_region. */ + +bool +sized_region::get_bit_size (bit_size_t *out) const +{ + byte_size_t byte_size; + if (!get_byte_size (&byte_size)) + return false; + *out = byte_size * BITS_PER_UNIT; + return true; +} + /* class cast_region : public region. */ /* Implementation of region::accept vfunc for cast_region. */ diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h index 175a82a..353d5c4 100644 --- a/gcc/analyzer/region.h +++ b/gcc/analyzer/region.h @@ -43,6 +43,7 @@ enum region_kind RK_FIELD, RK_ELEMENT, RK_OFFSET, + RK_SIZED, RK_CAST, RK_HEAP_ALLOCATED, RK_ALLOCA, @@ -70,6 +71,7 @@ enum region_kind field_region (RK_FIELD) element_region (RK_ELEMENT) offset_region (RK_OFFSET) + sized_region (RK_SIZED) cast_region (RK_CAST) heap_allocated_region (RK_HEAP_ALLOCATED) alloca_region (RK_ALLOCA) @@ -107,6 +109,8 @@ public: dyn_cast_element_region () const { return NULL; } virtual const offset_region * dyn_cast_offset_region () const { return NULL; } + virtual const sized_region * + dyn_cast_sized_region () const { return NULL; } virtual const cast_region * dyn_cast_cast_region () const { return NULL; } virtual const string_region * @@ -138,8 +142,25 @@ public: static int cmp_ptr_ptr (const void *, const void *); region_offset get_offset () const; - bool get_byte_size (byte_size_t *out) const; - bool get_bit_size (bit_size_t *out) const; + + /* Attempt to get the size of this region as a concrete number of bytes. + If successful, return true and write the size to *OUT. + Otherwise return false. */ + virtual bool get_byte_size (byte_size_t *out) const; + + /* Attempt to get the size of this region as a concrete number of bits. + If successful, return true and write the size to *OUT. + Otherwise return false. */ + virtual bool get_bit_size (bit_size_t *out) const; + + /* Get a symbolic value describing the size of this region in bytes + (which could be "unknown"). */ + virtual const svalue *get_byte_size_sval (region_model_manager *mgr) const; + + /* Attempt to get the offset in bits of this region relative to its parent. + If successful, return true and write to *OUT. + Otherwise return false. */ + virtual bool get_relative_concrete_offset (bit_offset_t *out) const; void get_subregions_for_binding (region_model_manager *mgr, @@ -670,6 +691,8 @@ public: tree get_field () const { return m_field; } + bool get_relative_concrete_offset (bit_offset_t *out) const FINAL OVERRIDE; + private: tree m_field; }; @@ -751,6 +774,9 @@ public: const svalue *get_index () const { return m_index; } + virtual bool + get_relative_concrete_offset (bit_offset_t *out) const FINAL OVERRIDE; + private: const svalue *m_index; }; @@ -833,6 +859,8 @@ public: const svalue *get_byte_offset () const { return m_byte_offset; } + bool get_relative_concrete_offset (bit_offset_t *out) const FINAL OVERRIDE; + private: const svalue *m_byte_offset; }; @@ -855,6 +883,99 @@ template <> struct default_hash_traits namespace ana { +/* A region that is size BYTES_SIZE_SVAL in size within its parent + region (or possibly larger, which would lead to an overflow. */ + +class sized_region : public region +{ +public: + /* A support class for uniquifying instances of sized_region. */ + struct key_t + { + key_t (const region *parent, tree element_type, + const svalue *byte_size_sval) + : m_parent (parent), m_element_type (element_type), + m_byte_size_sval (byte_size_sval) + { + gcc_assert (byte_size_sval); + } + + hashval_t hash () const + { + inchash::hash hstate; + hstate.add_ptr (m_parent); + hstate.add_ptr (m_element_type); + hstate.add_ptr (m_byte_size_sval); + return hstate.end (); + } + + bool operator== (const key_t &other) const + { + return (m_parent == other.m_parent + && m_element_type == other.m_element_type + && m_byte_size_sval == other.m_byte_size_sval); + } + + void mark_deleted () { m_byte_size_sval = reinterpret_cast (1); } + void mark_empty () { m_byte_size_sval = NULL; } + bool is_deleted () const + { + return m_byte_size_sval == reinterpret_cast (1); + } + bool is_empty () const { return m_byte_size_sval == NULL; } + + const region *m_parent; + tree m_element_type; + const svalue *m_byte_size_sval; + const svalue *m_end_offset; + }; + + sized_region (unsigned id, const region *parent, tree type, + const svalue *byte_size_sval) + : region (complexity::from_pair (parent, byte_size_sval), + id, parent, type), + m_byte_size_sval (byte_size_sval) + {} + + enum region_kind get_kind () const FINAL OVERRIDE { return RK_SIZED; } + const sized_region * + dyn_cast_sized_region () const FINAL OVERRIDE { return this; } + + void accept (visitor *v) const FINAL OVERRIDE; + + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; + + bool get_byte_size (byte_size_t *out) const FINAL OVERRIDE; + bool get_bit_size (bit_size_t *out) const FINAL OVERRIDE; + + const svalue * + get_byte_size_sval (region_model_manager *) const FINAL OVERRIDE + { + return m_byte_size_sval; + } + +private: + const svalue *m_byte_size_sval; +}; + +} // namespace ana + +template <> +template <> +inline bool +is_a_helper ::test (const region *reg) +{ + return reg->get_kind () == RK_SIZED; +} + +template <> struct default_hash_traits +: public member_function_hash_traits +{ + static const bool empty_zero_p = true; +}; + +namespace ana { + /* A region that views another region using a different type. */ class cast_region : public region diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index d5f8798..a65c741 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -118,52 +118,25 @@ uncertainty_t::dump (bool simple) const pp_flush (&pp); } -/* Get a human-readable string for KIND for dumps. */ - -const char *binding_kind_to_string (enum binding_kind kind) -{ - switch (kind) - { - default: - case BK_empty: - case BK_deleted: - /* We shouldn't be attempting to print the hash kinds. */ - gcc_unreachable (); - case BK_direct: - return "direct"; - case BK_default: - return "default"; - } -} - /* class binding_key. */ const binding_key * -binding_key::make (store_manager *mgr, const region *r, - enum binding_kind kind) +binding_key::make (store_manager *mgr, const region *r) { region_offset offset = r->get_offset (); if (offset.symbolic_p ()) - return mgr->get_symbolic_binding (r, kind); + return mgr->get_symbolic_binding (r); else { bit_size_t bit_size; if (r->get_bit_size (&bit_size)) return mgr->get_concrete_binding (offset.get_bit_offset (), - bit_size, kind); + bit_size); else - return mgr->get_symbolic_binding (r, kind); + return mgr->get_symbolic_binding (r); } } -/* Base class implementation of binding_key::dump_to_pp vfunc. */ - -void -binding_key::dump_to_pp (pretty_printer *pp, bool /*simple*/) const -{ - pp_printf (pp, "kind: %s", binding_kind_to_string (m_kind)); -} - /* Dump this binding_key to stderr. */ DEBUG_FUNCTION void @@ -204,11 +177,6 @@ binding_key::cmp_ptrs (const void *p1, const void *p2) int binding_key::cmp (const binding_key *k1, const binding_key *k2) { - enum binding_kind kind1 = k1->get_kind (); - enum binding_kind kind2 = k2->get_kind (); - if (kind1 != kind2) - return (int)kind1 - (int)kind2; - int concrete1 = k1->concrete_p (); int concrete2 = k2->concrete_p (); if (int concrete_cmp = concrete1 - concrete2) @@ -236,7 +204,7 @@ binding_key::cmp (const binding_key *k1, const binding_key *k2) } } -/* struct struct bit_range. */ +/* struct bit_range. */ void bit_range::dump_to_pp (pretty_printer *pp) const @@ -267,6 +235,24 @@ bit_range::dump () const pp_flush (&pp); } +/* If OTHER is a subset of this, return true and write + to *OUT the relative range of OTHER within this. + Otherwise return false. */ + +bool +bit_range::contains_p (const bit_range &other, bit_range *out) const +{ + if (contains_p (other.get_start_bit_offset ()) + && contains_p (other.get_last_bit_offset ())) + { + out->m_start_bit_offset = other.m_start_bit_offset - m_start_bit_offset; + out->m_size_in_bits = other.m_size_in_bits; + return true; + } + else + return false; +} + int bit_range::cmp (const bit_range &br1, const bit_range &br2) { @@ -371,15 +357,57 @@ byte_range::dump_to_pp (pretty_printer *pp) const } } +/* Dump this object to stderr. */ + +DEBUG_FUNCTION void +byte_range::dump () const +{ + pretty_printer pp; + pp.buffer->stream = stderr; + dump_to_pp (&pp); + pp_newline (&pp); + pp_flush (&pp); +} + +/* If OTHER is a subset of this, return true and write + to *OUT the relative range of OTHER within this. + Otherwise return false. */ + +bool +byte_range::contains_p (const byte_range &other, byte_range *out) const +{ + if (contains_p (other.get_start_byte_offset ()) + && contains_p (other.get_last_byte_offset ())) + { + out->m_start_byte_offset = other.m_start_byte_offset - m_start_byte_offset; + out->m_size_in_bytes = other.m_size_in_bytes; + return true; + } + else + return false; +} + +/* qsort comparator for byte ranges. */ + +int +byte_range::cmp (const byte_range &br1, const byte_range &br2) +{ + /* Order first by offset. */ + if (int start_cmp = wi::cmps (br1.m_start_byte_offset, + br2.m_start_byte_offset)) + return start_cmp; + + /* ...then by size. */ + return wi::cmpu (br1.m_size_in_bytes, br2.m_size_in_bytes); +} + /* class concrete_binding : public binding_key. */ /* Implementation of binding_key::dump_to_pp vfunc for concrete_binding. */ void -concrete_binding::dump_to_pp (pretty_printer *pp, bool simple) const +concrete_binding::dump_to_pp (pretty_printer *pp, bool) const { - binding_key::dump_to_pp (pp, simple); - pp_string (pp, ", "); m_bit_range.dump_to_pp (pp); } @@ -402,9 +430,6 @@ concrete_binding::cmp_ptr_ptr (const void *p1, const void *p2) const concrete_binding *b1 = *(const concrete_binding * const *)p1; const concrete_binding *b2 = *(const concrete_binding * const *)p2; - if (int kind_cmp = b1->get_kind () - b2->get_kind ()) - return kind_cmp; - return bit_range::cmp (b1->m_bit_range, b2->m_bit_range); } @@ -413,8 +438,8 @@ concrete_binding::cmp_ptr_ptr (const void *p1, const void *p2) void symbolic_binding::dump_to_pp (pretty_printer *pp, bool simple) const { - binding_key::dump_to_pp (pp, simple); - pp_string (pp, ", region: "); + //binding_key::dump_to_pp (pp, simple); + pp_string (pp, "region: "); m_region->dump_to_pp (pp, simple); } @@ -426,9 +451,6 @@ symbolic_binding::cmp_ptr_ptr (const void *p1, const void *p2) const symbolic_binding *b1 = *(const symbolic_binding * const *)p1; const symbolic_binding *b2 = *(const symbolic_binding * const *)p2; - if (int kind_cmp = b1->get_kind () - b2->get_kind ()) - return kind_cmp; - return region::cmp_ids (b1->get_region (), b2->get_region ()); } @@ -777,8 +799,7 @@ binding_map::apply_ctor_val_to_range (const region *parent_reg, return false; bit_offset_t start_bit_offset = min_offset.get_bit_offset (); store_manager *smgr = mgr->get_store_manager (); - const binding_key *max_element_key - = binding_key::make (smgr, max_element, BK_direct); + const binding_key *max_element_key = binding_key::make (smgr, max_element); if (max_element_key->symbolic_p ()) return false; const concrete_binding *max_element_ckey @@ -786,8 +807,7 @@ binding_map::apply_ctor_val_to_range (const region *parent_reg, bit_size_t range_size_in_bits = max_element_ckey->get_next_bit_offset () - start_bit_offset; const concrete_binding *range_key - = smgr->get_concrete_binding (start_bit_offset, range_size_in_bits, - BK_direct); + = smgr->get_concrete_binding (start_bit_offset, range_size_in_bits); if (range_key->symbolic_p ()) return false; @@ -819,8 +839,7 @@ binding_map::apply_ctor_pair_to_child_region (const region *parent_reg, { const svalue *sval = get_svalue_for_ctor_val (val, mgr); const binding_key *k - = binding_key::make (mgr->get_store_manager (), child_reg, - BK_direct); + = binding_key::make (mgr->get_store_manager (), child_reg); /* Handle the case where we have an unknown size for child_reg (e.g. due to it being a trailing field with incomplete array type. */ @@ -844,7 +863,7 @@ binding_map::apply_ctor_pair_to_child_region (const region *parent_reg, - parent_base_offset.get_bit_offset ()); /* Create a concrete key for the child within the parent. */ k = mgr->get_store_manager ()->get_concrete_binding - (child_parent_offset, sval_bit_size, BK_direct); + (child_parent_offset, sval_bit_size); } gcc_assert (k->concrete_p ()); put (k, sval); @@ -852,6 +871,166 @@ binding_map::apply_ctor_pair_to_child_region (const region *parent_reg, } } +/* Populate OUT with all bindings within this map that overlap KEY. */ + +void +binding_map::get_overlapping_bindings (const binding_key *key, + auto_vec *out) +{ + for (auto iter : *this) + { + const binding_key *iter_key = iter.first; + if (const concrete_binding *ckey + = key->dyn_cast_concrete_binding ()) + { + if (const concrete_binding *iter_ckey + = iter_key->dyn_cast_concrete_binding ()) + { + if (ckey->overlaps_p (*iter_ckey)) + out->safe_push (iter_key); + } + else + { + /* Assume overlap. */ + out->safe_push (iter_key); + } + } + else + { + /* Assume overlap. */ + out->safe_push (iter_key); + } + } +} + +/* Remove, truncate, and/or split any bindings within this map that + overlap DROP_KEY. + + For example, if we have: + + +------------------------------------+ + | old binding | + +------------------------------------+ + + which is to be overwritten with: + + .......+----------------------+....... + .......| new binding |....... + .......+----------------------+....... + + this function "cuts a hole" out of the old binding: + + +------+......................+------+ + |prefix| hole for new binding |suffix| + +------+......................+------+ + + into which the new binding can be added without + overlapping the prefix or suffix. + + The prefix and suffix (if added) will be bound to the pertinent + parts of the value of the old binding. + + For example, given: + struct s5 + { + char arr[8]; + }; + void test_5 (struct s5 *p) + { + struct s5 f = *p; + f.arr[3] = 42; + } + then after the "f = *p;" we have: + cluster for: f: INIT_VAL((*INIT_VAL(p_33(D)))) + and at the "f.arr[3] = 42;" we remove the bindings overlapping + "f.arr[3]", replacing it with a prefix (bytes 0-2) and suffix (bytes 4-7) + giving: + cluster for: f + key: {bytes 0-2} + value: {BITS_WITHIN(bytes 0-2, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))} + key: {bytes 4-7} + value: {BITS_WITHIN(bytes 4-7, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))} + punching a hole into which the new value can be written at byte 3: + cluster for: f + key: {bytes 0-2} + value: {BITS_WITHIN(bytes 0-2, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))} + key: {byte 3} + value: 'char' {(char)42} + key: {bytes 4-7} + value: {BITS_WITHIN(bytes 4-7, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))} + + If UNCERTAINTY is non-NULL, use it to record any svalues that + were removed, as being maybe-bound. */ + +void +binding_map::remove_overlapping_bindings (store_manager *mgr, + const binding_key *drop_key, + uncertainty_t *uncertainty) +{ + auto_vec bindings; + get_overlapping_bindings (drop_key, &bindings); + + unsigned i; + const binding_key *iter_binding; + FOR_EACH_VEC_ELT (bindings, i, iter_binding) + { + const svalue *old_sval = get (iter_binding); + if (uncertainty) + uncertainty->on_maybe_bound_sval (old_sval); + + /* Begin by removing the old binding. */ + m_map.remove (iter_binding); + + /* Now potentially add the prefix and suffix. */ + if (const concrete_binding *drop_ckey + = drop_key->dyn_cast_concrete_binding ()) + if (const concrete_binding *iter_ckey + = iter_binding->dyn_cast_concrete_binding ()) + { + gcc_assert (drop_ckey->overlaps_p (*iter_ckey)); + + const bit_range &drop_bits = drop_ckey->get_bit_range (); + const bit_range &iter_bits = iter_ckey->get_bit_range (); + + if (iter_bits.get_start_bit_offset () + < drop_bits.get_start_bit_offset ()) + { + /* We have a truncated prefix. */ + bit_range prefix_bits (iter_bits.get_start_bit_offset (), + (drop_bits.get_start_bit_offset () + - iter_bits.get_start_bit_offset ())); + const concrete_binding *prefix_key + = mgr->get_concrete_binding (prefix_bits); + bit_range rel_prefix (0, prefix_bits.m_size_in_bits); + const svalue *prefix_sval + = old_sval->extract_bit_range (NULL_TREE, + rel_prefix, + mgr->get_svalue_manager ()); + m_map.put (prefix_key, prefix_sval); + } + + if (iter_bits.get_next_bit_offset () + > drop_bits.get_next_bit_offset ()) + { + /* We have a truncated suffix. */ + bit_range suffix_bits (drop_bits.get_next_bit_offset (), + (iter_bits.get_next_bit_offset () + - drop_bits.get_next_bit_offset ())); + const concrete_binding *suffix_key + = mgr->get_concrete_binding (suffix_bits); + bit_range rel_suffix (drop_bits.get_next_bit_offset () + - iter_bits.get_start_bit_offset (), + suffix_bits.m_size_in_bits); + const svalue *suffix_sval + = old_sval->extract_bit_range (NULL_TREE, + rel_suffix, + mgr->get_svalue_manager ()); + m_map.put (suffix_key, suffix_sval); + } + } + } +} + /* class binding_cluster. */ /* binding_cluster's copy ctor. */ @@ -964,6 +1143,27 @@ binding_cluster::dump (bool simple) const pp_flush (&pp); } +/* Assert that this object is valid. */ + +void +binding_cluster::validate () const +{ + int num_symbolic = 0; + int num_concrete = 0; + for (auto iter : m_map) + { + if (iter.first->symbolic_p ()) + num_symbolic++; + else + num_concrete++; + } + /* We shouldn't have more than one symbolic key per cluster + (or one would have clobbered the other). */ + gcc_assert (num_symbolic < 2); + /* We can't have both concrete and symbolic keys. */ + gcc_assert (num_concrete == 0 || num_symbolic == 0); +} + /* Return a new json::object of the form {"escaped": true/false, "touched": true/false, @@ -986,8 +1186,7 @@ binding_cluster::to_json () const void binding_cluster::bind (store_manager *mgr, - const region *reg, const svalue *sval, - binding_kind kind) + const region *reg, const svalue *sval) { if (const compound_svalue *compound_sval = sval->dyn_cast_compound_svalue ()) @@ -996,7 +1195,7 @@ binding_cluster::bind (store_manager *mgr, return; } - const binding_key *binding = binding_key::make (mgr, reg, kind); + const binding_key *binding = binding_key::make (mgr, reg); bind_key (binding, sval); } @@ -1045,8 +1244,7 @@ binding_cluster::bind_compound_sval (store_manager *mgr, + reg_offset.get_bit_offset ()); const concrete_binding *effective_concrete_key = mgr->get_concrete_binding (effective_start, - concrete_key->get_size_in_bits (), - iter_key->get_kind ()); + concrete_key->get_size_in_bits ()); bind_key (effective_concrete_key, iter_sval); } else @@ -1069,31 +1267,35 @@ binding_cluster::purge_region (store_manager *mgr, const region *reg) { gcc_assert (reg->get_kind () == RK_DECL); const binding_key *binding - = binding_key::make (mgr, const_cast (reg), - BK_direct); + = binding_key::make (mgr, const_cast (reg)); m_map.remove (binding); } -/* Mark REG within this cluster as being filled with zeroes. - Remove all bindings, add a default binding to zero, and clear the - TOUCHED flag. */ +/* Clobber REG and fill it with repeated copies of SVAL. */ void -binding_cluster::zero_fill_region (store_manager *mgr, const region *reg) +binding_cluster::fill_region (store_manager *mgr, + const region *reg, + const svalue *sval) { clobber_region (mgr, reg); - /* Add a default binding to zero. */ region_model_manager *sval_mgr = mgr->get_svalue_manager (); - const svalue *cst_sval - = sval_mgr->get_or_create_int_cst (integer_type_node, 0); - const svalue *bound_sval = cst_sval; - if (reg->get_type ()) - bound_sval = sval_mgr->get_or_create_unaryop (reg->get_type (), NOP_EXPR, - cst_sval); - bind (mgr, reg, bound_sval, BK_default); + const svalue *byte_size_sval = reg->get_byte_size_sval (sval_mgr); + const svalue *fill_sval + = sval_mgr->get_or_create_repeated_svalue (reg->get_type (), + byte_size_sval, sval); + bind (mgr, reg, fill_sval); +} + +/* Clobber REG within this cluster and fill it with zeroes. */ - m_touched = false; +void +binding_cluster::zero_fill_region (store_manager *mgr, const region *reg) +{ + region_model_manager *sval_mgr = mgr->get_svalue_manager (); + const svalue *zero_sval = sval_mgr->get_or_create_int_cst (char_type_node, 0); + fill_region (mgr, reg, zero_sval); } /* Mark REG within this cluster as being unknown. @@ -1111,7 +1313,7 @@ binding_cluster::mark_region_as_unknown (store_manager *mgr, region_model_manager *sval_mgr = mgr->get_svalue_manager (); const svalue *sval = sval_mgr->get_or_create_unknown_svalue (reg->get_type ()); - bind (mgr, reg, sval, BK_default); + bind (mgr, reg, sval); } /* Get any SVAL bound to REG within this cluster via kind KIND, @@ -1119,10 +1321,9 @@ binding_cluster::mark_region_as_unknown (store_manager *mgr, const svalue * binding_cluster::get_binding (store_manager *mgr, - const region *reg, - binding_kind kind) const + const region *reg) const { - const binding_key *reg_binding = binding_key::make (mgr, reg, kind); + const binding_key *reg_binding = binding_key::make (mgr, reg); const svalue *sval = m_map.get (reg_binding); if (sval) { @@ -1140,7 +1341,7 @@ binding_cluster::get_binding (store_manager *mgr, while (const region *parent_reg = reg->get_parent_region ()) { const binding_key *parent_reg_binding - = binding_key::make (mgr, parent_reg, kind); + = binding_key::make (mgr, parent_reg); if (parent_reg_binding == reg_binding && sval->get_type () && reg->get_type () @@ -1161,7 +1362,7 @@ binding_cluster::get_binding (store_manager *mgr, FOR_EACH_VEC_ELT_REVERSE (regions, i, iter_reg) { region_model_manager *rmm_mgr = mgr->get_svalue_manager (); - sval = rmm_mgr->get_or_create_sub_svalue (reg->get_type (), + sval = rmm_mgr->get_or_create_sub_svalue (iter_reg->get_type (), sval, iter_reg); } } @@ -1169,21 +1370,20 @@ binding_cluster::get_binding (store_manager *mgr, return sval; } -/* Get any SVAL bound to REG within this cluster via kind KIND, +/* Get any SVAL bound to REG within this cluster, either directly for REG, or recursively checking for bindings within parent regions and extracting subvalues if need be. */ const svalue * binding_cluster::get_binding_recursive (store_manager *mgr, - const region *reg, - enum binding_kind kind) const + const region *reg) const { - if (const svalue *sval = get_binding (mgr, reg, kind)) + if (const svalue *sval = get_binding (mgr, reg)) return sval; if (reg != m_base_region) if (const region *parent_reg = reg->get_parent_region ()) if (const svalue *parent_sval - = get_binding_recursive (mgr, parent_reg, kind)) + = get_binding_recursive (mgr, parent_reg)) { /* Extract child svalue from parent svalue. */ region_model_manager *rmm_mgr = mgr->get_svalue_manager (); @@ -1199,18 +1399,11 @@ const svalue * binding_cluster::get_any_binding (store_manager *mgr, const region *reg) const { - /* Look for a "direct" binding. */ + /* Look for a direct binding. */ if (const svalue *direct_sval - = get_binding_recursive (mgr, reg, BK_direct)) + = get_binding_recursive (mgr, reg)) return direct_sval; - /* Look for a "default" binding, but not if there's been a symbolic - write. */ - if (!m_touched) - if (const svalue *default_sval - = get_binding_recursive (mgr, reg, BK_default)) - return default_sval; - /* If this cluster has been touched by a symbolic write, then the content of any subregion not currently specifically bound is "UNKNOWN". */ if (m_touched) @@ -1251,8 +1444,6 @@ const svalue * binding_cluster::maybe_get_compound_binding (store_manager *mgr, const region *reg) const { - binding_map map; - region_offset cluster_offset = m_base_region->get_offset (); if (cluster_offset.symbolic_p ()) return NULL; @@ -1260,6 +1451,36 @@ binding_cluster::maybe_get_compound_binding (store_manager *mgr, if (reg_offset.symbolic_p ()) return NULL; + region_model_manager *sval_mgr = mgr->get_svalue_manager (); + + /* We will a build the result map in two parts: + (a) result_map, holding the concrete keys from this cluster, + + (b) default_map, holding the initial values for the region + (e.g. uninitialized, initializer values, or zero), unless this + cluster has been touched. + + We will populate (a), and as we do, clobber (b), trimming and + splitting its bindings as necessary. + Finally, we will merge (b) into (a), giving a concrete map + that merges both the initial values and the bound values from + the binding_cluster. + Doing it this way reduces N for the O(N^2) intersection-finding, + perhaps we should have a spatial-organized data structure for + concrete keys, though. */ + + binding_map result_map; + binding_map default_map; + + /* Set up default values in default_map. */ + const svalue *default_sval; + if (m_touched) + default_sval = sval_mgr->get_or_create_unknown_svalue (reg->get_type ()); + else + default_sval = sval_mgr->get_or_create_initial_value (reg); + const binding_key *default_key = binding_key::make (mgr, reg); + default_map.put (default_key, default_sval); + for (map_t::iterator iter = m_map.begin (); iter != m_map.end (); ++iter) { const binding_key *key = (*iter).first; @@ -1268,78 +1489,77 @@ binding_cluster::maybe_get_compound_binding (store_manager *mgr, if (const concrete_binding *concrete_key = key->dyn_cast_concrete_binding ()) { - /* Skip bindings that are outside the bit range of REG. */ - if (concrete_key->get_start_bit_offset () - < reg_offset.get_bit_offset ()) - continue; - bit_size_t reg_bit_size; - if (reg->get_bit_size (®_bit_size)) - if (concrete_key->get_start_bit_offset () - >= reg_offset.get_bit_offset () + reg_bit_size) - continue; - - /* Get offset of KEY relative to REG, rather than to - the cluster. */ - bit_offset_t relative_start - = (concrete_key->get_start_bit_offset () - - reg_offset.get_bit_offset ()); - const concrete_binding *offset_concrete_key - = mgr->get_concrete_binding (relative_start, - concrete_key->get_size_in_bits (), - key->get_kind ()); - map.put (offset_concrete_key, sval); - } - else - return NULL; - } + const bit_range &bound_range = concrete_key->get_bit_range (); - if (map.elements () == 0) - return NULL; + bit_size_t reg_bit_size; + if (!reg->get_bit_size (®_bit_size)) + return NULL; - region_model_manager *sval_mgr = mgr->get_svalue_manager (); - return sval_mgr->get_or_create_compound_svalue (reg->get_type (), map); -} + bit_range reg_range (reg_offset.get_bit_offset (), + reg_bit_size); + /* Skip bindings that are outside the bit range of REG. */ + if (!bound_range.intersects_p (reg_range)) + continue; -/* Populate OUT with all bindings within this cluster that overlap REG. */ + /* We shouldn't have an exact match; that should have been + handled already. */ + gcc_assert (!(reg_range == bound_range)); -void -binding_cluster::get_overlapping_bindings (store_manager *mgr, - const region *reg, - auto_vec *out) -{ - const binding_key *binding - = binding_key::make (mgr, reg, BK_direct); - for (map_t::iterator iter = m_map.begin (); - iter != m_map.end (); ++iter) - { - const binding_key *iter_key = (*iter).first; - if (const concrete_binding *ckey - = binding->dyn_cast_concrete_binding ()) - { - if (const concrete_binding *iter_ckey - = iter_key->dyn_cast_concrete_binding ()) + bit_range subrange (0, 0); + if (reg_range.contains_p (bound_range, &subrange)) { - if (ckey->overlaps_p (*iter_ckey)) - out->safe_push (iter_key); + /* We have a bound range fully within REG. + Add it to map, offsetting accordingly. */ + + /* Get offset of KEY relative to REG, rather than to + the cluster. */ + const concrete_binding *offset_concrete_key + = mgr->get_concrete_binding (subrange); + result_map.put (offset_concrete_key, sval); + + /* Clobber default_map, removing/trimming/spliting where + it overlaps with offset_concrete_key. */ + default_map.remove_overlapping_bindings (mgr, + offset_concrete_key, + NULL); + } + else if (bound_range.contains_p (reg_range, &subrange)) + { + /* REG is fully within the bound range, but + is not equal to it; we're extracting a subvalue. */ + return sval->extract_bit_range (reg->get_type (), + subrange, + mgr->get_svalue_manager ()); } else { - /* Assume overlap. */ - out->safe_push (iter_key); + /* REG and the bound range partially overlap. + We don't handle this case yet. */ + return NULL; } } else - { - /* Assume overlap. */ - out->safe_push (iter_key); - } + /* Can't handle symbolic bindings. */ + return NULL; + } + + if (result_map.elements () == 0) + return NULL; + + /* Merge any bindings from default_map into result_map. */ + for (auto iter : default_map) + { + const binding_key *key = iter.first; + const svalue *sval = iter.second; + result_map.put (key, sval); } + + return sval_mgr->get_or_create_compound_svalue (reg->get_type (), result_map); } -/* Remove any bindings within this cluster that overlap REG, - but retain default bindings that overlap but aren't fully covered - by REG. +/* Remove, truncate, and/or split any bindings within this map that + overlap REG. If UNCERTAINTY is non-NULL, use it to record any svalues that were removed, as being maybe-bound. */ @@ -1348,26 +1568,9 @@ binding_cluster::remove_overlapping_bindings (store_manager *mgr, const region *reg, uncertainty_t *uncertainty) { - auto_vec bindings; - get_overlapping_bindings (mgr, reg, &bindings); + const binding_key *reg_binding = binding_key::make (mgr, reg); - unsigned i; - const binding_key *iter_binding; - FOR_EACH_VEC_ELT (bindings, i, iter_binding) - { - /* Don't remove default bindings, unless the default binding - is fully covered by REG. */ - if (iter_binding->get_kind () == BK_default) - { - const binding_key *reg_binding - = binding_key::make (mgr, reg, BK_default); - if (reg_binding != iter_binding) - continue; - } - if (uncertainty) - uncertainty->on_maybe_bound_sval (m_map.get (iter_binding)); - m_map.remove (iter_binding); - } + m_map.remove_overlapping_bindings (mgr, reg_binding, uncertainty); } /* Attempt to merge CLUSTER_A and CLUSTER_B into OUT_CLUSTER, using @@ -1428,6 +1631,8 @@ binding_cluster::can_merge_p (const binding_cluster *cluster_a, const binding_key *key_b = (*iter_b).first; keys.add (key_b); } + int num_symbolic_keys = 0; + int num_concrete_keys = 0; for (hash_set::iterator iter = keys.begin (); iter != keys.end (); ++iter) { @@ -1435,6 +1640,11 @@ binding_cluster::can_merge_p (const binding_cluster *cluster_a, const svalue *sval_a = cluster_a->get_any_value (key); const svalue *sval_b = cluster_b->get_any_value (key); + if (key->symbolic_p ()) + num_symbolic_keys++; + else + num_concrete_keys++; + if (sval_a == sval_b) { gcc_assert (sval_a); @@ -1463,29 +1673,15 @@ binding_cluster::can_merge_p (const binding_cluster *cluster_a, out_cluster->m_map.put (key, unknown_sval); } - /* Handle the case where we get a default binding from one and a direct - binding from the other. */ - auto_vec duplicate_keys; - for (map_t::iterator iter = out_cluster->m_map.begin (); - iter != out_cluster->m_map.end (); ++iter) - { - const concrete_binding *ckey - = (*iter).first->dyn_cast_concrete_binding (); - if (!ckey) - continue; - if (ckey->get_kind () != BK_direct) - continue; - const concrete_binding *def_ckey - = mgr->get_concrete_binding (ckey->get_start_bit_offset (), - ckey->get_size_in_bits (), - BK_default); - if (out_cluster->m_map.get (def_ckey)) - duplicate_keys.safe_push (def_ckey); + /* We can only have at most one symbolic key per cluster, + and if we do, we can't have any concrete keys. + If this happens, mark the cluster as touched, with no keys. */ + if (num_symbolic_keys >= 2 + || (num_concrete_keys > 0 && num_symbolic_keys > 0)) + { + out_cluster->m_touched = true; + out_cluster->m_map.empty (); } - unsigned i; - const concrete_binding *key; - FOR_EACH_VEC_ELT (duplicate_keys, i, key) - out_cluster->m_map.remove (key); /* We don't handle other kinds of overlaps yet. */ @@ -1558,7 +1754,7 @@ binding_cluster::on_unknown_fncall (const gcall *call, const svalue *sval = mgr->get_svalue_manager ()->get_or_create_conjured_svalue (m_base_region->get_type (), call, m_base_region); - bind (mgr, m_base_region, sval, BK_direct); + bind (mgr, m_base_region, sval); m_touched = true; } @@ -1665,7 +1861,7 @@ binding_cluster::maybe_get_simple_value (store_manager *mgr) const if (m_map.elements () != 1) return NULL; - const binding_key *key = binding_key::make (mgr, m_base_region, BK_direct); + const binding_key *key = binding_key::make (mgr, m_base_region); return get_any_value (key); } @@ -1675,10 +1871,9 @@ binding_cluster::maybe_get_simple_value (store_manager *mgr) const const concrete_binding * store_manager::get_concrete_binding (bit_offset_t start_bit_offset, - bit_offset_t size_in_bits, - enum binding_kind kind) + bit_offset_t size_in_bits) { - concrete_binding b (start_bit_offset, size_in_bits, kind); + concrete_binding b (start_bit_offset, size_in_bits); if (concrete_binding *existing = m_concrete_binding_key_mgr.get (b)) return existing; @@ -1688,10 +1883,9 @@ store_manager::get_concrete_binding (bit_offset_t start_bit_offset, } const symbolic_binding * -store_manager::get_symbolic_binding (const region *reg, - enum binding_kind kind) +store_manager::get_symbolic_binding (const region *reg) { - symbolic_binding b (reg, kind); + symbolic_binding b (reg); if (symbolic_binding *existing = m_symbolic_binding_key_mgr.get (b)) return existing; @@ -1952,6 +2146,15 @@ store::dump (bool simple) const pp_flush (&pp); } +/* Assert that this object is valid. */ + +void +store::validate () const +{ + for (auto iter : m_cluster_map) + iter.second->validate (); +} + /* Return a new json::object of the form {PARENT_REGION_DESC: {BASE_REGION_DESC: object for binding_map, ... for each cluster within parent region}, @@ -2027,7 +2230,7 @@ store::get_any_binding (store_manager *mgr, const region *reg) const void store::set_value (store_manager *mgr, const region *lhs_reg, - const svalue *rhs_sval, enum binding_kind kind, + const svalue *rhs_sval, uncertainty_t *uncertainty) { remove_overlapping_bindings (mgr, lhs_reg); @@ -2054,7 +2257,7 @@ store::set_value (store_manager *mgr, const region *lhs_reg, else { lhs_cluster = get_or_create_cluster (lhs_base_reg); - lhs_cluster->bind (mgr, lhs_reg, rhs_sval, kind); + lhs_cluster->bind (mgr, lhs_reg, rhs_sval); } /* Bindings to a cluster can affect other clusters if a symbolic @@ -2209,16 +2412,26 @@ store::purge_region (store_manager *mgr, const region *reg) } } -/* Zero-fill REG. */ +/* Fill REG with SVAL. */ void -store::zero_fill_region (store_manager *mgr, const region *reg) +store::fill_region (store_manager *mgr, const region *reg, const svalue *sval) { const region *base_reg = reg->get_base_region (); if (base_reg->symbolic_for_unknown_ptr_p ()) return; binding_cluster *cluster = get_or_create_cluster (base_reg); - cluster->zero_fill_region (mgr, reg); + cluster->fill_region (mgr, reg, sval); +} + +/* Zero-fill REG. */ + +void +store::zero_fill_region (store_manager *mgr, const region *reg) +{ + region_model_manager *sval_mgr = mgr->get_svalue_manager (); + const svalue *zero_sval = sval_mgr->get_or_create_int_cst (char_type_node, 0); + fill_region (mgr, reg, zero_sval); } /* Mark REG as having unknown content. */ @@ -2740,26 +2953,18 @@ test_binding_key_overlap () store_manager mgr (NULL); /* Various 8-bit bindings. */ - const concrete_binding *cb_0_7 - = mgr.get_concrete_binding (0, 8, BK_direct); - const concrete_binding *cb_8_15 - = mgr.get_concrete_binding (8, 8, BK_direct); - const concrete_binding *cb_16_23 - = mgr.get_concrete_binding (16, 8, BK_direct); - const concrete_binding *cb_24_31 - = mgr.get_concrete_binding (24, 8, BK_direct); + const concrete_binding *cb_0_7 = mgr.get_concrete_binding (0, 8); + const concrete_binding *cb_8_15 = mgr.get_concrete_binding (8, 8); + const concrete_binding *cb_16_23 = mgr.get_concrete_binding (16, 8); + const concrete_binding *cb_24_31 = mgr.get_concrete_binding (24, 8); /* 16-bit bindings. */ - const concrete_binding *cb_0_15 - = mgr.get_concrete_binding (0, 16, BK_direct); - const concrete_binding *cb_8_23 - = mgr.get_concrete_binding (8, 16, BK_direct); - const concrete_binding *cb_16_31 - = mgr.get_concrete_binding (16, 16, BK_direct); + const concrete_binding *cb_0_15 = mgr.get_concrete_binding (0, 16); + const concrete_binding *cb_8_23 = mgr.get_concrete_binding (8, 16); + const concrete_binding *cb_16_31 = mgr.get_concrete_binding (16, 16); /* 32-bit binding. */ - const concrete_binding *cb_0_31 - = mgr.get_concrete_binding (0, 32, BK_direct); + const concrete_binding *cb_0_31 = mgr.get_concrete_binding (0, 32); /* Everything should self-overlap. */ ASSERT_OVERLAP (cb_0_7, cb_0_7); diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h index e0c60e1..2ac2923 100644 --- a/gcc/analyzer/store.h +++ b/gcc/analyzer/store.h @@ -199,29 +199,6 @@ private: class byte_range; class concrete_binding; -/* An enum for discriminating between "direct" vs "default" levels of - mapping. */ - -enum binding_kind -{ - /* Special-case value for hash support. - This is the initial entry, so that hash traits can have - empty_zero_p = true. */ - BK_empty = 0, - - /* Special-case value for hash support. */ - BK_deleted, - - /* The normal kind of mapping. */ - BK_direct, - - /* A lower-priority kind of mapping, for use when inheriting - default values from a parent region. */ - BK_default -}; - -extern const char *binding_kind_to_string (enum binding_kind kind); - /* Abstract base class for describing ranges of bits within a binding_map that can have svalues bound to them. */ @@ -232,10 +209,9 @@ public: virtual bool concrete_p () const = 0; bool symbolic_p () const { return !concrete_p (); } - static const binding_key *make (store_manager *mgr, const region *r, - enum binding_kind kind); + static const binding_key *make (store_manager *mgr, const region *r); - virtual void dump_to_pp (pretty_printer *pp, bool simple) const; + virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0; void dump (bool simple) const; label_text get_desc (bool simple=true) const; @@ -244,28 +220,6 @@ public: virtual const concrete_binding *dyn_cast_concrete_binding () const { return NULL; } - - enum binding_kind get_kind () const { return m_kind; } - - void mark_deleted () { m_kind = BK_deleted; } - void mark_empty () { m_kind = BK_empty; } - bool is_deleted () const { return m_kind == BK_deleted; } - bool is_empty () const { return m_kind == BK_empty; } - -protected: - binding_key (enum binding_kind kind) : m_kind (kind) {} - - hashval_t impl_hash () const - { - return m_kind; - } - bool impl_eq (const binding_key &other) const - { - return m_kind == other.m_kind; - } - -private: - enum binding_kind m_kind; }; /* A concrete range of bits. */ @@ -288,6 +242,10 @@ struct bit_range { return m_start_bit_offset + m_size_in_bits; } + bit_offset_t get_last_bit_offset () const + { + return get_next_bit_offset () - 1; + } bool contains_p (bit_offset_t offset) const { @@ -295,6 +253,8 @@ struct bit_range && offset < get_next_bit_offset ()); } + bool contains_p (const bit_range &other, bit_range *out) const; + bool operator== (const bit_range &other) const { return (m_start_bit_offset == other.m_start_bit_offset @@ -327,12 +287,42 @@ struct byte_range {} void dump_to_pp (pretty_printer *pp) const; + void dump () const; + + bool contains_p (byte_offset_t offset) const + { + return (offset >= get_start_byte_offset () + && offset < get_next_byte_offset ()); + } + bool contains_p (const byte_range &other, byte_range *out) const; + + bool operator== (const byte_range &other) const + { + return (m_start_byte_offset == other.m_start_byte_offset + && m_size_in_bytes == other.m_size_in_bytes); + } + byte_offset_t get_start_byte_offset () const + { + return m_start_byte_offset; + } + byte_offset_t get_next_byte_offset () const + { + return m_start_byte_offset + m_size_in_bytes; + } byte_offset_t get_last_byte_offset () const { return m_start_byte_offset + m_size_in_bytes - 1; } + bit_range as_bit_range () const + { + return bit_range (m_start_byte_offset * BITS_PER_UNIT, + m_size_in_bytes * BITS_PER_UNIT); + } + + static int cmp (const byte_range &br1, const byte_range &br2); + byte_offset_t m_start_byte_offset; byte_size_t m_size_in_bytes; }; @@ -346,10 +336,8 @@ public: /* This class is its own key for the purposes of consolidation. */ typedef concrete_binding key_t; - concrete_binding (bit_offset_t start_bit_offset, bit_size_t size_in_bits, - enum binding_kind kind) - : binding_key (kind), - m_bit_range (start_bit_offset, size_in_bits) + concrete_binding (bit_offset_t start_bit_offset, bit_size_t size_in_bits) + : m_bit_range (start_bit_offset, size_in_bits) {} bool concrete_p () const FINAL OVERRIDE { return true; } @@ -358,12 +346,10 @@ public: inchash::hash hstate; hstate.add_wide_int (m_bit_range.m_start_bit_offset); hstate.add_wide_int (m_bit_range.m_size_in_bits); - return hstate.end () ^ binding_key::impl_hash (); + return hstate.end (); } bool operator== (const concrete_binding &other) const { - if (!binding_key::impl_eq (other)) - return false; return m_bit_range == other.m_bit_range; } @@ -392,6 +378,11 @@ public: static int cmp_ptr_ptr (const void *, const void *); + void mark_deleted () { m_bit_range.m_start_bit_offset = -1; } + void mark_empty () { m_bit_range.m_start_bit_offset = -2; } + bool is_deleted () const { return m_bit_range.m_start_bit_offset == -1; } + bool is_empty () const { return m_bit_range.m_start_bit_offset == -2; } + private: bit_range m_bit_range; }; @@ -401,7 +392,7 @@ private: template <> struct default_hash_traits : public member_function_hash_traits { - static const bool empty_zero_p = true; + static const bool empty_zero_p = false; }; namespace ana { @@ -415,21 +406,16 @@ public: /* This class is its own key for the purposes of consolidation. */ typedef symbolic_binding key_t; - symbolic_binding (const region *region, enum binding_kind kind) - : binding_key (kind), - m_region (region) - {} + symbolic_binding (const region *region) : m_region (region) {} bool concrete_p () const FINAL OVERRIDE { return false; } hashval_t hash () const { - return (binding_key::impl_hash () ^ (intptr_t)m_region); + return (intptr_t)m_region; } bool operator== (const symbolic_binding &other) const { - if (!binding_key::impl_eq (other)) - return false; - return (m_region == other.m_region); + return m_region == other.m_region; } void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; @@ -438,6 +424,12 @@ public: static int cmp_ptr_ptr (const void *, const void *); + void mark_deleted () { m_region = reinterpret_cast (1); } + void mark_empty () { m_region = NULL; } + bool is_deleted () const + { return m_region == reinterpret_cast (1); } + bool is_empty () const { return m_region == NULL; } + private: const region *m_region; }; @@ -504,7 +496,13 @@ public: static int cmp (const binding_map &map1, const binding_map &map2); + void remove_overlapping_bindings (store_manager *mgr, + const binding_key *drop_key, + uncertainty_t *uncertainty); + private: + void get_overlapping_bindings (const binding_key *key, + auto_vec *out); bool apply_ctor_val_to_range (const region *parent_reg, region_model_manager *mgr, tree min_index, tree max_index, @@ -553,22 +551,22 @@ public: void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const; void dump (bool simple) const; + void validate () const; + json::object *to_json () const; - void bind (store_manager *mgr, const region *, const svalue *, - binding_kind kind); + void bind (store_manager *mgr, const region *, const svalue *); void clobber_region (store_manager *mgr, const region *reg); void purge_region (store_manager *mgr, const region *reg); + void fill_region (store_manager *mgr, const region *reg, const svalue *sval); void zero_fill_region (store_manager *mgr, const region *reg); void mark_region_as_unknown (store_manager *mgr, const region *reg, uncertainty_t *uncertainty); - const svalue *get_binding (store_manager *mgr, const region *reg, - binding_kind kind) const; + const svalue *get_binding (store_manager *mgr, const region *reg) const; const svalue *get_binding_recursive (store_manager *mgr, - const region *reg, - enum binding_kind kind) const; + const region *reg) const; const svalue *get_any_binding (store_manager *mgr, const region *reg) const; const svalue *maybe_get_compound_binding (store_manager *mgr, @@ -630,8 +628,6 @@ public: private: const svalue *get_any_value (const binding_key *key) const; - void get_overlapping_bindings (store_manager *mgr, const region *reg, - auto_vec *out); void bind_compound_sval (store_manager *mgr, const region *reg, const compound_svalue *compound_sval); @@ -684,6 +680,8 @@ public: void dump (bool simple) const; void summarize_to_pp (pretty_printer *pp, bool simple) const; + void validate () const; + json::object *to_json () const; const svalue *get_any_binding (store_manager *mgr, const region *reg) const; @@ -691,10 +689,11 @@ public: bool called_unknown_fn_p () const { return m_called_unknown_fn; } void set_value (store_manager *mgr, const region *lhs_reg, - const svalue *rhs_sval, enum binding_kind kind, + const svalue *rhs_sval, uncertainty_t *uncertainty); void clobber_region (store_manager *mgr, const region *reg); void purge_region (store_manager *mgr, const region *reg); + void fill_region (store_manager *mgr, const region *reg, const svalue *sval); void zero_fill_region (store_manager *mgr, const region *reg); void mark_region_as_unknown (store_manager *mgr, const region *reg, uncertainty_t *uncertainty); @@ -773,19 +772,15 @@ public: /* binding consolidation. */ const concrete_binding * get_concrete_binding (bit_offset_t start_bit_offset, - bit_offset_t size_in_bits, - enum binding_kind kind); + bit_offset_t size_in_bits); const concrete_binding * - get_concrete_binding (const bit_range &bits, - enum binding_kind kind) + get_concrete_binding (const bit_range &bits) { return get_concrete_binding (bits.get_start_bit_offset (), - bits.m_size_in_bits, - kind); + bits.m_size_in_bits); } const symbolic_binding * - get_symbolic_binding (const region *region, - enum binding_kind kind); + get_symbolic_binding (const region *region); region_model_manager *get_svalue_manager () const { diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc index a16563d..6c8afef 100644 --- a/gcc/analyzer/svalue.cc +++ b/gcc/analyzer/svalue.cc @@ -415,6 +415,27 @@ svalue::cmp_ptr (const svalue *sval1, const svalue *sval2) sub_sval2->get_subregion ()); } break; + case SK_REPEATED: + { + const repeated_svalue *repeated_sval1 = (const repeated_svalue *)sval1; + const repeated_svalue *repeated_sval2 = (const repeated_svalue *)sval2; + return svalue::cmp_ptr (repeated_sval1->get_inner_svalue (), + repeated_sval2->get_inner_svalue ()); + } + break; + case SK_BITS_WITHIN: + { + const bits_within_svalue *bits_within_sval1 + = (const bits_within_svalue *)sval1; + const bits_within_svalue *bits_within_sval2 + = (const bits_within_svalue *)sval2; + if (int cmp = bit_range::cmp (bits_within_sval1->get_bits (), + bits_within_sval2->get_bits ())) + return cmp; + return svalue::cmp_ptr (bits_within_sval1->get_inner_svalue (), + bits_within_sval2->get_inner_svalue ()); + } + break; case SK_UNMERGEABLE: { const unmergeable_svalue *unmergeable_sval1 @@ -515,6 +536,27 @@ svalue::involves_p (const svalue *other) const return v.found_p (); } +/* Extract SUBRANGE from this value, of type TYPE. */ + +const svalue * +svalue::extract_bit_range (tree type, + const bit_range &subrange, + region_model_manager *mgr) const +{ + return mgr->get_or_create_bits_within (type, subrange, this); +} + +/* Base implementation of svalue::maybe_fold_bits_within vfunc. */ + +const svalue * +svalue::maybe_fold_bits_within (tree, + const bit_range &, + region_model_manager *) const +{ + /* By default, don't fold. */ + return NULL; +} + /* class region_svalue : public svalue. */ /* Implementation of svalue::dump_to_pp vfunc for region_svalue. */ @@ -680,6 +722,26 @@ constant_svalue::eval_condition (const constant_svalue *lhs, return tristate::TS_UNKNOWN; } +/* Implementation of svalue::maybe_fold_bits_within vfunc + for constant_svalue. */ + +const svalue * +constant_svalue::maybe_fold_bits_within (tree type, + const bit_range &, + region_model_manager *mgr) const +{ + /* Bits within an all-zero value are also all zero. */ + if (zerop (m_cst_expr)) + { + if (type) + return mgr->get_or_create_cast (type, this); + else + return this; + } + /* Otherwise, don't fold. */ + return NULL; +} + /* class unknown_svalue : public svalue. */ /* Implementation of svalue::dump_to_pp vfunc for unknown_svalue. */ @@ -711,6 +773,18 @@ unknown_svalue::accept (visitor *v) const v->visit_unknown_svalue (this); } +/* Implementation of svalue::maybe_fold_bits_within vfunc + for unknown_svalue. */ + +const svalue * +unknown_svalue::maybe_fold_bits_within (tree type, + const bit_range &, + region_model_manager *mgr) const +{ + /* Bits within an unknown_svalue are themselves unknown. */ + return mgr->get_or_create_unknown_svalue (type); +} + /* Get a string for KIND for use in debug dumps. */ const char * @@ -892,6 +966,34 @@ unaryop_svalue::implicitly_live_p (const svalue_set *live_svalues, return get_arg ()->live_p (live_svalues, model); } +/* Implementation of svalue::maybe_fold_bits_within vfunc + for unaryop_svalue. */ + +const svalue * +unaryop_svalue::maybe_fold_bits_within (tree type, + const bit_range &, + region_model_manager *mgr) const +{ + switch (m_op) + { + default: + break; + case NOP_EXPR: + /* A cast of zero is zero. */ + if (tree cst = m_arg->maybe_get_constant ()) + if (zerop (cst)) + { + if (type) + return mgr->get_or_create_cast (type, this); + else + return this; + } + break; + } + /* Otherwise, don't fold. */ + return NULL; +} + /* class binop_svalue : public svalue. */ /* Implementation of svalue::dump_to_pp vfunc for binop_svalue. */ @@ -995,6 +1097,216 @@ sub_svalue::implicitly_live_p (const svalue_set *live_svalues, return get_parent ()->live_p (live_svalues, model); } +/* class repeated_svalue : public svalue. */ + +/* repeated_svalue'c ctor. */ + +repeated_svalue::repeated_svalue (tree type, + const svalue *outer_size, + const svalue *inner_svalue) +: svalue (complexity::from_pair (outer_size, inner_svalue), type), + m_outer_size (outer_size), + m_inner_svalue (inner_svalue) +{ +} + +/* Implementation of svalue::dump_to_pp vfunc for repeated_svalue. */ + +void +repeated_svalue::dump_to_pp (pretty_printer *pp, bool simple) const +{ + if (simple) + { + pp_string (pp, "REPEATED("); + if (get_type ()) + { + print_quoted_type (pp, get_type ()); + pp_string (pp, ", "); + } + pp_string (pp, "outer_size: "); + m_outer_size->dump_to_pp (pp, simple); + pp_string (pp, ", inner_val: "); + m_inner_svalue->dump_to_pp (pp, simple); + pp_character (pp, ')'); + } + else + { + pp_string (pp, "repeated_svalue ("); + if (get_type ()) + { + print_quoted_type (pp, get_type ()); + pp_string (pp, ", "); + } + pp_string (pp, "outer_size: "); + m_outer_size->dump_to_pp (pp, simple); + pp_string (pp, ", inner_val: "); + m_inner_svalue->dump_to_pp (pp, simple); + pp_character (pp, ')'); + } +} + +/* Implementation of svalue::accept vfunc for repeated_svalue. */ + +void +repeated_svalue::accept (visitor *v) const +{ + v->visit_repeated_svalue (this); + m_inner_svalue->accept (v); +} + +/* Return true if this value is known to be all zeroes. */ + +bool +repeated_svalue::all_zeroes_p () const +{ + if (tree cst = m_inner_svalue->maybe_get_constant ()) + if (zerop (cst)) + return true; + return false; +} + +/* Implementation of svalue::maybe_fold_bits_within vfunc + for repeated_svalue. */ + +const svalue * +repeated_svalue::maybe_fold_bits_within (tree type, + const bit_range &bits, + region_model_manager *mgr) const +{ + const svalue *innermost_sval = m_inner_svalue; + /* Fold + BITS_WITHIN (range, REPEATED_SVALUE (ZERO)) + to: + REPEATED_SVALUE (ZERO). */ + if (all_zeroes_p ()) + { + byte_range bytes (0,0); + if (bits.as_byte_range (&bytes)) + { + const svalue *byte_size + = mgr->get_or_create_int_cst (size_type_node, + bytes.m_size_in_bytes.to_uhwi ()); + return mgr->get_or_create_repeated_svalue (type, byte_size, + innermost_sval); + } + } + + /* Fold: + BITS_WITHIN (range, REPEATED_SVALUE (INNERMOST_SVALUE)) + to: + BITS_WITHIN (range - offset, INNERMOST_SVALUE) + if range is fully within one instance of INNERMOST_SVALUE. */ + if (tree innermost_type = innermost_sval->get_type ()) + { + bit_size_t element_bit_size; + if (int_size_in_bits (innermost_type, &element_bit_size) + && element_bit_size > 0) + { + HOST_WIDE_INT start_idx + = (bits.get_start_bit_offset () + / element_bit_size).to_shwi (); + HOST_WIDE_INT last_idx + = (bits.get_last_bit_offset () + / element_bit_size).to_shwi (); + if (start_idx == last_idx) + { + bit_offset_t start_of_element + = start_idx * element_bit_size; + bit_range range_within_element + (bits.m_start_bit_offset - start_of_element, + bits.m_size_in_bits); + return mgr->get_or_create_bits_within (type, + range_within_element, + innermost_sval); + } + } + } + + return NULL; +} + +/* class bits_within_svalue : public svalue. */ + +/* bits_within_svalue'c ctor. */ + +bits_within_svalue::bits_within_svalue (tree type, + const bit_range &bits, + const svalue *inner_svalue) +: svalue (complexity (inner_svalue), type), + m_bits (bits), + m_inner_svalue (inner_svalue) +{ +} + +/* Implementation of svalue::dump_to_pp vfunc for bits_within_svalue. */ + +void +bits_within_svalue::dump_to_pp (pretty_printer *pp, bool simple) const +{ + if (simple) + { + pp_string (pp, "BITS_WITHIN("); + if (get_type ()) + { + print_quoted_type (pp, get_type ()); + pp_string (pp, ", "); + } + m_bits.dump_to_pp (pp); + pp_string (pp, ", inner_val: "); + m_inner_svalue->dump_to_pp (pp, simple); + pp_character (pp, ')'); + } + else + { + pp_string (pp, "bits_within_svalue ("); + if (get_type ()) + { + print_quoted_type (pp, get_type ()); + pp_string (pp, ", "); + } + m_bits.dump_to_pp (pp); + pp_string (pp, ", inner_val: "); + m_inner_svalue->dump_to_pp (pp, simple); + pp_character (pp, ')'); + } +} + +/* Implementation of svalue::maybe_fold_bits_within vfunc + for bits_within_svalue. */ + +const svalue * +bits_within_svalue::maybe_fold_bits_within (tree type, + const bit_range &bits, + region_model_manager *mgr) const +{ + /* Fold: + BITS_WITHIN (range1, BITS_WITHIN (range2, VAL)) + to: + BITS_WITHIN (range1 in range 2, VAL). */ + bit_range offset_bits (m_bits.get_start_bit_offset () + + bits.m_start_bit_offset, + bits.m_size_in_bits); + return mgr->get_or_create_bits_within (type, offset_bits, m_inner_svalue); +} + +/* Implementation of svalue::accept vfunc for bits_within_svalue. */ + +void +bits_within_svalue::accept (visitor *v) const +{ + v->visit_bits_within_svalue (this); + m_inner_svalue->accept (v); +} + +/* Implementation of svalue::implicitly_live_p vfunc for bits_within_svalue. */ + +bool +bits_within_svalue::implicitly_live_p (const svalue_set *live_svalues, + const region_model *model) const +{ + return m_inner_svalue->live_p (live_svalues, model); +} + /* class widening_svalue : public svalue. */ /* Implementation of svalue::dump_to_pp vfunc for widening_svalue. */ @@ -1291,6 +1603,75 @@ compound_svalue::calc_complexity (const binding_map &map) return complexity (num_child_nodes + 1, max_child_depth + 1); } +/* Implementation of svalue::maybe_fold_bits_within vfunc + for compound_svalue. */ + +const svalue * +compound_svalue::maybe_fold_bits_within (tree type, + const bit_range &bits, + region_model_manager *mgr) const +{ + binding_map result_map; + for (auto iter : m_map) + { + const binding_key *key = iter.first; + if (const concrete_binding *conc_key + = key->dyn_cast_concrete_binding ()) + { + /* Ignore concrete bindings outside BITS. */ + if (!conc_key->get_bit_range ().intersects_p (bits)) + continue; + + const svalue *sval = iter.second; + /* Get the position of conc_key relative to BITS. */ + bit_range result_location (conc_key->get_start_bit_offset () + - bits.get_start_bit_offset (), + conc_key->get_size_in_bits ()); + /* If conc_key starts after BITS, trim off leading bits + from the svalue and adjust binding location. */ + if (result_location.m_start_bit_offset < 0) + { + bit_size_t leading_bits_to_drop + = -result_location.m_start_bit_offset; + result_location = bit_range + (0, result_location.m_size_in_bits - leading_bits_to_drop); + bit_range bits_within_sval (leading_bits_to_drop, + result_location.m_size_in_bits); + /* Trim off leading bits from iter_sval. */ + sval = mgr->get_or_create_bits_within (NULL_TREE, + bits_within_sval, + sval); + } + /* If conc_key finishes after BITS, trim off trailing bits + from the svalue and adjust binding location. */ + if (conc_key->get_next_bit_offset () + > bits.get_next_bit_offset ()) + { + bit_size_t trailing_bits_to_drop + = (conc_key->get_next_bit_offset () + - bits.get_next_bit_offset ()); + result_location = bit_range + (result_location.m_start_bit_offset, + result_location.m_size_in_bits - trailing_bits_to_drop); + bit_range bits_within_sval (0, + result_location.m_size_in_bits); + /* Trim off leading bits from iter_sval. */ + sval = mgr->get_or_create_bits_within (NULL_TREE, + bits_within_sval, + sval); + } + const concrete_binding *offset_conc_key + = mgr->get_store_manager ()->get_concrete_binding + (result_location); + result_map.put (offset_conc_key, sval); + } + else + /* If we have any symbolic keys we can't get it as bits. */ + return NULL; + } + return mgr->get_or_create_compound_svalue (type, result_map); +} + /* class conjured_svalue : public svalue. */ /* Implementation of svalue::dump_to_pp vfunc for conjured_svalue. */ diff --git a/gcc/analyzer/svalue.h b/gcc/analyzer/svalue.h index d9e34aa..3965a5f 100644 --- a/gcc/analyzer/svalue.h +++ b/gcc/analyzer/svalue.h @@ -41,6 +41,8 @@ enum svalue_kind SK_UNARYOP, SK_BINOP, SK_SUB, + SK_REPEATED, + SK_BITS_WITHIN, SK_UNMERGEABLE, SK_PLACEHOLDER, SK_WIDENING, @@ -63,6 +65,9 @@ enum svalue_kind unaryop_svalue (SK_UNARYOP): unary operation on another svalue binop_svalue (SK_BINOP): binary operation on two svalues sub_svalue (SK_SUB): the result of accessing a subregion + repeated_svalue (SK_REPEATED): repeating an svalue to fill a larger region + bits_within_svalue (SK_BITS_WITHIN): a range of bits/bytes within a larger + svalue unmergeable_svalue (SK_UNMERGEABLE): a value that is so interesting from a control-flow perspective that it can inhibit state-merging placeholder_svalue (SK_PLACEHOLDER): for use in selftests. @@ -107,6 +112,10 @@ public: dyn_cast_binop_svalue () const { return NULL; } virtual const sub_svalue * dyn_cast_sub_svalue () const { return NULL; } + virtual const repeated_svalue * + dyn_cast_repeated_svalue () const { return NULL; } + virtual const bits_within_svalue * + dyn_cast_bits_within_svalue () const { return NULL; } virtual const unmergeable_svalue * dyn_cast_unmergeable_svalue () const { return NULL; } virtual const widening_svalue * @@ -138,6 +147,16 @@ public: bool involves_p (const svalue *other) const; + const svalue * + extract_bit_range (tree type, + const bit_range &subrange, + region_model_manager *mgr) const; + + virtual const svalue * + maybe_fold_bits_within (tree type, + const bit_range &subrange, + region_model_manager *mgr) const; + protected: svalue (complexity c, tree type) : m_complexity (c), m_type (type) @@ -175,9 +194,9 @@ public: } void mark_deleted () { m_type = reinterpret_cast (1); } - void mark_empty () { m_type = NULL_TREE; } + void mark_empty () { m_type = reinterpret_cast (2); } bool is_deleted () const { return m_type == reinterpret_cast (1); } - bool is_empty () const { return m_type == NULL_TREE; } + bool is_empty () const { return m_type == reinterpret_cast (2); } tree m_type; const region *m_reg; @@ -222,7 +241,7 @@ is_a_helper ::test (const svalue *sval) template <> struct default_hash_traits : public member_function_hash_traits { - static const bool empty_zero_p = true; + static const bool empty_zero_p = false; }; namespace ana { @@ -253,6 +272,11 @@ public: enum tree_code op, const constant_svalue *rhs); + const svalue * + maybe_fold_bits_within (tree type, + const bit_range &subrange, + region_model_manager *mgr) const FINAL OVERRIDE; + private: tree m_cst_expr; }; @@ -285,6 +309,11 @@ public: void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; void accept (visitor *v) const FINAL OVERRIDE; + + const svalue * + maybe_fold_bits_within (tree type, + const bit_range &subrange, + region_model_manager *mgr) const FINAL OVERRIDE; }; /* An enum describing a particular kind of "poisoned" value. */ @@ -327,9 +356,9 @@ public: } void mark_deleted () { m_type = reinterpret_cast (1); } - void mark_empty () { m_type = NULL_TREE; } + void mark_empty () { m_type = reinterpret_cast (2); } bool is_deleted () const { return m_type == reinterpret_cast (1); } - bool is_empty () const { return m_type == NULL_TREE; } + bool is_empty () const { return m_type == reinterpret_cast (2); } enum poison_kind m_kind; tree m_type; @@ -364,7 +393,7 @@ is_a_helper ::test (const svalue *sval) template <> struct default_hash_traits : public member_function_hash_traits { - static const bool empty_zero_p = true; + static const bool empty_zero_p = false; }; namespace ana { @@ -426,9 +455,9 @@ public: } void mark_deleted () { m_type = reinterpret_cast (1); } - void mark_empty () { m_type = NULL_TREE; } + void mark_empty () { m_type = reinterpret_cast (2); } bool is_deleted () const { return m_type == reinterpret_cast (1); } - bool is_empty () const { return m_type == NULL_TREE; } + bool is_empty () const { return m_type == reinterpret_cast (2); } setjmp_record m_record; tree m_type; @@ -467,7 +496,7 @@ is_a_helper ::test (const svalue *sval) template <> struct default_hash_traits : public member_function_hash_traits { - static const bool empty_zero_p = true; + static const bool empty_zero_p = false; }; namespace ana { @@ -548,9 +577,9 @@ public: } void mark_deleted () { m_type = reinterpret_cast (1); } - void mark_empty () { m_type = NULL_TREE; } + void mark_empty () { m_type = reinterpret_cast (2); } bool is_deleted () const { return m_type == reinterpret_cast (1); } - bool is_empty () const { return m_type == NULL_TREE; } + bool is_empty () const { return m_type == reinterpret_cast (2); } tree m_type; enum tree_code m_op; @@ -574,6 +603,11 @@ public: enum tree_code get_op () const { return m_op; } const svalue *get_arg () const { return m_arg; } + const svalue * + maybe_fold_bits_within (tree type, + const bit_range &subrange, + region_model_manager *mgr) const FINAL OVERRIDE; + private: enum tree_code m_op; const svalue *m_arg; @@ -592,7 +626,7 @@ is_a_helper ::test (const svalue *sval) template <> struct default_hash_traits : public member_function_hash_traits { - static const bool empty_zero_p = true; + static const bool empty_zero_p = false; }; namespace ana { @@ -630,9 +664,9 @@ public: } void mark_deleted () { m_type = reinterpret_cast (1); } - void mark_empty () { m_type = NULL_TREE; } + void mark_empty () { m_type = reinterpret_cast (2); } bool is_deleted () const { return m_type == reinterpret_cast (1); } - bool is_empty () const { return m_type == NULL_TREE; } + bool is_empty () const { return m_type == reinterpret_cast (2); } tree m_type; enum tree_code m_op; @@ -683,7 +717,7 @@ is_a_helper ::test (const svalue *sval) template <> struct default_hash_traits : public member_function_hash_traits { - static const bool empty_zero_p = true; + static const bool empty_zero_p = false; }; namespace ana { @@ -719,9 +753,9 @@ public: } void mark_deleted () { m_type = reinterpret_cast (1); } - void mark_empty () { m_type = NULL_TREE; } + void mark_empty () { m_type = reinterpret_cast (2); } bool is_deleted () const { return m_type == reinterpret_cast (1); } - bool is_empty () const { return m_type == NULL_TREE; } + bool is_empty () const { return m_type == reinterpret_cast (2); } tree m_type; const svalue *m_parent_svalue; @@ -762,7 +796,182 @@ is_a_helper ::test (const svalue *sval) template <> struct default_hash_traits : public member_function_hash_traits { - static const bool empty_zero_p = true; + static const bool empty_zero_p = false; +}; + +namespace ana { + +/* Concrete subclass of svalue representing repeating an inner svalue + (possibly not a whole number of times) to fill a larger region of + type TYPE of size OUTER_SIZE bytes. */ + +class repeated_svalue : public svalue +{ +public: + /* A support class for uniquifying instances of repeated_svalue. */ + struct key_t + { + key_t (tree type, + const svalue *outer_size, + const svalue *inner_svalue) + : m_type (type), m_outer_size (outer_size), m_inner_svalue (inner_svalue) + {} + + hashval_t hash () const + { + inchash::hash hstate; + hstate.add_ptr (m_type); + hstate.add_ptr (m_outer_size); + hstate.add_ptr (m_inner_svalue); + return hstate.end (); + } + + bool operator== (const key_t &other) const + { + return (m_type == other.m_type + && m_outer_size == other.m_outer_size + && m_inner_svalue == other.m_inner_svalue); + } + + void mark_deleted () { m_type = reinterpret_cast (1); } + void mark_empty () { m_type = reinterpret_cast (2); } + bool is_deleted () const { return m_type == reinterpret_cast (1); } + bool is_empty () const { return m_type == reinterpret_cast (2); } + + tree m_type; + const svalue *m_outer_size; + const svalue *m_inner_svalue; + }; + repeated_svalue (tree type, + const svalue *outer_size, + const svalue *inner_svalue); + + enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_REPEATED; } + const repeated_svalue *dyn_cast_repeated_svalue () const FINAL OVERRIDE + { + return this; + } + + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; + void accept (visitor *v) const FINAL OVERRIDE; + + const svalue *get_outer_size () const { return m_outer_size; } + const svalue *get_inner_svalue () const { return m_inner_svalue; } + + bool all_zeroes_p () const; + + const svalue * + maybe_fold_bits_within (tree type, + const bit_range &subrange, + region_model_manager *mgr) const FINAL OVERRIDE; + + private: + const svalue *m_outer_size; + const svalue *m_inner_svalue; +}; + +} // namespace ana + +template <> +template <> +inline bool +is_a_helper ::test (const svalue *sval) +{ + return sval->get_kind () == SK_REPEATED; +} + +template <> struct default_hash_traits +: public member_function_hash_traits +{ + static const bool empty_zero_p = false; +}; + +namespace ana { + +/* A range of bits/bytes within another svalue + e.g. bytes 5-39 of INITIAL_SVALUE(R). + These can be generated for prefixes and suffixes when part of a binding + is clobbered, so that we don't lose too much information. */ + +class bits_within_svalue : public svalue +{ +public: + /* A support class for uniquifying instances of bits_within_svalue. */ + struct key_t + { + key_t (tree type, + const bit_range &bits, + const svalue *inner_svalue) + : m_type (type), m_bits (bits), m_inner_svalue (inner_svalue) + {} + + hashval_t hash () const + { + inchash::hash hstate; + hstate.add_ptr (m_type); + hstate.add_ptr (m_inner_svalue); + return hstate.end (); + } + + bool operator== (const key_t &other) const + { + return (m_type == other.m_type + && m_bits == other.m_bits + && m_inner_svalue == other.m_inner_svalue); + } + + void mark_deleted () { m_type = reinterpret_cast (1); } + void mark_empty () { m_type = reinterpret_cast (2); } + bool is_deleted () const { return m_type == reinterpret_cast (1); } + bool is_empty () const { return m_type == reinterpret_cast (2); } + + tree m_type; + bit_range m_bits; + const svalue *m_inner_svalue; + }; + bits_within_svalue (tree type, + const bit_range &bits, + const svalue *inner_svalue); + + enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_BITS_WITHIN; } + const bits_within_svalue * + dyn_cast_bits_within_svalue () const FINAL OVERRIDE + { + return this; + } + + void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE; + void accept (visitor *v) const FINAL OVERRIDE; + bool implicitly_live_p (const svalue_set *, + const region_model *) const FINAL OVERRIDE; + + const bit_range &get_bits () const { return m_bits; } + const svalue *get_inner_svalue () const { return m_inner_svalue; } + + const svalue * + maybe_fold_bits_within (tree type, + const bit_range &subrange, + region_model_manager *mgr) const FINAL OVERRIDE; + + private: + const bit_range m_bits; + const svalue *m_inner_svalue; +}; + +} // namespace ana + +template <> +template <> +inline bool +is_a_helper ::test (const svalue *sval) +{ + return sval->get_kind () == SK_BITS_WITHIN; +} + +template <> struct default_hash_traits +: public member_function_hash_traits +{ + static const bool empty_zero_p = false; }; namespace ana { @@ -888,9 +1097,9 @@ public: } void mark_deleted () { m_type = reinterpret_cast (1); } - void mark_empty () { m_type = NULL_TREE; } + void mark_empty () { m_type = reinterpret_cast (2); } bool is_deleted () const { return m_type == reinterpret_cast (1); } - bool is_empty () const { return m_type == NULL_TREE; } + bool is_empty () const { return m_type == reinterpret_cast (2); } tree m_type; function_point m_point; @@ -952,7 +1161,7 @@ is_a_helper ::test (svalue *sval) template <> struct default_hash_traits : public member_function_hash_traits { - static const bool empty_zero_p = true; + static const bool empty_zero_p = false; }; namespace ana { @@ -1000,9 +1209,9 @@ public: } void mark_deleted () { m_type = reinterpret_cast (1); } - void mark_empty () { m_type = NULL_TREE; } + void mark_empty () { m_type = reinterpret_cast (2); } bool is_deleted () const { return m_type == reinterpret_cast (1); } - bool is_empty () const { return m_type == NULL_TREE; } + bool is_empty () const { return m_type == reinterpret_cast (2); } tree m_type; const binding_map *m_map_ptr; @@ -1029,6 +1238,11 @@ public: return key_t (get_type (), &m_map); } + const svalue * + maybe_fold_bits_within (tree type, + const bit_range &subrange, + region_model_manager *mgr) const FINAL OVERRIDE; + private: static complexity calc_complexity (const binding_map &map); @@ -1048,7 +1262,7 @@ is_a_helper ::test (svalue *sval) template <> struct default_hash_traits : public member_function_hash_traits { - static const bool empty_zero_p = true; + static const bool empty_zero_p = false; }; namespace ana { diff --git a/gcc/testsuite/gcc.dg/analyzer/clobbers-1.c b/gcc/testsuite/gcc.dg/analyzer/clobbers-1.c new file mode 100644 index 0000000..824dbd4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/clobbers-1.c @@ -0,0 +1,98 @@ +#include "analyzer-decls.h" + +struct foo +{ + int i; + int j; +}; + +struct coord +{ + int x; + int y; + int z; +}; + +struct foo g; + +void test_1 (void) +{ + g.i = 42; + if (g.j) + __analyzer_eval (g.j); /* { dg-warning "TRUE" } */ + else + __analyzer_eval (g.j); /* { dg-warning "FALSE" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} + +void test_2 (void) +{ + struct foo f; + f.i = 42; + if (f.j) + __analyzer_eval (f.j); /* { dg-warning "TRUE" } */ + else + __analyzer_eval (f.j); /* { dg-warning "FALSE" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} + +void test_3 (struct foo *p) +{ + struct foo f = *p; + f.i = 42; + if (f.j) + __analyzer_eval (f.j); /* { dg-warning "TRUE" } */ + else + __analyzer_eval (f.j); /* { dg-warning "FALSE" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} + +void test_4 (struct coord *p) +{ + struct coord f = *p; + f.x = 42; + __analyzer_eval (f.y == p->y); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.z == p->z); /* { dg-warning "TRUE" } */ +} + +struct s5 +{ + char arr[8]; +}; + +void test_5 (struct s5 *p) +{ + struct s5 f = *p; + f.arr[3] = 42; + __analyzer_eval (f.arr[0] == p->arr[0]); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[1] == p->arr[1]); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[2] == p->arr[2]); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[3] == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[4] == p->arr[4]); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[5] == p->arr[5]); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[6] == p->arr[6]); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[7] == p->arr[7]); /* { dg-warning "TRUE" } */ +} + +struct s6 +{ + int before; /* Give "arr" a nonzero offset. */ + struct foo arr[4]; + int after; +}; + +void test_6 (struct s6 *p, struct foo *q) +{ + struct s6 f = *p; + f.arr[1] = *q; + __analyzer_eval (f.before == p->before); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[0].i == p->arr[0].i); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[0].j == p->arr[0].j); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[1].i == q->i); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[1].j == q->j); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[2].i == p->arr[2].i); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[2].j == p->arr[2].j); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[3].i == p->arr[3].i); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.arr[3].j == p->arr[3].j); /* { dg-warning "TRUE" } */ + __analyzer_eval (f.after == p->after); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/clobbers-2.c b/gcc/testsuite/gcc.dg/analyzer/clobbers-2.c new file mode 100644 index 0000000..9a88349 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/clobbers-2.c @@ -0,0 +1,72 @@ +#include "analyzer-decls.h" + +typedef __SIZE_TYPE__ size_t; +extern void bzero (void *s, size_t n); +extern void *memset(void *s, int c, size_t n); + +void test_1 (void) +{ + char arr[16]; + bzero (arr, sizeof (arr)); + __analyzer_eval (arr[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[7] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[8] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[9] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[15] == 0); /* { dg-warning "TRUE" } */ + + /* Clobber in the middle (with prefix and suffix). */ + arr[8] = 42; + __analyzer_eval (arr[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[7] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[8] == 0); /* { dg-warning "FALSE" } */ + __analyzer_eval (arr[8] == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[9] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[15] == 0); /* { dg-warning "TRUE" } */ +} + +void test_2 (void) +{ + char arr[16]; + bzero (arr, sizeof (arr)); + __analyzer_eval (arr[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[1] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[15] == 0); /* { dg-warning "TRUE" } */ + + /* Clobber at the front (suffix, but no prefix). */ + arr[0] = 42; + __analyzer_eval (arr[0] == 0); /* { dg-warning "FALSE" } */ + __analyzer_eval (arr[0] == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[1] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[15] == 0); /* { dg-warning "TRUE" } */ +} + +void test_3 (void) +{ + char arr[16]; + bzero (arr, sizeof (arr)); + __analyzer_eval (arr[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[14] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[15] == 0); /* { dg-warning "TRUE" } */ + + /* Clobber at the end (prefix, but no suffix). */ + arr[15] = 42; + __analyzer_eval (arr[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[14] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[15] == 0); /* { dg-warning "FALSE" } */ + __analyzer_eval (arr[15] == 42); /* { dg-warning "TRUE" } */ +} + +void test_4 (void) +{ + char arr[16]; + bzero (arr, sizeof (arr)); + __analyzer_eval (arr[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[15] == 0); /* { dg-warning "TRUE" } */ + + /* Exact overlap, no prefix or suffix. */ + memset (arr, 1, 16); + __analyzer_eval (arr[0] == 0); /* { dg-warning "FALSE" } */ + __analyzer_eval (arr[15] == 0); /* { dg-warning "FALSE" } */ + __analyzer_eval (arr[0] == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[15] == 1); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c index 4a62a0e..34932da 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c @@ -503,9 +503,7 @@ void test_26 (struct coord *p, struct coord *q) the dest value. */ *p = *q; __analyzer_eval (p->x); /* { dg-warning "UNKNOWN" } */ - __analyzer_eval (p->y == 17); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail): should have been overwritten with q->y + __analyzer_eval (p->y == 17); /* { dg-warning "TRUE" } */ __analyzer_eval (q->x); /* { dg-warning "UNKNOWN" } */ __analyzer_eval (q->y == 17); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ @@ -522,19 +520,11 @@ void test_27 (struct coord *p) void test_28 (struct coord *p) { memset (p, 0, sizeof (struct coord) * 10); - __analyzer_eval (p[0].x == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail): - __analyzer_eval (p[0].y == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail): + __analyzer_eval (p[0].x == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (p[0].y == 0); /* { dg-warning "TRUE" } */ - __analyzer_eval (p[9].x == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail): - __analyzer_eval (p[9].y == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail): + __analyzer_eval (p[9].x == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (p[9].y == 0); /* { dg-warning "TRUE" } */ __analyzer_eval (p[10].x == 0); /* { dg-warning "UNKNOWN" } */ __analyzer_eval (p[10].y == 0); /* { dg-warning "UNKNOWN" } */ @@ -1035,8 +1025,8 @@ void test_52 (struct big b) { struct big d; memcpy (&d, &b, sizeof (struct big)); - __analyzer_eval (b.ia[0] == d.ia[0]); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ + __analyzer_eval (b.ia[0] == d.ia[0]); /* { dg-warning "TRUE" } */ + __analyzer_eval (b.ia[1023] == d.ia[1023]); /* { dg-warning "TRUE" } */ } void test_53 (const char *msg) diff --git a/gcc/testsuite/gcc.dg/analyzer/explode-1.c b/gcc/testsuite/gcc.dg/analyzer/explode-1.c index 6b62e8e..f48408e 100644 --- a/gcc/testsuite/gcc.dg/analyzer/explode-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/explode-1.c @@ -12,7 +12,7 @@ void test (void) { void *p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8; void **pp; - while (get ()) + while (get ()) /* { dg-warning "leak" } */ { switch (get ()) { diff --git a/gcc/testsuite/gcc.dg/analyzer/memset-1.c b/gcc/testsuite/gcc.dg/analyzer/memset-1.c index 5748aa1..94c5a1b 100644 --- a/gcc/testsuite/gcc.dg/analyzer/memset-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/memset-1.c @@ -36,22 +36,16 @@ void test_3 (int val) { char buf[256]; memset (buf, 'A', 256); - /* We currently merely mark such regions as "unknown", so querying - values within them yields UNKNOWN when ideally it would be TRUE. */ - __analyzer_eval (buf[42] == 'A'); /* { dg-warning "TRUE" "known nonzero" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (buf[42] == 'A'); /* { dg-warning "TRUE" } */ } /* A "memset" with unknown value. */ -void test_4 (int val) +void test_4 (char val) { char buf[256]; memset (buf, val, 256); - /* We currently merely mark such regions as "unknown", so querying - values within them yields UNKNOWN when ideally it would be TRUE. */ - __analyzer_eval (buf[42] == (char)val); /* { dg-warning "TRUE" "known nonzero" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (buf[42] == (char)val); /* { dg-warning "TRUE" } */ } /* A "memset" with unknown num bytes. */ @@ -98,6 +92,14 @@ void test_6 (int val) __analyzer_eval (buf[42] == 'A'); /* { dg-warning "TRUE" } */ } +void test_6b (int val) +{ + char buf[256]; + memset (buf, 'A', sizeof (buf)); + memset (buf, 'B', get_zero ()); + __analyzer_eval (buf[42] == 'A'); /* { dg-warning "TRUE" } */ +} + /* A "memset" of known size that's not the full buffer. */ void test_7 (void) @@ -105,10 +107,96 @@ void test_7 (void) char buf[256]; buf[128] = 'A'; memset (buf, 0, 128); - /* We currently merely mark the whole region as "unknown", so querying - values within them yields UNKNOWN. */ - __analyzer_eval (buf[127] == '\0'); /* { dg-warning "TRUE" "known nonzero" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ - __analyzer_eval (buf[128] == 'A'); /* { dg-warning "TRUE" "known nonzero" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (buf[0] == '\0'); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[127] == '\0'); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[128] == 'A'); /* { dg-warning "TRUE" } */ +} + +void test_8 (void) +{ + char buf[20]; + memset (buf + 0, 0, 1); + memset (buf + 1, 1, 1); + memset (buf + 2, 2, 1); + memset (buf + 3, 3, 1); + memset (buf + 4, 4, 2); + memset (buf + 6, 6, 2); + memset (buf + 8, 8, 4); + memset (buf + 12, 12, 8); + __analyzer_eval (buf[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[1] == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[2] == 2); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[3] == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[4] == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[5] == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[6] == 6); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[7] == 6); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[8] == 8); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[9] == 8); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[10] == 8); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[11] == 8); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[12] == 12); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[13] == 12); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[14] == 12); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[15] == 12); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[16] == 12); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[17] == 12); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[18] == 12); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[19] == 12); /* { dg-warning "TRUE" } */ +} + +/* Various overlapping memset calls with different sizes and values. */ + +void test_9 (void) +{ + char buf[8]; + memset (buf, 0, 8); + __analyzer_eval (buf[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[1] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[2] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[3] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[4] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[5] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[6] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[7] == 0); /* { dg-warning "TRUE" } */ + + memset (buf + 1, 1, 4); + __analyzer_eval (buf[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[1] == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[2] == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[3] == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[4] == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[5] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[6] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[7] == 0); /* { dg-warning "TRUE" } */ + + memset (buf + 2, 2, 4); + __analyzer_eval (buf[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[1] == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[2] == 2); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[3] == 2); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[4] == 2); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[5] == 2); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[6] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[7] == 0); /* { dg-warning "TRUE" } */ + + memset (buf + 4, 3, 3); + __analyzer_eval (buf[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[1] == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[2] == 2); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[3] == 2); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[4] == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[5] == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[6] == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[7] == 0); /* { dg-warning "TRUE" } */ + + memset (buf + 0, 4, 3); + __analyzer_eval (buf[0] == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[1] == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[2] == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[3] == 2); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[4] == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[5] == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[6] == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (buf[7] == 0); /* { dg-warning "TRUE" } */ } diff --git a/gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c b/gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c new file mode 100644 index 0000000..9dd1139 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c @@ -0,0 +1,107 @@ +/* This is a very simplified version of CVE-2017-18549, + a use of uninitialized padding values affecting the Linux kernel + (and thus GPLv2). + + It was fixed by e.g. 342ffc26693b528648bdc9377e51e4f2450b4860 on linux-4.13.y + in linux-stable. */ + +#include "analyzer-decls.h" +#include + +typedef unsigned int __u32; +typedef unsigned int u32; +typedef unsigned char u8; + +/* Adapted from include/uapi/linux/types.h */ + +#define __bitwise +typedef __u32 __bitwise __le32; + +/* Adapted from drivers/scsi/aacraid/aacraid.h */ + +#define AAC_SENSE_BUFFERSIZE 30 + +struct aac_srb_reply +{ + __le32 status; + __le32 srb_status; + __le32 scsi_status; + __le32 data_xfer_length; + __le32 sense_data_size; + u8 sense_data[AAC_SENSE_BUFFERSIZE]; + + /* Manually added to help verify the fix. */ + u8 padding[2]; +}; + +#define ST_OK 0 +#define SRB_STATUS_SUCCESS 0x01 + +/* Adapted from drivers/scsi/aacraid/commctrl.c */ + +static int aac_send_raw_srb(/* [...snip...] */) +{ + u32 byte_count = 0; + + /* [...snip...] */ + + struct aac_srb_reply reply; + + reply.status = ST_OK; + + /* [...snip...] */ + + reply.srb_status = SRB_STATUS_SUCCESS; + reply.scsi_status = 0; + reply.data_xfer_length = byte_count; + reply.sense_data_size = 0; + memset(reply.sense_data, 0, AAC_SENSE_BUFFERSIZE); + + /* [...snip...] */ + + __analyzer_eval (reply.status == ST_OK); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.srb_status == SRB_STATUS_SUCCESS); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.scsi_status == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.data_xfer_length == byte_count); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.sense_data_size == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.sense_data[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.sense_data[AAC_SENSE_BUFFERSIZE - 1] == 0); /* { dg-warning "TRUE" } */ + /* TODO: the following should be detected as uninitialized, when + that diagnostic is reimplemented. */ + __analyzer_eval (reply.padding[0] == 0); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (reply.padding[1] == 0); /* { dg-warning "UNKNOWN" } */ +} + +static int aac_send_raw_srb_fixed(/* [...snip...] */) +{ + u32 byte_count = 0; + + /* [...snip...] */ + + struct aac_srb_reply reply; + + /* This is the fix. */ + memset(&reply, 0, sizeof(reply)); + + reply.status = ST_OK; + + /* [...snip...] */ + + reply.srb_status = SRB_STATUS_SUCCESS; + reply.scsi_status = 0; + reply.data_xfer_length = byte_count; + reply.sense_data_size = 0; + memset(reply.sense_data, 0, AAC_SENSE_BUFFERSIZE); + + /* [...snip...] */ + + __analyzer_eval (reply.status == ST_OK); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.srb_status == SRB_STATUS_SUCCESS); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.scsi_status == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.data_xfer_length == byte_count); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.sense_data_size == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.sense_data[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.sense_data[AAC_SENSE_BUFFERSIZE - 1] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.padding[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (reply.padding[1] == 0); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/symbolic-8.c b/gcc/testsuite/gcc.dg/analyzer/symbolic-8.c new file mode 100644 index 0000000..f9c3596 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/symbolic-8.c @@ -0,0 +1,11 @@ +/* Merger where "arr" has two different symbolic bindings. */ + +void test (int i, int j, int flag) +{ + int arr[16]; + + if (flag) + arr[i] = 42; + else + arr[j] = 17; +} -- cgit v1.1 From a075350ee7bffa6c90d9d233de78515f498b5149 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 30 Jun 2021 12:35:45 +0200 Subject: tree-optimization/101267 - fix SLP vect with masked operations This fixes the missed handling of external/constant mask SLP operations, for the testcase in particular masked loads. The patch adjusts the vect_check_scalar_mask API to reflect the required vect_is_simple_use SLP compatible API plus adjusts for the special handling of masked loads in SLP discovery. The issue is likely latent. 2021-06-30 Richard Biener PR tree-optimization/101267 * tree-vect-stmts.c (vect_check_scalar_mask): Adjust API and use SLP compatible interface of vect_is_simple_use. Reject not vectorized SLP defs for callers that do not support that. (vect_check_store_rhs): Handle masked stores and pass down the appropriate operator index. (vectorizable_call): Adjust. (vectorizable_store): Likewise. (vectorizable_load): Likewise. Handle SLP pecularity of masked loads. (vect_is_simple_use): Remove special-casing of masked stores. * gfortran.dg/pr101267.f90: New testcase. --- gcc/testsuite/gfortran.dg/pr101267.f90 | 23 +++++++++ gcc/tree-vect-stmts.c | 92 ++++++++++++++++++++-------------- 2 files changed, 77 insertions(+), 38 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/pr101267.f90 (limited to 'gcc') diff --git a/gcc/testsuite/gfortran.dg/pr101267.f90 b/gcc/testsuite/gfortran.dg/pr101267.f90 new file mode 100644 index 0000000..12723cf --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr101267.f90 @@ -0,0 +1,23 @@ +! { dg-do compile } +! { dg-options "-Ofast" } +! { dg-additional-options "-march=znver2" { target x86_64-*-* i?86-*-* } } + SUBROUTINE sfddagd( regime, znt,ite ,jte ) + REAL, DIMENSION( ime, IN) :: regime, znt + REAL, DIMENSION( ite, jte) :: wndcor_u + LOGICAL wrf_dm_on_monitor + IF( int4 == 1 ) THEN + DO j=jts,jtf + DO i=itsu,itf + reg = regime(i, j) + IF( reg > 10.0 ) THEN + znt0 = znt(i-1, j) + znt(i, j) + IF( znt0 <= 0.2) THEN + wndcor_u(i,j) = 0.2 + ENDIF + ENDIF + ENDDO + ENDDO + IF ( wrf_dm_on_monitor()) THEN + ENDIF + ENDIF + END diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 4ee11b2..e590f34 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -2439,17 +2439,31 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, return true; } -/* Return true if boolean argument MASK is suitable for vectorizing - conditional operation STMT_INFO. When returning true, store the type - of the definition in *MASK_DT_OUT and the type of the vectorized mask - in *MASK_VECTYPE_OUT. */ +/* Return true if boolean argument at MASK_INDEX is suitable for vectorizing + conditional operation STMT_INFO. When returning true, store the mask + in *MASK, the type of its definition in *MASK_DT_OUT, the type of the + vectorized mask in *MASK_VECTYPE_OUT and the SLP node corresponding + to the mask in *MASK_NODE if MASK_NODE is not NULL. */ static bool -vect_check_scalar_mask (vec_info *vinfo, stmt_vec_info stmt_info, tree mask, - vect_def_type *mask_dt_out, - tree *mask_vectype_out) +vect_check_scalar_mask (vec_info *vinfo, stmt_vec_info stmt_info, + slp_tree slp_node, unsigned mask_index, + tree *mask, slp_tree *mask_node, + vect_def_type *mask_dt_out, tree *mask_vectype_out) { - if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (mask))) + enum vect_def_type mask_dt; + tree mask_vectype; + slp_tree mask_node_1; + if (!vect_is_simple_use (vinfo, stmt_info, slp_node, mask_index, + mask, &mask_node_1, &mask_dt, &mask_vectype)) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "mask use not simple.\n"); + return false; + } + + if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (*mask))) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, @@ -2457,7 +2471,7 @@ vect_check_scalar_mask (vec_info *vinfo, stmt_vec_info stmt_info, tree mask, return false; } - if (TREE_CODE (mask) != SSA_NAME) + if (TREE_CODE (*mask) != SSA_NAME) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, @@ -2465,13 +2479,15 @@ vect_check_scalar_mask (vec_info *vinfo, stmt_vec_info stmt_info, tree mask, return false; } - enum vect_def_type mask_dt; - tree mask_vectype; - if (!vect_is_simple_use (mask, vinfo, &mask_dt, &mask_vectype)) + /* If the caller is not prepared for adjusting an external/constant + SLP mask vector type fail. */ + if (slp_node + && !mask_node + && SLP_TREE_DEF_TYPE (mask_node_1) != vect_internal_def) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "mask use not simple.\n"); + "SLP mask argument is not vectorized.\n"); return false; } @@ -2501,6 +2517,8 @@ vect_check_scalar_mask (vec_info *vinfo, stmt_vec_info stmt_info, tree mask, *mask_dt_out = mask_dt; *mask_vectype_out = mask_vectype; + if (mask_node) + *mask_node = mask_node_1; return true; } @@ -2525,10 +2543,18 @@ vect_check_store_rhs (vec_info *vinfo, stmt_vec_info stmt_info, return false; } + unsigned op_no = 0; + if (gcall *call = dyn_cast (stmt_info->stmt)) + { + if (gimple_call_internal_p (call) + && internal_store_fn_p (gimple_call_internal_fn (call))) + op_no = internal_fn_stored_value_index (gimple_call_internal_fn (call)); + } + enum vect_def_type rhs_dt; tree rhs_vectype; slp_tree slp_op; - if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 0, + if (!vect_is_simple_use (vinfo, stmt_info, slp_node, op_no, &rhs, &slp_op, &rhs_dt, &rhs_vectype)) { if (dump_enabled_p ()) @@ -3163,9 +3189,8 @@ vectorizable_call (vec_info *vinfo, { if ((int) i == mask_opno) { - op = gimple_call_arg (stmt, i); - if (!vect_check_scalar_mask (vinfo, - stmt_info, op, &dt[i], &vectypes[i])) + if (!vect_check_scalar_mask (vinfo, stmt_info, slp_node, mask_opno, + &op, &slp_op[i], &dt[i], &vectypes[i])) return false; continue; } @@ -7213,13 +7238,10 @@ vectorizable_store (vec_info *vinfo, } int mask_index = internal_fn_mask_index (ifn); - if (mask_index >= 0) - { - mask = gimple_call_arg (call, mask_index); - if (!vect_check_scalar_mask (vinfo, stmt_info, mask, &mask_dt, - &mask_vectype)) - return false; - } + if (mask_index >= 0 + && !vect_check_scalar_mask (vinfo, stmt_info, slp_node, mask_index, + &mask, NULL, &mask_dt, &mask_vectype)) + return false; } op = vect_get_store_rhs (stmt_info); @@ -8494,13 +8516,13 @@ vectorizable_load (vec_info *vinfo, return false; int mask_index = internal_fn_mask_index (ifn); - if (mask_index >= 0) - { - mask = gimple_call_arg (call, mask_index); - if (!vect_check_scalar_mask (vinfo, stmt_info, mask, &mask_dt, - &mask_vectype)) - return false; - } + if (mask_index >= 0 + && !vect_check_scalar_mask (vinfo, stmt_info, slp_node, + /* ??? For SLP we only have operands for + the mask operand. */ + slp_node ? 0 : mask_index, + &mask, NULL, &mask_dt, &mask_vectype)) + return false; } tree vectype = STMT_VINFO_VECTYPE (stmt_info); @@ -11484,13 +11506,7 @@ vect_is_simple_use (vec_info *vinfo, stmt_vec_info stmt, slp_tree slp_node, *op = gimple_op (ass, operand + 1); } else if (gcall *call = dyn_cast (stmt->stmt)) - { - if (gimple_call_internal_p (call) - && internal_store_fn_p (gimple_call_internal_fn (call))) - operand = internal_fn_stored_value_index (gimple_call_internal_fn - (call)); - *op = gimple_call_arg (call, operand); - } + *op = gimple_call_arg (call, operand); else gcc_unreachable (); return vect_is_simple_use (*op, vinfo, dt, vectype, def_stmt_info_out); -- cgit v1.1 From e66d0b7b87d105d24da8c4784a0b907fb6b2c095 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Tue, 29 Jun 2021 14:30:51 -0400 Subject: c++: DR2397 - auto specifier for * and & to arrays [PR100975] This patch implements DR2397, which removes the restriction in [dcl.array]p4 that the array element type may not be a placeholder type. We don't need to worry about decltype(auto) here, so this allows code like int a[3]; auto (*p)[3] = &a; auto (&r)[3] = a; However, note that auto (&&r)[2] = { 1, 2 }; auto arr[2] = { 1, 2 }; still doesn't work (although one day it might) and neither does int arr[5]; auto x[5] = arr; given that auto deduction is performed in terms of function template argument deduction, so the array decays to *. PR c++/100975 DR 2397 gcc/cp/ChangeLog: * decl.c (create_array_type_for_decl): Allow array of auto. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/auto24.C: Remove dg-error. * g++.dg/cpp0x/auto3.C: Adjust dg-error. * g++.dg/cpp0x/auto42.C: Likewise. * g++.dg/cpp0x/initlist75.C: Likewise. * g++.dg/cpp0x/initlist80.C: Likewise. * g++.dg/diagnostic/auto1.C: Remove dg-error. * g++.dg/cpp23/auto-array.C: New test. --- gcc/cp/decl.c | 11 ---------- gcc/testsuite/g++.dg/cpp0x/auto24.C | 3 ++- gcc/testsuite/g++.dg/cpp0x/auto3.C | 4 ++-- gcc/testsuite/g++.dg/cpp0x/auto42.C | 2 +- gcc/testsuite/g++.dg/cpp0x/initlist75.C | 2 +- gcc/testsuite/g++.dg/cpp0x/initlist80.C | 2 +- gcc/testsuite/g++.dg/cpp23/auto-array.C | 36 +++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/diagnostic/auto1.C | 3 ++- 8 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-array.C (limited to 'gcc') diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index fa6af6f..7672947 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -10969,17 +10969,6 @@ create_array_type_for_decl (tree name, tree type, tree size, location_t loc) if (type == error_mark_node || size == error_mark_node) return error_mark_node; - /* 8.3.4/1: If the type of the identifier of D contains the auto - type-specifier, the program is ill-formed. */ - if (type_uses_auto (type)) - { - if (name) - error_at (loc, "%qD declared as array of %qT", name, type); - else - error ("creating array of %qT", type); - return error_mark_node; - } - /* If there are some types which cannot be array elements, issue an error-message and return. */ switch (TREE_CODE (type)) diff --git a/gcc/testsuite/g++.dg/cpp0x/auto24.C b/gcc/testsuite/g++.dg/cpp0x/auto24.C index 193f92e..ac1ba24 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto24.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto24.C @@ -1,5 +1,6 @@ // PR c++/48599 // { dg-do compile { target c++11 } } +// Allowed since DR2397. int v[1]; -auto (*p)[1] = &v; // { dg-error "8:.p. declared as array of .auto" } +auto (*p)[1] = &v; diff --git a/gcc/testsuite/g++.dg/cpp0x/auto3.C b/gcc/testsuite/g++.dg/cpp0x/auto3.C index 2cd0520..7cde745 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto3.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto3.C @@ -9,8 +9,8 @@ auto x; // { dg-error "auto" } // deduction, the program is ill-formed. auto i = 42, j = 42.0; // { dg-error "auto" } -// New CWG issue -auto a[2] = { 1, 2 }; // { dg-error "6:.a. declared as array of .auto" } +// CWG issue 2397: [dcl.type.auto.deduct]/2: "T shall not be an array type". +auto a[2] = { 1, 2 }; // { dg-error "20:unable to deduce" } template struct A { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/auto42.C b/gcc/testsuite/g++.dg/cpp0x/auto42.C index 8d15fc9..5b2f677 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto42.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto42.C @@ -5,5 +5,5 @@ void foo(int i) { - auto x[1] = { 0 }; // { dg-error "8:.x. declared as array of .auto" } + auto x[1] = { 0 }; // { dg-error "19:unable to deduce" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist75.C b/gcc/testsuite/g++.dg/cpp0x/initlist75.C index 9a45087..f572f51 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist75.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist75.C @@ -3,4 +3,4 @@ #include -auto foo[] = {}; // { dg-error "6:.foo. declared as array of .auto" } +auto foo[] = {}; // { dg-error "15:unable to deduce" } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist80.C b/gcc/testsuite/g++.dg/cpp0x/initlist80.C index 15723be..a6ab40c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist80.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist80.C @@ -3,4 +3,4 @@ #include -auto x[2] = {}; // { dg-error "6:.x. declared as array of .auto" } +auto x[2] = {}; // { dg-error "14:unable to deduce" } diff --git a/gcc/testsuite/g++.dg/cpp23/auto-array.C b/gcc/testsuite/g++.dg/cpp23/auto-array.C new file mode 100644 index 0000000..42f2b0c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-array.C @@ -0,0 +1,36 @@ +// PR c++/100975 +// DR 2397 - auto specifier for pointers and references to arrays +// { dg-do compile { target c++11 } } + +struct false_type { static constexpr bool value = false; }; +struct true_type { static constexpr bool value = true; }; +template +struct is_same : false_type {}; +template +struct is_same : true_type {}; + +using U = int[3]; + +void +g () +{ + int a[3]; + auto (*p)[3] = &a; + auto (&r)[3] = a; + int aa[3][3]; + auto (*pp)[3][3] = &aa; + auto (&rr)[3][3] = aa; + + auto (&&rv)[3] = U{}; + + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + +#if __cplusplus >= 201402L + // In a generic lambda parameter this was OK even before. + auto l = [](auto (&arr)[5]) { return arr[0]; }; +#endif +} diff --git a/gcc/testsuite/g++.dg/diagnostic/auto1.C b/gcc/testsuite/g++.dg/diagnostic/auto1.C index ee2eefd..9d9979e 100644 --- a/gcc/testsuite/g++.dg/diagnostic/auto1.C +++ b/gcc/testsuite/g++.dg/diagnostic/auto1.C @@ -1,4 +1,5 @@ // PR c++/86915 // { dg-do compile { target c++17 } } +// Allowed since DR2397. -template struct S; // { dg-error "creating array of .auto." } +template struct S; -- cgit v1.1 From 251697a64ba4d7f10f072702771a59d30364cc26 Mon Sep 17 00:00:00 2001 From: Hafiz Abid Qadeer Date: Fri, 28 May 2021 17:49:46 +0100 Subject: [amdgcn] Update CFI configuration Currently we don't get any call frame information for the amdgcn target. This patch makes necessary adjustments to generate CFI that can work with ROCGDB (ROCm 3.8+). gcc/ * config/gcn/gcn.c (move_callee_saved_registers): Emit CFI notes for prologue register saves. (gcn_debug_unwind_info): Use UI_DWARF2. (gcn_dwarf_register_number): Map DWARF_LINK_REGISTER to DWARF PC. (gcn_dwarf_register_span): DWARF_LINK_REGISTER doesn't span. * config/gcn/gcn.h: (DWARF_FRAME_RETURN_COLUMN): New define. (DWARF_LINK_REGISTER): New define. (FIRST_PSEUDO_REGISTER): Increment. (FIXED_REGISTERS): Add entry for DWARF_LINK_REGISTER. (CALL_USED_REGISTERS): Likewise. (REGISTER_NAMES): Likewise. --- gcc/config/gcn/gcn.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++----- gcc/config/gcn/gcn.h | 10 ++++--- 2 files changed, 81 insertions(+), 11 deletions(-) (limited to 'gcc') diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c index aa9d455..ef4ed7c 100644 --- a/gcc/config/gcn/gcn.c +++ b/gcc/config/gcn/gcn.c @@ -2649,6 +2649,7 @@ move_callee_saved_registers (rtx sp, machine_function *offsets, rtx as = gen_rtx_CONST_INT (VOIDmode, STACK_ADDR_SPACE); HOST_WIDE_INT exec_set = 0; int offreg_set = 0; + auto_vec saved_sgprs; start_sequence (); @@ -2665,7 +2666,10 @@ move_callee_saved_registers (rtx sp, machine_function *offsets, int lane = saved_scalars % 64; if (prologue) - emit_insn (gen_vec_setv64si (vreg, reg, GEN_INT (lane))); + { + emit_insn (gen_vec_setv64si (vreg, reg, GEN_INT (lane))); + saved_sgprs.safe_push (regno); + } else emit_insn (gen_vec_extractv64sisi (reg, vreg, GEN_INT (lane))); @@ -2698,7 +2702,7 @@ move_callee_saved_registers (rtx sp, machine_function *offsets, gcn_gen_undef (V64SImode), exec)); /* Move vectors. */ - for (regno = FIRST_VGPR_REG, offset = offsets->pretend_size; + for (regno = FIRST_VGPR_REG, offset = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if ((df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno)) || (regno == VGPR_REGNO (6) && saved_scalars > 0) @@ -2719,8 +2723,67 @@ move_callee_saved_registers (rtx sp, machine_function *offsets, } if (prologue) - emit_insn (gen_scatterv64si_insn_1offset_exec (vsp, const0_rtx, reg, - as, const0_rtx, exec)); + { + rtx insn = emit_insn (gen_scatterv64si_insn_1offset_exec + (vsp, const0_rtx, reg, as, const0_rtx, + exec)); + + /* Add CFI metadata. */ + rtx note; + if (regno == VGPR_REGNO (6) || regno == VGPR_REGNO (7)) + { + int start = (regno == VGPR_REGNO (7) ? 64 : 0); + int count = MIN (saved_scalars - start, 64); + int add_lr = (regno == VGPR_REGNO (6) + && df_regs_ever_live_p (LINK_REGNUM)); + int lrdest = -1; + rtvec seq = rtvec_alloc (count + add_lr); + + /* Add an REG_FRAME_RELATED_EXPR entry for each scalar + register that was saved in this batch. */ + for (int idx = 0; idx < count; idx++) + { + int stackaddr = offset + idx * 4; + rtx dest = gen_rtx_MEM (SImode, + gen_rtx_PLUS + (DImode, sp, + GEN_INT (stackaddr))); + rtx src = gen_rtx_REG (SImode, saved_sgprs[start + idx]); + rtx set = gen_rtx_SET (dest, src); + RTX_FRAME_RELATED_P (set) = 1; + RTVEC_ELT (seq, idx) = set; + + if (saved_sgprs[start + idx] == LINK_REGNUM) + lrdest = stackaddr; + } + + /* Add an additional expression for DWARF_LINK_REGISTER if + LINK_REGNUM was saved. */ + if (lrdest != -1) + { + rtx dest = gen_rtx_MEM (DImode, + gen_rtx_PLUS + (DImode, sp, + GEN_INT (lrdest))); + rtx src = gen_rtx_REG (DImode, DWARF_LINK_REGISTER); + rtx set = gen_rtx_SET (dest, src); + RTX_FRAME_RELATED_P (set) = 1; + RTVEC_ELT (seq, count) = set; + } + + note = gen_rtx_SEQUENCE (VOIDmode, seq); + } + else + { + rtx dest = gen_rtx_MEM (V64SImode, + gen_rtx_PLUS (DImode, sp, + GEN_INT (offset))); + rtx src = gen_rtx_REG (V64SImode, regno); + note = gen_rtx_SET (dest, src); + } + RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_FRAME_RELATED_EXPR, note); + } else emit_insn (gen_gatherv64si_insn_1offset_exec (reg, vsp, const0_rtx, as, const0_rtx, @@ -3224,8 +3287,7 @@ gcn_cannot_copy_insn_p (rtx_insn *insn) static enum unwind_info_type gcn_debug_unwind_info () { - /* No support for debug info, yet. */ - return UI_NONE; + return UI_DWARF2; } /* Determine if there is a suitable hardware conversion instruction. @@ -6251,6 +6313,8 @@ gcn_dwarf_register_number (unsigned int regno) return 768; */ else if (regno == SCC_REG) return 128; + else if (regno == DWARF_LINK_REGISTER) + return 16; else if (SGPR_REGNO_P (regno)) { if (regno - FIRST_SGPR_REG < 64) @@ -6280,8 +6344,12 @@ gcn_dwarf_register_span (rtx rtl) if (GET_MODE_SIZE (mode) != 8) return NULL_RTX; - rtx p = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); unsigned regno = REGNO (rtl); + + if (regno == DWARF_LINK_REGISTER) + return NULL_RTX; + + rtx p = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); XVECEXP (p, 0, 0) = gen_rtx_REG (SImode, regno); XVECEXP (p, 0, 1) = gen_rtx_REG (SImode, regno + 1); diff --git a/gcc/config/gcn/gcn.h b/gcc/config/gcn/gcn.h index 540835b..5822ec3 100644 --- a/gcc/config/gcn/gcn.h +++ b/gcc/config/gcn/gcn.h @@ -88,6 +88,7 @@ #define FIRST_PARM_OFFSET(FNDECL) 0 #define DYNAMIC_CHAIN_ADDRESS(FP) plus_constant (Pmode, (FP), -16) #define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LINK_REGNUM) +#define DWARF_FRAME_RETURN_COLUMN 16 #define STACK_DYNAMIC_OFFSET(FNDECL) (-crtl->outgoing_args_size) #define ACCUMULATE_OUTGOING_ARGS 1 #define RETURN_ADDR_RTX(COUNT,FRAMEADDR) \ @@ -138,7 +139,8 @@ #define WORK_ITEM_ID_Z_REG 162 #define SOFT_ARG_REG 416 #define FRAME_POINTER_REGNUM 418 -#define FIRST_PSEUDO_REGISTER 420 +#define DWARF_LINK_REGISTER 420 +#define FIRST_PSEUDO_REGISTER 421 #define FIRST_PARM_REG 24 #define NUM_PARM_REGS 6 @@ -200,7 +202,7 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ /* Other registers. */ \ - 1, 1, 1, 1 \ + 1, 1, 1, 1, 1 \ } #define CALL_USED_REGISTERS { \ @@ -238,7 +240,7 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ /* Other registers. */ \ - 1, 1, 1, 1 \ + 1, 1, 1, 1, 1 \ } @@ -517,7 +519,7 @@ enum gcn_address_spaces "v236", "v237", "v238", "v239", "v240", "v241", "v242", "v243", "v244", \ "v245", "v246", "v247", "v248", "v249", "v250", "v251", "v252", "v253", \ "v254", "v255", \ - "?ap0", "?ap1", "?fp0", "?fp1" } + "?ap0", "?ap1", "?fp0", "?fp1", "?dwlr" } #define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE, X, CODE) #define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) -- cgit v1.1 From 22f201e4b32a4f8bc1e6462ee19643edae5d25a3 Mon Sep 17 00:00:00 2001 From: Hafiz Abid Qadeer Date: Mon, 21 Jun 2021 22:47:58 +0100 Subject: [amdgcn] Use frame pointer for CFA expressions. As size of address is bigger than registers in amdgcn, we are forced to use DW_CFA_def_cfa_expression to make an expression that concatenates multiple registers for the value of the CFA. This then prohibits us from using many of the dwarf ops which expect CFA rule to be a single regsiter plus an offset. Using frame pointer in the CFA rule is only real possibility as it is saved in every frame and it is easy to unwind its value. So unless user gives fomit-frame-pointer, we use frame pointer for the cfi information. This options also has a different default now. gcc/ * common/config/gcn/gcn-common.c (gcn_option_optimization_table): Change OPT_fomit_frame_pointer to -O3. * config/gcn/gcn.c (gcn_expand_prologue): Prefer the frame pointer when emitting CFI. (gcn_expand_prologue): Prefer the frame pointer when emitting CFI. (gcn_frame_pointer_rqd): New function. (TARGET_FRAME_POINTER_REQUIRED): New hook. --- gcc/common/config/gcn/gcn-common.c | 2 +- gcc/config/gcn/gcn.c | 60 +++++++++++++++++++++++++++++--------- 2 files changed, 47 insertions(+), 15 deletions(-) (limited to 'gcc') diff --git a/gcc/common/config/gcn/gcn-common.c b/gcc/common/config/gcn/gcn-common.c index 305c310..695eb46 100644 --- a/gcc/common/config/gcn/gcn-common.c +++ b/gcc/common/config/gcn/gcn-common.c @@ -27,7 +27,7 @@ /* Set default optimization options. */ static const struct default_options gcn_option_optimization_table[] = { - { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, + { OPT_LEVELS_3_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, { OPT_LEVELS_NONE, 0, NULL, 0 } }; diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c index ef4ed7c..a999897 100644 --- a/gcc/config/gcn/gcn.c +++ b/gcc/config/gcn/gcn.c @@ -2900,10 +2900,14 @@ gcn_expand_prologue () rtx adjustment = gen_int_mode (sp_adjust, SImode); rtx insn = emit_insn (gen_addsi3_scalar_carry (sp_lo, sp_lo, adjustment, scc)); - RTX_FRAME_RELATED_P (insn) = 1; - add_reg_note (insn, REG_FRAME_RELATED_EXPR, - gen_rtx_SET (sp, - gen_rtx_PLUS (DImode, sp, adjustment))); + if (!offsets->need_frame_pointer) + { + RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_FRAME_RELATED_EXPR, + gen_rtx_SET (sp, + gen_rtx_PLUS (DImode, sp, + adjustment))); + } emit_insn (gen_addcsi3_scalar_zero (sp_hi, sp_hi, scc)); } @@ -2917,25 +2921,24 @@ gcn_expand_prologue () rtx adjustment = gen_int_mode (fp_adjust, SImode); rtx insn = emit_insn (gen_addsi3_scalar_carry(fp_lo, sp_lo, adjustment, scc)); - RTX_FRAME_RELATED_P (insn) = 1; - add_reg_note (insn, REG_FRAME_RELATED_EXPR, - gen_rtx_SET (fp, - gen_rtx_PLUS (DImode, sp, adjustment))); emit_insn (gen_addcsi3_scalar (fp_hi, sp_hi, (fp_adjust < 0 ? GEN_INT (-1) : const0_rtx), scc, scc)); + + /* Set the CFA to the entry stack address, as an offset from the + frame pointer. This is preferred because the frame pointer is + saved in each frame, whereas the stack pointer is not. */ + RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_DEF_CFA, + gen_rtx_PLUS (DImode, fp, + GEN_INT (-(offsets->pretend_size + + offsets->callee_saves)))); } rtx_insn *seq = get_insns (); end_sequence (); - /* FIXME: Prologue insns should have this flag set for debug output, etc. - but it causes issues for now. - for (insn = seq; insn; insn = NEXT_INSN (insn)) - if (INSN_P (insn)) - RTX_FRAME_RELATED_P (insn) = 1;*/ - emit_insn (seq); } else @@ -3011,6 +3014,16 @@ gcn_expand_prologue () gen_rtx_SET (sp, gen_rtx_PLUS (DImode, sp, dbg_adjustment))); + if (offsets->need_frame_pointer) + { + /* Set the CFA to the entry stack address, as an offset from the + frame pointer. This is necessary when alloca is used, and + harmless otherwise. */ + rtx neg_adjust = gen_int_mode (-offsets->callee_saves, DImode); + add_reg_note (insn, REG_CFA_DEF_CFA, + gen_rtx_PLUS (DImode, fp, neg_adjust)); + } + /* Make sure the flat scratch reg doesn't get optimised away. */ emit_insn (gen_prologue_use (gen_rtx_REG (DImode, FLAT_SCRATCH_REG))); } @@ -3114,6 +3127,23 @@ gcn_expand_epilogue (void) emit_jump_insn (gen_gcn_return ()); } +/* Implement TARGET_FRAME_POINTER_REQUIRED. + + Return true if the frame pointer should not be eliminated. */ + +bool +gcn_frame_pointer_rqd (void) +{ + /* GDB needs the frame pointer in order to unwind properly, + but that's not important for the entry point, unless alloca is used. + It's not important for code execution, so we should repect the + -fomit-frame-pointer flag. */ + return (!flag_omit_frame_pointer + && cfun + && (cfun->calls_alloca + || (cfun->machine && cfun->machine->normal_function))); +} + /* Implement TARGET_CAN_ELIMINATE. Return true if the compiler is allowed to try to replace register number @@ -6410,6 +6440,8 @@ gcn_dwarf_register_span (rtx rtl) #define TARGET_EMUTLS_VAR_INIT gcn_emutls_var_init #undef TARGET_EXPAND_BUILTIN #define TARGET_EXPAND_BUILTIN gcn_expand_builtin +#undef TARGET_FRAME_POINTER_REQUIRED +#define TARGET_FRAME_POINTER_REQUIRED gcn_frame_pointer_rqd #undef TARGET_FUNCTION_ARG #undef TARGET_FUNCTION_ARG_ADVANCE #define TARGET_FUNCTION_ARG_ADVANCE gcn_function_arg_advance -- cgit v1.1 From b5bb7f328d56cccfb85932ff586138e5a4ef1436 Mon Sep 17 00:00:00 2001 From: Hafiz Abid Qadeer Date: Fri, 28 May 2021 18:06:57 +0100 Subject: [amdgcn] Add hook for DWARF address spaces. Map GCN address spaces to the proposed DWARF address spaces defined by AMD at https://llvm.org/docs/AMDGPUUsage.html#amdgpu-dwarf-address-class-mapping-table gcc/ * config/gcn/gcn.c: Include dwarf2.h. (gcn_addr_space_debug): New function. (TARGET_ADDR_SPACE_DEBUG): New hook. --- gcc/config/gcn/gcn.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'gcc') diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c index a999897..6d02a4a 100644 --- a/gcc/config/gcn/gcn.c +++ b/gcc/config/gcn/gcn.c @@ -50,6 +50,7 @@ #include "varasm.h" #include "intl.h" #include "rtl-iter.h" +#include "dwarf2.h" /* This file should be included last. */ #include "target-def.h" @@ -1497,6 +1498,32 @@ gcn_addr_space_convert (rtx op, tree from_type, tree to_type) gcc_unreachable (); } +/* Implement TARGET_ADDR_SPACE_DEBUG. + + Return the dwarf address space class for each hardware address space. */ + +static int +gcn_addr_space_debug (addr_space_t as) +{ + switch (as) + { + case ADDR_SPACE_DEFAULT: + case ADDR_SPACE_FLAT: + case ADDR_SPACE_SCALAR_FLAT: + case ADDR_SPACE_FLAT_SCRATCH: + return DW_ADDR_none; + case ADDR_SPACE_GLOBAL: + return 1; // DW_ADDR_LLVM_global + case ADDR_SPACE_LDS: + return 3; // DW_ADDR_LLVM_group + case ADDR_SPACE_SCRATCH: + return 4; // DW_ADDR_LLVM_private + case ADDR_SPACE_GDS: + return 0x8000; // DW_ADDR_AMDGPU_region + } + gcc_unreachable (); +} + /* Implement REGNO_MODE_CODE_OK_FOR_BASE_P via gcn.h @@ -6391,6 +6418,8 @@ gcn_dwarf_register_span (rtx rtl) #undef TARGET_ADDR_SPACE_ADDRESS_MODE #define TARGET_ADDR_SPACE_ADDRESS_MODE gcn_addr_space_address_mode +#undef TARGET_ADDR_SPACE_DEBUG +#define TARGET_ADDR_SPACE_DEBUG gcn_addr_space_debug #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \ gcn_addr_space_legitimate_address_p -- cgit v1.1 From c28e1d288ab727de6eb493e1aa2eadf5d5eef3ab Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 30 Jun 2021 13:12:36 -0400 Subject: c++: Fix push_access_scope and introduce RAII wrapper for it When push_access_scope is passed a TYPE_DECL for a class type (which can happen during e.g. satisfaction), we undesirably push only the enclosing context of the class instead of the class itself. This causes us to mishandle e.g. testcase below due to us not entering the scope of A before checking its constraints. This patch adjusts push_access_scope accordingly, and introduces an RAII wrapper for it. We make use of this wrapper right away by replacing the only user of push_nested_class_guard with this new wrapper, which means we can remove push_nested_class_guard (whose functionality is basically subsumed by the new wrapper). gcc/cp/ChangeLog: * constraint.cc (get_normalized_constraints_from_decl): Use push_access_scope_guard instead of push_nested_class_guard. * cp-tree.h (struct push_nested_class_guard): Replace with ... (struct push_access_scope_guard): ... this. * pt.c (push_access_scope): When the argument corresponds to a class type, push the class instead of its context. (pop_access_scope): Adjust accordingly. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-access2.C: New test. --- gcc/cp/constraint.cc | 7 +------ gcc/cp/cp-tree.h | 23 +++++++++++++---------- gcc/cp/pt.c | 7 ++++++- gcc/testsuite/g++.dg/cpp2a/concepts-access2.C | 13 +++++++++++++ 4 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-access2.C (limited to 'gcc') diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 6df3ca6..99d3ccc 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -926,12 +926,7 @@ get_normalized_constraints_from_decl (tree d, bool diag = false) tree norm = NULL_TREE; if (tree ci = get_constraints (decl)) { - push_nested_class_guard pncs (DECL_CONTEXT (d)); - - temp_override ovr (current_function_decl); - if (TREE_CODE (decl) == FUNCTION_DECL) - current_function_decl = decl; - + push_access_scope_guard pas (decl); norm = get_normalized_constraints_from_info (ci, tmpl, diag); } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6f71371..58da746 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -8463,21 +8463,24 @@ is_constrained_auto (const_tree t) return is_auto (t) && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t); } -/* RAII class to push/pop class scope T; if T is not a class, do nothing. */ +/* RAII class to push/pop the access scope for T. */ -struct push_nested_class_guard +struct push_access_scope_guard { - bool push; - push_nested_class_guard (tree t) - : push (t && CLASS_TYPE_P (t)) + tree decl; + push_access_scope_guard (tree t) + : decl (t) { - if (push) - push_nested_class (t); + if (VAR_OR_FUNCTION_DECL_P (decl) + || TREE_CODE (decl) == TYPE_DECL) + push_access_scope (decl); + else + decl = NULL_TREE; } - ~push_nested_class_guard () + ~push_access_scope_guard () { - if (push) - pop_nested_class (); + if (decl) + pop_access_scope (decl); } }; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d2936c1..f8f7616 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -224,7 +224,7 @@ static void instantiate_body (tree pattern, tree args, tree d, bool nested); /* Make the current scope suitable for access checking when we are processing T. T can be FUNCTION_DECL for instantiated function template, VAR_DECL for static member variable, or TYPE_DECL for - alias template (needed by instantiate_decl). */ + for a class or alias template (needed by instantiate_decl). */ void push_access_scope (tree t) @@ -234,6 +234,9 @@ push_access_scope (tree t) if (DECL_FRIEND_CONTEXT (t)) push_nested_class (DECL_FRIEND_CONTEXT (t)); + else if (DECL_IMPLICIT_TYPEDEF_P (t) + && CLASS_TYPE_P (TREE_TYPE (t))) + push_nested_class (TREE_TYPE (t)); else if (DECL_CLASS_SCOPE_P (t)) push_nested_class (DECL_CONTEXT (t)); else if (deduction_guide_p (t) && DECL_ARTIFICIAL (t)) @@ -260,6 +263,8 @@ pop_access_scope (tree t) current_function_decl = saved_access_scope->pop(); if (DECL_FRIEND_CONTEXT (t) + || (DECL_IMPLICIT_TYPEDEF_P (t) + && CLASS_TYPE_P (TREE_TYPE (t))) || DECL_CLASS_SCOPE_P (t) || (deduction_guide_p (t) && DECL_ARTIFICIAL (t))) pop_nested_class (); diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-access2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-access2.C new file mode 100644 index 0000000..8ddcad2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-access2.C @@ -0,0 +1,13 @@ +// { dg-do compile { target concepts } } + +template requires T::value struct A { }; +template requires T::value struct B { }; // { dg-error "private" } + +struct S { +private: + static constexpr bool value = true; + template requires T::value friend struct A; +}; + +A x; +B y; // { dg-error "constraint" } -- cgit v1.1 From 730d021e3e4acc7c0031113ec720c82e31d405e5 Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Wed, 30 Jun 2021 14:54:48 -0400 Subject: Fix IEEE 128-bit min/max test. This patch fixes the float128-minmax.c test so that it can accommodate the generation of xsmincqp and xsmaxcqp instructions on power10. I changed the effective target from 'float128' to 'ppc_float128_hw', since this needs the IEEE 128-bit float hardware support. Changing to use 'ppc_float128_hw' allows the 'lp64' test to be dropped. The 'lp64' test originally was needed because big endian 32-bit code cannot enable the IEEE 128-bit floating point instructions. gcc/testsuite/ 2021-06-30 Michael Meissner * gcc.target/powerpc/float128-minmax.c: Adjust expected code for power10. * lib/target-supports.exp (check_effective_target_has_arch_pwr10): New. --- gcc/testsuite/gcc.target/powerpc/float128-minmax.c | 11 ++++++----- gcc/testsuite/lib/target-supports.exp | 10 ++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/powerpc/float128-minmax.c b/gcc/testsuite/gcc.target/powerpc/float128-minmax.c index fe39751..ef8f729 100644 --- a/gcc/testsuite/gcc.target/powerpc/float128-minmax.c +++ b/gcc/testsuite/gcc.target/powerpc/float128-minmax.c @@ -1,6 +1,4 @@ -/* { dg-do compile { target lp64 } } */ -/* { dg-require-effective-target powerpc_p9vector_ok } */ -/* { dg-require-effective-target float128 } */ +/* { dg-require-effective-target ppc_float128_hw } */ /* { dg-options "-mpower9-vector -O2 -ffast-math" } */ #ifndef TYPE @@ -12,5 +10,8 @@ TYPE f128_min (TYPE a, TYPE b) { return __builtin_fminf128 (a, b); } TYPE f128_max (TYPE a, TYPE b) { return __builtin_fmaxf128 (a, b); } -/* { dg-final { scan-assembler {\mxscmpuqp\M} } } */ -/* { dg-final { scan-assembler-not {\mbl\M} } } */ +/* Adjust code power10 which has native min/max instructions. */ +/* { dg-final { scan-assembler-times {\mxscmpuqp\M} 2 { target { ! has_arch_pwr10 } } } } */ +/* { dg-final { scan-assembler-times {\mxsmincqp\M} 1 { target has_arch_pwr10 } } } */ +/* { dg-final { scan-assembler-times {\mxsmaxcqp\M} 1 { target has_arch_pwr10 } } } */ +/* { dg-final { scan-assembler-not {\mbl\M} } } */ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 7f78c55..789723f 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -6127,6 +6127,16 @@ proc check_effective_target_has_arch_pwr9 { } { }] } +proc check_effective_target_has_arch_pwr10 { } { + return [check_no_compiler_messages arch_pwr10 assembly { + #ifndef _ARCH_PWR10 + #error does not have power10 support. + #else + /* "has power10 support" */ + #endif + }] +} + # Return 1 if this is a PowerPC target supporting -mcpu=power10. # Limit this to 64-bit linux systems for now until other targets support # power10. -- cgit v1.1 From aa31ae697087940c60d0bb2fa60c951750bb65c4 Mon Sep 17 00:00:00 2001 From: Indu Bhagat Date: Wed, 30 Jun 2021 15:13:50 -0700 Subject: testsuite: Add missing dg-add-options to CTF testcase ctf-skip-types-4.c The test already has the appropriate dg-require-effective-target, but requires the dg-add-options to use the flags needed, if any. This patch fixes the failure of this testcase on powerpc64. 2021-06-30 Indu Bhagat gcc/testsuite/ * gcc.dg/debug/ctf/ctf-skip-types-4.c: Add dg-add-options float64 and float64x. --- gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-4.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-4.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-4.c index f4374e6..7033121 100644 --- a/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-4.c +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-4.c @@ -14,6 +14,8 @@ /* { dg-require-effective-target float64 } */ /* { dg-require-effective-target float64x } */ +/* { dg-add-options float64 } */ +/* { dg-add-options float64x } */ _Float64 f64; _Float64x f64x; -- cgit v1.1 From 25b6bfea5f14da53116f2d3efe2446de89b9bc03 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 1 Jul 2021 00:16:41 +0000 Subject: Daily bump. --- gcc/ChangeLog | 109 ++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/analyzer/ChangeLog | 237 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/cp/ChangeLog | 16 ++++ gcc/testsuite/ChangeLog | 65 +++++++++++++ 5 files changed, 428 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 52d2397..0b2c08f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,112 @@ +2021-06-30 Hafiz Abid Qadeer + + * config/gcn/gcn.c: Include dwarf2.h. + (gcn_addr_space_debug): New function. + (TARGET_ADDR_SPACE_DEBUG): New hook. + +2021-06-30 Hafiz Abid Qadeer + + * common/config/gcn/gcn-common.c + (gcn_option_optimization_table): Change OPT_fomit_frame_pointer to -O3. + * config/gcn/gcn.c (gcn_expand_prologue): Prefer the frame pointer + when emitting CFI. + (gcn_expand_prologue): Prefer the frame pointer when emitting CFI. + (gcn_frame_pointer_rqd): New function. + (TARGET_FRAME_POINTER_REQUIRED): New hook. + +2021-06-30 Hafiz Abid Qadeer + + * config/gcn/gcn.c (move_callee_saved_registers): Emit CFI notes for + prologue register saves. + (gcn_debug_unwind_info): Use UI_DWARF2. + (gcn_dwarf_register_number): Map DWARF_LINK_REGISTER to DWARF PC. + (gcn_dwarf_register_span): DWARF_LINK_REGISTER doesn't span. + * config/gcn/gcn.h: (DWARF_FRAME_RETURN_COLUMN): New define. + (DWARF_LINK_REGISTER): New define. + (FIRST_PSEUDO_REGISTER): Increment. + (FIXED_REGISTERS): Add entry for DWARF_LINK_REGISTER. + (CALL_USED_REGISTERS): Likewise. + (REGISTER_NAMES): Likewise. + +2021-06-30 Richard Biener + + PR tree-optimization/101267 + * tree-vect-stmts.c (vect_check_scalar_mask): Adjust + API and use SLP compatible interface of vect_is_simple_use. + Reject not vectorized SLP defs for callers that do not support + that. + (vect_check_store_rhs): Handle masked stores and pass down + the appropriate operator index. + (vectorizable_call): Adjust. + (vectorizable_store): Likewise. + (vectorizable_load): Likewise. Handle SLP pecularity of + masked loads. + (vect_is_simple_use): Remove special-casing of masked stores. + +2021-06-30 Tobias Burnus + + * common.opt (foffload): Remove help as Driver only. + * gcc.c (display_help): Add -foffload. + +2021-06-30 Tobias Burnus + + * gcc.c (close_at_file, execute): Replace alloca by XALLOCAVEC. + (check_offload_target_name): Fix splitting OFFLOAD_TARGETS into + a candidate list; better inform no offload target is configured + and fix hint extraction when passed target is not '\0' at [len]. + * common.opt (foffload): Add tailing '.'. + (foffload-options): Likewise; fix flag name in the help string. + +2021-06-30 prathamesh.kulkarni + + PR target/66791 + * config/arm/arm_neon.h: Move vabs intrinsics before vcage_f32. + (vcage_f32): Gate comparison on __FAST_MATH__. + (vcageq_f32): Likewise. + (vcale_f32): Likewise. + (vcaleq_f32): Likewise. + (vcagt_f32): Likewise. + (vcagtq_f32): Likewise. + (vcalt_f32): Likewise. + (vcaltq_f32): Likewise. + (vcage_f16): Likewise. + (vcageq_f16): Likewise. + (vcale_f16): Likewise. + (vcaleq_f16): Likewise. + (vcagt_f16): Likewise. + (vcagtq_f16): Likewise. + (vcalt_f16): Likewise. + (vcaltq_f16): Likewise. + +2021-06-30 Richard Biener + + PR tree-optimization/101264 + * tree-vect-slp.c (vect_optimize_slp): Propagate the + computed perm_in to all "any" permute successors + we cannot de-duplicate immediately. + +2021-06-30 liuhongt + + PR target/101248 + * config/i386/sse.md + (avx512f_sfixupimm): + Refined to .. + (avx512f_sfixupimm): + this. + (avx512f_sfixupimm_mask"): Refined. + * config/i386/subst.md (maskz_scalar): New define_subst. + (maskz_scalar_name): New subst_attr. + (maskz_scalar_op5): Ditto. + (round_saeonly_maskz_scalar_op5): Ditto. + (round_saeonly_maskz_scalar_operand5): Ditto. + +2021-06-30 David Edelsohn + + * config/rs6000/rs6000.c (rs6000_xcoff_section_type_flags): + Increase code CSECT alignment to at least 32 bytes. + * config/rs6000/xcoff.h (TEXT_SECTION_ASM_OP): Add 32 byte + alignment designation. + 2021-06-29 Sergei Trofimovich * doc/generic.texi: Fix s/net yet/not yet/ typo. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 80bc3a6..8d2a207 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210630 +20210701 diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index cc0eb11..bb9f4d3 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,240 @@ +2021-06-30 David Malcolm + + PR analyzer/95006 + * analyzer.h (class repeated_svalue): New forward decl. + (class bits_within_svalue): New forward decl. + (class sized_region): New forward decl. + (get_field_at_bit_offset): New forward decl. + * engine.cc (exploded_graph::get_or_create_node): Validate the + merged state. + (exploded_graph::maybe_process_run_of_before_supernode_enodes): + Validate the states at each stage. + * program-state.cc (program_state::validate): Validate + m_region_model. + * region-model-impl-calls.cc (region_model::impl_call_memset): + Replace special-case logic for handling constant sizes with + a call to fill_region of a sized_region with the given fill value. + * region-model-manager.cc (maybe_undo_optimize_bit_field_compare): + Drop DK_direct. + (region_model_manager::maybe_fold_sub_svalue): Fold element-based + subregions of an initial value into initial values of an element. + Fold subvalues of repeated svalues. + (region_model_manager::maybe_fold_repeated_svalue): New. + (region_model_manager::get_or_create_repeated_svalue): New. + (get_bit_range_for_field): New. + (get_byte_range_for_field): New. + (get_field_at_byte_range): New. + (region_model_manager::maybe_fold_bits_within_svalue): New. + (region_model_manager::get_or_create_bits_within): New. + (region_model_manager::get_sized_region): New. + (region_model_manager::log_stats): Update for addition of + m_repeated_values_map, m_bits_within_values_map, and + m_sized_regions. + * region-model.cc (region_model::validate): New. + (region_model::on_assignment): Drop enum binding_kind. + (region_model::get_initial_value_for_global): Likewise. + (region_model::get_rvalue_for_bits): Replace body with call to + get_or_create_bits_within. + (region_model::get_capacity): Handle RK_SIZED. + (region_model::set_value): Drop enum binding_kind. + (region_model::fill_region): New. + (region_model::get_representative_path_var_1): Handle RK_SIZED. + * region-model.h (visitor::visit_repeated_svalue): New. + (visitor::visit_bits_within_svalue): New. + (region_model_manager::get_or_create_repeated_svalue): New decl. + (region_model_manager::get_or_create_bits_within): New decl. + (region_model_manager::get_sized_region): New decl. + (region_model_manager::maybe_fold_repeated_svalue): New decl. + (region_model_manager::maybe_fold_bits_within_svalue): New decl. + (region_model_manager::repeated_values_map_t): New typedef. + (region_model_manager::m_repeated_values_map): New field. + (region_model_manager::bits_within_values_map_t): New typedef. + (region_model_manager::m_bits_within_values_map): New field. + (region_model_manager::m_sized_regions): New field. + (region_model::fill_region): New decl. + * region.cc (region::get_base_region): Handle RK_SIZED. + (region::base_region_p): Likewise. + (region::get_byte_size_sval): New. + (get_field_at_bit_offset): Make non-static. + (region::calc_offset): Move implementation of cases to + get_relative_concrete_offset vfunc implementations. Handle + RK_SIZED. + (region::get_relative_concrete_offset): New. + (decl_region::get_svalue_for_initializer): Drop enum binding_kind. + (field_region::get_relative_concrete_offset): New, from + region::calc_offset. + (element_region::get_relative_concrete_offset): Likewise. + (offset_region::get_relative_concrete_offset): Likewise. + (sized_region::accept): New. + (sized_region::dump_to_pp): New. + (sized_region::get_byte_size): New. + (sized_region::get_bit_size): New. + * region.h (enum region_kind): Add RK_SIZED. + (region::dyn_cast_sized_region): New. + (region::get_byte_size): Make virtual. + (region::get_bit_size): Likewise. + (region::get_byte_size_sval): New decl. + (region::get_relative_concrete_offset): New decl. + (field_region::get_relative_concrete_offset): New decl. + (element_region::get_relative_concrete_offset): Likewise. + (offset_region::get_relative_concrete_offset): Likewise. + (class sized_region): New. + * store.cc (binding_kind_to_string): Delete. + (binding_key::make): Drop enum binding_kind. + (binding_key::dump_to_pp): Delete. + (binding_key::cmp_ptrs): Drop enum binding_kind. + (bit_range::contains_p): New. + (byte_range::dump): New. + (byte_range::contains_p): New. + (byte_range::cmp): New. + (concrete_binding::dump_to_pp): Drop enum binding_kind. + (concrete_binding::cmp_ptr_ptr): Likewise. + (symbolic_binding::dump_to_pp): Likewise. + (symbolic_binding::cmp_ptr_ptr): Likewise. + (binding_map::apply_ctor_val_to_range): Likewise. + (binding_map::apply_ctor_pair_to_child_region): Likewise. + (binding_map::get_overlapping_bindings): New. + (binding_map::remove_overlapping_bindings): New. + (binding_cluster::validate): New. + (binding_cluster::bind): Drop enum binding_kind. + (binding_cluster::bind_compound_sval): Likewise. + (binding_cluster::purge_region): Likewise. + (binding_cluster::zero_fill_region): Reimplement in terms of... + (binding_cluster::fill_region): New. + (binding_cluster::mark_region_as_unknown): Drop enum binding_kind. + (binding_cluster::get_binding): Likewise. + (binding_cluster::get_binding_recursive): Likewise. + (binding_cluster::get_any_binding): Likewise. + (binding_cluster::maybe_get_compound_binding): Reimplement. + (binding_cluster::get_overlapping_bindings): Delete. + (binding_cluster::remove_overlapping_bindings): Reimplement in + terms of binding_map::remove_overlapping_bindings. + (binding_cluster::can_merge_p): Update for removal of + enum binding_kind. + (binding_cluster::on_unknown_fncall): Drop enum binding_kind. + (binding_cluster::maybe_get_simple_value): Likewise. + (store_manager::get_concrete_binding): Likewise. + (store_manager::get_symbolic_binding): Likewise. + (store::validate): New. + (store::set_value): Drop enum binding_kind. + (store::zero_fill_region): Reimplement in terms of... + (store::fill_region): New. + (selftest::test_binding_key_overlap): Drop enum binding_kind. + * store.h (enum binding_kind): Delete. + (binding_kind_to_string): Delete decl. + (binding_key::make): Drop enum binding_kind. + (binding_key::dump_to_pp): Make pure virtual. + (binding_key::get_kind): Delete. + (binding_key::mark_deleted): Delete. + (binding_key::mark_empty): Delete. + (binding_key::is_deleted): Delete. + (binding_key::is_empty): Delete. + (binding_key::binding_key): Delete. + (binding_key::impl_hash): Delete. + (binding_key::impl_eq): Delete. + (binding_key::m_kind): Delete. + (bit_range::get_last_bit_offset): New. + (bit_range::contains_p): New. + (byte_range::contains_p): New. + (byte_range::operator==): New. + (byte_range::get_start_byte_offset): New. + (byte_range::get_next_byte_offset): New. + (byte_range::get_last_byte_offset): New. + (byte_range::as_bit_range): New. + (byte_range::cmp): New. + (concrete_binding::concrete_binding): Drop enum binding_kind. + (concrete_binding::hash): Likewise. + (concrete_binding::operator==): Likewise. + (concrete_binding::mark_deleted): New. + (concrete_binding::mark_empty): New. + (concrete_binding::is_deleted): New. + (concrete_binding::is_empty): New. + (default_hash_traits::empty_zero_p): Make false. + (symbolic_binding::symbolic_binding): Drop enum binding_kind. + (symbolic_binding::hash): Likewise. + (symbolic_binding::operator==): Likewise. + (symbolic_binding::mark_deleted): New. + (symbolic_binding::mark_empty): New. + (symbolic_binding::is_deleted): New. + (symbolic_binding::is_empty): New. + (binding_map::remove_overlapping_bindings): New decl. + (binding_map::get_overlapping_bindings): New decl. + (binding_cluster::validate): New decl. + (binding_cluster::bind): Drop enum binding_kind. + (binding_cluster::fill_region): New decl. + (binding_cluster::get_binding): Drop enum binding_kind. + (binding_cluster::get_binding_recursive): Likewise. + (binding_cluster::get_overlapping_bindings): Delete. + (store::validate): New decl. + (store::set_value): Drop enum binding_kind. + (store::fill_region): New decl. + (store_manager::get_concrete_binding): Drop enum binding_kind. + (store_manager::get_symbolic_binding): Likewise. + * svalue.cc (svalue::cmp_ptr): Handle SK_REPEATED and + SK_BITS_WITHIN. + (svalue::extract_bit_range): New. + (svalue::maybe_fold_bits_within): New. + (constant_svalue::maybe_fold_bits_within): New. + (unknown_svalue::maybe_fold_bits_within): New. + (unaryop_svalue::maybe_fold_bits_within): New. + (repeated_svalue::repeated_svalue): New. + (repeated_svalue::dump_to_pp): New. + (repeated_svalue::accept): New. + (repeated_svalue::all_zeroes_p): New. + (repeated_svalue::maybe_fold_bits_within): New. + (bits_within_svalue::bits_within_svalue): New. + (bits_within_svalue::dump_to_pp): New. + (bits_within_svalue::maybe_fold_bits_within): New. + (bits_within_svalue::accept): New. + (bits_within_svalue::implicitly_live_p): New. + (compound_svalue::maybe_fold_bits_within): New. + * svalue.h (enum svalue_kind): Add SK_REPEATED and SK_BITS_WITHIN. + (svalue::dyn_cast_repeated_svalue): New. + (svalue::dyn_cast_bits_within_svalue): New. + (svalue::extract_bit_range): New decl. + (svalue::maybe_fold_bits_within): New vfunc decl. + (region_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. + (region_svalue::key_t::is_empty): Likewise. + (default_hash_traits::empty_zero_p): Make false. + (constant_svalue::maybe_fold_bits_within): New. + (unknown_svalue::maybe_fold_bits_within): New. + (poisoned_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. + (poisoned_svalue::key_t::is_empty): Likewise. + (default_hash_traits::empty_zero_p): Make + false. + (setjmp_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. + (setjmp_svalue::key_t::is_empty): Likewise. + (default_hash_traits::empty_zero_p): Make + false. + (unaryop_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. + (unaryop_svalue::key_t::is_empty): Likewise. + (unaryop_svalue::maybe_fold_bits_within): New. + (default_hash_traits::empty_zero_p): Make + false. + (binop_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. + (binop_svalue::key_t::is_empty): Likewise. + (default_hash_traits::empty_zero_p): Make + false. + (sub_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. + (sub_svalue::key_t::is_empty): Likewise. + (default_hash_traits::empty_zero_p): Make + false. + (class repeated_svalue): New. + (is_a_helper ::test): New. + (struct default_hash_traits): New. + (class bits_within_svalue): New. + (is_a_helper ::test): New. + (struct default_hash_traits): New. + (widening_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. + (widening_svalue::key_t::is_empty): Likewise. + (default_hash_traits::empty_zero_p): Make + false. + (compound_svalue::key_t::mark_empty): Use 2 rather than NULL_TREE. + (compound_svalue::key_t::is_empty): Likewise. + (compound_svalue::maybe_fold_bits_within): New. + (default_hash_traits::empty_zero_p): Make + false. + 2021-06-28 David Malcolm * analyzer.h (byte_offset_t): New typedef. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 01b29b1..d861f29 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2021-06-30 Patrick Palka + + * constraint.cc (get_normalized_constraints_from_decl): Use + push_access_scope_guard instead of push_nested_class_guard. + * cp-tree.h (struct push_nested_class_guard): Replace with ... + (struct push_access_scope_guard): ... this. + * pt.c (push_access_scope): When the argument corresponds to + a class type, push the class instead of its context. + (pop_access_scope): Adjust accordingly. + +2021-06-30 Marek Polacek + + PR c++/100975 + DR 2397 + * decl.c (create_array_type_for_decl): Allow array of auto. + 2021-06-29 Jason Merrill * pt.c (instantiate_decl): Only consider partial specializations of diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 51fc7ad..c14ff6e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,68 @@ +2021-06-30 Indu Bhagat + + * gcc.dg/debug/ctf/ctf-skip-types-4.c: Add dg-add-options float64 and + float64x. + +2021-06-30 Michael Meissner + + * gcc.target/powerpc/float128-minmax.c: Adjust expected code for + power10. + * lib/target-supports.exp (check_effective_target_has_arch_pwr10): + New. + +2021-06-30 Patrick Palka + + * g++.dg/cpp2a/concepts-access2.C: New test. + +2021-06-30 Marek Polacek + + PR c++/100975 + DR 2397 + * g++.dg/cpp0x/auto24.C: Remove dg-error. + * g++.dg/cpp0x/auto3.C: Adjust dg-error. + * g++.dg/cpp0x/auto42.C: Likewise. + * g++.dg/cpp0x/initlist75.C: Likewise. + * g++.dg/cpp0x/initlist80.C: Likewise. + * g++.dg/diagnostic/auto1.C: Remove dg-error. + * g++.dg/cpp23/auto-array.C: New test. + +2021-06-30 Richard Biener + + PR tree-optimization/101267 + * gfortran.dg/pr101267.f90: New testcase. + +2021-06-30 David Malcolm + + PR analyzer/95006 + * gcc.dg/analyzer/clobbers-1.c: New test. + * gcc.dg/analyzer/clobbers-2.c: New test. + * gcc.dg/analyzer/data-model-1.c (test_26): Mark xfail as fixed. + (test_28): Likewise. + (test_52): Likewise. Add coverage for end of buffer. + * gcc.dg/analyzer/explode-1.c: Add leak warning. + * gcc.dg/analyzer/memset-1.c (test_3): Mark xfail as fixed. + (test_4): Use char. Mark xfail as fixed. + (test_6b): New. + (test_7): Mark xfail as fixed. Add coverage for start of buffer. + (test_8): New. + (test_9): New. + * gcc.dg/analyzer/memset-CVE-2017-18549-1.c: New test. + * gcc.dg/analyzer/symbolic-8.c: New test. + +2021-06-30 Christophe Lyon + + * gcc.dg/debug/ctf/ctf-skip-types-2.c: Add dg-add-options float16. + +2021-06-30 Richard Biener + + PR tree-optimization/101264 + * gfortran.dg/pr101264.f90: New testcase. + +2021-06-30 liuhongt + + PR target/101248 + * gcc.target/i386/pr101248.c: New test. + 2021-06-29 Andrew MacLeod * gcc.dg/pr101254.c: New. -- cgit v1.1 From 613497aa6e28ca009d8498002424019d2a8a9ca5 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 30 Jun 2021 20:21:16 -0400 Subject: c++: Extend the PR96204 fix to variable templates too r12-1829 corrected the access scope during partial specialization matching of class templates, but overlooked the variable template case. This patch moves the access scope adjustment to within most_specialized_partial_spec so that all callers can benefit. This patch also adjusts a couple of these callers to avoid always passing the most general template of a variable template specialization, since that'd cause us to push the wrong access scope for e.g. the second testcase below (we'd push A instead of A/A). We ought to be passing the partially instantiated template instead. PR c++/96204 gcc/cp/ChangeLog: * pt.c (finish_template_variable): Pass the partially instantiated template and its args to instantiate_template. (instantiate_class_template_1): No need to call push_nested_class and pop_nested_class around the call to most_specialized_partial_spec. (instantiate_template_1): Pass the partially instantiated template to lookup_template_variable. (most_specialized_partial_spec): Use push_access_scope_guard to set the access scope appropriately. Use deferring_access_check_sentinel to force access to get checked immediately. (instantiate_decl): Just pass the VAR_DECL to most_specialized_partial_spec. gcc/testsuite/ChangeLog: * g++.dg/template/access41.C: New test. * g++.dg/template/access41a.C: New test. --- gcc/cp/pt.c | 21 ++++++++++----------- gcc/testsuite/g++.dg/template/access41.C | 24 ++++++++++++++++++++++++ gcc/testsuite/g++.dg/template/access41a.C | 29 +++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/access41.C create mode 100644 gcc/testsuite/g++.dg/template/access41a.C (limited to 'gcc') diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f8f7616..dda6c9e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10268,10 +10268,6 @@ finish_template_variable (tree var, tsubst_flags_t complain) tree templ = TREE_OPERAND (var, 0); tree arglist = TREE_OPERAND (var, 1); - tree tmpl_args = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (templ)); - arglist = add_outermost_template_args (tmpl_args, arglist); - - templ = most_general_template (templ); tree parms = DECL_TEMPLATE_PARMS (templ); arglist = coerce_innermost_template_parms (parms, arglist, templ, complain, /*req_all*/true, @@ -11774,11 +11770,8 @@ instantiate_class_template_1 (tree type) deferring_access_check_sentinel acs (dk_no_deferred); /* Determine what specialization of the original template to - instantiate; do this relative to the scope of the class for - sake of access checking. */ - push_nested_class (type); + instantiate. */ t = most_specialized_partial_spec (type, tf_warning_or_error); - pop_nested_class (); if (t == error_mark_node) return error_mark_node; else if (t) @@ -21134,7 +21127,7 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain) /* We need to determine if we're using a partial or explicit specialization now, because the type of the variable could be different. */ - tree tid = lookup_template_variable (gen_tmpl, targ_ptr); + tree tid = lookup_template_variable (tmpl, targ_ptr); tree elt = most_specialized_partial_spec (tid, complain); if (elt == error_mark_node) pattern = error_mark_node; @@ -24987,26 +24980,33 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) tree outer_args = NULL_TREE; tree tmpl, args; + tree decl; if (TYPE_P (target)) { tree tinfo = CLASSTYPE_TEMPLATE_INFO (target); tmpl = TI_TEMPLATE (tinfo); args = TI_ARGS (tinfo); + decl = TYPE_NAME (target); } else if (TREE_CODE (target) == TEMPLATE_ID_EXPR) { tmpl = TREE_OPERAND (target, 0); args = TREE_OPERAND (target, 1); + decl = DECL_TEMPLATE_RESULT (tmpl); } else if (VAR_P (target)) { tree tinfo = DECL_TEMPLATE_INFO (target); tmpl = TI_TEMPLATE (tinfo); args = TI_ARGS (tinfo); + decl = target; } else gcc_unreachable (); + push_access_scope_guard pas (decl); + deferring_access_check_sentinel acs (dk_no_deferred); + tree main_tmpl = most_general_template (tmpl); /* For determining which partial specialization to use, only the @@ -26011,8 +26011,7 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p) if (variable_template_specialization_p (d)) { /* Look up an explicit specialization, if any. */ - tree tid = lookup_template_variable (gen_tmpl, gen_args); - tree elt = most_specialized_partial_spec (tid, tf_warning_or_error); + tree elt = most_specialized_partial_spec (d, tf_warning_or_error); if (elt && elt != error_mark_node) { td = TREE_VALUE (elt); diff --git a/gcc/testsuite/g++.dg/template/access41.C b/gcc/testsuite/g++.dg/template/access41.C new file mode 100644 index 0000000..1ab9a1a --- /dev/null +++ b/gcc/testsuite/g++.dg/template/access41.C @@ -0,0 +1,24 @@ +// PR c++/96204 +// { dg-do compile { target c++14 } } +// A variant of access40.C where has_type_member is a variable template instead +// of a class template. + +template +constexpr bool has_type_member = false; + +template +constexpr bool has_type_member = true; + +struct Parent; + +struct Child { +private: + friend struct Parent; + typedef void type; +}; + +struct Parent { + // The partial specialization does not match despite Child::type + // being accessible from the current scope. + static_assert(!has_type_member, ""); +}; diff --git a/gcc/testsuite/g++.dg/template/access41a.C b/gcc/testsuite/g++.dg/template/access41a.C new file mode 100644 index 0000000..e108049 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/access41a.C @@ -0,0 +1,29 @@ +// PR c++/96204 +// { dg-do compile { target c++14 } } +// A variant of access40a.C where has_type_member is a variable template instead +// of a class template. + +template +struct A { + template + static constexpr bool has_type_member = false; +}; + +template +template +constexpr int A::has_type_member = true; + +struct Child { +private: + friend struct A; + typedef void type; +}; + +// The partial specialization matches because A is a friend of Child. +static_assert(A::has_type_member, ""); +using type1 = const int; +using type1 = decltype(A::has_type_member); + +static_assert(!A::has_type_member, ""); +using type2 = const bool; +using type2 = decltype(A::has_type_member); -- cgit v1.1 From a688c284dd3848b6c4ea553035f0f9769fb4fbc9 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 30 Jun 2021 20:44:52 -0400 Subject: c++: cxx_eval_array_reference and empty elem type [PR101194] Here the initializer for x is represented as an empty CONSTRUCTOR due to its empty element type. So during constexpr evaluation of the ARRAY_REF x[0], we end up trying to value initialize the omitted element at index 0, which fails because the element type is not default constructible. This patch makes cxx_eval_array_reference specifically handle the case where the element type is an empty type. PR c++/101194 gcc/cp/ChangeLog: * constexpr.c (cxx_eval_array_reference): When the element type is an empty type and the corresponding element is omitted, just return an empty CONSTRUCTOR instead of attempting value initialization. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-empty16.C: New test. --- gcc/cp/constexpr.c | 4 +++- gcc/testsuite/g++.dg/cpp0x/constexpr-empty16.C | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-empty16.C (limited to 'gcc') diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 4cd9db3..39787f3 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3845,7 +3845,9 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, directly for non-aggregates to avoid creating a garbage CONSTRUCTOR. */ tree val; constexpr_ctx new_ctx; - if (CP_AGGREGATE_TYPE_P (elem_type)) + if (is_really_empty_class (elem_type, /*ignore_vptr*/false)) + return build_constructor (elem_type, NULL); + else if (CP_AGGREGATE_TYPE_P (elem_type)) { tree empty_ctor = build_constructor (init_list_type_node, NULL); val = digest_init (elem_type, empty_ctor, tf_warning_or_error); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty16.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty16.C new file mode 100644 index 0000000..79be244 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty16.C @@ -0,0 +1,10 @@ +// PR c++/101194 +// { dg-do compile { target c++11 } } + +struct nodefault { + constexpr nodefault(int) { } +}; + +constexpr nodefault x[1] = { nodefault{0} }; + +constexpr nodefault y = x[0]; -- cgit v1.1 From 91c771ec8a3b649765de3e0a7b04cf946c6649ef Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 1 Jul 2021 08:55:49 +0200 Subject: openmp - Fix up && and || reductions [PR94366] As the testcase shows, the special treatment of && and || reduction combiners where we expand them as omp_out = (omp_out != 0) && (omp_in != 0) (or with ||) is not needed just for &&/|| on floating point or complex types, but for all &&/|| reductions - when expanded as omp_out = omp_out && omp_in (not in C but GENERIC) it is actually gimplified into NOP_EXPRs to bool from both operands, which turns non-zero values multiple of 2 into 0 rather than 1. This patch just treats all &&/|| the same and furthermore uses bool type instead of int for the comparisons. 2021-07-01 Jakub Jelinek PR middle-end/94366 gcc/ * omp-low.c (lower_rec_input_clauses): Rename is_fp_and_or to is_truth_op, set it for TRUTH_*IF_EXPR regardless of new_var's type, use boolean_type_node instead of integer_type_node as NE_EXPR type. (lower_reduction_clauses): Likewise. libgomp/ * testsuite/libgomp.c-c++-common/pr94366.c: New test. --- gcc/omp-low.c | 55 ++++++++++++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 31 deletions(-) (limited to 'gcc') diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 410a4a6..e7049c8 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -6505,11 +6505,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, if (code == MINUS_EXPR) code = PLUS_EXPR; - /* C/C++ permits FP/complex with || and &&. */ - bool is_fp_and_or - = ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR) - && (FLOAT_TYPE_P (TREE_TYPE (new_var)) - || TREE_CODE (TREE_TYPE (new_var)) == COMPLEX_TYPE)); + bool is_truth_op + = (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR); tree new_vard = new_var; if (is_simd && omp_is_reference (var)) { @@ -6560,17 +6557,18 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, } tree ivar2 = ivar; tree ref2 = ref; - if (is_fp_and_or) + if (is_truth_op) { tree zero = build_zero_cst (TREE_TYPE (ivar)); ivar2 = fold_build2_loc (clause_loc, NE_EXPR, - integer_type_node, ivar, + boolean_type_node, ivar, zero); ref2 = fold_build2_loc (clause_loc, NE_EXPR, - integer_type_node, ref, zero); + boolean_type_node, ref, + zero); } x = build2 (code, TREE_TYPE (ref), ref2, ivar2); - if (is_fp_and_or) + if (is_truth_op) x = fold_convert (TREE_TYPE (ref), x); ref = build_outer_var_ref (var, ctx); gimplify_assign (ref, x, &llist[1]); @@ -6592,19 +6590,19 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, tree ref = build_outer_var_ref (var, ctx); tree new_var2 = new_var; tree ref2 = ref; - if (is_fp_and_or) + if (is_truth_op) { tree zero = build_zero_cst (TREE_TYPE (new_var)); new_var2 = fold_build2_loc (clause_loc, NE_EXPR, - integer_type_node, new_var, + boolean_type_node, new_var, zero); ref2 = fold_build2_loc (clause_loc, NE_EXPR, - integer_type_node, ref, + boolean_type_node, ref, zero); } x = build2 (code, TREE_TYPE (ref2), ref2, new_var2); - if (is_fp_and_or) + if (is_truth_op) x = fold_convert (TREE_TYPE (new_var), x); ref = build_outer_var_ref (var, ctx); gimplify_assign (ref, x, dlist); @@ -7548,12 +7546,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, if (code == MINUS_EXPR) code = PLUS_EXPR; - /* C/C++ permits FP/complex with || and &&. */ - bool is_fp_and_or = ((code == TRUTH_ANDIF_EXPR - || code == TRUTH_ORIF_EXPR) - && (FLOAT_TYPE_P (TREE_TYPE (new_var)) - || (TREE_CODE (TREE_TYPE (new_var)) - == COMPLEX_TYPE))); + bool is_truth_op = (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR); if (count == 1) { tree addr = build_fold_addr_expr_loc (clause_loc, ref); @@ -7562,17 +7555,17 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr); tree new_var2 = new_var; tree ref2 = ref; - if (is_fp_and_or) + if (is_truth_op) { tree zero = build_zero_cst (TREE_TYPE (new_var)); new_var2 = fold_build2_loc (clause_loc, NE_EXPR, - integer_type_node, new_var, zero); - ref2 = fold_build2_loc (clause_loc, NE_EXPR, integer_type_node, + boolean_type_node, new_var, zero); + ref2 = fold_build2_loc (clause_loc, NE_EXPR, boolean_type_node, ref, zero); } x = fold_build2_loc (clause_loc, code, TREE_TYPE (new_var2), ref2, new_var2); - if (is_fp_and_or) + if (is_truth_op) x = fold_convert (TREE_TYPE (new_var), x); x = build2 (OMP_ATOMIC, void_type_node, addr, x); OMP_ATOMIC_MEMORY_ORDER (x) = OMP_MEMORY_ORDER_RELAXED; @@ -7680,16 +7673,16 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, { tree out2 = out; tree priv2 = priv; - if (is_fp_and_or) + if (is_truth_op) { tree zero = build_zero_cst (TREE_TYPE (out)); out2 = fold_build2_loc (clause_loc, NE_EXPR, - integer_type_node, out, zero); + boolean_type_node, out, zero); priv2 = fold_build2_loc (clause_loc, NE_EXPR, - integer_type_node, priv, zero); + boolean_type_node, priv, zero); } x = build2 (code, TREE_TYPE (out2), out2, priv2); - if (is_fp_and_or) + if (is_truth_op) x = fold_convert (TREE_TYPE (out), x); out = unshare_expr (out); gimplify_assign (out, x, &sub_seq); @@ -7726,16 +7719,16 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, { tree new_var2 = new_var; tree ref2 = ref; - if (is_fp_and_or) + if (is_truth_op) { tree zero = build_zero_cst (TREE_TYPE (new_var)); new_var2 = fold_build2_loc (clause_loc, NE_EXPR, - integer_type_node, new_var, zero); - ref2 = fold_build2_loc (clause_loc, NE_EXPR, integer_type_node, + boolean_type_node, new_var, zero); + ref2 = fold_build2_loc (clause_loc, NE_EXPR, boolean_type_node, ref, zero); } x = build2 (code, TREE_TYPE (ref), ref2, new_var2); - if (is_fp_and_or) + if (is_truth_op) x = fold_convert (TREE_TYPE (new_var), x); ref = build_outer_var_ref (var, ctx); gimplify_assign (ref, x, &sub_seq); -- cgit v1.1 From b0ab968999c9af88d45acf552ca673ef3960306a Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 1 Jul 2021 09:45:02 +0200 Subject: dwarf2out: Handle COMPOUND_LITERAL_EXPR in loc_list_from_tree_1 [PR101266] In this case dwarf2out_decl is called from the FEs with GENERIC but not yet gimplified expressions in it. As loc_list_from_tree_1 has an exhaustive list of tree codes it wants to handle and for checking asserts no other codes makes it in, we should handle even GENERIC trees that shouldn't be valid in GIMPLE. The following patch handles COMPOUND_LITERAL_EXPR by hnadling it like the underlying VAR_DECL temporary. Verified the emitted DWARF is correct (but unoptimized, we emit DW_OP_lit1 DW_OP_lit1 DW_OP_minus for the upper bound). 2021-07-01 Jakub Jelinek PR debug/101266 * dwarf2out.c (loc_list_from_tree_1): Handle COMPOUND_LITERAL_EXPR. * gcc.dg/pr101266.c: New test. --- gcc/dwarf2out.c | 4 ++++ gcc/testsuite/gcc.dg/pr101266.c | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/pr101266.c (limited to 'gcc') diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 13998b2..82783c4 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -19404,6 +19404,10 @@ loc_list_from_tree_1 (tree loc, int want_address, case FIX_TRUNC_EXPR: return 0; + case COMPOUND_LITERAL_EXPR: + return loc_list_from_tree_1 (COMPOUND_LITERAL_EXPR_DECL (loc), + 0, context); + default: /* Leave front-end specific codes as simply unknown. This comes up, for instance, with the C STMT_EXPR. */ diff --git a/gcc/testsuite/gcc.dg/pr101266.c b/gcc/testsuite/gcc.dg/pr101266.c new file mode 100644 index 0000000..d198089 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101266.c @@ -0,0 +1,8 @@ +/* PR debug/101266 */ +/* { dg-do compile } */ +/* { dg-options "-g -O2" } */ + +void +foo (int (*p)[(int){1}]) +{ +} -- cgit v1.1 From 7d8211603a3d04384812b481b0ae01205a287a72 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 30 Jun 2021 16:28:50 +0200 Subject: tree-optimization/101178 - handle VEC_PERM in SLP permute propagation This adds handling of VEC_PERM nodes to SLP permute propagation. Previously VEC_PERM acted as forced materialization of incoming permutes since it is a good place to do that (with the constraint of those only appearing for two-operator nodes). The following patch, in addition to supporting (but not forcing) this, enables VEC_PERM nodes acting as "any" permute on the outgoing side since they also can consume arbitrary permutes on that side. This again (meh) changes how we represent permutes and materialization on the graph vertices now explicitely having the common incoming permute as well as an outgoing permute and in case both are different the vertex acts as materialization point of the incoming permute. 2021-06-30 Richard Biener PR tree-optimization/101178 * tree-vect-slp.c (slpg_vertex::materialize): Remove. (slpg::perm_in): Add. (slpg::get_perm_in): Remove. (slpg::get_perm_materialized): Add. (vect_optimize_slp): Handle VEC_PERM nodes more optimally during permute propagation and materialization. * gcc.dg/vect/bb-slp-72.c: New testcase. * gcc.dg/vect/bb-slp-73.c: Likewise. * gcc.dg/vect/bb-slp-74.c: Likewise. --- gcc/testsuite/gcc.dg/vect/bb-slp-72.c | 29 +++++ gcc/testsuite/gcc.dg/vect/bb-slp-73.c | 29 +++++ gcc/testsuite/gcc.dg/vect/bb-slp-74.c | 30 +++++ gcc/tree-vect-slp.c | 200 ++++++++++++++++++++-------------- 4 files changed, 204 insertions(+), 84 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vect/bb-slp-72.c create mode 100644 gcc/testsuite/gcc.dg/vect/bb-slp-73.c create mode 100644 gcc/testsuite/gcc.dg/vect/bb-slp-74.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-72.c b/gcc/testsuite/gcc.dg/vect/bb-slp-72.c new file mode 100644 index 0000000..5b243fc --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-72.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ + +#include "tree-vect.h" + +double x[2], y[2], z[2], w[2]; + +void __attribute__((noipa)) foo () +{ + double tem0 = x[1] + y[1]; + double tem1 = x[0] - y[0]; + double tem2 = z[1] * tem0; + double tem3 = z[0] * tem1; + z[0] = tem2 - w[0]; + z[1] = tem3 + w[1]; +} + +int main() +{ + check_vect (); + + x[0] = 1.; x[1] = 2.; + y[0] = 7.; y[1] = -5.; + z[0] = 2.; z[1] = 3.; + w[0] = 9.; w[1] = -5.; + foo (); + if (z[0] != -18. || z[1] != -17.) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-73.c b/gcc/testsuite/gcc.dg/vect/bb-slp-73.c new file mode 100644 index 0000000..d4c8a51 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-73.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ + +#include "tree-vect.h" + +double x[2], y[2], z[2], w[2]; + +void __attribute__((noipa)) foo () +{ + double tem0 = x[1] + y[1]; + double tem1 = x[0] - y[0]; + double tem2 = z[1] * tem0; + double tem3 = z[0] * tem1; + z[0] = tem2 - w[1]; + z[1] = tem3 + w[0]; +} + +int main() +{ + check_vect (); + + x[0] = 1.; x[1] = 2.; + y[0] = 7.; y[1] = -5.; + z[0] = 2.; z[1] = 3.; + w[0] = 9.; w[1] = -5.; + foo (); + if (z[0] != -4. || z[1] != -3.) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-74.c b/gcc/testsuite/gcc.dg/vect/bb-slp-74.c new file mode 100644 index 0000000..d3d5a02 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-74.c @@ -0,0 +1,30 @@ +/* { dg-do run } */ + +#include "tree-vect.h" + +double a[2], b[2], c[2]; + +void __attribute__((noipa)) foo () +{ + double tem0 = a[1] + b[1]; + double tem1 = a[0] - b[0]; + c[0] = 2. * tem0; + c[1] = 5. * tem1; +} + +int main() +{ + check_vect (); + + a[0] = 1.; a[1] = 3.; + b[0] = -5.; b[1] = 13.; + foo (); + if (c[0] != 32. || c[1] != 30.) + __builtin_abort (); + return 0; +} + +/* We'd like to see at most one VEC_PERM_EXPR, not one for a blend + and one for a permute materialized somewhere else. But addsub + pattern recog can likely get in the way here. */ +/* { dg-final { scan-tree-dump-times " \[^ \]\+ = VEC_PERM_EXPR" 1 "slp2" } } */ diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 10195d3..966b281 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -3470,16 +3470,19 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size) struct slpg_vertex { slpg_vertex (slp_tree node_) - : node (node_), perm_out (-1), materialize (0) {} + : node (node_), perm_in (-1), perm_out (-1) {} - int get_perm_in () const { return materialize ? materialize : perm_out; } + int get_perm_materialized () const + { return perm_in != perm_out ? perm_in : 0; } slp_tree node; - /* The permutation on the outgoing lanes (towards SLP parents). */ + /* The common permutation on the incoming lanes (towards SLP children). */ + int perm_in; + /* The permutation on the outgoing lanes (towards SLP parents). When + the node is a materialization point for a permute this differs + from perm_in (and is then usually zero). Materialization happens + on the input side. */ int perm_out; - /* The permutation that is applied by this node. perm_out is - relative to this. */ - int materialize; }; /* Fill the vertices and leafs vector with all nodes in the SLP graph. */ @@ -3614,7 +3617,11 @@ vect_optimize_slp (vec_info *vinfo) /* Leafs do not change across iterations. Note leafs also double as entries to the reverse graph. */ if (!slpg->vertices[idx].succ) - vertices[idx].perm_out = 0; + { + vertices[idx].perm_in = 0; + vertices[idx].perm_out = 0; + } + /* Loads are the only thing generating permutes. */ if (!SLP_TREE_LOAD_PERMUTATION (node).exists ()) continue; @@ -3663,6 +3670,7 @@ vect_optimize_slp (vec_info *vinfo) for (unsigned j = 0; j < SLP_TREE_LANES (node); ++j) perm[j] = SLP_TREE_LOAD_PERMUTATION (node)[j] - imin; perms.safe_push (perm); + vertices[idx].perm_in = perms.length () - 1; vertices[idx].perm_out = perms.length () - 1; } @@ -3702,8 +3710,11 @@ vect_optimize_slp (vec_info *vinfo) if (STMT_VINFO_DATA_REF (rep) && DR_IS_WRITE (STMT_VINFO_DATA_REF (rep))) { + /* ??? We're forcing materialization in place + of the child here, we'd need special handling + in materialization to leave perm_in -1 here. */ + vertices[idx].perm_in = 0; vertices[idx].perm_out = 0; - continue; } /* We cannot move a permute across an operation that is not independent on lanes. Note this is an explicit @@ -3717,20 +3728,19 @@ vect_optimize_slp (vec_info *vinfo) case CFN_COMPLEX_MUL: case CFN_COMPLEX_MUL_CONJ: case CFN_VEC_ADDSUB: + vertices[idx].perm_in = 0; vertices[idx].perm_out = 0; - continue; default:; } } - int perm; if (!slpg->vertices[idx].succ) /* Pick up pre-computed leaf values. */ - perm = vertices[idx].perm_out; + ; else { bool any_succ_perm_out_m1 = false; - perm = vertices[idx].get_perm_in (); + int perm_in = vertices[idx].perm_in; for (graph_edge *succ = slpg->vertices[idx].succ; succ; succ = succ->succ_next) { @@ -3752,18 +3762,18 @@ vect_optimize_slp (vec_info *vinfo) any_succ_perm_out_m1 = true; continue; } - if (perm == -1) - perm = succ_perm; + if (perm_in == -1) + perm_in = succ_perm; else if (succ_perm == 0 - || !vect_slp_perms_eq (perms, perm, succ_perm)) + || !vect_slp_perms_eq (perms, perm_in, succ_perm)) { - perm = 0; + perm_in = 0; break; } } /* Adjust any incoming permutes we treated optimistically. */ - if (perm != -1 && any_succ_perm_out_m1) + if (perm_in != -1 && any_succ_perm_out_m1) { for (graph_edge *succ = slpg->vertices[idx].succ; succ; succ = succ->succ_next) @@ -3772,24 +3782,36 @@ vect_optimize_slp (vec_info *vinfo) if (vertices[succ->dest].perm_out == -1 && SLP_TREE_DEF_TYPE (succ_node) != vect_external_def && SLP_TREE_DEF_TYPE (succ_node) != vect_constant_def) - vertices[succ->dest].perm_out = perm; + { + vertices[succ->dest].perm_out = perm_in; + /* And ensure this propagates. */ + if (vertices[succ->dest].perm_in == -1) + vertices[succ->dest].perm_in = perm_in; + } } changed = true; } - if (!vect_slp_perms_eq (perms, perm, - vertices[idx].get_perm_in ())) + if (!vect_slp_perms_eq (perms, perm_in, + vertices[idx].perm_in)) { /* Make sure we eventually converge. */ - gcc_checking_assert (vertices[idx].get_perm_in () == -1 - || perm == 0); - if (perm == 0) - { - vertices[idx].perm_out = 0; - vertices[idx].materialize = 0; - } - if (!vertices[idx].materialize) - vertices[idx].perm_out = perm; + gcc_checking_assert (vertices[idx].perm_in == -1 + || perm_in == 0); + vertices[idx].perm_in = perm_in; + + /* While we can handle VEC_PERM nodes as transparent + pass-through they can be a cheap materialization + point as well. In addition they can act as source + of a random permutation as well. + The following ensures that former materialization + points that now have zero incoming permutes no + longer appear as such and that former "any" permutes + get pass-through. We keep VEC_PERM nodes optimistic + as "any" outgoing permute though. */ + if (vertices[idx].perm_out != 0 + && SLP_TREE_CODE (node) != VEC_PERM_EXPR) + vertices[idx].perm_out = perm_in; changed = true; } } @@ -3799,25 +3821,19 @@ vect_optimize_slp (vec_info *vinfo) if (!do_materialization) continue; + int perm = vertices[idx].perm_out; if (perm == 0 || perm == -1) continue; /* Decide on permute materialization. Look whether there's a use (pred) edge that is permuted differently than us. - In that case mark ourselves so the permutation is applied. - For VEC_PERM_EXPRs the permutation doesn't carry along - from children to parents so force materialization at the - point of the VEC_PERM_EXPR. In principle VEC_PERM_EXPRs - are a source of an arbitrary permutation again, similar - to constants/externals - that's something we do not yet - optimally handle. */ - bool all_preds_permuted = (SLP_TREE_CODE (node) != VEC_PERM_EXPR - && slpg->vertices[idx].pred != NULL); + In that case mark ourselves so the permutation is applied. */ + bool all_preds_permuted = slpg->vertices[idx].pred != NULL; if (all_preds_permuted) for (graph_edge *pred = slpg->vertices[idx].pred; pred; pred = pred->pred_next) { - int pred_perm = vertices[pred->src].get_perm_in (); + int pred_perm = vertices[pred->src].perm_in; gcc_checking_assert (pred_perm != -1); if (!vect_slp_perms_eq (perms, perm, pred_perm)) { @@ -3827,10 +3843,8 @@ vect_optimize_slp (vec_info *vinfo) } if (!all_preds_permuted) { - if (!vertices[idx].materialize) - changed = true; - vertices[idx].materialize = perm; vertices[idx].perm_out = 0; + changed = true; } } @@ -3848,46 +3862,43 @@ vect_optimize_slp (vec_info *vinfo) /* Materialize. */ for (i = 0; i < vertices.length (); ++i) { - int perm = vertices[i].get_perm_in (); - if (perm <= 0) - continue; - + int perm_in = vertices[i].perm_in; slp_tree node = vertices[i].node; - /* First permute invariant/external original successors. */ + /* First permute invariant/external original successors, we handle + those optimistically during propagation and duplicate them if + they are used with different permutations. */ unsigned j; slp_tree child; - FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child) - { - if (!child - || (SLP_TREE_DEF_TYPE (child) != vect_constant_def - && SLP_TREE_DEF_TYPE (child) != vect_external_def)) - continue; + if (perm_in > 0) + FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child) + { + if (!child + || (SLP_TREE_DEF_TYPE (child) != vect_constant_def + && SLP_TREE_DEF_TYPE (child) != vect_external_def)) + continue; - /* If the vector is uniform there's nothing to do. */ - if (vect_slp_tree_uniform_p (child)) - continue; + /* If the vector is uniform there's nothing to do. */ + if (vect_slp_tree_uniform_p (child)) + continue; - /* We can end up sharing some externals via two_operator - handling. Be prepared to unshare those. */ - if (child->refcnt != 1) - { - gcc_assert (slpg->vertices[child->vertex].pred->pred_next); - SLP_TREE_CHILDREN (node)[j] = child - = vect_create_new_slp_node - (SLP_TREE_SCALAR_OPS (child).copy ()); - } - vect_slp_permute (perms[perm], - SLP_TREE_SCALAR_OPS (child), true); - } + /* We can end up sharing some externals via two_operator + handling. Be prepared to unshare those. */ + if (child->refcnt != 1) + { + gcc_assert (slpg->vertices[child->vertex].pred->pred_next); + SLP_TREE_CHILDREN (node)[j] = child + = vect_create_new_slp_node + (SLP_TREE_SCALAR_OPS (child).copy ()); + } + vect_slp_permute (perms[perm_in], + SLP_TREE_SCALAR_OPS (child), true); + } - if (vertices[i].materialize) + if (SLP_TREE_CODE (node) == VEC_PERM_EXPR) { - if (SLP_TREE_LOAD_PERMUTATION (node).exists ()) - /* For loads simply drop the permutation, the load permutation - already performs the desired permutation. */ - ; - else if (SLP_TREE_LANE_PERMUTATION (node).exists ()) + /* Apply the common permutes to the input vectors. */ + if (perm_in > 0) { /* If the node is already a permute node we can apply the permutation to the lane selection, effectively @@ -3896,12 +3907,30 @@ vect_optimize_slp (vec_info *vinfo) dump_printf_loc (MSG_NOTE, vect_location, "simplifying permute node %p\n", node); - for (unsigned k = 0; k < SLP_TREE_LANE_PERMUTATION (node).length (); ++k) SLP_TREE_LANE_PERMUTATION (node)[k].second - = perms[perm][SLP_TREE_LANE_PERMUTATION (node)[k].second]; + = perms[perm_in][SLP_TREE_LANE_PERMUTATION (node)[k].second]; + } + /* Apply the anticipated output permute to the permute and + stmt vectors. */ + int perm_out = vertices[i].perm_out; + if (perm_out > 0) + { + vect_slp_permute (perms[perm_out], + SLP_TREE_SCALAR_STMTS (node), true); + vect_slp_permute (perms[perm_out], + SLP_TREE_LANE_PERMUTATION (node), true); } + } + else if (vertices[i].get_perm_materialized () != 0) + { + if (SLP_TREE_LOAD_PERMUTATION (node).exists ()) + /* For loads simply drop the permutation, the load permutation + already performs the desired permutation. */ + ; + else if (SLP_TREE_LANE_PERMUTATION (node).exists ()) + gcc_unreachable (); else { if (dump_enabled_p ()) @@ -3916,7 +3945,7 @@ vect_optimize_slp (vec_info *vinfo) SLP_TREE_CHILDREN (node) = vNULL; SLP_TREE_SCALAR_STMTS (copy) = SLP_TREE_SCALAR_STMTS (node).copy (); - vect_slp_permute (perms[perm], + vect_slp_permute (perms[perm_in], SLP_TREE_SCALAR_STMTS (copy), true); gcc_assert (!SLP_TREE_SCALAR_OPS (node).exists ()); SLP_TREE_REPRESENTATIVE (copy) = SLP_TREE_REPRESENTATIVE (node); @@ -3936,28 +3965,31 @@ vect_optimize_slp (vec_info *vinfo) SLP_TREE_LANE_PERMUTATION (node).create (SLP_TREE_LANES (node)); for (unsigned j = 0; j < SLP_TREE_LANES (node); ++j) SLP_TREE_LANE_PERMUTATION (node) - .quick_push (std::make_pair (0, perms[perm][j])); + .quick_push (std::make_pair (0, perms[perm_in][j])); SLP_TREE_CODE (node) = VEC_PERM_EXPR; } } - else + else if (perm_in > 0) /* perm_in == perm_out */ { /* Apply the reverse permutation to our stmts. */ - vect_slp_permute (perms[perm], + vect_slp_permute (perms[perm_in], SLP_TREE_SCALAR_STMTS (node), true); - /* And to the load permutation, which we can simply + /* And to the lane/load permutation, which we can simply make regular by design. */ if (SLP_TREE_LOAD_PERMUTATION (node).exists ()) { + gcc_assert (!SLP_TREE_LANE_PERMUTATION (node).exists ()); /* ??? When we handle non-bijective permutes the idea is that we can force the load-permutation to be { min, min + 1, min + 2, ... max }. But then the scalar defs might no longer match the lane content which means wrong-code with live lane vectorization. So we possibly have to have NULL entries for those. */ - vect_slp_permute (perms[perm], + vect_slp_permute (perms[perm_in], SLP_TREE_LOAD_PERMUTATION (node), true); } + else if (SLP_TREE_LANE_PERMUTATION (node).exists ()) + gcc_unreachable (); } } @@ -3991,14 +4023,14 @@ vect_optimize_slp (vec_info *vinfo) } else if (SLP_TREE_LOAD_PERMUTATION (old).exists () && SLP_TREE_REF_COUNT (old) == 1 - && vertices[old->vertex].materialize) + && vertices[old->vertex].get_perm_materialized () != 0) { /* ??? For loads the situation is more complex since we can't modify the permute in place in case the node is used multiple times. In fact for loads this should be somehow handled in the propagation engine. */ /* Apply the reverse permutation to our stmts. */ - int perm = vertices[old->vertex].get_perm_in (); + int perm = vertices[old->vertex].get_perm_materialized (); vect_slp_permute (perms[perm], SLP_TREE_SCALAR_STMTS (old), true); vect_slp_permute (perms[perm], -- cgit v1.1 From 9f6aeb85ee87c6b4e580b6b71e26cbe99e1dab70 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 1 Jul 2021 10:56:32 +0200 Subject: i386: Add integer nabs instructions [PR101044] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The patch adds integer nabs "(NEG (ABS (...)))" instructions, adds STV conversion and adjusts STV cost calculations accordingly. When CMOV instruction is used to implement abs, the sign is determined from the preceeding operand negation, and CMOVS is used to select between negated and non-negated value. To implement nabs, just reverse the condition and emit CMOVNS instead. The STV costs are adjusted for inherent NOT of nabs insn. V2DI NOT is somehow costly operation, since it is implemented as a load of zero, followed by a SUB insn. OTOH, integer nabs with inherent NOT is relatively cheap, so some STV chains became less profitable for conversion. The patch rewrites operand scanner in compute_convert_gain to a switch and reorders case instances in general_scalar_to_vector_candidate_p to benefit from fallthroughs, and to remove special processing of andnot in the later case. gcc/ 2021-07-01 Uroš Bizjak PR target/101044 * config/i386/i386.md (*nabs2_doubleword): New insn_and_split pattern. (*nabs2_1): Ditto. * config/i386/i386-features.c (general_scalar_chain::compute_convert_gain): Handle (NEG (ABS (...))) RTX. Rewrite src code scanner as switch statement. (general_scalar_chain::convert_insn): Handle (NEG (ABS (...))) RTX. (general_scalar_to_vector_candidate_p): Detect (NEG (ABS (...))) RTX. Reorder case statements for (AND (NOT (...) ...)) fallthrough. gcc/testsuite/ 2021-07-01 Uroš Bizjak PR target/101044 * gcc.target/i386/pr101044.c: New test. --- gcc/config/i386/i386-features.c | 195 ++++++++++++++++++------------- gcc/config/i386/i386.md | 72 ++++++++++++ gcc/testsuite/gcc.target/i386/pr101044.c | 9 ++ 3 files changed, 196 insertions(+), 80 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr101044.c (limited to 'gcc') diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c index a25769a..cbd430a 100644 --- a/gcc/config/i386/i386-features.c +++ b/gcc/config/i386/i386-features.c @@ -544,71 +544,83 @@ general_scalar_chain::compute_convert_gain () += m * ix86_cost->int_store[2] - ix86_cost->sse_store[sse_cost_idx]; else if (MEM_P (src) && REG_P (dst)) igain += m * ix86_cost->int_load[2] - ix86_cost->sse_load[sse_cost_idx]; - else if (GET_CODE (src) == ASHIFT - || GET_CODE (src) == ASHIFTRT - || GET_CODE (src) == LSHIFTRT) - { - if (m == 2) - { - if (INTVAL (XEXP (src, 1)) >= 32) - igain += ix86_cost->add; - else - igain += ix86_cost->shift_const; - } + else + switch (GET_CODE (src)) + { + case ASHIFT: + case ASHIFTRT: + case LSHIFTRT: + if (m == 2) + { + if (INTVAL (XEXP (src, 1)) >= 32) + igain += ix86_cost->add; + else + igain += ix86_cost->shift_const; + } - igain += ix86_cost->shift_const - ix86_cost->sse_op; + igain += ix86_cost->shift_const - ix86_cost->sse_op; - if (CONST_INT_P (XEXP (src, 0))) - igain -= vector_const_cost (XEXP (src, 0)); - } - else if (GET_CODE (src) == PLUS - || GET_CODE (src) == MINUS - || GET_CODE (src) == IOR - || GET_CODE (src) == XOR - || GET_CODE (src) == AND) - { - igain += m * ix86_cost->add - ix86_cost->sse_op; - /* Additional gain for andnot for targets without BMI. */ - if (GET_CODE (XEXP (src, 0)) == NOT - && !TARGET_BMI) - igain += m * ix86_cost->add; - - if (CONST_INT_P (XEXP (src, 0))) - igain -= vector_const_cost (XEXP (src, 0)); - if (CONST_INT_P (XEXP (src, 1))) - igain -= vector_const_cost (XEXP (src, 1)); - } - else if (GET_CODE (src) == NEG - || GET_CODE (src) == NOT) - igain += m * ix86_cost->add - ix86_cost->sse_op - COSTS_N_INSNS (1); - else if (GET_CODE (src) == ABS - || GET_CODE (src) == SMAX - || GET_CODE (src) == SMIN - || GET_CODE (src) == UMAX - || GET_CODE (src) == UMIN) - { - /* We do not have any conditional move cost, estimate it as a - reg-reg move. Comparisons are costed as adds. */ - igain += m * (COSTS_N_INSNS (2) + ix86_cost->add); - /* Integer SSE ops are all costed the same. */ - igain -= ix86_cost->sse_op; - } - else if (GET_CODE (src) == COMPARE) - { - /* Assume comparison cost is the same. */ - } - else if (CONST_INT_P (src)) - { - if (REG_P (dst)) - /* DImode can be immediate for TARGET_64BIT and SImode always. */ - igain += m * COSTS_N_INSNS (1); - else if (MEM_P (dst)) - igain += (m * ix86_cost->int_store[2] - - ix86_cost->sse_store[sse_cost_idx]); - igain -= vector_const_cost (src); - } - else - gcc_unreachable (); + if (CONST_INT_P (XEXP (src, 0))) + igain -= vector_const_cost (XEXP (src, 0)); + break; + + case AND: + case IOR: + case XOR: + case PLUS: + case MINUS: + igain += m * ix86_cost->add - ix86_cost->sse_op; + /* Additional gain for andnot for targets without BMI. */ + if (GET_CODE (XEXP (src, 0)) == NOT + && !TARGET_BMI) + igain += m * ix86_cost->add; + + if (CONST_INT_P (XEXP (src, 0))) + igain -= vector_const_cost (XEXP (src, 0)); + if (CONST_INT_P (XEXP (src, 1))) + igain -= vector_const_cost (XEXP (src, 1)); + break; + + case NEG: + case NOT: + igain -= ix86_cost->sse_op + COSTS_N_INSNS (1); + + if (GET_CODE (XEXP (src, 0)) != ABS) + { + igain += m * ix86_cost->add; + break; + } + /* FALLTHRU */ + + case ABS: + case SMAX: + case SMIN: + case UMAX: + case UMIN: + /* We do not have any conditional move cost, estimate it as a + reg-reg move. Comparisons are costed as adds. */ + igain += m * (COSTS_N_INSNS (2) + ix86_cost->add); + /* Integer SSE ops are all costed the same. */ + igain -= ix86_cost->sse_op; + break; + + case COMPARE: + /* Assume comparison cost is the same. */ + break; + + case CONST_INT: + if (REG_P (dst)) + /* DImode can be immediate for TARGET_64BIT and SImode always. */ + igain += m * COSTS_N_INSNS (1); + else if (MEM_P (dst)) + igain += (m * ix86_cost->int_store[2] + - ix86_cost->sse_store[sse_cost_idx]); + igain -= vector_const_cost (src); + break; + + default: + gcc_unreachable (); + } if (igain != 0 && dump_file) { @@ -1009,7 +1021,19 @@ general_scalar_chain::convert_insn (rtx_insn *insn) case NEG: src = XEXP (src, 0); - convert_op (&src, insn); + + if (GET_CODE (src) == ABS) + { + src = XEXP (src, 0); + convert_op (&src, insn); + subreg = gen_reg_rtx (vmode); + emit_insn_before (gen_rtx_SET (subreg, + gen_rtx_ABS (vmode, src)), insn); + src = subreg; + } + else + convert_op (&src, insn); + subreg = gen_reg_rtx (vmode); emit_insn_before (gen_move_insn (subreg, CONST0_RTX (vmode)), insn); src = gen_rtx_MINUS (vmode, subreg, src); @@ -1042,9 +1066,10 @@ general_scalar_chain::convert_insn (rtx_insn *insn) gcc_assert (REG_P (src) && GET_MODE (src) == DImode); subreg = gen_rtx_SUBREG (V2DImode, src, 0); - emit_insn_before (gen_vec_interleave_lowv2di (copy_rtx_if_shared (subreg), - copy_rtx_if_shared (subreg), - copy_rtx_if_shared (subreg)), + emit_insn_before (gen_vec_interleave_lowv2di + (copy_rtx_if_shared (subreg), + copy_rtx_if_shared (subreg), + copy_rtx_if_shared (subreg)), insn); dst = gen_rtx_REG (CCmode, FLAGS_REG); src = gen_rtx_UNSPEC (CCmode, gen_rtvec (2, copy_rtx_if_shared (subreg), @@ -1400,11 +1425,11 @@ general_scalar_to_vector_candidate_p (rtx_insn *insn, enum machine_mode mode) return false; /* Fallthru. */ - case PLUS: - case MINUS: + case AND: case IOR: case XOR: - case AND: + case PLUS: + case MINUS: if (!REG_P (XEXP (src, 1)) && !MEM_P (XEXP (src, 1)) && !CONST_INT_P (XEXP (src, 1))) @@ -1413,18 +1438,32 @@ general_scalar_to_vector_candidate_p (rtx_insn *insn, enum machine_mode mode) if (GET_MODE (XEXP (src, 1)) != mode && !CONST_INT_P (XEXP (src, 1))) return false; + + /* Check for andnot case. */ + if (GET_CODE (src) != AND + || GET_CODE (XEXP (src, 0)) != NOT) + break; + + src = XEXP (src, 0); + /* FALLTHRU */ + + case NOT: break; + case NEG: + /* Check for nabs case. */ + if (GET_CODE (XEXP (src, 0)) != ABS) + break; + + src = XEXP (src, 0); + /* FALLTHRU */ + case ABS: if ((mode == DImode && !TARGET_AVX512VL) || (mode == SImode && !TARGET_SSSE3)) return false; break; - case NEG: - case NOT: - break; - case REG: return true; @@ -1438,12 +1477,8 @@ general_scalar_to_vector_candidate_p (rtx_insn *insn, enum machine_mode mode) if (!REG_P (XEXP (src, 0)) && !MEM_P (XEXP (src, 0)) - && !CONST_INT_P (XEXP (src, 0)) - /* Check for andnot case. */ - && (GET_CODE (src) != AND - || GET_CODE (XEXP (src, 0)) != NOT - || !REG_P (XEXP (XEXP (src, 0), 0)))) - return false; + && !CONST_INT_P (XEXP (src, 0))) + return false; if (GET_MODE (XEXP (src, 0)) != mode && !CONST_INT_P (XEXP (src, 0))) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 9b619e2..156c6a9 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -10305,6 +10305,50 @@ split_double_mode (mode, &operands[0], 3, &operands[0], &operands[3]); }) +(define_insn_and_split "*nabs2_doubleword" + [(set (match_operand: 0 "register_operand") + (neg: + (abs: + (match_operand: 1 "general_operand")))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_CMOVE + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(parallel + [(set (reg:CCC FLAGS_REG) + (ne:CCC (match_dup 1) (const_int 0))) + (set (match_dup 2) (neg:DWIH (match_dup 1)))]) + (parallel + [(set (match_dup 5) + (plus:DWIH (plus:DWIH (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 4)) + (const_int 0))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (reg:CCGOC FLAGS_REG) + (compare:CCGOC + (neg:DWIH (match_dup 5)) + (const_int 0))) + (set (match_dup 5) + (neg:DWIH (match_dup 5)))]) + (set (match_dup 0) + (if_then_else:DWIH + (lt (reg:CCGOC FLAGS_REG) (const_int 0)) + (match_dup 2) + (match_dup 1))) + (set (match_dup 3) + (if_then_else:DWIH + (lt (reg:CCGOC FLAGS_REG) (const_int 0)) + (match_dup 5) + (match_dup 4)))] +{ + operands[1] = force_reg (mode, operands[1]); + operands[2] = gen_reg_rtx (mode); + + split_double_mode (mode, &operands[0], 3, &operands[0], &operands[3]); +}) + (define_insn_and_split "*abs2_1" [(set (match_operand:SWI 0 "register_operand") (abs:SWI @@ -10332,6 +10376,34 @@ operands[2] = gen_reg_rtx (mode); }) +(define_insn_and_split "*nabs2_1" + [(set (match_operand:SWI 0 "register_operand") + (neg:SWI + (abs:SWI + (match_operand:SWI 1 "general_operand")))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_CMOVE + && (mode != QImode || !TARGET_PARTIAL_REG_STALL) + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(parallel + [(set (reg:CCGOC FLAGS_REG) + (compare:CCGOC + (neg:SWI (match_dup 1)) + (const_int 0))) + (set (match_dup 2) + (neg:SWI (match_dup 1)))]) + (set (match_dup 0) + (if_then_else:SWI + (lt (reg:CCGOC FLAGS_REG) (const_int 0)) + (match_dup 2) + (match_dup 1)))] +{ + operands[1] = force_reg (mode, operands[1]); + operands[2] = gen_reg_rtx (mode); +}) + (define_expand "tf2" [(set (match_operand:TF 0 "register_operand") (absneg:TF (match_operand:TF 1 "register_operand")))] diff --git a/gcc/testsuite/gcc.target/i386/pr101044.c b/gcc/testsuite/gcc.target/i386/pr101044.c new file mode 100644 index 0000000..03df86d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr101044.c @@ -0,0 +1,9 @@ +/* PR target/101044 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse2 -mno-sse3 -mtune=generic" } */ +/* { dg-final { scan-assembler-times "neg" 1 } } */ + +int foo (int x) +{ + return (x < 0) ? x : -x; +} -- cgit v1.1 From a3aaba68405751bae3f630669515b7ecdf77efa6 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 1 Jul 2021 10:35:38 +0200 Subject: tree-optimization/100778 - fix placement of trapping vectorized ops This avoids placing possibly trapping vectorized operations where the corresponding scalar operation was possibly not executed. 2021-01-07 Richard Biener PR tree-optimization/100778 * tree-vect-slp.c (vect_schedule_slp_node): Do not place trapping vectorized ops ahead of their scalar BB. * gcc.dg/torture/pr100778.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr100778.c | 31 +++++++++++++++++++++++++++++++ gcc/tree-vect-slp.c | 15 +++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/torture/pr100778.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/torture/pr100778.c b/gcc/testsuite/gcc.dg/torture/pr100778.c new file mode 100644 index 0000000..7997f2f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr100778.c @@ -0,0 +1,31 @@ +/* { dg-do run { target *-*-*gnu* } } */ +/* { dg-additional-options "-fno-tree-sink -fno-math-errno -ftree-vectorize -D_GNU_SOURCE" } */ +/* { dg-require-effective-target fenv_exceptions } */ + +#include + +double a[2]; +void __attribute__((noipa)) foo () +{ + double x = a[0]; + double y = a[1]; + double norm = __builtin_sqrt (x*x + y*y); + if (norm > 1.) + { + x = x / norm; + y = y / norm; + } + a[0] = x; + a[1] = y; +} + +int main() +{ + feenableexcept (FE_INVALID); + a[0] = 0.; + a[1] = 0.; + foo (); + if (a[0] != 0. || a[1] != 0.) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 966b281..f08797c 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -7100,6 +7100,21 @@ vect_schedule_slp_node (vec_info *vinfo, gcc_assert (seen_vector_def); si = gsi_after_labels (as_a (vinfo)->bbs[0]); } + else if (is_a (vinfo) + && gimple_bb (last_stmt) != gimple_bb (stmt_info->stmt) + && gimple_could_trap_p (stmt_info->stmt)) + { + /* We've constrained possibly trapping operations to all come + from the same basic-block, if vectorized defs would allow earlier + scheduling still force vectorized stmts to the original block. + This is only necessary for BB vectorization since for loop vect + all operations are in a single BB and scalar stmt based + placement doesn't play well with epilogue vectorization. */ + gcc_assert (dominated_by_p (CDI_DOMINATORS, + gimple_bb (stmt_info->stmt), + gimple_bb (last_stmt))); + si = gsi_after_labels (gimple_bb (stmt_info->stmt)); + } else if (is_a (last_stmt)) si = gsi_after_labels (gimple_bb (last_stmt)); else -- cgit v1.1 From 4a87605938428f6c4c62d5b92cfc183cd2b2554e Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 1 Jul 2021 11:16:01 +0200 Subject: tree-optimization/101278 - handle self-use in DSE analysis DSE store classification short-cuts the to-be classified stmt itself from chaining but fails to first check whether the store uses itself which can be the case when it is a call with the LHS also passed by value as argument. 2021-07-01 Richard Biener PR tree-optimization/101278 * tree-ssa-dse.c (dse_classify_store): First check for uses, then ignore stmt for chaining purposes. * gcc.dg/torture/pr101278.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr101278.c | 21 +++++++++++++++++++++ gcc/tree-ssa-dse.c | 10 +++++----- 2 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr101278.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/torture/pr101278.c b/gcc/testsuite/gcc.dg/torture/pr101278.c new file mode 100644 index 0000000..1d25658 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr101278.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ + +struct X { int counter; }; + +struct X __attribute__((noipa)) foo (struct X x) +{ + x.counter++; + if (x.counter == 5) + __builtin_exit (0); + return x; +} + +int +main () +{ + struct X x; + x.counter = 0; + for (int i = 0; i < 10; ++i) + x = foo (x); + __builtin_abort (); +} diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index c3939a6..98daa8a 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -813,15 +813,11 @@ dse_classify_store (ao_ref *ref, gimple *stmt, break; } - /* We have visited ourselves already so ignore STMT for the - purpose of chaining. */ - if (use_stmt == stmt) - ; /* In simple cases we can look through PHI nodes, but we have to be careful with loops and with memory references containing operands that are also operands of PHI nodes. See gcc.c-torture/execute/20051110-*.c. */ - else if (gimple_code (use_stmt) == GIMPLE_PHI) + if (gimple_code (use_stmt) == GIMPLE_PHI) { /* If we already visited this PHI ignore it for further processing. */ @@ -861,6 +857,10 @@ dse_classify_store (ao_ref *ref, gimple *stmt, fail = true; break; } + /* We have visited ourselves already so ignore STMT for the + purpose of chaining. */ + else if (use_stmt == stmt) + ; /* If this is a store, remember it as we possibly need to walk the defs uses. */ else if (gimple_vdef (use_stmt)) -- cgit v1.1 From 0a77c07b9b3fe83679358c3ef57721e09e2ad5fb Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 1 Jul 2021 12:49:45 +0200 Subject: tree-optimization/101280 - revise interchange fix for PR101173 The following revises the original fix for PR101173 to correctly check for a reversed dependence rather than disallowing a zero distance. It also adds a check from TSVC which asks for this kind of interchange (but with a valid dependence). 2021-07-01 Richard Biener PR tree-optimization/101280 PR tree-optimization/101173 * gimple-loop-interchange.cc (tree_loop_interchange::valid_data_dependences): Revert previous change and instead correctly handle DDR_REVERSED_P dependence. * gcc.dg/tree-ssa/loop-interchange-16.c: New testcase. --- gcc/gimple-loop-interchange.cc | 7 +++++-- .../gcc.dg/tree-ssa/loop-interchange-16.c | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/loop-interchange-16.c (limited to 'gcc') diff --git a/gcc/gimple-loop-interchange.cc b/gcc/gimple-loop-interchange.cc index 43045c54..43ef112 100644 --- a/gcc/gimple-loop-interchange.cc +++ b/gcc/gimple-loop-interchange.cc @@ -1043,8 +1043,11 @@ tree_loop_interchange::valid_data_dependences (unsigned i_idx, unsigned o_idx, continue; /* Be conservative, skip case if either direction at i_idx/o_idx - levels is not '=' (for the inner loop) or '<'. */ - if (dist_vect[i_idx] < 0 || dist_vect[o_idx] <= 0) + levels is not '=' or '<'. */ + if (dist_vect[i_idx] < 0 + || (DDR_REVERSED_P (ddr) && dist_vect[i_idx] > 0) + || dist_vect[o_idx] < 0 + || (DDR_REVERSED_P (ddr) && dist_vect[o_idx] > 0)) return false; } } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-interchange-16.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-interchange-16.c new file mode 100644 index 0000000..781555e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-interchange-16.c @@ -0,0 +1,22 @@ +/* PR/101280 */ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-linterchange-details" } */ + +void dummy (double *, double *); +#define LEN_2D 32 +double aa[LEN_2D][LEN_2D], bb[LEN_2D][LEN_2D]; +double s231(int iterations) +{ +// loop interchange +// loop with data dependency + for (int nl = 0; nl < 100*(iterations/LEN_2D); nl++) { + for (int i = 0; i < LEN_2D; ++i) { + for (int j = 1; j < LEN_2D; j++) { + aa[j][i] = aa[j - 1][i] + bb[j][i]; + } + } + dummy(aa[0],bb[0]); + } +} + +/* { dg-final { scan-tree-dump "loops interchanged" "linterchange" } } */ -- cgit v1.1 From a86b3453fc6e29cf0e19916b01c393652d838d56 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 1 Jul 2021 15:18:50 +0200 Subject: Change the type of predicates to bool. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The patch was tested on many targets, but some fallout is expected. To fix the build error, simply change the function type from int to bool, as was done in the patch for several targets. 2021-07-01 Uroš Bizjak gcc/ * genpreds.c (write_predicate_subfunction): Change the type of written subfunction to bool. (write_one_predicate_function): Change the type of written function to bool. (write_tm_preds_h): Ditto. * recog.h (*insn_operand_predicate_fn): Change the type to bool. * recog.c (general_operand): Change the type to bool. (address_operand): Ditto. (register_operand): Ditto. (pmode_register_operand): Ditto. (scratch_operand): Ditto. (immediate_operand): Ditto. (const_int_operand): Ditto. (const_scalar_int_operand): Ditto. (const_double_operand): Ditto. (nonimmediate_operand): Ditto. (nonmemory_operand): Ditto. (push_operand): Ditto. (pop_operand): Ditto. (memory_operand): Ditto. (indirect_operand): Ditto. (ordered_comparison_operator): Ditto. (comparison_operator): Ditto. * config/i386/i386-expand.c (ix86_expand_sse_cmp): Change the type of indirect predicate function to bool. * config/rs6000/rs6000.c (easy_vector_constant): Change the type to bool. * config/mips/mips-protos.h (m16_based_address_p): Change the type of operand 3 to bool. --- gcc/config/i386/i386-expand.c | 2 +- gcc/config/mips/mips-protos.h | 2 +- gcc/config/rs6000/rs6000.c | 2 +- gcc/genpreds.c | 8 ++--- gcc/recog.c | 73 ++++++++++++++++++++++--------------------- gcc/recog.h | 2 +- 6 files changed, 45 insertions(+), 44 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index e9763eb..76d6afd 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -3571,7 +3571,7 @@ ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1, cmp_op0 = force_reg (cmp_ops_mode, cmp_op0); - int (*op1_predicate)(rtx, machine_mode) + bool (*op1_predicate)(rtx, machine_mode) = VECTOR_MODE_P (cmp_ops_mode) ? vector_operand : nonimmediate_operand; if (!op1_predicate (cmp_op1, cmp_ops_mode)) diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 2cf4ed5..51b82b1 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -366,7 +366,7 @@ extern bool umips_12bit_offset_address_p (rtx, machine_mode); extern bool mips_9bit_offset_address_p (rtx, machine_mode); extern bool lwsp_swsp_address_p (rtx, machine_mode); extern bool m16_based_address_p (rtx, machine_mode, - int (*)(rtx_def*, machine_mode)); + bool (*)(rtx_def*, machine_mode)); extern rtx mips_expand_thread_pointer (rtx); extern void mips16_expand_get_fcsr (rtx); extern void mips16_expand_set_fcsr (rtx); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 075c156..f3e5f95 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1146,7 +1146,7 @@ static bool set_to_load_agen (rtx_insn *,rtx_insn *); static bool insn_terminates_group_p (rtx_insn *, enum group_termination); static bool insn_must_be_first_in_group (rtx_insn *); static bool insn_must_be_last_in_group (rtx_insn *); -int easy_vector_constant (rtx, machine_mode); +bool easy_vector_constant (rtx, machine_mode); static rtx rs6000_debug_legitimize_address (rtx, rtx, machine_mode); static rtx rs6000_legitimize_tls_address (rtx, enum tls_model); #if TARGET_MACHO diff --git a/gcc/genpreds.c b/gcc/genpreds.c index 63fac0c..9d9715f 100644 --- a/gcc/genpreds.c +++ b/gcc/genpreds.c @@ -110,7 +110,7 @@ process_define_predicate (md_rtx_info *info) becomes - static inline int basereg_operand_1(rtx op, machine_mode mode) + static inline bool basereg_operand_1(rtx op, machine_mode mode) { if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); @@ -151,7 +151,7 @@ write_predicate_subfunction (struct pred_data *p) p->exp = and_exp; - printf ("static inline int\n" + printf ("static inline bool\n" "%s_1 (rtx op ATTRIBUTE_UNUSED, machine_mode mode ATTRIBUTE_UNUSED)\n", p->name); rtx_reader_ptr->print_md_ptr_loc (p->c_block); @@ -651,7 +651,7 @@ write_one_predicate_function (struct pred_data *p) /* A normal predicate can legitimately not look at machine_mode if it accepts only CONST_INTs and/or CONST_WIDE_INT and/or CONST_DOUBLEs. */ - printf ("int\n%s (rtx op, machine_mode mode ATTRIBUTE_UNUSED)\n{\n", + printf ("bool\n%s (rtx op, machine_mode mode ATTRIBUTE_UNUSED)\n{\n", p->name); write_predicate_stmts (p->exp); fputs ("}\n\n", stdout); @@ -1416,7 +1416,7 @@ write_tm_preds_h (void) #ifdef HAVE_MACHINE_MODES"); FOR_ALL_PREDICATES (p) - printf ("extern int %s (rtx, machine_mode);\n", p->name); + printf ("extern bool %s (rtx, machine_mode);\n", p->name); puts ("#endif /* HAVE_MACHINE_MODES */\n"); diff --git a/gcc/recog.c b/gcc/recog.c index eb617f1..9d88043 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -1393,7 +1393,7 @@ valid_insn_p (rtx_insn *insn) return true; } -/* Return 1 if OP is a valid general operand for machine mode MODE. +/* Return true if OP is a valid general operand for machine mode MODE. This is either a register reference, a memory reference, or a constant. In the case of a memory reference, the address is checked for general validity for the target machine. @@ -1407,7 +1407,7 @@ valid_insn_p (rtx_insn *insn) The main use of this function is as a predicate in match_operand expressions in the machine description. */ -int +bool general_operand (rtx op, machine_mode mode) { enum rtx_code code = GET_CODE (op); @@ -1515,13 +1515,13 @@ general_operand (rtx op, machine_mode mode) return 0; } -/* Return 1 if OP is a valid memory address for a memory reference +/* Return true if OP is a valid memory address for a memory reference of mode MODE. The main use of this function is as a predicate in match_operand expressions in the machine description. */ -int +bool address_operand (rtx op, machine_mode mode) { /* Wrong mode for an address expr. */ @@ -1532,13 +1532,13 @@ address_operand (rtx op, machine_mode mode) return memory_address_p (mode, op); } -/* Return 1 if OP is a register reference of mode MODE. +/* Return true if OP is a register reference of mode MODE. If MODE is VOIDmode, accept a register in any mode. The main use of this function is as a predicate in match_operand expressions in the machine description. */ -int +bool register_operand (rtx op, machine_mode mode) { if (GET_CODE (op) == SUBREG) @@ -1559,18 +1559,18 @@ register_operand (rtx op, machine_mode mode) return general_operand (op, mode); } -/* Return 1 for a register in Pmode; ignore the tested mode. */ +/* Return true for a register in Pmode; ignore the tested mode. */ -int +bool pmode_register_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED) { return register_operand (op, Pmode); } -/* Return 1 if OP should match a MATCH_SCRATCH, i.e., if it is a SCRATCH +/* Return true if OP should match a MATCH_SCRATCH, i.e., if it is a SCRATCH or a hard register. */ -int +bool scratch_operand (rtx op, machine_mode mode) { if (GET_MODE (op) != mode && mode != VOIDmode) @@ -1583,12 +1583,12 @@ scratch_operand (rtx op, machine_mode mode) && REGNO_REG_CLASS (REGNO (op)) != NO_REGS)))); } -/* Return 1 if OP is a valid immediate operand for mode MODE. +/* Return true if OP is a valid immediate operand for mode MODE. The main use of this function is as a predicate in match_operand expressions in the machine description. */ -int +bool immediate_operand (rtx op, machine_mode mode) { /* Don't accept CONST_INT or anything similar @@ -1612,9 +1612,9 @@ immediate_operand (rtx op, machine_mode mode) : mode, op)); } -/* Returns 1 if OP is an operand that is a CONST_INT of mode MODE. */ +/* Return true if OP is an operand that is a CONST_INT of mode MODE. */ -int +bool const_int_operand (rtx op, machine_mode mode) { if (!CONST_INT_P (op)) @@ -1628,9 +1628,9 @@ const_int_operand (rtx op, machine_mode mode) } #if TARGET_SUPPORTS_WIDE_INT -/* Returns 1 if OP is an operand that is a CONST_INT or CONST_WIDE_INT +/* Return true if OP is an operand that is a CONST_INT or CONST_WIDE_INT of mode MODE. */ -int +bool const_scalar_int_operand (rtx op, machine_mode mode) { if (!CONST_SCALAR_INT_P (op)) @@ -1661,20 +1661,20 @@ const_scalar_int_operand (rtx op, machine_mode mode) return 1; } -/* Returns 1 if OP is an operand that is a constant integer or constant +/* Return true if OP is an operand that is a constant integer or constant floating-point number of MODE. */ -int +bool const_double_operand (rtx op, machine_mode mode) { return (GET_CODE (op) == CONST_DOUBLE) && (GET_MODE (op) == mode || mode == VOIDmode); } #else -/* Returns 1 if OP is an operand that is a constant integer or constant +/* Return true if OP is an operand that is a constant integer or constant floating-point number of MODE. */ -int +bool const_double_operand (rtx op, machine_mode mode) { /* Don't accept CONST_INT or anything similar @@ -1689,18 +1689,19 @@ const_double_operand (rtx op, machine_mode mode) || GET_MODE (op) == VOIDmode)); } #endif -/* Return 1 if OP is a general operand that is not an immediate +/* Return true if OP is a general operand that is not an immediate operand of mode MODE. */ -int +bool nonimmediate_operand (rtx op, machine_mode mode) { return (general_operand (op, mode) && ! CONSTANT_P (op)); } -/* Return 1 if OP is a register reference or immediate value of mode MODE. */ +/* Return true if OP is a register reference or + immediate value of mode MODE. */ -int +bool nonmemory_operand (rtx op, machine_mode mode) { if (CONSTANT_P (op)) @@ -1708,13 +1709,13 @@ nonmemory_operand (rtx op, machine_mode mode) return register_operand (op, mode); } -/* Return 1 if OP is a valid operand that stands for pushing a +/* Return true if OP is a valid operand that stands for pushing a value of mode MODE onto the stack. The main use of this function is as a predicate in match_operand expressions in the machine description. */ -int +bool push_operand (rtx op, machine_mode mode) { if (!MEM_P (op)) @@ -1752,13 +1753,13 @@ push_operand (rtx op, machine_mode mode) return XEXP (op, 0) == stack_pointer_rtx; } -/* Return 1 if OP is a valid operand that stands for popping a +/* Return true if OP is a valid operand that stands for popping a value of mode MODE off the stack. The main use of this function is as a predicate in match_operand expressions in the machine description. */ -int +bool pop_operand (rtx op, machine_mode mode) { if (!MEM_P (op)) @@ -1794,13 +1795,13 @@ memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED, #endif } -/* Return 1 if OP is a valid memory reference with mode MODE, +/* Return true if OP is a valid memory reference with mode MODE, including a valid address. The main use of this function is as a predicate in match_operand expressions in the machine description. */ -int +bool memory_operand (rtx op, machine_mode mode) { rtx inner; @@ -1820,10 +1821,10 @@ memory_operand (rtx op, machine_mode mode) return (MEM_P (inner) && general_operand (op, mode)); } -/* Return 1 if OP is a valid indirect memory reference with mode MODE; +/* Return true if OP is a valid indirect memory reference with mode MODE; that is, a memory reference whose address is a general_operand. */ -int +bool indirect_operand (rtx op, machine_mode mode) { /* Before reload, a SUBREG isn't in memory (see memory_operand, above). */ @@ -1848,10 +1849,10 @@ indirect_operand (rtx op, machine_mode mode) && general_operand (XEXP (op, 0), Pmode)); } -/* Return 1 if this is an ordered comparison operator (not including +/* Return true if this is an ordered comparison operator (not including ORDERED and UNORDERED). */ -int +bool ordered_comparison_operator (rtx op, machine_mode mode) { if (mode != VOIDmode && GET_MODE (op) != mode) @@ -1874,10 +1875,10 @@ ordered_comparison_operator (rtx op, machine_mode mode) } } -/* Return 1 if this is a comparison operator. This allows the use of +/* Return true if this is a comparison operator. This allows the use of MATCH_OPERATOR to recognize all the branch insns. */ -int +bool comparison_operator (rtx op, machine_mode mode) { return ((mode == VOIDmode || GET_MODE (op) == mode) diff --git a/gcc/recog.h b/gcc/recog.h index e96e66e..653d0b0 100644 --- a/gcc/recog.h +++ b/gcc/recog.h @@ -393,7 +393,7 @@ which_op_alt () /* A table defined in insn-output.c that give information about each insn-code value. */ -typedef int (*insn_operand_predicate_fn) (rtx, machine_mode); +typedef bool (*insn_operand_predicate_fn) (rtx, machine_mode); typedef const char * (*insn_output_fn) (rtx *, rtx_insn *); struct insn_gen_fn -- cgit v1.1 From cfeffe9c461762bf95ba63dce535c81ddb36f109 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 1 Jul 2021 16:52:11 +0200 Subject: Return true/false instead of 1/0 from generic predicates. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes. 2021-07-01 Uroš Bizjak gcc/ * recog.c (general_operand): Return true/false instead of 1/0. (register_operand): Ditto. (immediate_operand): Ditto. (const_int_operand): Ditto. (const_scalar_int_operand): Ditto. (const_double_operand): Ditto. (push_operand): Ditto. (pop_operand): Ditto. (memory_operand): Ditto. (indirect_operand): Ditto. --- gcc/recog.c | 64 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'gcc') diff --git a/gcc/recog.c b/gcc/recog.c index 9d88043..2114df8 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -1420,12 +1420,12 @@ general_operand (rtx op, machine_mode mode) if (GET_MODE (op) == VOIDmode && mode != VOIDmode && GET_MODE_CLASS (mode) != MODE_INT && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) - return 0; + return false; if (CONST_INT_P (op) && mode != VOIDmode && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) - return 0; + return false; if (CONSTANT_P (op)) return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode @@ -1439,7 +1439,7 @@ general_operand (rtx op, machine_mode mode) OP's mode must match MODE if MODE specifies a mode. */ if (GET_MODE (op) != mode) - return 0; + return false; if (code == SUBREG) { @@ -1452,7 +1452,7 @@ general_operand (rtx op, machine_mode mode) get cleaned up by cleanup_subreg_operands. */ if (!reload_completed && MEM_P (sub) && paradoxical_subreg_p (op)) - return 0; + return false; #endif /* Avoid memories with nonzero SUBREG_BYTE, as offsetting the memory may result in incorrect reference. We should simplify all valid @@ -1463,7 +1463,7 @@ general_operand (rtx op, machine_mode mode) if (!reload_completed && maybe_ne (SUBREG_BYTE (op), 0) && MEM_P (sub)) - return 0; + return false; if (REG_P (sub) && REGNO (sub) < FIRST_PSEUDO_REGISTER @@ -1474,7 +1474,7 @@ general_operand (rtx op, machine_mode mode) operand reload presentation. LRA needs to treat them as valid. */ && ! LRA_SUBREG_P (op)) - return 0; + return false; /* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally create such rtl, and we must reject it. */ @@ -1486,7 +1486,7 @@ general_operand (rtx op, machine_mode mode) mode. */ && ! lra_in_progress && paradoxical_subreg_p (op)) - return 0; + return false; op = sub; code = GET_CODE (op); @@ -1501,7 +1501,7 @@ general_operand (rtx op, machine_mode mode) rtx y = XEXP (op, 0); if (! volatile_ok && MEM_VOLATILE_P (op)) - return 0; + return false; /* Use the mem's mode, since it will be reloaded thus. LRA can generate move insn with invalid addresses which is made valid @@ -1509,10 +1509,10 @@ general_operand (rtx op, machine_mode mode) transformations. */ if (lra_in_progress || memory_address_addr_space_p (GET_MODE (op), y, MEM_ADDR_SPACE (op))) - return 1; + return true; } - return 0; + return false; } /* Return true if OP is a valid memory address for a memory reference @@ -1552,10 +1552,10 @@ register_operand (rtx op, machine_mode mode) but currently it does result from (SUBREG (REG)...) where the reg went on the stack.) */ if (!REG_P (sub) && (reload_completed || !MEM_P (sub))) - return 0; + return false; } else if (!REG_P (op)) - return 0; + return false; return general_operand (op, mode); } @@ -1574,7 +1574,7 @@ bool scratch_operand (rtx op, machine_mode mode) { if (GET_MODE (op) != mode && mode != VOIDmode) - return 0; + return false; return (GET_CODE (op) == SCRATCH || (REG_P (op) @@ -1596,12 +1596,12 @@ immediate_operand (rtx op, machine_mode mode) if (GET_MODE (op) == VOIDmode && mode != VOIDmode && GET_MODE_CLASS (mode) != MODE_INT && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) - return 0; + return false; if (CONST_INT_P (op) && mode != VOIDmode && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) - return 0; + return false; return (CONSTANT_P (op) && (GET_MODE (op) == mode || mode == VOIDmode @@ -1618,13 +1618,13 @@ bool const_int_operand (rtx op, machine_mode mode) { if (!CONST_INT_P (op)) - return 0; + return false; if (mode != VOIDmode && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) - return 0; + return false; - return 1; + return true; } #if TARGET_SUPPORTS_WIDE_INT @@ -1634,7 +1634,7 @@ bool const_scalar_int_operand (rtx op, machine_mode mode) { if (!CONST_SCALAR_INT_P (op)) - return 0; + return false; if (CONST_INT_P (op)) return const_int_operand (op, mode); @@ -1646,10 +1646,10 @@ const_scalar_int_operand (rtx op, machine_mode mode) int bitsize = GET_MODE_BITSIZE (int_mode); if (CONST_WIDE_INT_NUNITS (op) * HOST_BITS_PER_WIDE_INT > bitsize) - return 0; + return false; if (prec == bitsize) - return 1; + return true; else { /* Multiword partial int. */ @@ -1658,7 +1658,7 @@ const_scalar_int_operand (rtx op, machine_mode mode) return (sext_hwi (x, prec & (HOST_BITS_PER_WIDE_INT - 1)) == x); } } - return 1; + return true; } /* Return true if OP is an operand that is a constant integer or constant @@ -1682,7 +1682,7 @@ const_double_operand (rtx op, machine_mode mode) if (GET_MODE (op) == VOIDmode && mode != VOIDmode && GET_MODE_CLASS (mode) != MODE_INT && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) - return 0; + return false; return ((CONST_DOUBLE_P (op) || CONST_INT_P (op)) && (mode == VOIDmode || GET_MODE (op) == mode @@ -1719,10 +1719,10 @@ bool push_operand (rtx op, machine_mode mode) { if (!MEM_P (op)) - return 0; + return false; if (mode != VOIDmode && GET_MODE (op) != mode) - return 0; + return false; poly_int64 rounded_size = GET_MODE_SIZE (mode); @@ -1735,7 +1735,7 @@ push_operand (rtx op, machine_mode mode) if (known_eq (rounded_size, GET_MODE_SIZE (mode))) { if (GET_CODE (op) != STACK_PUSH_CODE) - return 0; + return false; } else { @@ -1747,7 +1747,7 @@ push_operand (rtx op, machine_mode mode) || (STACK_GROWS_DOWNWARD ? maybe_ne (offset, -rounded_size) : maybe_ne (offset, rounded_size))) - return 0; + return false; } return XEXP (op, 0) == stack_pointer_rtx; @@ -1763,15 +1763,15 @@ bool pop_operand (rtx op, machine_mode mode) { if (!MEM_P (op)) - return 0; + return false; if (mode != VOIDmode && GET_MODE (op) != mode) - return 0; + return false; op = XEXP (op, 0); if (GET_CODE (op) != STACK_POP_CODE) - return 0; + return false; return XEXP (op, 0) == stack_pointer_rtx; } @@ -1812,7 +1812,7 @@ memory_operand (rtx op, machine_mode mode) return MEM_P (op) && general_operand (op, mode); if (mode != VOIDmode && GET_MODE (op) != mode) - return 0; + return false; inner = op; if (GET_CODE (inner) == SUBREG) @@ -1832,7 +1832,7 @@ indirect_operand (rtx op, machine_mode mode) && GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))) { if (mode != VOIDmode && GET_MODE (op) != mode) - return 0; + return false; /* The only way that we can have a general_operand as the resulting address is if OFFSET is zero and the address already is an operand -- cgit v1.1 From d63454815de3b93331025bd990efdad5296ae706 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 1 Jul 2021 16:57:57 +0200 Subject: i386: Return true/false instead of 1/0 from predicates. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes. 2021-07-01 Uroš Bizjak gcc/ * config/i386/predicates.md (ix86_endbr_immediate_operand): Return true/false instead of 1/0. (movq_parallel): Ditto. --- gcc/config/i386/predicates.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index e7a8968..c4b35c8 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -145,16 +145,16 @@ unsigned HOST_WIDE_INT val = TARGET_64BIT ? 0xfa1e0ff3 : 0xfb1e0ff3; if (imm == val) - return 1; + return true; /* NB: Encoding is byte based. */ if (TARGET_64BIT) for (; imm >= val; imm >>= 8) if (imm == val) - return 1; + return true; } - return 0; + return false; }) ;; Return true if VALUE can be stored in a sign extended immediate field. @@ -1559,15 +1559,15 @@ unsigned HOST_WIDE_INT ei; if (!CONST_INT_P (er)) - return 0; + return false; ei = INTVAL (er); if (i < nelt2 && ei != i) - return 0; + return false; if (i >= nelt2 && (ei < nelt || ei >= nelt << 1)) - return 0; + return false; } - return 1; + return true; }) ;; Return true if OP is a vzeroall operation, known to be a PARALLEL. -- cgit v1.1 From edafb35bdadf309ebb9d1eddc5549f9e1ad49c09 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 2 Jun 2021 07:15:45 -0700 Subject: x86: Convert CONST_WIDE_INT/CONST_VECTOR to broadcast 1. Update move expanders to convert the CONST_WIDE_INT and CONST_VECTOR operands to vector broadcast from an integer with AVX. 2. Add ix86_gen_scratch_sse_rtx to return a scratch SSE register which won't increase stack alignment requirement and blocks transformation by the combine pass. A small benchmark: https://gitlab.com/x86-benchmarks/microbenchmark/-/tree/memset/broadcast shows that broadcast is a little bit faster on Intel Core i7-8559U: $ make gcc -g -I. -O2 -c -o test.o test.c gcc -g -c -o memory.o memory.S gcc -g -c -o broadcast.o broadcast.S gcc -g -c -o vec_dup_sse2.o vec_dup_sse2.S gcc -o test test.o memory.o broadcast.o vec_dup_sse2.o ./test memory : 147215 broadcast : 121213 vec_dup_sse2: 171366 $ broadcast is also smaller: $ size memory.o broadcast.o text data bss dec hex filename 132 0 0 132 84 memory.o 122 0 0 122 7a broadcast.o $ 3. Update PR 87767 tests to expect integer broadcast instead of broadcast from memory. 4. Update avx512f_cond_move.c to expect integer broadcast. A small benchmark: https://gitlab.com/x86-benchmarks/microbenchmark/-/tree/vpaddd/broadcast shows that integer broadcast is faster than embedded memory broadcast: $ make gcc -g -I. -O2 -march=skylake-avx512 -c -o test.o test.c gcc -g -c -o memory.o memory.S gcc -g -c -o broadcast.o broadcast.S gcc -o test test.o memory.o broadcast.o ./test memory : 425538 broadcast : 375260 $ gcc/ PR target/100865 * config/i386/i386-expand.c (ix86_expand_vector_init_duplicate): New prototype. (ix86_byte_broadcast): New function. (ix86_convert_const_wide_int_to_broadcast): Likewise. (ix86_expand_move): Convert CONST_WIDE_INT to broadcast if mode size is 16 bytes or bigger. (ix86_broadcast_from_integer_constant): New function. (ix86_expand_vector_move): Convert CONST_WIDE_INT and CONST_VECTOR to broadcast if mode size is 16 bytes or bigger. * config/i386/i386-protos.h (ix86_gen_scratch_sse_rtx): New prototype. * config/i386/i386.c (ix86_gen_scratch_sse_rtx): New function. gcc/testsuite/ PR target/100865 * gcc.target/i386/avx512f-broadcast-pr87767-1.c: Expect integer broadcast. * gcc.target/i386/avx512f-broadcast-pr87767-5.c: Likewise. * gcc.target/i386/avx512vl-broadcast-pr87767-1.c: Likewise. * gcc.target/i386/avx512vl-broadcast-pr87767-5.c: Likewise. * gcc.target/i386/avx512f_cond_move.c: Also pass -mprefer-vector-width=512 and expect integer broadcast. * gcc.target/i386/pr100865-1.c: New test. * gcc.target/i386/pr100865-2.c: Likewise. * gcc.target/i386/pr100865-3.c: Likewise. * gcc.target/i386/pr100865-4a.c: Likewise. * gcc.target/i386/pr100865-4b.c: Likewise. * gcc.target/i386/pr100865-5a.c: Likewise. * gcc.target/i386/pr100865-5b.c: Likewise. * gcc.target/i386/pr100865-6a.c: Likewise. * gcc.target/i386/pr100865-6b.c: Likewise. * gcc.target/i386/pr100865-6c.c: Likewise. * gcc.target/i386/pr100865-7a.c: Likewise. * gcc.target/i386/pr100865-7b.c: Likewise. * gcc.target/i386/pr100865-7c.c: Likewise. * gcc.target/i386/pr100865-8a.c: Likewise. * gcc.target/i386/pr100865-8b.c: Likewise. * gcc.target/i386/pr100865-8c.c: Likewise. * gcc.target/i386/pr100865-9a.c: Likewise. * gcc.target/i386/pr100865-9b.c: Likewise. * gcc.target/i386/pr100865-9c.c: Likewise. * gcc.target/i386/pr100865-10a.c: Likewise. * gcc.target/i386/pr100865-10b.c: Likewise. * gcc.target/i386/pr100865-11a.c: Likewise. * gcc.target/i386/pr100865-11b.c: Likewise. * gcc.target/i386/pr100865-11c.c: Likewise. * gcc.target/i386/pr100865-12a.c: Likewise. * gcc.target/i386/pr100865-12b.c: Likewise. * gcc.target/i386/pr100865-12c.c: Likewise. --- gcc/config/i386/i386-expand.c | 194 +++++++++++++++++++-- gcc/config/i386/i386-protos.h | 2 + gcc/config/i386/i386.c | 13 ++ .../gcc.target/i386/avx512f-broadcast-pr87767-1.c | 7 +- .../gcc.target/i386/avx512f-broadcast-pr87767-5.c | 5 +- gcc/testsuite/gcc.target/i386/avx512f_cond_move.c | 4 +- .../gcc.target/i386/avx512vl-broadcast-pr87767-1.c | 12 +- .../gcc.target/i386/avx512vl-broadcast-pr87767-5.c | 9 +- gcc/testsuite/gcc.target/i386/pr100865-1.c | 13 ++ gcc/testsuite/gcc.target/i386/pr100865-10a.c | 33 ++++ gcc/testsuite/gcc.target/i386/pr100865-10b.c | 7 + gcc/testsuite/gcc.target/i386/pr100865-11a.c | 23 +++ gcc/testsuite/gcc.target/i386/pr100865-11b.c | 8 + gcc/testsuite/gcc.target/i386/pr100865-11c.c | 8 + gcc/testsuite/gcc.target/i386/pr100865-12a.c | 20 +++ gcc/testsuite/gcc.target/i386/pr100865-12b.c | 8 + gcc/testsuite/gcc.target/i386/pr100865-12c.c | 8 + gcc/testsuite/gcc.target/i386/pr100865-2.c | 14 ++ gcc/testsuite/gcc.target/i386/pr100865-3.c | 15 ++ gcc/testsuite/gcc.target/i386/pr100865-4a.c | 16 ++ gcc/testsuite/gcc.target/i386/pr100865-4b.c | 9 + gcc/testsuite/gcc.target/i386/pr100865-5a.c | 16 ++ gcc/testsuite/gcc.target/i386/pr100865-5b.c | 9 + gcc/testsuite/gcc.target/i386/pr100865-6a.c | 16 ++ gcc/testsuite/gcc.target/i386/pr100865-6b.c | 9 + gcc/testsuite/gcc.target/i386/pr100865-6c.c | 16 ++ gcc/testsuite/gcc.target/i386/pr100865-7a.c | 17 ++ gcc/testsuite/gcc.target/i386/pr100865-7b.c | 9 + gcc/testsuite/gcc.target/i386/pr100865-7c.c | 17 ++ gcc/testsuite/gcc.target/i386/pr100865-8a.c | 24 +++ gcc/testsuite/gcc.target/i386/pr100865-8b.c | 7 + gcc/testsuite/gcc.target/i386/pr100865-8c.c | 7 + gcc/testsuite/gcc.target/i386/pr100865-9a.c | 25 +++ gcc/testsuite/gcc.target/i386/pr100865-9b.c | 7 + gcc/testsuite/gcc.target/i386/pr100865-9c.c | 7 + 35 files changed, 590 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-10a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-10b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-11a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-11b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-11c.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-12a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-12b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-12c.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-4a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-4b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-5a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-5b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-6a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-6b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-6c.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-7a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-7b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-7c.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-8a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-8b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-8c.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-9a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-9b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr100865-9c.c (limited to 'gcc') diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index 76d6afd..0738141 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -93,6 +93,9 @@ along with GCC; see the file COPYING3. If not see #include "i386-builtins.h" #include "i386-expand.h" +static bool ix86_expand_vector_init_duplicate (bool, machine_mode, rtx, + rtx); + /* Split one or more double-mode RTL references into pairs of half-mode references. The RTL can be REG, offsettable MEM, integer constant, or CONST_DOUBLE. "operands" is a pointer to an array of double-mode RTLs to @@ -190,6 +193,82 @@ ix86_expand_clear (rtx dest) emit_insn (tmp); } +/* Return true if V can be broadcasted from an integer of WIDTH bits + which is returned in VAL_BROADCAST. Otherwise, return false. */ + +static bool +ix86_broadcast (HOST_WIDE_INT v, unsigned int width, + HOST_WIDE_INT &val_broadcast) +{ + wide_int val = wi::uhwi (v, HOST_BITS_PER_WIDE_INT); + val_broadcast = wi::extract_uhwi (val, 0, width); + for (unsigned int i = width; i < HOST_BITS_PER_WIDE_INT; i += width) + { + HOST_WIDE_INT each = wi::extract_uhwi (val, i, width); + if (val_broadcast != each) + return false; + } + val_broadcast = sext_hwi (val_broadcast, width); + return true; +} + +/* Convert the CONST_WIDE_INT operand OP to broadcast in MODE. */ + +static rtx +ix86_convert_const_wide_int_to_broadcast (machine_mode mode, rtx op) +{ + /* Don't use integer vector broadcast if we can't move from GPR to SSE + register directly. */ + if (!TARGET_INTER_UNIT_MOVES_TO_VEC) + return nullptr; + + /* Convert CONST_WIDE_INT to a non-standard SSE constant integer + broadcast only if vector broadcast is available. */ + if (!TARGET_AVX + || !CONST_WIDE_INT_P (op) + || standard_sse_constant_p (op, mode)) + return nullptr; + + HOST_WIDE_INT val = CONST_WIDE_INT_ELT (op, 0); + HOST_WIDE_INT val_broadcast; + scalar_int_mode broadcast_mode; + if (TARGET_AVX2 + && ix86_broadcast (val, GET_MODE_BITSIZE (QImode), + val_broadcast)) + broadcast_mode = QImode; + else if (TARGET_AVX2 + && ix86_broadcast (val, GET_MODE_BITSIZE (HImode), + val_broadcast)) + broadcast_mode = HImode; + else if (ix86_broadcast (val, GET_MODE_BITSIZE (SImode), + val_broadcast)) + broadcast_mode = SImode; + else if (TARGET_64BIT + && ix86_broadcast (val, GET_MODE_BITSIZE (DImode), + val_broadcast)) + broadcast_mode = DImode; + else + return nullptr; + + /* Check if OP can be broadcasted from VAL. */ + for (int i = 1; i < CONST_WIDE_INT_NUNITS (op); i++) + if (val != CONST_WIDE_INT_ELT (op, i)) + return nullptr; + + unsigned int nunits = (GET_MODE_SIZE (mode) + / GET_MODE_SIZE (broadcast_mode)); + machine_mode vector_mode; + if (!mode_for_vector (broadcast_mode, nunits).exists (&vector_mode)) + gcc_unreachable (); + rtx target = ix86_gen_scratch_sse_rtx (vector_mode); + bool ok = ix86_expand_vector_init_duplicate (false, vector_mode, + target, + GEN_INT (val_broadcast)); + gcc_assert (ok); + target = lowpart_subreg (mode, target, vector_mode); + return target; +} + void ix86_expand_move (machine_mode mode, rtx operands[]) { @@ -347,20 +426,29 @@ ix86_expand_move (machine_mode mode, rtx operands[]) && optimize) op1 = copy_to_mode_reg (mode, op1); - if (can_create_pseudo_p () - && CONST_DOUBLE_P (op1)) + if (can_create_pseudo_p ()) { - /* If we are loading a floating point constant to a register, - force the value to memory now, since we'll get better code - out the back end. */ + if (CONST_DOUBLE_P (op1)) + { + /* If we are loading a floating point constant to a + register, force the value to memory now, since we'll + get better code out the back end. */ - op1 = validize_mem (force_const_mem (mode, op1)); - if (!register_operand (op0, mode)) + op1 = validize_mem (force_const_mem (mode, op1)); + if (!register_operand (op0, mode)) + { + rtx temp = gen_reg_rtx (mode); + emit_insn (gen_rtx_SET (temp, op1)); + emit_move_insn (op0, temp); + return; + } + } + else if (GET_MODE_SIZE (mode) >= 16) { - rtx temp = gen_reg_rtx (mode); - emit_insn (gen_rtx_SET (temp, op1)); - emit_move_insn (op0, temp); - return; + rtx tmp = ix86_convert_const_wide_int_to_broadcast + (GET_MODE (op0), op1); + if (tmp != nullptr) + op1 = tmp; } } } @@ -368,6 +456,59 @@ ix86_expand_move (machine_mode mode, rtx operands[]) emit_insn (gen_rtx_SET (op0, op1)); } +static rtx +ix86_broadcast_from_integer_constant (machine_mode mode, rtx op) +{ + int nunits = GET_MODE_NUNITS (mode); + if (nunits < 2) + return nullptr; + + /* Don't use integer vector broadcast if we can't move from GPR to SSE + register directly. */ + if (!TARGET_INTER_UNIT_MOVES_TO_VEC) + return nullptr; + + /* Convert CONST_VECTOR to a non-standard SSE constant integer + broadcast only if vector broadcast is available. */ + if (!(TARGET_AVX2 + || (TARGET_AVX + && (GET_MODE_INNER (mode) == SImode + || GET_MODE_INNER (mode) == DImode))) + || standard_sse_constant_p (op, mode)) + return nullptr; + + /* Don't broadcast from a 64-bit integer constant in 32-bit mode. */ + if (GET_MODE_INNER (mode) == DImode && !TARGET_64BIT) + return nullptr; + + rtx constant = get_pool_constant (XEXP (op, 0)); + if (GET_CODE (constant) != CONST_VECTOR) + return nullptr; + + /* There could be some rtx like + (mem/u/c:V16QI (symbol_ref/u:DI ("*.LC1"))) + but with "*.LC1" refer to V2DI constant vector. */ + if (GET_MODE (constant) != mode) + { + constant = simplify_subreg (mode, constant, GET_MODE (constant), + 0); + if (constant == nullptr || GET_CODE (constant) != CONST_VECTOR) + return nullptr; + } + + rtx first = XVECEXP (constant, 0, 0); + + for (int i = 1; i < nunits; ++i) + { + rtx tmp = XVECEXP (constant, 0, i); + /* Vector duplicate value. */ + if (!rtx_equal_p (tmp, first)) + return nullptr; + } + + return first; +} + void ix86_expand_vector_move (machine_mode mode, rtx operands[]) { @@ -407,7 +548,36 @@ ix86_expand_vector_move (machine_mode mode, rtx operands[]) op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1)); } else - op1 = validize_mem (force_const_mem (mode, op1)); + { + machine_mode mode = GET_MODE (op0); + rtx tmp = ix86_convert_const_wide_int_to_broadcast + (mode, op1); + if (tmp == nullptr) + op1 = validize_mem (force_const_mem (mode, op1)); + else + op1 = tmp; + } + } + + if (can_create_pseudo_p () + && GET_MODE_SIZE (mode) >= 16 + && GET_MODE_CLASS (mode) == MODE_VECTOR_INT + && (MEM_P (op1) + && SYMBOL_REF_P (XEXP (op1, 0)) + && CONSTANT_POOL_ADDRESS_P (XEXP (op1, 0)))) + { + rtx first = ix86_broadcast_from_integer_constant (mode, op1); + if (first != nullptr) + { + /* Broadcast to XMM/YMM/ZMM register from an integer + constant. */ + op1 = ix86_gen_scratch_sse_rtx (mode); + bool ok = ix86_expand_vector_init_duplicate (false, mode, + op1, first); + gcc_assert (ok); + emit_move_insn (op0, op1); + return; + } } /* We need to check memory alignment for SSE mode since attribute diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 65fc307..71745b9 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -50,6 +50,8 @@ extern void ix86_reset_previous_fndecl (void); extern bool ix86_using_red_zone (void); +extern rtx ix86_gen_scratch_sse_rtx (machine_mode); + extern unsigned int ix86_regmode_natural_size (machine_mode); #ifdef RTX_CODE extern int standard_80387_constant_p (rtx); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index a93128f..2fbaae7 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -23163,6 +23163,19 @@ ix86_optab_supported_p (int op, machine_mode mode1, machine_mode, } } +/* Return a scratch register in MODE for vector load and store. */ + +rtx +ix86_gen_scratch_sse_rtx (machine_mode mode) +{ + if (TARGET_SSE) + return gen_rtx_REG (mode, (TARGET_64BIT + ? LAST_REX_SSE_REG + : LAST_SSE_REG)); + else + return gen_reg_rtx (mode); +} + /* Address space support. This is not "far pointers" in the 16-bit sense, but an easy way diff --git a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-1.c b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-1.c index 0563e69..a2664d8 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-1.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-1.c @@ -2,8 +2,11 @@ /* { dg-do compile } */ /* { dg-options "-O2 -mavx512f -mavx512dq" } */ /* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } } -/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 5 } } */ -/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to16\\\}" 5 } } */ +/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 2 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 5 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to16\\\}" 2 } } */ +/* { dg-final { scan-assembler-times "vpbroadcastd\[\\t \]+%(?:r|e)\[^\n\]*, %zmm\[0-9\]+" 3 } } */ +/* { dg-final { scan-assembler-times "vpbroadcastq\[\\t \]+%r\[^\n\]*, %zmm\[0-9\]+" 3 { target { ! ia32 } } } } */ typedef int v16si __attribute__ ((vector_size (64))); typedef long long v8di __attribute__ ((vector_size (64))); diff --git a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-5.c b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-5.c index ffbe959..477f9ca 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-5.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-5.c @@ -2,8 +2,9 @@ /* { dg-do compile } */ /* { dg-options "-O2 -mavx512f" } */ /* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } } -/* { dg-final { scan-assembler-times "\[^n\n\]*\\\{1to8\\\}" 4 } } */ -/* { dg-final { scan-assembler-times "\[^n\n\]*\\\{1to16\\\}" 4 } } */ +/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 4 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "vpbroadcastd\[\\t \]+%(?:r|e)\[^\n\]*, %zmm\[0-9\]+" 4 } } */ +/* { dg-final { scan-assembler-times "vpbroadcastq\[\\t \]+%r\[^\n\]*, %zmm\[0-9\]+" 4 { target { ! ia32 } } } } */ typedef int v16si __attribute__ ((vector_size (64))); typedef long long v8di __attribute__ ((vector_size (64))); diff --git a/gcc/testsuite/gcc.target/i386/avx512f_cond_move.c b/gcc/testsuite/gcc.target/i386/avx512f_cond_move.c index 99a89f5..ca49a58 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f_cond_move.c +++ b/gcc/testsuite/gcc.target/i386/avx512f_cond_move.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -mavx512f" } */ -/* { dg-final { scan-assembler-times "(?:vpblendmd|vmovdqa32)\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 8 } } */ +/* { dg-options "-O3 -mavx512f -mprefer-vector-width=512" } */ +/* { dg-final { scan-assembler-times "(?:vpbroadcastd|vmovdqa32)\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 8 } } */ unsigned int x[128]; int y[128]; diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-1.c index c06369d..f8eb99f 100644 --- a/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-1.c +++ b/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-1.c @@ -2,9 +2,15 @@ /* { dg-do compile } */ /* { dg-options "-O2 -mavx512f -mavx512vl -mavx512dq" } */ /* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } } -/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to2\\\}" 5 } } */ -/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to4\\\}" 10 } } */ -/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 5 } } */ +/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to2\\\}" 2 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to4\\\}" 4 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to2\\\}" 5 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to4\\\}" 7 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 2 } } */ +/* { dg-final { scan-assembler-times "vpbroadcastd\[\\t \]+%(?:r|e)\[^\n\]*, %xmm\[0-9\]+" 3 } } */ +/* { dg-final { scan-assembler-times "vpbroadcastd\[\\t \]+%(?:r|e)\[^\n\]*, %ymm\[0-9\]+" 3 } } */ +/* { dg-final { scan-assembler-times "vpbroadcastq\[\\t \]+%r\[^\n\]*, %xmm\[0-9\]+" 3 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "vpbroadcastq\[\\t \]+%r\[^\n\]*, %ymm\[0-9\]+" 3 { target { ! ia32 } } } } */ typedef int v4si __attribute__ ((vector_size (16))); typedef int v8si __attribute__ ((vector_size (32))); diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-5.c b/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-5.c index 4998a9b..32f6ac8 100644 --- a/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-5.c +++ b/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-5.c @@ -2,9 +2,12 @@ /* { dg-do compile } */ /* { dg-options "-O2 -mavx512f -mavx512vl" } */ /* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } } -/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to2\\\}" 4 } } */ -/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to4\\\}" 8 } } */ -/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 4 } } */ +/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to2\\\}" 4 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to4\\\}" 4 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "vpbroadcastd\[\\t \]+%(?:r|e)\[^\n\]*, %xmm\[0-9\]+" 4 } } */ +/* { dg-final { scan-assembler-times "vpbroadcastd\[\\t \]+%(?:r|e)\[^\n\]*, %ymm\[0-9\]+" 4 } } */ +/* { dg-final { scan-assembler-times "vpbroadcastq\[\\t \]+%r\[^\n\]*, %xmm\[0-9\]+" 4 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "vpbroadcastq\[\\t \]+%r\[^\n\]*, %ymm\[0-9\]+" 4 { target { ! ia32 } } } } */ typedef int v4si __attribute__ ((vector_size (16))); typedef int v8si __attribute__ ((vector_size (32))); diff --git a/gcc/testsuite/gcc.target/i386/pr100865-1.c b/gcc/testsuite/gcc.target/i386/pr100865-1.c new file mode 100644 index 0000000..6c3097f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -march=x86-64" } */ + +extern char *dst; + +void +foo (void) +{ + __builtin_memset (dst, 3, 16); +} + +/* { dg-final { scan-assembler-times "movdqa\[ \\t\]+\[^\n\]*%xmm" 1 } } */ +/* { dg-final { scan-assembler-times "movups\[\\t \]%xmm\[0-9\]+, \\(%\[\^,\]+\\)" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-10a.c b/gcc/testsuite/gcc.target/i386/pr100865-10a.c new file mode 100644 index 0000000..7ffc19e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-10a.c @@ -0,0 +1,33 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake" } */ + +extern __int128 array[16]; + +#define MK_CONST128_BROADCAST(A) \ + ((((unsigned __int128) (unsigned char) A) << 120) \ + | (((unsigned __int128) (unsigned char) A) << 112) \ + | (((unsigned __int128) (unsigned char) A) << 104) \ + | (((unsigned __int128) (unsigned char) A) << 96) \ + | (((unsigned __int128) (unsigned char) A) << 88) \ + | (((unsigned __int128) (unsigned char) A) << 80) \ + | (((unsigned __int128) (unsigned char) A) << 72) \ + | (((unsigned __int128) (unsigned char) A) << 64) \ + | (((unsigned __int128) (unsigned char) A) << 56) \ + | (((unsigned __int128) (unsigned char) A) << 48) \ + | (((unsigned __int128) (unsigned char) A) << 40) \ + | (((unsigned __int128) (unsigned char) A) << 32) \ + | (((unsigned __int128) (unsigned char) A) << 24) \ + | (((unsigned __int128) (unsigned char) A) << 16) \ + | (((unsigned __int128) (unsigned char) A) << 8) \ + | ((unsigned __int128) (unsigned char) A) ) + +void +foo (void) +{ + int i; + for (i = 0; i < sizeof (array) / sizeof (array[0]); i++) + array[i] = MK_CONST128_BROADCAST (0x1f); +} + +/* { dg-final { scan-assembler-times "vpbroadcastb\[\\t \]+\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-10b.c b/gcc/testsuite/gcc.target/i386/pr100865-10b.c new file mode 100644 index 0000000..edf5276 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-10b.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake-avx512" } */ + +#include "pr100865-10a.c" + +/* { dg-final { scan-assembler-times "vpbroadcastb\[\\t \]+%(?:r|e)\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-11a.c b/gcc/testsuite/gcc.target/i386/pr100865-11a.c new file mode 100644 index 0000000..04ce166 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-11a.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake" } */ + +extern __int128 array[16]; + +#define MK_CONST128_BROADCAST(A) \ + ((((unsigned __int128) (unsigned long long) A) << 64) \ + | ((unsigned __int128) (unsigned long long) A) ) + +#define MK_CONST128_BROADCAST_SIGNED(A) \ + ((__int128) MK_CONST128_BROADCAST (A)) + +void +foo (void) +{ + int i; + for (i = 0; i < sizeof (array) / sizeof (array[0]); i++) + array[i] = MK_CONST128_BROADCAST_SIGNED (-0x1ffffffffLL); +} + +/* { dg-final { scan-assembler-times "movabsq" 1 } } */ +/* { dg-final { scan-assembler-times "(?:vpbroadcastq|vpunpcklqdq)\[\\t \]+\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-11b.c b/gcc/testsuite/gcc.target/i386/pr100865-11b.c new file mode 100644 index 0000000..12d55b9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-11b.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake-avx512" } */ + +#include "pr100865-11a.c" + +/* { dg-final { scan-assembler-times "movabsq" 1 } } */ +/* { dg-final { scan-assembler-times "vpbroadcastq\[\\t \]+%(?:r|e)\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-11c.c b/gcc/testsuite/gcc.target/i386/pr100865-11c.c new file mode 100644 index 0000000..de56c84 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-11c.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake -mno-avx2" } */ + +#include "pr100865-11a.c" + +/* { dg-final { scan-assembler-times "movabsq" 1 } } */ +/* { dg-final { scan-assembler-times "vpunpcklqdq\[\\t \]+\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-12a.c b/gcc/testsuite/gcc.target/i386/pr100865-12a.c new file mode 100644 index 0000000..d4833d4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-12a.c @@ -0,0 +1,20 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake" } */ + +extern __int128 array[16]; + +#define MK_CONST128_BROADCAST(A) \ + ((((unsigned __int128) (unsigned long long) A) << 64) \ + | ((unsigned __int128) (unsigned long long) A) ) + +void +foo (void) +{ + int i; + for (i = 0; i < sizeof (array) / sizeof (array[0]); i++) + array[i] = MK_CONST128_BROADCAST (0x1ffffffffLL); +} + +/* { dg-final { scan-assembler-times "movabsq" 1 } } */ +/* { dg-final { scan-assembler-times "(?:vpbroadcastq|vpunpcklqdq)\[\\t \]+\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-12b.c b/gcc/testsuite/gcc.target/i386/pr100865-12b.c new file mode 100644 index 0000000..63a5629 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-12b.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake-avx512" } */ + +#include "pr100865-12a.c" + +/* { dg-final { scan-assembler-times "movabsq" 1 } } */ +/* { dg-final { scan-assembler-times "vpbroadcastq\[\\t \]+%(?:r|e)\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-12c.c b/gcc/testsuite/gcc.target/i386/pr100865-12c.c new file mode 100644 index 0000000..77415f2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-12c.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake -mno-avx2" } */ + +#include "pr100865-12a.c" + +/* { dg-final { scan-assembler-times "movabsq" 1 } } */ +/* { dg-final { scan-assembler-times "vpunpcklqdq\[\\t \]+\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-2.c b/gcc/testsuite/gcc.target/i386/pr100865-2.c new file mode 100644 index 0000000..17efe2d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -march=skylake" } */ + +extern char *dst; + +void +foo (void) +{ + __builtin_memset (dst, 3, 16); +} + +/* { dg-final { scan-assembler-times "vpbroadcastb\[\\t \]+%xmm\[0-9\]+, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[\\t \]%xmm\[0-9\]+, \\(%\[\^,\]+\\)" 1 } } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-3.c b/gcc/testsuite/gcc.target/i386/pr100865-3.c new file mode 100644 index 0000000..b6dbcf7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-3.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -march=skylake-avx512" } */ + +extern char *dst; + +void +foo (void) +{ + __builtin_memset (dst, 3, 16); +} + +/* { dg-final { scan-assembler-times "vpbroadcastb\[\\t \]+%(?:r|e)\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[\\t \]%xmm\[0-9\]+, \\(%\[\^,\]+\\)" 1 } } */ +/* { dg-final { scan-assembler-not "vpbroadcastb\[\\t \]+%xmm\[0-9\]+, %xmm\[0-9\]+" } } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-4a.c b/gcc/testsuite/gcc.target/i386/pr100865-4a.c new file mode 100644 index 0000000..f558835 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-4a.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -march=skylake" } */ + +extern char array[64]; + +void +foo (void) +{ + int i; + for (i = 0; i < sizeof (array) / sizeof (array[0]); i++) + array[i] = -45; +} + +/* { dg-final { scan-assembler-times "vpbroadcastb\[\\t \]+%xmm\[0-9\]+, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[\\t \]%xmm\[0-9\]+, " 4 } } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-4b.c b/gcc/testsuite/gcc.target/i386/pr100865-4b.c new file mode 100644 index 0000000..f41e614 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-4b.c @@ -0,0 +1,9 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -march=skylake-avx512" } */ + +#include "pr100865-4a.c" + +/* { dg-final { scan-assembler-times "vpbroadcastb\[\\t \]+%(?:r|e)\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[\\t \]%xmm\[0-9\]+, " 4 } } */ +/* { dg-final { scan-assembler-not "vpbroadcastb\[\\t \]+%xmm\[0-9\]+, %xmm\[0-9\]+" } } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-5a.c b/gcc/testsuite/gcc.target/i386/pr100865-5a.c new file mode 100644 index 0000000..4149797 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-5a.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake" } */ + +extern short array[64]; + +void +foo (void) +{ + int i; + for (i = 0; i < sizeof (array) / sizeof (array[0]); i++) + array[i] = -45; +} + +/* { dg-final { scan-assembler-times "vpbroadcastw\[\\t \]+%xmm\[0-9\]+, %ymm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[\\t \]%ymm\[0-9\]+, " 4 } } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-5b.c b/gcc/testsuite/gcc.target/i386/pr100865-5b.c new file mode 100644 index 0000000..ded41b68 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-5b.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake-avx512" } */ + +#include "pr100865-5a.c" + +/* { dg-final { scan-assembler-times "vpbroadcastw\[\\t \]+%(?:r|e)\[^\n\]*, %ymm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqu16\[\\t \]%ymm\[0-9\]+, " 4 } } */ +/* { dg-final { scan-assembler-not "vpbroadcastw\[\\t \]+%xmm\[0-9\]+, %ymm\[0-9\]+" } } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-6a.c b/gcc/testsuite/gcc.target/i386/pr100865-6a.c new file mode 100644 index 0000000..3fde549 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-6a.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake" } */ + +extern int array[64]; + +void +foo (void) +{ + int i; + for (i = 0; i < sizeof (array) / sizeof (array[0]); i++) + array[i] = -45; +} + +/* { dg-final { scan-assembler-times "vpbroadcastd\[\\t \]+%xmm\[0-9\]+, %ymm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[\\t \]%ymm\[0-9\]+, " 8 } } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-6b.c b/gcc/testsuite/gcc.target/i386/pr100865-6b.c new file mode 100644 index 0000000..44e74c6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-6b.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake-avx512" } */ + +#include "pr100865-6a.c" + +/* { dg-final { scan-assembler-times "vpbroadcastd\[\\t \]+%(?:r|e)\[^\n\]*, %ymm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[\\t \]%ymm\[0-9\]+, " 8 } } */ +/* { dg-final { scan-assembler-not "vpbroadcastd\[\\t \]+%xmm\[0-9\]+, %ymm\[0-9\]+" } } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-6c.c b/gcc/testsuite/gcc.target/i386/pr100865-6c.c new file mode 100644 index 0000000..46d3103 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-6c.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake -mno-avx2" } */ + +extern int array[64]; + +void +foo (void) +{ + int i; + for (i = 0; i < sizeof (array) / sizeof (array[0]); i++) + array[i] = -45; +} + +/* { dg-final { scan-assembler-times "vbroadcastss" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[\\t \]%ymm\[0-9\]+, " 8 } } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-7a.c b/gcc/testsuite/gcc.target/i386/pr100865-7a.c new file mode 100644 index 0000000..f6f2be9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-7a.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake" } */ + +extern long long int array[64]; + +void +foo (void) +{ + int i; + for (i = 0; i < sizeof (array) / sizeof (array[0]); i++) + array[i] = -45; +} + +/* { dg-final { scan-assembler-times "vpbroadcastq\[\\t \]+\[^\n\]*, %ymm\[0-9\]+" 1 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[\\t \]%ymm\[0-9\]+, " 16 } } */ +/* { dg-final { scan-assembler-not "vpbroadcastq" { target ia32 } } } */ +/* { dg-final { scan-assembler-not "vmovdqa" { target { ! ia32 } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-7b.c b/gcc/testsuite/gcc.target/i386/pr100865-7b.c new file mode 100644 index 0000000..0a68820 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-7b.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake-avx512" } */ + +#include "pr100865-7a.c" + +/* { dg-final { scan-assembler-times "vpbroadcastq\[\\t \]+%r\[^\n\]*, %ymm\[0-9\]+" 1 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "vpbroadcastq\[\\t \]+\[^\n\]*, %ymm\[0-9\]+" 1 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[\\t \]%ymm\[0-9\]+, " 16 } } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-7c.c b/gcc/testsuite/gcc.target/i386/pr100865-7c.c new file mode 100644 index 0000000..4d50bb7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-7c.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=skylake -mno-avx2" } */ + +extern long long int array[64]; + +void +foo (void) +{ + int i; + for (i = 0; i < sizeof (array) / sizeof (array[0]); i++) + array[i] = -45; +} + +/* { dg-final { scan-assembler-times "vbroadcastsd" 1 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[\\t \]%ymm\[0-9\]+, " 16 } } */ +/* { dg-final { scan-assembler-not "vbroadcastsd" { target ia32 } } } */ +/* { dg-final { scan-assembler-not "vmovdqa" { target { ! ia32 } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-8a.c b/gcc/testsuite/gcc.target/i386/pr100865-8a.c new file mode 100644 index 0000000..544a14d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-8a.c @@ -0,0 +1,24 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake" } */ + +extern __int128 array[16]; + +#define MK_CONST128_BROADCAST(A) \ + ((((unsigned __int128) (unsigned int) A) << 96) \ + | (((unsigned __int128) (unsigned int) A) << 64) \ + | (((unsigned __int128) (unsigned int) A) << 32) \ + | ((unsigned __int128) (unsigned int) A) ) + +#define MK_CONST128_BROADCAST_SIGNED(A) \ + ((__int128) MK_CONST128_BROADCAST (A)) + +void +foo (void) +{ + int i; + for (i = 0; i < sizeof (array) / sizeof (array[0]); i++) + array[i] = MK_CONST128_BROADCAST_SIGNED (-45); +} + +/* { dg-final { scan-assembler-times "(?:vpbroadcastd|vpshufd)\[\\t \]+\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-8b.c b/gcc/testsuite/gcc.target/i386/pr100865-8b.c new file mode 100644 index 0000000..99a10ad --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-8b.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake-avx512" } */ + +#include "pr100865-8a.c" + +/* { dg-final { scan-assembler-times "vpbroadcastd\[\\t \]+%(?:r|e)\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-8c.c b/gcc/testsuite/gcc.target/i386/pr100865-8c.c new file mode 100644 index 0000000..efee048 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-8c.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake -mno-avx2" } */ + +#include "pr100865-8a.c" + +/* { dg-final { scan-assembler-times "vpshufd\[\\t \]+\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-9a.c b/gcc/testsuite/gcc.target/i386/pr100865-9a.c new file mode 100644 index 0000000..45d0e0d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-9a.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake" } */ + +extern __int128 array[16]; + +#define MK_CONST128_BROADCAST(A) \ + ((((unsigned __int128) (unsigned short) A) << 112) \ + | (((unsigned __int128) (unsigned short) A) << 96) \ + | (((unsigned __int128) (unsigned short) A) << 80) \ + | (((unsigned __int128) (unsigned short) A) << 64) \ + | (((unsigned __int128) (unsigned short) A) << 48) \ + | (((unsigned __int128) (unsigned short) A) << 32) \ + | (((unsigned __int128) (unsigned short) A) << 16) \ + | ((unsigned __int128) (unsigned short) A) ) + +void +foo (void) +{ + int i; + for (i = 0; i < sizeof (array) / sizeof (array[0]); i++) + array[i] = MK_CONST128_BROADCAST (0x1fff); +} + +/* { dg-final { scan-assembler-times "vpbroadcastw\[\\t \]+%xmm\[0-9\]+, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-9b.c b/gcc/testsuite/gcc.target/i386/pr100865-9b.c new file mode 100644 index 0000000..1469624 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-9b.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake-avx512" } */ + +#include "pr100865-9a.c" + +/* { dg-final { scan-assembler-times "vpbroadcastw\[\\t \]+%(?:r|e)\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100865-9c.c b/gcc/testsuite/gcc.target/i386/pr100865-9c.c new file mode 100644 index 0000000..e6f2590 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100865-9c.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -march=skylake -mno-avx2" } */ + +#include "pr100865-9a.c" + +/* { dg-final { scan-assembler-times "vpshufd\[\\t \]+\[^\n\]*, %xmm\[0-9\]+" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqa\[\\t \]%xmm\[0-9\]+, " 16 } } */ -- cgit v1.1 From 51c30227fa6c739e2d367abf327b3b7dfd86dd46 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Mon, 7 Jun 2021 14:23:04 -0700 Subject: x86: Add vec_duplicate expander Add vec_duplicate expander for SSE2 if we can move from GPR to SSE register directly. * config/i386/i386-expand.c (ix86_expand_vector_init_duplicate): Make it global. * config/i386/i386-protos.h (ix86_expand_vector_init_duplicate): New prototype. * config/i386/sse.md (INT_BROADCAST_MODE): New mode iterator. (vec_duplicate): New expander. --- gcc/config/i386/i386-expand.c | 5 +---- gcc/config/i386/i386-protos.h | 2 ++ gcc/config/i386/sse.md | 31 +++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index 0738141..5c9170e 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -93,9 +93,6 @@ along with GCC; see the file COPYING3. If not see #include "i386-builtins.h" #include "i386-expand.h" -static bool ix86_expand_vector_init_duplicate (bool, machine_mode, rtx, - rtx); - /* Split one or more double-mode RTL references into pairs of half-mode references. The RTL can be REG, offsettable MEM, integer constant, or CONST_DOUBLE. "operands" is a pointer to an array of double-mode RTLs to @@ -13909,7 +13906,7 @@ static bool expand_vec_perm_1 (struct expand_vec_perm_d *d); /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector with all elements equal to VAR. Return true if successful. */ -static bool +bool ix86_expand_vector_init_duplicate (bool mmx_ok, machine_mode mode, rtx target, rtx val) { diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 71745b9..51376fc 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -258,6 +258,8 @@ extern void ix86_expand_mul_widen_hilo (rtx, rtx, rtx, bool, bool); extern void ix86_expand_sse2_mulv4si3 (rtx, rtx, rtx); extern void ix86_expand_sse2_mulvxdi3 (rtx, rtx, rtx); extern void ix86_expand_sse2_abs (rtx, rtx); +extern bool ix86_expand_vector_init_duplicate (bool, machine_mode, rtx, + rtx); /* In i386-c.c */ extern void ix86_target_macros (void); diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index d3f5a74..f0b450a 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -24814,3 +24814,34 @@ "TARGET_WIDEKL" "aes\t{%0}" [(set_attr "type" "other")]) + +;; Modes handled by broadcast patterns. NB: Allow V64QI and V32HI with +;; TARGET_AVX512F since ix86_expand_vector_init_duplicate can expand +;; without TARGET_AVX512BW which is used by memset vector broadcast +;; expander to XI with: +;; vmovd %edi, %xmm15 +;; vpbroadcastb %xmm15, %ymm15 +;; vinserti64x4 $0x1, %ymm15, %zmm15, %zmm15 + +(define_mode_iterator INT_BROADCAST_MODE + [(V64QI "TARGET_AVX512F") (V32QI "TARGET_AVX") V16QI + (V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI + (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI + (V8DI "TARGET_AVX512F && TARGET_64BIT") + (V4DI "TARGET_AVX && TARGET_64BIT") (V2DI "TARGET_64BIT")]) + +;; Broadcast from an integer. NB: Enable broadcast only if we can move +;; from GPR to SSE register directly. +(define_expand "vec_duplicate" + [(set (match_operand:INT_BROADCAST_MODE 0 "register_operand") + (vec_duplicate:INT_BROADCAST_MODE + (match_operand: 1 "nonimmediate_operand")))] + "TARGET_SSE2 && TARGET_INTER_UNIT_MOVES_TO_VEC" +{ + if (!ix86_expand_vector_init_duplicate (false, + GET_MODE (operands[0]), + operands[0], + operands[1])) + gcc_unreachable (); + DONE; +}) -- cgit v1.1 From cc8453012f75dc6dbd20bf3a94c4819a2bff46db Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Thu, 1 Jul 2021 15:02:43 +0100 Subject: Darwin: Define a suitable section name for CTF [PR101283] This is a placeholder name ahead of any CTF implementation on LLVM (which sets Darwin ABI). Ideally, we would get agreement on this choice (or any replacement) before GCC12 is shipped. PR debug/101283 - Several tests fail on Darwin with -gctf PR debug/101283 gcc/ChangeLog: * config/darwin.h (CTF_INFO_SECTION_NAME): New. --- gcc/config/darwin.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gcc') diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index d2b2c14..b7c3af3 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -1115,4 +1115,8 @@ extern void darwin_driver_init (unsigned int *,struct cl_decoded_option **); # endif #endif +/* CTF support. */ +#undef CTF_INFO_SECTION_NAME +#define CTF_INFO_SECTION_NAME "__CTF,__ctf,regular,debug" + #endif /* CONFIG_DARWIN_H */ -- cgit v1.1 From cdf4576b201aa81fd853b06242b16e4215ead5a9 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 1 Jul 2021 17:57:16 +0200 Subject: Use intermediate integer type with proper signedness This is a minor regression present on mainline and 11 branch, whereby the value of the Enum_Rep attribute is always unsigned. gcc/ada/ PR ada/101094 * exp_attr.adb (Get_Integer_Type): Return an integer type with the same signedness as the input type. --- gcc/ada/exp_attr.adb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 2e1cb85..af7f205d 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -1851,14 +1851,13 @@ package body Exp_Attr is ---------------------- function Get_Integer_Type (Typ : Entity_Id) return Entity_Id is - Siz : constant Uint := Esize (Base_Type (Typ)); + Siz : constant Uint := Esize (Base_Type (Typ)); begin -- We need to accommodate invalid values of the base type since we - -- accept them for Enum_Rep and Pos, so we reason on the Esize. And - -- we use an unsigned type since the enumeration type is unsigned. + -- accept them for Enum_Rep and Pos, so we reason on the Esize. - return Small_Integer_Type_For (Siz, Uns => True); + return Small_Integer_Type_For (Siz, Uns => Is_Unsigned_Type (Typ)); end Get_Integer_Type; --------------------------------- -- cgit v1.1 From 506c68e25fb6aea135468972dbc9d8abf816a443 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 1 Jul 2021 18:02:47 +0200 Subject: Fix duplicate name issues in output of -fdump-ada-spec #2 This extends the type name conflict detection mechanism to variables. gcc/c-family/ * c-ada-spec.c (check_name): Rename into... (check_type_name_conflict): ...this. Minor tweak. (dump_ada_function_declaration): Adjust to above renaming. (dump_ada_array_domains): Fix oversight. (dump_ada_declaration): Call check_type_name_conflict for variables. --- gcc/c-family/c-ada-spec.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c index a2669c6..ea52be6 100644 --- a/gcc/c-family/c-ada-spec.c +++ b/gcc/c-family/c-ada-spec.c @@ -1540,9 +1540,8 @@ dump_ada_import (pretty_printer *buffer, tree t, int spc) otherwise in BUFFER. */ static void -check_name (pretty_printer *buffer, tree t) +check_type_name_conflict (pretty_printer *buffer, tree t) { - const char *s; tree tmp = TREE_TYPE (t); while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp)) @@ -1550,6 +1549,8 @@ check_name (pretty_printer *buffer, tree t) if (TREE_CODE (tmp) != FUNCTION_TYPE) { + const char *s; + if (TREE_CODE (tmp) == IDENTIFIER_NODE) s = IDENTIFIER_POINTER (tmp); else if (!TYPE_NAME (tmp)) @@ -1641,7 +1642,7 @@ dump_ada_function_declaration (pretty_printer *buffer, tree func, { if (DECL_NAME (arg)) { - check_name (buffer, arg); + check_type_name_conflict (buffer, arg); pp_ada_tree_identifier (buffer, DECL_NAME (arg), NULL_TREE, false); pp_string (buffer, " : "); @@ -1710,7 +1711,8 @@ dump_ada_function_declaration (pretty_printer *buffer, tree func, static void dump_ada_array_domains (pretty_printer *buffer, tree node, int spc) { - int first = 1; + bool first = true; + pp_left_paren (buffer); for (; TREE_CODE (node) == ARRAY_TYPE; node = TREE_TYPE (node)) @@ -1724,7 +1726,7 @@ dump_ada_array_domains (pretty_printer *buffer, tree node, int spc) if (!first) pp_string (buffer, ", "); - first = 0; + first = false; if (min) dump_ada_node (buffer, min, NULL_TREE, spc, false, true); @@ -1738,7 +1740,10 @@ dump_ada_array_domains (pretty_printer *buffer, tree node, int spc) pp_string (buffer, "0"); } else - pp_string (buffer, "size_t"); + { + pp_string (buffer, "size_t"); + first = false; + } } pp_right_paren (buffer); } @@ -3152,8 +3157,9 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) if (need_indent) INDENT (spc); - if (TREE_CODE (t) == FIELD_DECL && DECL_NAME (t)) - check_name (buffer, t); + if ((TREE_CODE (t) == FIELD_DECL || TREE_CODE (t) == VAR_DECL) + && DECL_NAME (t)) + check_type_name_conflict (buffer, t); /* Print variable/type's name. */ dump_ada_node (buffer, t, t, spc, false, true); -- cgit v1.1 From a3d8860d6386cd12942bc0b1995765ea516297bd Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 1 Jul 2021 18:06:46 +0200 Subject: Improve packed record layout support with -fdump-ada-spec We cannot fully support packed record layout in -fdump-ada-spec, as packing in C and Ada does not behave the same, so we issue a warning. But simple cases are OK and can actually be handled without much work. gcc/c-family/ * c-ada-spec.c (packed_layout): New global variable. (dump_ada_declaration): Set it upon seeing a packed record type. Do not put the "aliased" keyword if it is set. (dump_ada_structure): Add Pack aspect if it is set and clear it. gcc/testsuite/ * c-c++-common/dump-ada-spec-14.c: Adjust dg-warning directive. --- gcc/c-family/c-ada-spec.c | 18 +++++++++++------- gcc/testsuite/c-c++-common/dump-ada-spec-14.c | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c index ea52be6..827bcc7 100644 --- a/gcc/c-family/c-ada-spec.c +++ b/gcc/c-family/c-ada-spec.c @@ -2038,6 +2038,7 @@ is_float128 (tree node) } static bool bitfield_used = false; +static bool packed_layout = false; /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type TYPE. SPC is the indentation level. LIMITED_ACCESS indicates whether NODE @@ -2851,14 +2852,14 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) return 1; } - /* ??? Packed record layout is not supported. */ + /* Packed record layout is not fully supported. */ if (TYPE_PACKED (TREE_TYPE (t))) { - warning_at (DECL_SOURCE_LOCATION (t), 0, - "unsupported record layout"); + warning_at (DECL_SOURCE_LOCATION (t), 0, "packed layout"); pp_string (buffer, "pragma Compile_Time_Warning (True, "); - pp_string (buffer, "\"probably incorrect record layout\");"); + pp_string (buffer, "\"packed layout may be incorrect\");"); newline_and_indent (buffer, spc); + packed_layout = true; } if (orig && TYPE_NAME (orig)) @@ -2951,7 +2952,8 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) pp_string (buffer, " : "); - if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != POINTER_TYPE) + if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != POINTER_TYPE + && !packed_layout) pp_string (buffer, "aliased "); if (TYPE_NAME (TREE_TYPE (t))) @@ -3185,7 +3187,8 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE && (TYPE_NAME (TREE_TYPE (t)) || (TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE - && TREE_CODE (TREE_TYPE (t)) != ENUMERAL_TYPE))) + && TREE_CODE (TREE_TYPE (t)) != ENUMERAL_TYPE)) + && !packed_layout) pp_string (buffer, "aliased "); if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL) @@ -3352,7 +3355,7 @@ dump_ada_structure (pretty_printer *buffer, tree node, tree type, bool nested, pp_string (buffer, "Unchecked_Union => True"); } - if (bitfield_used) + if (bitfield_used || packed_layout) { char buf[32]; pp_comma (buffer); @@ -3363,6 +3366,7 @@ dump_ada_structure (pretty_printer *buffer, tree node, tree type, bool nested, sprintf (buf, "Alignment => %d", TYPE_ALIGN (node) / BITS_PER_UNIT); pp_string (buffer, buf); bitfield_used = false; + packed_layout = false; } if (nested) diff --git a/gcc/testsuite/c-c++-common/dump-ada-spec-14.c b/gcc/testsuite/c-c++-common/dump-ada-spec-14.c index bfdec61..291eea8 100644 --- a/gcc/testsuite/c-c++-common/dump-ada-spec-14.c +++ b/gcc/testsuite/c-c++-common/dump-ada-spec-14.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-fdump-ada-spec" } */ -struct __attribute__((packed)) S /* { dg-warning "unsupported record layout" } */ +struct __attribute__((packed)) S /* { dg-warning "packed layout" } */ { char c; int t; -- cgit v1.1 From b97486f465ff7ee2ed1a5305bcc211563891c37e Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Thu, 1 Jul 2021 14:50:34 -0400 Subject: Add IEEE 128-bit fp conditional move on PowerPC. This patch adds the support for power10 IEEE 128-bit floating point conditional move and for automatically generating min/max. In this patch, I simplified things compared to previous patches. Instead of allowing any four of the modes to be used for the conditional move comparison and the move itself could use different modes, I restricted the conditional move to just the same mode. I.e. you can do: _Float128 a, b, c, d, e, r; r = (a == b) ? c : d; But you can't do: _Float128 c, d, r; double a, b; r = (a == b) ? c : d; or: _Float128 a, b; double c, d, r; r = (a == b) ? c : d; This eliminates a lot of the complexity of the code, because you don't have to worry about the sizes being different, and the IEEE 128-bit types being restricted to Altivec registers, while the SF/DF modes can use any VSX register. I did not modify the existing support that allowed conditional moves where SFmode operands are compared and DFmode operands are moved (and vice versa). I modified the test cases that I added to reflect this change. I have also fixed the test for not equal to use '!=' instead of '=='. 2021-07-01 Michael Meissner gcc/ * config/rs6000/rs6000.c (rs6000_maybe_emit_fp_cmove): Add IEEE 128-bit floating point conditional move support. (have_compare_and_set_mask): Add IEEE 128-bit floating point types. * config/rs6000/rs6000.md (movcc, IEEE128 iterator): New insn. (movcc_p10, IEEE128 iterator): New insn. (movcc_invert_p10, IEEE128 iterator): New insn. (fpmask, IEEE128 iterator): New insn. (xxsel, IEEE128 iterator): New insn. gcc/testsuite/ * gcc.target/powerpc/float128-cmove.c: New test. * gcc.target/powerpc/float128-minmax-3.c: New test. --- gcc/config/rs6000/rs6000.c | 32 ++++++- gcc/config/rs6000/rs6000.md | 106 +++++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/float128-cmove.c | 58 +++++++++++ .../gcc.target/powerpc/float128-minmax-3.c | 15 +++ 4 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-cmove.c create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-minmax-3.c (limited to 'gcc') diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index f3e5f95..9a5db63 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -15699,8 +15699,8 @@ rs6000_emit_vector_cond_expr (rtx dest, rtx op_true, rtx op_false, return 1; } -/* Possibly emit the xsmaxcdp and xsmincdp instructions to emit a maximum or - minimum with "C" semantics. +/* Possibly emit the xsmaxc{dp,qp} and xsminc{dp,qp} instructions to emit a + maximum or minimum with "C" semantics. Unless you use -ffast-math, you can't use these instructions to replace conditions that implicitly reverse the condition because the comparison @@ -15776,6 +15776,7 @@ rs6000_maybe_emit_fp_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) enum rtx_code code = GET_CODE (op); rtx op0 = XEXP (op, 0); rtx op1 = XEXP (op, 1); + machine_mode compare_mode = GET_MODE (op0); machine_mode result_mode = GET_MODE (dest); rtx compare_rtx; rtx cmove_rtx; @@ -15784,6 +15785,29 @@ rs6000_maybe_emit_fp_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) if (!can_create_pseudo_p ()) return 0; + /* We allow the comparison to be either SFmode/DFmode and the true/false + condition to be either SFmode/DFmode. I.e. we allow: + + float a, b; + double c, d, r; + + r = (a == b) ? c : d; + + and: + + double a, b; + float c, d, r; + + r = (a == b) ? c : d; + + but we don't allow intermixing the IEEE 128-bit floating point types with + the 32/64-bit scalar types. */ + + if (!(compare_mode == result_mode + || (compare_mode == SFmode && result_mode == DFmode) + || (compare_mode == DFmode && result_mode == SFmode))) + return false; + switch (code) { case EQ: @@ -15836,6 +15860,10 @@ have_compare_and_set_mask (machine_mode mode) case E_DFmode: return TARGET_P9_MINMAX; + case E_KFmode: + case E_TFmode: + return TARGET_POWER10 && TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode); + default: break; } diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index abd825f..e84d031 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -5449,6 +5449,112 @@ "xxsel %x0,%x4,%x3,%x1" [(set_attr "type" "vecmove")]) +;; Support for ISA 3.1 IEEE 128-bit conditional move. The mode used in the +;; comparison must be the same as used in the move. +(define_expand "movcc" + [(set (match_operand:IEEE128 0 "gpc_reg_operand") + (if_then_else:IEEE128 (match_operand 1 "comparison_operator") + (match_operand:IEEE128 2 "gpc_reg_operand") + (match_operand:IEEE128 3 "gpc_reg_operand")))] + "TARGET_POWER10 && TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" +{ + if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3])) + DONE; + else + FAIL; +}) + +(define_insn_and_split "*movcc_p10" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=&v,v") + (if_then_else:IEEE128 + (match_operator:CCFP 1 "fpmask_comparison_operator" + [(match_operand:IEEE128 2 "altivec_register_operand" "v,v") + (match_operand:IEEE128 3 "altivec_register_operand" "v,v")]) + (match_operand:IEEE128 4 "altivec_register_operand" "v,v") + (match_operand:IEEE128 5 "altivec_register_operand" "v,v"))) + (clobber (match_scratch:V2DI 6 "=0,&v"))] + "TARGET_POWER10 && TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" + "#" + "&& 1" + [(set (match_dup 6) + (if_then_else:V2DI (match_dup 1) + (match_dup 7) + (match_dup 8))) + (set (match_dup 0) + (if_then_else:IEEE128 (ne (match_dup 6) + (match_dup 8)) + (match_dup 4) + (match_dup 5)))] +{ + if (GET_CODE (operands[6]) == SCRATCH) + operands[6] = gen_reg_rtx (V2DImode); + + operands[7] = CONSTM1_RTX (V2DImode); + operands[8] = CONST0_RTX (V2DImode); +} + [(set_attr "length" "8") + (set_attr "type" "vecperm")]) + +;; Handle inverting the fpmask comparisons. +(define_insn_and_split "*movcc_invert_p10" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=&v,v") + (if_then_else:IEEE128 + (match_operator:CCFP 1 "invert_fpmask_comparison_operator" + [(match_operand:IEEE128 2 "altivec_register_operand" "v,v") + (match_operand:IEEE128 3 "altivec_register_operand" "v,v")]) + (match_operand:IEEE128 4 "altivec_register_operand" "v,v") + (match_operand:IEEE128 5 "altivec_register_operand" "v,v"))) + (clobber (match_scratch:V2DI 6 "=0,&v"))] + "TARGET_POWER10 && TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" + "#" + "&& 1" + [(set (match_dup 6) + (if_then_else:V2DI (match_dup 9) + (match_dup 7) + (match_dup 8))) + (set (match_dup 0) + (if_then_else:IEEE128 (ne (match_dup 6) + (match_dup 8)) + (match_dup 5) + (match_dup 4)))] +{ + rtx op1 = operands[1]; + enum rtx_code cond = reverse_condition_maybe_unordered (GET_CODE (op1)); + + if (GET_CODE (operands[6]) == SCRATCH) + operands[6] = gen_reg_rtx (V2DImode); + + operands[7] = CONSTM1_RTX (V2DImode); + operands[8] = CONST0_RTX (V2DImode); + + operands[9] = gen_rtx_fmt_ee (cond, CCFPmode, operands[2], operands[3]); +} + [(set_attr "length" "8") + (set_attr "type" "vecperm")]) + +(define_insn "*fpmask" + [(set (match_operand:V2DI 0 "altivec_register_operand" "=v") + (if_then_else:V2DI + (match_operator:CCFP 1 "fpmask_comparison_operator" + [(match_operand:IEEE128 2 "altivec_register_operand" "v") + (match_operand:IEEE128 3 "altivec_register_operand" "v")]) + (match_operand:V2DI 4 "all_ones_constant" "") + (match_operand:V2DI 5 "zero_constant" "")))] + "TARGET_POWER10 && TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" + "xscmp%V1qp %0,%2,%3" + [(set_attr "type" "fpcompare")]) + +(define_insn "*xxsel" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (if_then_else:IEEE128 + (ne (match_operand:V2DI 1 "altivec_register_operand" "v") + (match_operand:V2DI 2 "zero_constant" "")) + (match_operand:IEEE128 3 "altivec_register_operand" "v") + (match_operand:IEEE128 4 "altivec_register_operand" "v")))] + "TARGET_POWER10 && TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" + "xxsel %x0,%x4,%x3,%x1" + [(set_attr "type" "vecmove")]) + ;; Conversions to and from floating-point. diff --git a/gcc/testsuite/gcc.target/powerpc/float128-cmove.c b/gcc/testsuite/gcc.target/powerpc/float128-cmove.c new file mode 100644 index 0000000..2fae8dc --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/float128-cmove.c @@ -0,0 +1,58 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ppc_float128_hw } */ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ + +#ifndef TYPE +#ifdef __LONG_DOUBLE_IEEE128__ +#define TYPE long double + +#else +#define TYPE _Float128 +#endif +#endif + +/* Verify that the ISA 3.1 (power10) IEEE 128-bit conditional move instructions + are generated. */ + +TYPE +eq (TYPE a, TYPE b, TYPE c, TYPE d) +{ + return (a == b) ? c : d; +} + +TYPE +ne (TYPE a, TYPE b, TYPE c, TYPE d) +{ + return (a != b) ? c : d; +} + +TYPE +lt (TYPE a, TYPE b, TYPE c, TYPE d) +{ + return (a < b) ? c : d; +} + +TYPE +le (TYPE a, TYPE b, TYPE c, TYPE d) +{ + return (a <= b) ? c : d; +} + +TYPE +gt (TYPE a, TYPE b, TYPE c, TYPE d) +{ + return (a > b) ? c : d; +} + +TYPE +ge (TYPE a, TYPE b, TYPE c, TYPE d) +{ + return (a >= b) ? c : d; +} + +/* { dg-final { scan-assembler-times {\mxscmpeqqp\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mxscmpgeqp\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mxscmpgtqp\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mxxsel\M} 6 } } */ +/* { dg-final { scan-assembler-not {\mxscmpuqp\M} } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/float128-minmax-3.c b/gcc/testsuite/gcc.target/powerpc/float128-minmax-3.c new file mode 100644 index 0000000..6f7627c --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/float128-minmax-3.c @@ -0,0 +1,15 @@ +/* { dg-require-effective-target ppc_float128_hw } */ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ + +#ifndef TYPE +#define TYPE _Float128 +#endif + +/* Test that the fminf128/fmaxf128 functions generate if/then/else and not a + call. */ +TYPE f128_min (TYPE a, TYPE b) { return (a < b) ? a : b; } +TYPE f128_max (TYPE a, TYPE b) { return (b > a) ? b : a; } + +/* { dg-final { scan-assembler {\mxsmaxcqp\M} } } */ +/* { dg-final { scan-assembler {\mxsmincqp\M} } } */ -- cgit v1.1 From b544c348e13ad33d55f0d954370ab1fb0f2bf683 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 1 Jul 2021 17:44:51 -0400 Subject: input.c: move file caching globals to a new file_cache class This moves some global state from input.c to a new file_cache class, of which an instance is owned by global_dc. Various state is also made private. No functional change intended. gcc/ChangeLog: * diagnostic.h (diagnostic_context::m_file_cache): New field. * input.c (class fcache): Rename to... (class file_cache_slot): ...this, making most members private and prefixing fields with "m_". (file_cache_slot::get_file_path): New accessor. (file_cache_slot::get_use_count): New accessor. (file_cache_slot::missing_trailing_newline_p): New accessor. (file_cache_slot::inc_use_count): New. (fcache_buffer_size): Move to... (file_cache_slot::buffer_size): ...here. (fcache_line_record_size): Move to... (file_cache_slot::line_record_size): ...here. (fcache_tab): Delete, in favor of global_dc->m_file_cache. (fcache_tab_size): Move to file_cache::num_file_slots. (diagnostic_file_cache_init): Update for move of fcache_tab to global_dc->m_file_cache. (diagnostic_file_cache_fini): Likewise. (lookup_file_in_cache_tab): Convert to... (file_cache::lookup_file): ...this. (diagnostics_file_cache_forcibly_evict_file): Update for move of fcache_tab to global_dc->m_file_cache, moving most of implementation to... (file_cache::forcibly_evict_file): ...this new function and... (file_cache_slot::evict): ...this new function. (evicted_cache_tab_entry): Convert to... (file_cache::evicted_cache_tab_entry): ...this. (add_file_to_cache_tab): Convert to... (file_cache::add_file): ...this, moving bulk of implementation to... (file_cache_slot::create): ..this new function. (file_cache::file_cache): New. (file_cache::~file_cache): New. (lookup_or_add_file_to_cache_tab): Convert to... (file_cache::lookup_or_add_file): ..this new function. (fcache::fcache): Rename to... (file_cache_slot::file_cache_slot): ...this, adding "m_" prefixes to fields. (fcache::~fcache): Rename to... (file_cache_slot::~file_cache_slot): ...this, adding "m_" prefixes to fields. (needs_read): Convert to... (file_cache_slot::needs_read_p): ...this. (needs_grow): Convert to... (file_cache_slot::needs_grow_p): ...this. (maybe_grow): Convert to... (file_cache_slot::maybe_grow): ...this. (read_data): Convert to... (file_cache_slot::read_data): ...this. (maybe_read_data): Convert to... (file_cache_slot::maybe_read_data): ...this. (get_next_line): Convert to... (file_cache_slot::get_next_line): ...this. (goto_next_line): Convert to... (file_cache_slot::goto_next_line): ...this. (read_line_num): Convert to... (file_cache_slot::read_line_num): ...this. (location_get_source_line): Update for moving of globals to global_dc->m_file_cache. (location_missing_trailing_newline): Likewise. * input.h (class file_cache_slot): New forward decl. (class file_cache): New. Signed-off-by: David Malcolm --- gcc/diagnostic.h | 3 + gcc/input.c | 459 ++++++++++++++++++++++++++++++++----------------------- gcc/input.h | 33 ++++ 3 files changed, 301 insertions(+), 194 deletions(-) (limited to 'gcc') diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 1b9d6b1..086bc4f 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -136,6 +136,9 @@ struct diagnostic_context /* Where most of the diagnostic formatting work is done. */ pretty_printer *printer; + /* Cache of source code. */ + file_cache *m_file_cache; + /* The number of times we have issued diagnostics. */ int diagnostic_count[DK_LAST_DIAGNOSTIC_KIND]; diff --git a/gcc/input.c b/gcc/input.c index 9e39e7d..de20d98 100644 --- a/gcc/input.c +++ b/gcc/input.c @@ -32,9 +32,29 @@ along with GCC; see the file COPYING3. If not see /* This is a cache used by get_next_line to store the content of a file to be searched for file lines. */ -class fcache +class file_cache_slot { public: + file_cache_slot (); + ~file_cache_slot (); + + bool read_line_num (size_t line_num, + char ** line, ssize_t *line_len); + + /* Accessors. */ + const char *get_file_path () const { return m_file_path; } + unsigned get_use_count () const { return m_use_count; } + bool missing_trailing_newline_p () const + { + return m_missing_trailing_newline; + } + + void inc_use_count () { m_use_count++; } + + void create (const char *file_path, FILE *fp, unsigned highest_use_count); + void evict (); + + private: /* These are information used to store a line boundary. */ class line_info { @@ -61,36 +81,48 @@ public: {} }; + bool needs_read_p () const; + bool needs_grow_p () const; + void maybe_grow (); + bool read_data (); + bool maybe_read_data (); + bool get_next_line (char **line, ssize_t *line_len); + bool read_next_line (char ** line, ssize_t *line_len); + bool goto_next_line (); + + static const size_t buffer_size = 4 * 1024; + static const size_t line_record_size = 100; + /* The number of time this file has been accessed. This is used to designate which file cache to evict from the cache array. */ - unsigned use_count; + unsigned m_use_count; /* The file_path is the key for identifying a particular file in the cache. For libcpp-using code, the underlying buffer for this field is owned by the corresponding _cpp_file within the cpp_reader. */ - const char *file_path; + const char *m_file_path; - FILE *fp; + FILE *m_fp; /* This points to the content of the file that we've read so far. */ - char *data; + char *m_data; /* The size of the DATA array above.*/ - size_t size; + size_t m_size; /* The number of bytes read from the underlying file so far. This must be less (or equal) than SIZE above. */ - size_t nb_read; + size_t m_nb_read; /* The index of the beginning of the current line. */ - size_t line_start_idx; + size_t m_line_start_idx; /* The number of the previous line read. This starts at 1. Zero means we've read no line so far. */ - size_t line_num; + size_t m_line_num; /* This is the total number of lines of the current file. At the moment, we try to get this information from the line map @@ -100,24 +132,21 @@ public: the number of lines before compilation really starts. For e.g, the C front-end, it can happen that we start emitting diagnostics before the line map has seen the end of the file. */ - size_t total_lines; + size_t m_total_lines; /* Could this file be missing a trailing newline on its final line? Initially true (to cope with empty files), set to true/false as each line is read. */ - bool missing_trailing_newline; + bool m_missing_trailing_newline; /* This is a record of the beginning and end of the lines we've seen while reading the file. This is useful to avoid walking the data from the beginning when we are asked to read a line that is before LINE_START_IDX above. Note that the maximum size of this - record is fcache_line_record_size, so that the memory consumption + record is line_record_size, so that the memory consumption doesn't explode. We thus scale total_lines down to - fcache_line_record_size. */ - vec line_record; - - fcache (); - ~fcache (); + line_record_size. */ + vec m_line_record; }; /* Current position in real source file. */ @@ -133,11 +162,6 @@ class line_maps *line_table; class line_maps *saved_line_table; -static fcache *fcache_tab; -static const size_t fcache_tab_size = 16; -static const size_t fcache_buffer_size = 4 * 1024; -static const size_t fcache_line_record_size = 100; - /* Expand the source location LOC into a human readable location. If LOC resolves to a builtin location, the file name of the readable location is set to the string "". If EXPANSION_POINT_P is @@ -233,8 +257,9 @@ expand_location_1 (location_t loc, static void diagnostic_file_cache_init (void) { - if (fcache_tab == NULL) - fcache_tab = new fcache[fcache_tab_size]; + gcc_assert (global_dc); + if (global_dc->m_file_cache == NULL) + global_dc->m_file_cache = new file_cache (); } /* Free the resources used by the set of cache used for files accessed @@ -243,10 +268,10 @@ diagnostic_file_cache_init (void) void diagnostic_file_cache_fini (void) { - if (fcache_tab) + if (global_dc->m_file_cache) { - delete [] (fcache_tab); - fcache_tab = NULL; + delete global_dc->m_file_cache; + global_dc->m_file_cache = NULL; } } @@ -273,28 +298,25 @@ total_lines_num (const char *file_path) caret diagnostic. Return the found cached file, or NULL if no cached file was found. */ -static fcache* -lookup_file_in_cache_tab (const char *file_path) +file_cache_slot * +file_cache::lookup_file (const char *file_path) { - if (file_path == NULL) - return NULL; - - diagnostic_file_cache_init (); + gcc_assert (file_path); /* This will contain the found cached file. */ - fcache *r = NULL; - for (unsigned i = 0; i < fcache_tab_size; ++i) + file_cache_slot *r = NULL; + for (unsigned i = 0; i < num_file_slots; ++i) { - fcache *c = &fcache_tab[i]; - if (c->file_path && !strcmp (c->file_path, file_path)) + file_cache_slot *c = &m_file_slots[i]; + if (c->get_file_path () && !strcmp (c->get_file_path (), file_path)) { - ++c->use_count; + c->inc_use_count (); r = c; } } if (r) - ++r->use_count; + r->inc_use_count (); return r; } @@ -308,22 +330,39 @@ diagnostics_file_cache_forcibly_evict_file (const char *file_path) { gcc_assert (file_path); - fcache *r = lookup_file_in_cache_tab (file_path); + if (!global_dc->m_file_cache) + return; + + global_dc->m_file_cache->forcibly_evict_file (file_path); +} + +void +file_cache::forcibly_evict_file (const char *file_path) +{ + gcc_assert (file_path); + + file_cache_slot *r = lookup_file (file_path); if (!r) /* Not found. */ return; - r->file_path = NULL; - if (r->fp) - fclose (r->fp); - r->fp = NULL; - r->nb_read = 0; - r->line_start_idx = 0; - r->line_num = 0; - r->line_record.truncate (0); - r->use_count = 0; - r->total_lines = 0; - r->missing_trailing_newline = true; + r->evict (); +} + +void +file_cache_slot::evict () +{ + m_file_path = NULL; + if (m_fp) + fclose (m_fp); + m_fp = NULL; + m_nb_read = 0; + m_line_start_idx = 0; + m_line_num = 0; + m_line_record.truncate (0); + m_use_count = 0; + m_total_lines = 0; + m_missing_trailing_newline = true; } /* Return the file cache that has been less used, recently, or the @@ -331,26 +370,26 @@ diagnostics_file_cache_forcibly_evict_file (const char *file_path) *HIGHEST_USE_COUNT is set to the highest use count of the entries in the cache table. */ -static fcache* -evicted_cache_tab_entry (unsigned *highest_use_count) +file_cache_slot* +file_cache::evicted_cache_tab_entry (unsigned *highest_use_count) { diagnostic_file_cache_init (); - fcache *to_evict = &fcache_tab[0]; - unsigned huc = to_evict->use_count; - for (unsigned i = 1; i < fcache_tab_size; ++i) + file_cache_slot *to_evict = &m_file_slots[0]; + unsigned huc = to_evict->get_use_count (); + for (unsigned i = 1; i < num_file_slots; ++i) { - fcache *c = &fcache_tab[i]; - bool c_is_empty = (c->file_path == NULL); + file_cache_slot *c = &m_file_slots[i]; + bool c_is_empty = (c->get_file_path () == NULL); - if (c->use_count < to_evict->use_count - || (to_evict->file_path && c_is_empty)) + if (c->get_use_count () < to_evict->get_use_count () + || (to_evict->get_file_path () && c_is_empty)) /* We evict C because it's either an entry with a lower use count or one that is empty. */ to_evict = c; - if (huc < c->use_count) - huc = c->use_count; + if (huc < c->get_use_count ()) + huc = c->get_use_count (); if (c_is_empty) /* We've reached the end of the cache; subsequent elements are @@ -368,10 +407,10 @@ evicted_cache_tab_entry (unsigned *highest_use_count) accessed by caret diagnostic. This cache is added to an array of cache and can be retrieved by lookup_file_in_cache_tab. This function returns the created cache. Note that only the last - fcache_tab_size files are cached. */ + num_file_slots files are cached. */ -static fcache* -add_file_to_cache_tab (const char *file_path) +file_cache_slot* +file_cache::add_file (const char *file_path) { FILE *fp = fopen (file_path, "r"); @@ -379,22 +418,45 @@ add_file_to_cache_tab (const char *file_path) return NULL; unsigned highest_use_count = 0; - fcache *r = evicted_cache_tab_entry (&highest_use_count); - r->file_path = file_path; - if (r->fp) - fclose (r->fp); - r->fp = fp; - r->nb_read = 0; - r->line_start_idx = 0; - r->line_num = 0; - r->line_record.truncate (0); + file_cache_slot *r = evicted_cache_tab_entry (&highest_use_count); + r->create (file_path, fp, highest_use_count); + return r; +} + +/* Populate this slot for use on FILE_PATH and FP, dropping any + existing cached content within it. */ + +void +file_cache_slot::create (const char *file_path, FILE *fp, + unsigned highest_use_count) +{ + m_file_path = file_path; + if (m_fp) + fclose (m_fp); + m_fp = fp; + m_nb_read = 0; + m_line_start_idx = 0; + m_line_num = 0; + m_line_record.truncate (0); /* Ensure that this cache entry doesn't get evicted next time add_file_to_cache_tab is called. */ - r->use_count = ++highest_use_count; - r->total_lines = total_lines_num (file_path); - r->missing_trailing_newline = true; + m_use_count = ++highest_use_count; + m_total_lines = total_lines_num (file_path); + m_missing_trailing_newline = true; +} - return r; +/* file_cache's ctor. */ + +file_cache::file_cache () +: m_file_slots (new file_cache_slot[num_file_slots]) +{ +} + +/* file_cache's dtor. */ + +file_cache::~file_cache () +{ + delete[] m_file_slots; } /* Lookup the cache used for the content of a given file accessed by @@ -402,41 +464,41 @@ add_file_to_cache_tab (const char *file_path) for this file, add it to the array of cached file and return it. */ -static fcache* -lookup_or_add_file_to_cache_tab (const char *file_path) +file_cache_slot* +file_cache::lookup_or_add_file (const char *file_path) { - fcache *r = lookup_file_in_cache_tab (file_path); + file_cache_slot *r = lookup_file (file_path); if (r == NULL) - r = add_file_to_cache_tab (file_path); + r = add_file (file_path); return r; } /* Default constructor for a cache of file used by caret diagnostic. */ -fcache::fcache () -: use_count (0), file_path (NULL), fp (NULL), data (0), - size (0), nb_read (0), line_start_idx (0), line_num (0), - total_lines (0), missing_trailing_newline (true) +file_cache_slot::file_cache_slot () +: m_use_count (0), m_file_path (NULL), m_fp (NULL), m_data (0), + m_size (0), m_nb_read (0), m_line_start_idx (0), m_line_num (0), + m_total_lines (0), m_missing_trailing_newline (true) { - line_record.create (0); + m_line_record.create (0); } /* Destructor for a cache of file used by caret diagnostic. */ -fcache::~fcache () +file_cache_slot::~file_cache_slot () { - if (fp) + if (m_fp) { - fclose (fp); - fp = NULL; + fclose (m_fp); + m_fp = NULL; } - if (data) + if (m_data) { - XDELETEVEC (data); - data = 0; + XDELETEVEC (m_data); + m_data = 0; } - line_record.release (); + m_line_record.release (); } /* Returns TRUE iff the cache would need to be filled with data coming @@ -444,55 +506,55 @@ fcache::~fcache () current line is empty. Note that if the cache is full, it would need to be extended and filled again. */ -static bool -needs_read (fcache *c) +bool +file_cache_slot::needs_read_p () const { - return (c->nb_read == 0 - || c->nb_read == c->size - || (c->line_start_idx >= c->nb_read - 1)); + return (m_nb_read == 0 + || m_nb_read == m_size + || (m_line_start_idx >= m_nb_read - 1)); } /* Return TRUE iff the cache is full and thus needs to be extended. */ -static bool -needs_grow (fcache *c) +bool +file_cache_slot::needs_grow_p () const { - return c->nb_read == c->size; + return m_nb_read == m_size; } /* Grow the cache if it needs to be extended. */ -static void -maybe_grow (fcache *c) +void +file_cache_slot::maybe_grow () { - if (!needs_grow (c)) + if (!needs_grow_p ()) return; - size_t size = c->size == 0 ? fcache_buffer_size : c->size * 2; - c->data = XRESIZEVEC (char, c->data, size); - c->size = size; + size_t size = m_size == 0 ? buffer_size : m_size * 2; + m_data = XRESIZEVEC (char, m_data, size); + m_size = size; } /* Read more data into the cache. Extends the cache if need be. Returns TRUE iff new data could be read. */ -static bool -read_data (fcache *c) +bool +file_cache_slot::read_data () { - if (feof (c->fp) || ferror (c->fp)) + if (feof (m_fp) || ferror (m_fp)) return false; - maybe_grow (c); + maybe_grow (); - char * from = c->data + c->nb_read; - size_t to_read = c->size - c->nb_read; - size_t nb_read = fread (from, 1, to_read, c->fp); + char * from = m_data + m_nb_read; + size_t to_read = m_size - m_nb_read; + size_t nb_read = fread (from, 1, to_read, m_fp); - if (ferror (c->fp)) + if (ferror (m_fp)) return false; - c->nb_read += nb_read; + m_nb_read += nb_read; return !!nb_read; } @@ -500,12 +562,12 @@ read_data (fcache *c) coming from the file FP. Return TRUE iff the cache was filled with mode data. */ -static bool -maybe_read_data (fcache *c) +bool +file_cache_slot::maybe_read_data () { - if (!needs_read (c)) + if (!needs_read_p ()) return false; - return read_data (c); + return read_data (); } /* Read a new line from file FP, using C as a cache for the data @@ -518,18 +580,18 @@ maybe_read_data (fcache *c) otherwise. Note that subsequent calls to get_next_line might make the content of *LINE invalid. */ -static bool -get_next_line (fcache *c, char **line, ssize_t *line_len) +bool +file_cache_slot::get_next_line (char **line, ssize_t *line_len) { /* Fill the cache with data to process. */ - maybe_read_data (c); + maybe_read_data (); - size_t remaining_size = c->nb_read - c->line_start_idx; + size_t remaining_size = m_nb_read - m_line_start_idx; if (remaining_size == 0) /* There is no more data to process. */ return false; - char *line_start = c->data + c->line_start_idx; + char *line_start = m_data + m_line_start_idx; char *next_line_start = NULL; size_t len = 0; @@ -539,10 +601,10 @@ get_next_line (fcache *c, char **line, ssize_t *line_len) /* We haven't found the end-of-line delimiter in the cache. Fill the cache with more data from the file and look for the '\n'. */ - while (maybe_read_data (c)) + while (maybe_read_data ()) { - line_start = c->data + c->line_start_idx; - remaining_size = c->nb_read - c->line_start_idx; + line_start = m_data + m_line_start_idx; + remaining_size = m_nb_read - m_line_start_idx; line_end = (char *) memchr (line_start, '\n', remaining_size); if (line_end != NULL) { @@ -558,19 +620,19 @@ get_next_line (fcache *c, char **line, ssize_t *line_len) of when the line ends up with a '\n' and line_end points to that terminal '\n'. That consistency is useful below in the len calculation. */ - line_end = c->data + c->nb_read ; - c->missing_trailing_newline = true; + line_end = m_data + m_nb_read ; + m_missing_trailing_newline = true; } else - c->missing_trailing_newline = false; + m_missing_trailing_newline = false; } else { next_line_start = line_end + 1; - c->missing_trailing_newline = false; + m_missing_trailing_newline = false; } - if (ferror (c->fp)) + if (ferror (m_fp)) return false; /* At this point, we've found the end of the of line. It either @@ -580,54 +642,56 @@ get_next_line (fcache *c, char **line, ssize_t *line_len) len = line_end - line_start; - if (c->line_start_idx < c->nb_read) + if (m_line_start_idx < m_nb_read) *line = line_start; - ++c->line_num; + ++m_line_num; /* Before we update our line record, make sure the hint about the total number of lines of the file is correct. If it's not, then we give up recording line boundaries from now on. */ bool update_line_record = true; - if (c->line_num > c->total_lines) + if (m_line_num > m_total_lines) update_line_record = false; /* Now update our line record so that re-reading lines from the - before c->line_start_idx is faster. */ + before m_line_start_idx is faster. */ if (update_line_record - && c->line_record.length () < fcache_line_record_size) + && m_line_record.length () < line_record_size) { /* If the file lines fits in the line record, we just record all its lines ...*/ - if (c->total_lines <= fcache_line_record_size - && c->line_num > c->line_record.length ()) - c->line_record.safe_push (fcache::line_info (c->line_num, - c->line_start_idx, - line_end - c->data)); - else if (c->total_lines > fcache_line_record_size) + if (m_total_lines <= line_record_size + && m_line_num > m_line_record.length ()) + m_line_record.safe_push + (file_cache_slot::line_info (m_line_num, + m_line_start_idx, + line_end - m_data)); + else if (m_total_lines > line_record_size) { /* ... otherwise, we just scale total_lines down to - (fcache_line_record_size lines. */ - size_t n = (c->line_num * fcache_line_record_size) / c->total_lines; - if (c->line_record.length () == 0 - || n >= c->line_record.length ()) - c->line_record.safe_push (fcache::line_info (c->line_num, - c->line_start_idx, - line_end - c->data)); + (line_record_size lines. */ + size_t n = (m_line_num * line_record_size) / m_total_lines; + if (m_line_record.length () == 0 + || n >= m_line_record.length ()) + m_line_record.safe_push + (file_cache_slot::line_info (m_line_num, + m_line_start_idx, + line_end - m_data)); } } - /* Update c->line_start_idx so that it points to the next line to be + /* Update m_line_start_idx so that it points to the next line to be read. */ if (next_line_start) - c->line_start_idx = next_line_start - c->data; + m_line_start_idx = next_line_start - m_data; else /* We didn't find any terminal '\n'. Let's consider that the end of line is the end of the data in the cache. The next invocation of get_next_line will either read more data from the underlying file or return false early because we've reached the end of the file. */ - c->line_start_idx = c->nb_read; + m_line_start_idx = m_nb_read; *line_len = len; @@ -640,13 +704,13 @@ get_next_line (fcache *c, char **line, ssize_t *line_len) copying from the cache involved. Return TRUE upon successful completion. */ -static bool -goto_next_line (fcache *cache) +bool +file_cache_slot::goto_next_line () { char *l; ssize_t len; - return get_next_line (cache, &l, &len); + return get_next_line (&l, &len); } /* Read an arbitrary line number LINE_NUM from the file cached in C. @@ -656,54 +720,54 @@ goto_next_line (fcache *cache) *LINE is only valid until the next call of read_line_num. This function returns bool if a line was read. */ -static bool -read_line_num (fcache *c, size_t line_num, - char **line, ssize_t *line_len) +bool +file_cache_slot::read_line_num (size_t line_num, + char ** line, ssize_t *line_len) { gcc_assert (line_num > 0); - if (line_num <= c->line_num) + if (line_num <= m_line_num) { - /* We've been asked to read lines that are before c->line_num. + /* We've been asked to read lines that are before m_line_num. So lets use our line record (if it's not empty) to try to avoid re-reading the file from the beginning again. */ - if (c->line_record.is_empty ()) + if (m_line_record.is_empty ()) { - c->line_start_idx = 0; - c->line_num = 0; + m_line_start_idx = 0; + m_line_num = 0; } else { - fcache::line_info *i = NULL; - if (c->total_lines <= fcache_line_record_size) + file_cache_slot::line_info *i = NULL; + if (m_total_lines <= line_record_size) { /* In languages where the input file is not totally - preprocessed up front, the c->total_lines hint + preprocessed up front, the m_total_lines hint can be smaller than the number of lines of the file. In that case, only the first - c->total_lines have been recorded. + m_total_lines have been recorded. - Otherwise, the first c->total_lines we've read have + Otherwise, the first m_total_lines we've read have their start/end recorded here. */ - i = (line_num <= c->total_lines) - ? &c->line_record[line_num - 1] - : &c->line_record[c->total_lines - 1]; + i = (line_num <= m_total_lines) + ? &m_line_record[line_num - 1] + : &m_line_record[m_total_lines - 1]; gcc_assert (i->line_num <= line_num); } else { /* So the file had more lines than our line record size. Thus the number of lines we've recorded has - been scaled down to fcache_line_reacord_size. Let's + been scaled down to line_record_size. Let's pick the start/end of the recorded line that is closest to line_num. */ - size_t n = (line_num <= c->total_lines) - ? line_num * fcache_line_record_size / c->total_lines - : c ->line_record.length () - 1; - if (n < c->line_record.length ()) + size_t n = (line_num <= m_total_lines) + ? line_num * line_record_size / m_total_lines + : m_line_record.length () - 1; + if (n < m_line_record.length ()) { - i = &c->line_record[n]; + i = &m_line_record[n]; gcc_assert (i->line_num <= line_num); } } @@ -711,33 +775,33 @@ read_line_num (fcache *c, size_t line_num, if (i && i->line_num == line_num) { /* We have the start/end of the line. */ - *line = c->data + i->start_pos; + *line = m_data + i->start_pos; *line_len = i->end_pos - i->start_pos; return true; } if (i) { - c->line_start_idx = i->start_pos; - c->line_num = i->line_num - 1; + m_line_start_idx = i->start_pos; + m_line_num = i->line_num - 1; } else { - c->line_start_idx = 0; - c->line_num = 0; + m_line_start_idx = 0; + m_line_num = 0; } } } - /* Let's walk from line c->line_num up to line_num - 1, without + /* Let's walk from line m_line_num up to line_num - 1, without copying any line. */ - while (c->line_num < line_num - 1) - if (!goto_next_line (c)) + while (m_line_num < line_num - 1) + if (!goto_next_line ()) return false; /* The line we want is the next one. Let's read and copy it back to the caller. */ - return get_next_line (c, line, line_len); + return get_next_line (line, line_len); } /* Return the physical source line that corresponds to FILE_PATH/LINE. @@ -756,11 +820,16 @@ location_get_source_line (const char *file_path, int line) if (line == 0) return char_span (NULL, 0); - fcache *c = lookup_or_add_file_to_cache_tab (file_path); + if (file_path == NULL) + return char_span (NULL, 0); + + diagnostic_file_cache_init (); + + file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path); if (c == NULL) return char_span (NULL, 0); - bool read = read_line_num (c, line, &buffer, &len); + bool read = c->read_line_num (line, &buffer, &len); if (!read) return char_span (NULL, 0); @@ -774,11 +843,13 @@ location_get_source_line (const char *file_path, int line) bool location_missing_trailing_newline (const char *file_path) { - fcache *c = lookup_or_add_file_to_cache_tab (file_path); + diagnostic_file_cache_init (); + + file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path); if (c == NULL) return false; - return c->missing_trailing_newline; + return c->missing_trailing_newline_p (); } /* Test if the location originates from the spelling location of a diff --git a/gcc/input.h b/gcc/input.h index f1ef5d7..bbcec84 100644 --- a/gcc/input.h +++ b/gcc/input.h @@ -88,6 +88,39 @@ class char_span extern char_span location_get_source_line (const char *file_path, int line); extern bool location_missing_trailing_newline (const char *file_path); + +/* Forward decl of slot within file_cache, so that the definition doesn't + need to be in this header. */ +class file_cache_slot; + +/* A cache of source files for use when emitting diagnostics + (and in a few places in the C/C++ frontends). + + Results are only valid until the next call to the cache, as + slots can be evicted. + + Filenames are stored by pointer, and so must outlive the cache + instance. */ + +class file_cache +{ + public: + file_cache (); + ~file_cache (); + + file_cache_slot *lookup_or_add_file (const char *file_path); + void forcibly_evict_file (const char *file_path); + + private: + file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count); + file_cache_slot *add_file (const char *file_path); + file_cache_slot *lookup_file (const char *file_path); + + private: + static const size_t num_file_slots = 16; + file_cache_slot *m_file_slots; +}; + extern expanded_location expand_location_to_spelling_point (location_t, enum location_aspect aspect -- cgit v1.1 From bea7c16a467cd1278375df261e4bc1d2d6e48d3b Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 2 Jul 2021 00:16:47 +0000 Subject: Daily bump. --- gcc/ChangeLog | 217 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/ada/ChangeLog | 6 ++ gcc/c-family/ChangeLog | 15 ++++ gcc/cp/ChangeLog | 25 ++++++ gcc/testsuite/ChangeLog | 91 ++++++++++++++++++++ 6 files changed, 355 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0b2c08f..b514c21 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,220 @@ +2021-07-01 David Malcolm + + * diagnostic.h (diagnostic_context::m_file_cache): New field. + * input.c (class fcache): Rename to... + (class file_cache_slot): ...this, making most members private and + prefixing fields with "m_". + (file_cache_slot::get_file_path): New accessor. + (file_cache_slot::get_use_count): New accessor. + (file_cache_slot::missing_trailing_newline_p): New accessor. + (file_cache_slot::inc_use_count): New. + (fcache_buffer_size): Move to... + (file_cache_slot::buffer_size): ...here. + (fcache_line_record_size): Move to... + (file_cache_slot::line_record_size): ...here. + (fcache_tab): Delete, in favor of global_dc->m_file_cache. + (fcache_tab_size): Move to file_cache::num_file_slots. + (diagnostic_file_cache_init): Update for move of fcache_tab + to global_dc->m_file_cache. + (diagnostic_file_cache_fini): Likewise. + (lookup_file_in_cache_tab): Convert to... + (file_cache::lookup_file): ...this. + (diagnostics_file_cache_forcibly_evict_file): Update for move of + fcache_tab to global_dc->m_file_cache, moving most of + implementation to... + (file_cache::forcibly_evict_file): ...this new function and... + (file_cache_slot::evict): ...this new function. + (evicted_cache_tab_entry): Convert to... + (file_cache::evicted_cache_tab_entry): ...this. + (add_file_to_cache_tab): Convert to... + (file_cache::add_file): ...this, moving bulk of implementation + to... + (file_cache_slot::create): ..this new function. + (file_cache::file_cache): New. + (file_cache::~file_cache): New. + (lookup_or_add_file_to_cache_tab): Convert to... + (file_cache::lookup_or_add_file): ..this new function. + (fcache::fcache): Rename to... + (file_cache_slot::file_cache_slot): ...this, adding "m_" prefixes + to fields. + (fcache::~fcache): Rename to... + (file_cache_slot::~file_cache_slot): ...this, adding "m_" prefixes + to fields. + (needs_read): Convert to... + (file_cache_slot::needs_read_p): ...this. + (needs_grow): Convert to... + (file_cache_slot::needs_grow_p): ...this. + (maybe_grow): Convert to... + (file_cache_slot::maybe_grow): ...this. + (read_data): Convert to... + (file_cache_slot::read_data): ...this. + (maybe_read_data): Convert to... + (file_cache_slot::maybe_read_data): ...this. + (get_next_line): Convert to... + (file_cache_slot::get_next_line): ...this. + (goto_next_line): Convert to... + (file_cache_slot::goto_next_line): ...this. + (read_line_num): Convert to... + (file_cache_slot::read_line_num): ...this. + (location_get_source_line): Update for moving of globals to + global_dc->m_file_cache. + (location_missing_trailing_newline): Likewise. + * input.h (class file_cache_slot): New forward decl. + (class file_cache): New. + +2021-07-01 Michael Meissner + + * config/rs6000/rs6000.c (rs6000_maybe_emit_fp_cmove): Add IEEE + 128-bit floating point conditional move support. + (have_compare_and_set_mask): Add IEEE 128-bit floating point + types. + * config/rs6000/rs6000.md (movcc, IEEE128 iterator): New insn. + (movcc_p10, IEEE128 iterator): New insn. + (movcc_invert_p10, IEEE128 iterator): New insn. + (fpmask, IEEE128 iterator): New insn. + (xxsel, IEEE128 iterator): New insn. + +2021-07-01 Iain Sandoe + + PR debug/101283 + * config/darwin.h (CTF_INFO_SECTION_NAME): New. + +2021-07-01 H.J. Lu + + * config/i386/i386-expand.c (ix86_expand_vector_init_duplicate): + Make it global. + * config/i386/i386-protos.h (ix86_expand_vector_init_duplicate): + New prototype. + * config/i386/sse.md (INT_BROADCAST_MODE): New mode iterator. + (vec_duplicate): New expander. + +2021-07-01 H.J. Lu + + PR target/100865 + * config/i386/i386-expand.c (ix86_expand_vector_init_duplicate): + New prototype. + (ix86_byte_broadcast): New function. + (ix86_convert_const_wide_int_to_broadcast): Likewise. + (ix86_expand_move): Convert CONST_WIDE_INT to broadcast if mode + size is 16 bytes or bigger. + (ix86_broadcast_from_integer_constant): New function. + (ix86_expand_vector_move): Convert CONST_WIDE_INT and CONST_VECTOR + to broadcast if mode size is 16 bytes or bigger. + * config/i386/i386-protos.h (ix86_gen_scratch_sse_rtx): New + prototype. + * config/i386/i386.c (ix86_gen_scratch_sse_rtx): New function. + +2021-07-01 Uroš Bizjak + + * config/i386/predicates.md (ix86_endbr_immediate_operand): + Return true/false instead of 1/0. + (movq_parallel): Ditto. + +2021-07-01 Uroš Bizjak + + * recog.c (general_operand): Return true/false instead of 1/0. + (register_operand): Ditto. + (immediate_operand): Ditto. + (const_int_operand): Ditto. + (const_scalar_int_operand): Ditto. + (const_double_operand): Ditto. + (push_operand): Ditto. + (pop_operand): Ditto. + (memory_operand): Ditto. + (indirect_operand): Ditto. + +2021-07-01 Uroš Bizjak + + * genpreds.c (write_predicate_subfunction): + Change the type of written subfunction to bool. + (write_one_predicate_function): + Change the type of written function to bool. + (write_tm_preds_h): Ditto. + * recog.h (*insn_operand_predicate_fn): Change the type to bool. + * recog.c (general_operand): Change the type to bool. + (address_operand): Ditto. + (register_operand): Ditto. + (pmode_register_operand): Ditto. + (scratch_operand): Ditto. + (immediate_operand): Ditto. + (const_int_operand): Ditto. + (const_scalar_int_operand): Ditto. + (const_double_operand): Ditto. + (nonimmediate_operand): Ditto. + (nonmemory_operand): Ditto. + (push_operand): Ditto. + (pop_operand): Ditto. + (memory_operand): Ditto. + (indirect_operand): Ditto. + (ordered_comparison_operator): Ditto. + (comparison_operator): Ditto. + * config/i386/i386-expand.c (ix86_expand_sse_cmp): + Change the type of indirect predicate function to bool. + * config/rs6000/rs6000.c (easy_vector_constant): + Change the type to bool. + * config/mips/mips-protos.h (m16_based_address_p): + Change the type of operand 3 to bool. + +2021-07-01 Richard Biener + + PR tree-optimization/101280 + PR tree-optimization/101173 + * gimple-loop-interchange.cc + (tree_loop_interchange::valid_data_dependences): Revert + previous change and instead correctly handle DDR_REVERSED_P + dependence. + +2021-07-01 Richard Biener + + PR tree-optimization/101278 + * tree-ssa-dse.c (dse_classify_store): First check for + uses, then ignore stmt for chaining purposes. + +2021-07-01 Richard Biener + + PR tree-optimization/100778 + * tree-vect-slp.c (vect_schedule_slp_node): Do not place trapping + vectorized ops ahead of their scalar BB. + +2021-07-01 Uroš Bizjak + + PR target/101044 + * config/i386/i386.md (*nabs2_doubleword): + New insn_and_split pattern. + (*nabs2_1): Ditto. + * config/i386/i386-features.c + (general_scalar_chain::compute_convert_gain): + Handle (NEG (ABS (...))) RTX. Rewrite src code + scanner as switch statement. + (general_scalar_chain::convert_insn): + Handle (NEG (ABS (...))) RTX. + (general_scalar_to_vector_candidate_p): + Detect (NEG (ABS (...))) RTX. Reorder case statements + for (AND (NOT (...) ...)) fallthrough. + +2021-07-01 Richard Biener + + PR tree-optimization/101178 + * tree-vect-slp.c (slpg_vertex::materialize): Remove. + (slpg::perm_in): Add. + (slpg::get_perm_in): Remove. + (slpg::get_perm_materialized): Add. + (vect_optimize_slp): Handle VEC_PERM nodes more optimally + during permute propagation and materialization. + +2021-07-01 Jakub Jelinek + + PR debug/101266 + * dwarf2out.c (loc_list_from_tree_1): Handle COMPOUND_LITERAL_EXPR. + +2021-07-01 Jakub Jelinek + + PR middle-end/94366 + * omp-low.c (lower_rec_input_clauses): Rename is_fp_and_or to + is_truth_op, set it for TRUTH_*IF_EXPR regardless of new_var's type, + use boolean_type_node instead of integer_type_node as NE_EXPR type. + (lower_reduction_clauses): Likewise. + 2021-06-30 Hafiz Abid Qadeer * config/gcn/gcn.c: Include dwarf2.h. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 8d2a207..7369508 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210701 +20210702 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f07cc96..923c8a6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2021-07-01 Eric Botcazou + + PR ada/101094 + * exp_attr.adb (Get_Integer_Type): Return an integer type with the + same signedness as the input type. + 2021-06-29 Richard Kenner * sem_util.adb (Visit_Node): Add handling for N_Block_Statement diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index fe6a44c..ae7cafc 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,18 @@ +2021-07-01 Eric Botcazou + + * c-ada-spec.c (packed_layout): New global variable. + (dump_ada_declaration): Set it upon seeing a packed record type. + Do not put the "aliased" keyword if it is set. + (dump_ada_structure): Add Pack aspect if it is set and clear it. + +2021-07-01 Eric Botcazou + + * c-ada-spec.c (check_name): Rename into... + (check_type_name_conflict): ...this. Minor tweak. + (dump_ada_function_declaration): Adjust to above renaming. + (dump_ada_array_domains): Fix oversight. + (dump_ada_declaration): Call check_type_name_conflict for variables. + 2021-06-25 Martin Sebor * c-common.c (c_wrap_maybe_const): Remove TREE_NO_WARNING. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d861f29..13b009e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,28 @@ +2021-07-01 Patrick Palka + + PR c++/101194 + * constexpr.c (cxx_eval_array_reference): When the element type + is an empty type and the corresponding element is omitted, just + return an empty CONSTRUCTOR instead of attempting value + initialization. + +2021-07-01 Patrick Palka + + PR c++/96204 + * pt.c (finish_template_variable): Pass the partially + instantiated template and its args to instantiate_template. + (instantiate_class_template_1): No need to call + push_nested_class and pop_nested_class around the call to + most_specialized_partial_spec. + (instantiate_template_1): Pass the partially instantiated + template to lookup_template_variable. + (most_specialized_partial_spec): Use push_access_scope_guard + to set the access scope appropriately. Use + deferring_access_check_sentinel to force access to get checked + immediately. + (instantiate_decl): Just pass the VAR_DECL to + most_specialized_partial_spec. + 2021-06-30 Patrick Palka * constraint.cc (get_normalized_constraints_from_decl): Use diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c14ff6e..fd699df 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,94 @@ +2021-07-01 Michael Meissner + + * gcc.target/powerpc/float128-cmove.c: New test. + * gcc.target/powerpc/float128-minmax-3.c: New test. + +2021-07-01 Eric Botcazou + + * c-c++-common/dump-ada-spec-14.c: Adjust dg-warning directive. + +2021-07-01 H.J. Lu + + PR target/100865 + * gcc.target/i386/avx512f-broadcast-pr87767-1.c: Expect integer + broadcast. + * gcc.target/i386/avx512f-broadcast-pr87767-5.c: Likewise. + * gcc.target/i386/avx512vl-broadcast-pr87767-1.c: Likewise. + * gcc.target/i386/avx512vl-broadcast-pr87767-5.c: Likewise. + * gcc.target/i386/avx512f_cond_move.c: Also pass + -mprefer-vector-width=512 and expect integer broadcast. + * gcc.target/i386/pr100865-1.c: New test. + * gcc.target/i386/pr100865-2.c: Likewise. + * gcc.target/i386/pr100865-3.c: Likewise. + * gcc.target/i386/pr100865-4a.c: Likewise. + * gcc.target/i386/pr100865-4b.c: Likewise. + * gcc.target/i386/pr100865-5a.c: Likewise. + * gcc.target/i386/pr100865-5b.c: Likewise. + * gcc.target/i386/pr100865-6a.c: Likewise. + * gcc.target/i386/pr100865-6b.c: Likewise. + * gcc.target/i386/pr100865-6c.c: Likewise. + * gcc.target/i386/pr100865-7a.c: Likewise. + * gcc.target/i386/pr100865-7b.c: Likewise. + * gcc.target/i386/pr100865-7c.c: Likewise. + * gcc.target/i386/pr100865-8a.c: Likewise. + * gcc.target/i386/pr100865-8b.c: Likewise. + * gcc.target/i386/pr100865-8c.c: Likewise. + * gcc.target/i386/pr100865-9a.c: Likewise. + * gcc.target/i386/pr100865-9b.c: Likewise. + * gcc.target/i386/pr100865-9c.c: Likewise. + * gcc.target/i386/pr100865-10a.c: Likewise. + * gcc.target/i386/pr100865-10b.c: Likewise. + * gcc.target/i386/pr100865-11a.c: Likewise. + * gcc.target/i386/pr100865-11b.c: Likewise. + * gcc.target/i386/pr100865-11c.c: Likewise. + * gcc.target/i386/pr100865-12a.c: Likewise. + * gcc.target/i386/pr100865-12b.c: Likewise. + * gcc.target/i386/pr100865-12c.c: Likewise. + +2021-07-01 Richard Biener + + PR tree-optimization/101280 + PR tree-optimization/101173 + * gcc.dg/tree-ssa/loop-interchange-16.c: New testcase. + +2021-07-01 Richard Biener + + PR tree-optimization/101278 + * gcc.dg/torture/pr101278.c: New testcase. + +2021-07-01 Richard Biener + + PR tree-optimization/100778 + * gcc.dg/torture/pr100778.c: New testcase. + +2021-07-01 Uroš Bizjak + + PR target/101044 + * gcc.target/i386/pr101044.c: New test. + +2021-07-01 Richard Biener + + PR tree-optimization/101178 + * gcc.dg/vect/bb-slp-72.c: New testcase. + * gcc.dg/vect/bb-slp-73.c: Likewise. + * gcc.dg/vect/bb-slp-74.c: Likewise. + +2021-07-01 Jakub Jelinek + + PR debug/101266 + * gcc.dg/pr101266.c: New test. + +2021-07-01 Patrick Palka + + PR c++/101194 + * g++.dg/cpp0x/constexpr-empty16.C: New test. + +2021-07-01 Patrick Palka + + PR c++/96204 + * g++.dg/template/access41.C: New test. + * g++.dg/template/access41a.C: New test. + 2021-06-30 Indu Bhagat * gcc.dg/debug/ctf/ctf-skip-types-4.c: Add dg-add-options float64 and -- cgit v1.1 From 73494401241b183ca188954a035734fcc53d97de Mon Sep 17 00:00:00 2001 From: liuhongt Date: Wed, 30 Jun 2021 17:10:44 +0800 Subject: Fix typo in standard pattern name of trunc2. gcc/ChangeLog * config/i386/sse.md (trunc2): Refined to .. (trunc2): this. --- gcc/config/i386/sse.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index f0b450a..bcf1605 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -11199,12 +11199,14 @@ (define_mode_iterator PMOV_SRC_MODE_4 [V4DI V2DI V4SI]) (define_mode_attr pmov_dst_4 [(V4DI "V4HI") (V2DI "V2HI") (V4SI "V4HI")]) +(define_mode_attr pmov_dst_4_lower + [(V4DI "v4hi") (V2DI "v2hi") (V4SI "v4hi")]) (define_mode_attr pmov_dst_zeroed_4 [(V4DI "V4HI") (V2DI "V6HI") (V4SI "V4HI")]) (define_mode_attr pmov_suff_4 [(V4DI "qw") (V2DI "qw") (V4SI "dw")]) -(define_expand "trunc2" +(define_expand "trunc2" [(set (match_operand: 0 "register_operand") (truncate: (match_operand:PMOV_SRC_MODE_4 1 "register_operand")))] -- cgit v1.1 From 01d402c5e0ac1ddf5618bbe316b50067625fda46 Mon Sep 17 00:00:00 2001 From: Eugene Rozenfeld Date: Thu, 1 Jul 2021 16:21:36 -0700 Subject: Update gen_autofdo_event.py and gcc-auto-profile. gen_autofdo_event.py was stumbling on models with stepping so I updated the script to handle this case similar to the code in https://github.com/andikleen/pmu-tools/blob/c6a5f63aede19def8886d6a8b74d7a55c38ca947/event_download.py The second change was to tolerate cases when the CPU supports PEBS but the perf command with /p fails. This can happen in, e.g., a virtual machine. I regenerated gcc-auto-profile using the updated script. contrib/ChangeLog: * gen_autofdo_event.py: handle stepping, non-working PEBS gcc/ChangeLog: * config/i386/gcc-auto-profile: regenerate --- gcc/config/i386/gcc-auto-profile | 41 +++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/gcc-auto-profile b/gcc/config/i386/gcc-auto-profile index 5da5c63..56f64cb 100755 --- a/gcc/config/i386/gcc-auto-profile +++ b/gcc/config/i386/gcc-auto-profile @@ -1,7 +1,7 @@ #!/bin/sh -# profile workload for gcc profile feedback (autofdo) using Linux perf -# auto generated. to regenerate for new CPUs run -# contrib/gen_autofdo_event.py --shell --all in gcc source +# Profile workload for gcc profile feedback (autofdo) using Linux perf. +# Auto generated. To regenerate for new CPUs run +# contrib/gen_autofdo_event.py --script --all in gcc source # usages: # gcc-auto-profile program (profile program and children) @@ -10,7 +10,7 @@ # gcc-auto-profile --kernel -a sleep X (profile kernel) # gcc-auto-profile --all -a sleep X (profile kernel and user space) -# identify branches taken event for CPU +# Identify branches taken event for CPU. # FLAGS=u @@ -37,7 +37,12 @@ case `egrep -q "^cpu family\s*: 6" /proc/cpuinfo && egrep "^model\s*:" /proc/cpuinfo | head -n1` in model*:\ 55|\ model*:\ 77|\ -model*:\ 76) E="cpu/event=0xC4,umask=0xFE/p$FLAGS" ;; +model*:\ 76|\ +model*:\ 92|\ +model*:\ 95|\ +model*:\ 87|\ +model*:\ 133|\ +model*:\ 122) E="cpu/event=0xC4,umask=0xFE/p$FLAGS" ;; model*:\ 42|\ model*:\ 45|\ model*:\ 58|\ @@ -48,9 +53,16 @@ model*:\ 70|\ model*:\ 63|\ model*:\ 61|\ model*:\ 71|\ +model*:\ 79|\ model*:\ 86|\ model*:\ 78|\ -model*:\ 94) E="cpu/event=0xC4,umask=0x20/p$FLAGS" ;; +model*:\ 94|\ +model*:\ 142|\ +model*:\ 158|\ +model*:\ 165|\ +model*:\ 166|\ +model*:\ 85|\ +model*:\ 85) E="cpu/event=0xC4,umask=0x20/p$FLAGS" ;; model*:\ 46|\ model*:\ 30|\ model*:\ 31|\ @@ -63,8 +75,23 @@ model*:\ 38|\ model*:\ 39|\ model*:\ 54|\ model*:\ 53) E="cpu/event=0x88,umask=0x41/p$FLAGS" ;; +model*:\ 126|\ +model*:\ 140|\ +model*:\ 141|\ +model*:\ 106|\ +model*:\ 108) E="cpu/event=0xc4,umask=0x20/p$FLAGS" ;; *) echo >&2 "Unknown CPU. Run contrib/gen_autofdo_event.py --all --script to update script." exit 1 ;; esac -exec perf record -e $E -b "$@" +set -x +if ! perf record -e $E -b "$@" ; then + # PEBS may not actually be working even if the processor supports it + # (e.g., in a virtual machine). Trying to run without /p. + set +x + echo >&2 "Retrying without /p." + E="$(echo "${E}" | sed -e 's/\/p/\//')" + set -x + exec perf record -e $E -b "$@" + set +x +fi -- cgit v1.1 From 1aeefa5720a71e622e2f26bf10ec8e7ecbd76f4c Mon Sep 17 00:00:00 2001 From: Hongyu Wang Date: Wed, 30 Jun 2021 14:38:31 +0800 Subject: Clear odata for aes(enc|dec)(wide)?kl intrinsics when ZF is set. For Keylocker aesenc/aesdec intrinsics, current implementation moves idata to odata unconditionally, which causes safety issue when the instruction meets runtime error. So we add a branch to clear odata when ZF is set after instruction exectution. gcc/ChangeLog: * config/i386/i386-expand.c (ix86_expand_builtin): Add branch to clear odata when ZF is set for asedecenc_expand and wideaesdecenc_expand. gcc/testsuite/ChangeLog: * gcc.target/i386/keylocker-aesdec128kl.c: Update test. * gcc.target/i386/keylocker-aesdec256kl.c: Likewise. * gcc.target/i386/keylocker-aesdecwide128kl.c: Likewise. * gcc.target/i386/keylocker-aesdecwide256kl.c: Likewise. * gcc.target/i386/keylocker-aesenc128kl.c: Likewise. * gcc.target/i386/keylocker-aesenc256kl.c: Likewise. * gcc.target/i386/keylocker-aesencwide128kl.c: Likewise. * gcc.target/i386/keylocker-aesencwide256kl.c: Likewise. --- gcc/config/i386/i386-expand.c | 33 ++++++++++++++++++---- .../gcc.target/i386/keylocker-aesdec128kl.c | 2 ++ .../gcc.target/i386/keylocker-aesdec256kl.c | 2 ++ .../gcc.target/i386/keylocker-aesdecwide128kl.c | 9 ++++++ .../gcc.target/i386/keylocker-aesdecwide256kl.c | 9 ++++++ .../gcc.target/i386/keylocker-aesenc128kl.c | 2 ++ .../gcc.target/i386/keylocker-aesenc256kl.c | 2 ++ .../gcc.target/i386/keylocker-aesencwide128kl.c | 9 ++++++ .../gcc.target/i386/keylocker-aesencwide256kl.c | 9 ++++++ 9 files changed, 72 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index 5c9170e..a63319a 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -11753,10 +11753,24 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget, if (target == 0) target = gen_reg_rtx (QImode); - pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCZmode, FLAGS_REG), - const0_rtx); - emit_insn (gen_rtx_SET (target, pat)); + /* NB: For aesenc/aesdec keylocker insn, ZF will be set when runtime + error occurs. Then the output should be cleared for safety. */ + rtx_code_label *ok_label; + rtx tmp; + + tmp = gen_rtx_REG (CCZmode, FLAGS_REG); + pat = gen_rtx_EQ (QImode, tmp, const0_rtx); + ok_label = gen_label_rtx (); + emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp), + true, ok_label); + /* Usually the runtime error seldom occur, so predict OK path as + hotspot to optimize it as fallthrough block. */ + predict_jump (REG_BR_PROB_BASE * 90 / 100); + + emit_insn (gen_rtx_SET (op1, const0_rtx)); + emit_label (ok_label); + emit_insn (gen_rtx_SET (target, pat)); emit_insn (gen_rtx_SET (op0, op1)); return target; @@ -11811,8 +11825,17 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget, if (target == 0) target = gen_reg_rtx (QImode); - pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCZmode, FLAGS_REG), - const0_rtx); + tmp = gen_rtx_REG (CCZmode, FLAGS_REG); + pat = gen_rtx_EQ (QImode, tmp, const0_rtx); + ok_label = gen_label_rtx (); + emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp), + true, ok_label); + predict_jump (REG_BR_PROB_BASE * 90 / 100); + + for (i = 0; i < 8; i++) + emit_insn (gen_rtx_SET (xmm_regs[i], const0_rtx)); + + emit_label (ok_label); emit_insn (gen_rtx_SET (target, pat)); for (i = 0; i < 8; i++) diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesdec128kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesdec128kl.c index d134612..71111c3 100644 --- a/gcc/testsuite/gcc.target/i386/keylocker-aesdec128kl.c +++ b/gcc/testsuite/gcc.target/i386/keylocker-aesdec128kl.c @@ -2,8 +2,10 @@ /* { dg-options "-mkl -O2" } */ /* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */ /* { dg-final { scan-assembler "aesdec128kl\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */ +/* { dg-final { scan-assembler "j\[ez\]" } } */ /* { dg-final { scan-assembler "sete" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" } } */ #include diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesdec256kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesdec256kl.c index 34736d2..30189d6 100644 --- a/gcc/testsuite/gcc.target/i386/keylocker-aesdec256kl.c +++ b/gcc/testsuite/gcc.target/i386/keylocker-aesdec256kl.c @@ -2,8 +2,10 @@ /* { dg-options "-mkl -O2" } */ /* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */ /* { dg-final { scan-assembler "aesdec256kl\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */ +/* { dg-final { scan-assembler "j\[ez\]" } } */ /* { dg-final { scan-assembler "sete" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" } } */ #include diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide128kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide128kl.c index d23cf4b..93806e5 100644 --- a/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide128kl.c +++ b/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide128kl.c @@ -9,6 +9,7 @@ /* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*96\[^\\n\\r\]*, %xmm6" } } */ /* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*112\[^\\n\\r\]*, %xmm7" } } */ /* { dg-final { scan-assembler "aesdecwide128kl\[ \\t\]+\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "j\[ez\]" } } */ /* { dg-final { scan-assembler "sete" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */ @@ -18,6 +19,14 @@ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm5,\[^\\n\\r\]*80\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm6,\[^\\n\\r\]*96\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm7,\[^\\n\\r\]*112\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm1, %xmm1" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm2, %xmm2" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm3, %xmm3" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm4, %xmm4" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm5, %xmm5" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm6, %xmm6" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm7, %xmm7" } } */ #include diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide256kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide256kl.c index 44c3252..f9ccc82 100644 --- a/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide256kl.c +++ b/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide256kl.c @@ -9,6 +9,7 @@ /* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*96\[^\\n\\r\]*, %xmm6" } } */ /* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*112\[^\\n\\r\]*, %xmm7" } } */ /* { dg-final { scan-assembler "aesdecwide256kl\[ \\t\]+\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "j\[ez\]" } } */ /* { dg-final { scan-assembler "sete" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */ @@ -18,6 +19,14 @@ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm5,\[^\\n\\r\]*80\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm6,\[^\\n\\r\]*96\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm7,\[^\\n\\r\]*112\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm1, %xmm1" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm2, %xmm2" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm3, %xmm3" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm4, %xmm4" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm5, %xmm5" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm6, %xmm6" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm7, %xmm7" } } */ #include diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesenc128kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesenc128kl.c index 9ff4836..61a9cc2 100644 --- a/gcc/testsuite/gcc.target/i386/keylocker-aesenc128kl.c +++ b/gcc/testsuite/gcc.target/i386/keylocker-aesenc128kl.c @@ -2,8 +2,10 @@ /* { dg-options "-mkl -O2" } */ /* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */ /* { dg-final { scan-assembler "aesenc128kl\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */ +/* { dg-final { scan-assembler "j\[ez\]" } } */ /* { dg-final { scan-assembler "sete" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" } } */ #include diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesenc256kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesenc256kl.c index 1c5e076..f8e6bb7 100644 --- a/gcc/testsuite/gcc.target/i386/keylocker-aesenc256kl.c +++ b/gcc/testsuite/gcc.target/i386/keylocker-aesenc256kl.c @@ -2,8 +2,10 @@ /* { dg-options "-mkl -O2" } */ /* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */ /* { dg-final { scan-assembler "aesenc256kl\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */ +/* { dg-final { scan-assembler "j\[ez\]" } } */ /* { dg-final { scan-assembler "sete" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" } } */ #include diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesencwide128kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesencwide128kl.c index 9fb9c49..c0fcd28 100644 --- a/gcc/testsuite/gcc.target/i386/keylocker-aesencwide128kl.c +++ b/gcc/testsuite/gcc.target/i386/keylocker-aesencwide128kl.c @@ -9,6 +9,7 @@ /* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*96\[^\\n\\r\]*, %xmm6" } } */ /* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*112\[^\\n\\r\]*, %xmm7" } } */ /* { dg-final { scan-assembler "aesencwide128kl\[ \\t\]+\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "j\[ez\]" } } */ /* { dg-final { scan-assembler "sete" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */ @@ -18,6 +19,14 @@ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm5,\[^\\n\\r\]*80\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm6,\[^\\n\\r\]*96\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm7,\[^\\n\\r\]*112\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm1, %xmm1" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm2, %xmm2" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm3, %xmm3" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm4, %xmm4" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm5, %xmm5" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm6, %xmm6" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm7, %xmm7" } } */ #include diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesencwide256kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesencwide256kl.c index 125a787..31463a8 100644 --- a/gcc/testsuite/gcc.target/i386/keylocker-aesencwide256kl.c +++ b/gcc/testsuite/gcc.target/i386/keylocker-aesencwide256kl.c @@ -9,6 +9,7 @@ /* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*96\[^\\n\\r\]*, %xmm6" } } */ /* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*112\[^\\n\\r\]*, %xmm7" } } */ /* { dg-final { scan-assembler "aesencwide256kl\[ \\t\]+\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "j\[ez\]" } } */ /* { dg-final { scan-assembler "sete" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */ @@ -18,6 +19,14 @@ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm5,\[^\\n\\r\]*80\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm6,\[^\\n\\r\]*96\[^\\n\\r\]*" } } */ /* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm7,\[^\\n\\r\]*112\[^\\n\\r\]*" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm1, %xmm1" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm2, %xmm2" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm3, %xmm3" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm4, %xmm4" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm5, %xmm5" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm6, %xmm6" } } */ +/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm7, %xmm7" } } */ #include -- cgit v1.1 From c4804ff24401733e3b470a49b8a6c9306e6cfcfa Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 2 Jul 2021 08:51:43 +0200 Subject: tree-optimization/101280 - re-revise interchange fix for PR101173 The following fixes up the revision of the original fix for PR101173 to properly guard all dependence checks with DDR_REVERSED_P or its inverse. 2021-07-01 Richard Biener PR tree-optimization/101280 PR tree-optimization/101173 * gimple-loop-interchange.cc (tree_loop_interchange::valid_data_dependences): Properly guard all dependence checks with DDR_REVERSED_P or its inverse. --- gcc/gimple-loop-interchange.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/gimple-loop-interchange.cc b/gcc/gimple-loop-interchange.cc index 43ef112..7a88faa 100644 --- a/gcc/gimple-loop-interchange.cc +++ b/gcc/gimple-loop-interchange.cc @@ -1044,9 +1044,9 @@ tree_loop_interchange::valid_data_dependences (unsigned i_idx, unsigned o_idx, /* Be conservative, skip case if either direction at i_idx/o_idx levels is not '=' or '<'. */ - if (dist_vect[i_idx] < 0 + if ((!DDR_REVERSED_P (ddr) && dist_vect[i_idx] < 0) || (DDR_REVERSED_P (ddr) && dist_vect[i_idx] > 0) - || dist_vect[o_idx] < 0 + || (!DDR_REVERSED_P (ddr) && dist_vect[o_idx] < 0) || (DDR_REVERSED_P (ddr) && dist_vect[o_idx] > 0)) return false; } -- cgit v1.1 From f7cad1a0ffe9f003ec347521dfd33f320f4c2b04 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 2 Jul 2021 10:06:56 +0200 Subject: i386: Punt on broadcasts from TImode integers [PR101286] ix86_expand_vector_init_duplicate doesn't handle TImode -> V2TImode or TImode -> V4TImode broadcasts, so I think we should punt on TImode inner mode in ix86_broadcast_from_integer_constant, otherwise we ICE in ix86_expand_vector_move when ix86_broadcast_from_integer_constant returns non-NULL and ix86_expand_vector_init_duplicate returns false. In theory TImode element broadcasts could be handled by some permutations, but I'm not sure it is worth it. 2021-07-02 Jakub Jelinek PR target/101286 * config/i386/i386-expand.c (ix86_broadcast_from_integer_constant): Return nullptr for TImode inner mode. * gcc.target/i386/avx2-pr101286.c: New test. --- gcc/config/i386/i386-expand.c | 3 +++ gcc/testsuite/gcc.target/i386/avx2-pr101286.c | 11 +++++++++++ 2 files changed, 14 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/avx2-pr101286.c (limited to 'gcc') diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index a63319a..b37642e 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -478,6 +478,9 @@ ix86_broadcast_from_integer_constant (machine_mode mode, rtx op) if (GET_MODE_INNER (mode) == DImode && !TARGET_64BIT) return nullptr; + if (GET_MODE_INNER (mode) == TImode) + return nullptr; + rtx constant = get_pool_constant (XEXP (op, 0)); if (GET_CODE (constant) != CONST_VECTOR) return nullptr; diff --git a/gcc/testsuite/gcc.target/i386/avx2-pr101286.c b/gcc/testsuite/gcc.target/i386/avx2-pr101286.c new file mode 100644 index 0000000..81917bf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx2-pr101286.c @@ -0,0 +1,11 @@ +/* PR target/101286 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-mavx2" } */ + +typedef __attribute__((__vector_size__ (2 * sizeof (__int128)))) __int128 V; + +V +foo (void) +{ + return (V){(__int128) 1 << 64 | 1, (__int128) 1 << 64 | 1}; +} -- cgit v1.1 From 496e1d6a1f973b3952a37163441f9149501dfb26 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 2 Jul 2021 10:21:11 +0200 Subject: Change EH pointer encodings to PC relative on Windows A big difference between ELF and PE-COFF is that, with the latter, you can build position-independent executables or DLLs without generating PIC; as a matter of fact, flag_pic has historically been forced to 0 for 32-bit: /* Don't allow flag_pic to propagate since gas may produce invalid code otherwise. */ \ do { \ flag_pic = TARGET_64BIT ? 1 : 0; \ } while (0) The reason is that the linker builds a .reloc section that collects the absolute relocations in the generated binary, and the loader uses them to relocate it at load time if need be (e.g. if --dynamicbase is enabled). Up to binutils 2.35, the GNU linker didn't build the .reloc section for executables and defaulted to --enable-auto-image-base for DLLs, which means that DLLs had an essentially unique load address and, therefore, need not be relocated by the loader in most cases. With binutils 2.36 and later, the GNU linker builds a .reloc section for executables (thus making them PIE), --enable-auto-image-base is disabled and --dynamicbase is enabled by default, which means that essentially all the binaries are relocated at load time. This badly breaks the 32-bit compiler configured to use DWARF-2 EH because the loader corrupts the .eh_frame section when processing the relocations contained in the .reloc section. gcc/ * config/i386/i386.c (asm_preferred_eh_data_format): Always use the PIC encodings for PE-COFF targets. --- gcc/config/i386/i386.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 2fbaae7..cff2690 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -21930,10 +21930,12 @@ ix86_stack_protect_fail (void) After all, the relocation needed is the same as for the call insn. Whether or not a particular assembler allows us to enter such, I guess we'll have to see. */ + int asm_preferred_eh_data_format (int code, int global) { - if (flag_pic) + /* PE-COFF is effectively always -fPIC because of the .reloc section. */ + if (flag_pic || TARGET_PECOFF) { int type = DW_EH_PE_sdata8; if (!TARGET_64BIT @@ -21942,9 +21944,11 @@ asm_preferred_eh_data_format (int code, int global) type = DW_EH_PE_sdata4; return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | type; } + if (ix86_cmodel == CM_SMALL || (ix86_cmodel == CM_MEDIUM && code)) return DW_EH_PE_udata4; + return DW_EH_PE_absptr; } -- cgit v1.1 From 4546f423ecff96f223adfbec4963d2ff17f27c7b Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 2 Jul 2021 12:57:06 +0200 Subject: tree-optimization/101293 - further enhance LIMs ref canonicalization This makes sure to handle MEM[p + 4] and MEM[p].j with j at offset 4 as the same ref in store motion. For hashing we need to be more restrictive in what we handle since there's no poly-int handlers for inchash. For comparison we can compare poly_offsets directly. 2021-07-02 Richard Biener PR tree-optimization/101293 * tree-ssa-loop-im.c (mem_ref_hasher::equal): Compare MEM_REF bases with combined offsets. (gather_mem_refs_stmt): Hash MEM_REFs as if their offset were combined with the rest of the offset. * gcc.dg/tree-ssa/ssa-lim-15.c: New testcase. --- gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-15.c | 18 ++++++++++++++++++ gcc/tree-ssa-loop-im.c | 27 +++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-15.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-15.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-15.c new file mode 100644 index 0000000..5efb956 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-15.c @@ -0,0 +1,18 @@ +/* PR/101293 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-lim2-details" } */ + +struct X { int i; int j; }; + +void foo(struct X *x, int n) +{ + for (int i = 0; i < n; ++i) + { + int *p = &x->j; + int tem = *p; + x->j += tem * i; + } +} + +/* Make sure LIM can handle unifying MEM[x, 4] and MEM[x].j */ +/* { dg-final { scan-tree-dump "Executing store motion" "lim2" } } */ diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 48c952a..e7a3050 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -194,8 +194,14 @@ mem_ref_hasher::equal (const im_mem_ref *mem1, const ao_ref *obj2) { if (obj2->max_size_known_p ()) return (mem1->ref_decomposed - && operand_equal_p (mem1->mem.base, obj2->base, 0) - && known_eq (mem1->mem.offset, obj2->offset) + && ((TREE_CODE (mem1->mem.base) == MEM_REF + && TREE_CODE (obj2->base) == MEM_REF + && operand_equal_p (TREE_OPERAND (mem1->mem.base, 0), + TREE_OPERAND (obj2->base, 0), 0) + && known_eq (mem_ref_offset (mem1->mem.base) * BITS_PER_UNIT + mem1->mem.offset, + mem_ref_offset (obj2->base) * BITS_PER_UNIT + obj2->offset)) + || (operand_equal_p (mem1->mem.base, obj2->base, 0) + && known_eq (mem1->mem.offset, obj2->offset))) && known_eq (mem1->mem.size, obj2->size) && known_eq (mem1->mem.max_size, obj2->max_size) && mem1->mem.volatile_p == obj2->volatile_p @@ -1500,8 +1506,21 @@ gather_mem_refs_stmt (class loop *loop, gimple *stmt) && (mem_base = get_addr_base_and_unit_offset (aor.ref, &mem_off))) { ref_decomposed = true; - hash = iterative_hash_expr (ao_ref_base (&aor), 0); - hash = iterative_hash_host_wide_int (offset, hash); + tree base = ao_ref_base (&aor); + poly_int64 moffset; + HOST_WIDE_INT mcoffset; + if (TREE_CODE (base) == MEM_REF + && (mem_ref_offset (base) * BITS_PER_UNIT + offset).to_shwi (&moffset) + && moffset.is_constant (&mcoffset)) + { + hash = iterative_hash_expr (TREE_OPERAND (base, 0), 0); + hash = iterative_hash_host_wide_int (mcoffset, hash); + } + else + { + hash = iterative_hash_expr (base, 0); + hash = iterative_hash_host_wide_int (offset, hash); + } hash = iterative_hash_host_wide_int (size, hash); } else -- cgit v1.1 From a6fef2e1b6d7e8cea0c0489496cc8f96391200c6 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 2 Jul 2021 10:31:31 -0400 Subject: Fix xstormy16 target specific fallout from recent int->bool changes gcc/ * config/stormy16/stormy16-protos.h (xstormy16_below_100_symbol): Change return type to a bool. (nonimmediate_nonstack_operand): Likewise. (xstormy16_splittable_below100_operand): Likewise. * config/stormy16/stormy16.c (xstormy16_below_100_symbol): Fix return type. (xstormy16_splittable_below100_operand): Likewise. --- gcc/config/stormy16/stormy16-protos.h | 6 +++--- gcc/config/stormy16/stormy16.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/config/stormy16/stormy16-protos.h b/gcc/config/stormy16/stormy16-protos.h index c81ea8c..d8010af 100644 --- a/gcc/config/stormy16/stormy16-protos.h +++ b/gcc/config/stormy16/stormy16-protos.h @@ -54,7 +54,7 @@ extern void xstormy16_expand_andqi3 (rtx *); #if defined (HAVE_MACHINE_MODES) && defined (RTX_CODE) extern void xstormy16_split_cbranch (machine_mode, rtx, rtx, rtx); extern int short_memory_operand (rtx, machine_mode); -extern int nonimmediate_nonstack_operand (rtx, machine_mode); +extern bool nonimmediate_nonstack_operand (rtx, machine_mode); extern enum reg_class xstormy16_secondary_reload_class (enum reg_class, machine_mode, rtx); extern void xstormy16_split_move (machine_mode, rtx, rtx); @@ -63,8 +63,8 @@ extern void xstormy16_expand_arith (machine_mode, enum rtx_code, rtx, rtx, rtx); extern const char * xstormy16_output_shift (machine_mode, enum rtx_code, rtx, rtx, rtx); -extern int xstormy16_below100_symbol (rtx, machine_mode); -extern int xstormy16_splittable_below100_operand (rtx, machine_mode); +extern bool xstormy16_below100_symbol (rtx, machine_mode); +extern bool xstormy16_splittable_below100_operand (rtx, machine_mode); extern bool xstormy16_legitimate_address_p (machine_mode, rtx, bool); #endif diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c index fb7670f..92011fd 100644 --- a/gcc/config/stormy16/stormy16.c +++ b/gcc/config/stormy16/stormy16.c @@ -516,7 +516,7 @@ xstormy16_preferred_reload_class (rtx x, reg_class_t rclass) /* Predicate for symbols and addresses that reflect special 8-bit addressing. */ -int +bool xstormy16_below100_symbol (rtx x, machine_mode mode ATTRIBUTE_UNUSED) { @@ -542,7 +542,7 @@ xstormy16_below100_symbol (rtx x, /* Likewise, but only for non-volatile MEMs, for patterns where the MEM will get split into smaller sized accesses. */ -int +bool xstormy16_splittable_below100_operand (rtx x, machine_mode mode) { if (MEM_P (x) && MEM_VOLATILE_P (x)) -- cgit v1.1 From 021d6d542527de8cb266c098f36aa1b3e3675ea7 Mon Sep 17 00:00:00 2001 From: Maxim Kuvyrkov Date: Fri, 2 Jul 2021 14:15:35 +0000 Subject: Add description of how testsuite parallelization works ... for the benefit of the next poor soul who will need to debug it. gcc/testsuite/ * lib/gcc-defs.exp: Add a comment. --- gcc/testsuite/lib/gcc-defs.exp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'gcc') diff --git a/gcc/testsuite/lib/gcc-defs.exp b/gcc/testsuite/lib/gcc-defs.exp index e9119f0..d17308d 100644 --- a/gcc/testsuite/lib/gcc-defs.exp +++ b/gcc/testsuite/lib/gcc-defs.exp @@ -176,6 +176,40 @@ if { [info exists env(GCC_RUNTEST_PARALLELIZE_DIR)] \ global gcc_runtest_parallelize_dir global gcc_runtest_parallelize_last + # GCC testsuite is parallelised by starting N runtest processes -- each + # with its own test directory. These N runtest processes ALL go through + # the relevant .exp and ALL attempt to run every test. And they go + # through the tests the same order -- this is important, and if there is + # a bug that causes different runtest processes to enumerate the tests + # differently, then things will break and some tests will be skipped, while + # others will be ran several times. + # So, just before a runtest processes runs a specific test it asks + # "runtest_file_p" routine whether a particular test is part of + # the requested testsuite. We override this function so that it + # returns "yes" to the first-arrived runtest process, and "no" to all + # subsequent runtest processes -- this is implemented by creating a marker + # file, which persist till the end of the test run. We optimize this + # a bit by batching 10 tests and using a single marker file for the batch. + # + # Note that the runtest processes all race each other to get to the next + # test batch. This means that batch allocation between testsuite runs + # is very likely to change. + # + # To confirm or deny suspicion that tests are skipped or executed + # multiple times due to runtest processes enumerating tests differently ... + # 1. Uncomment the three below "verbose -log gcc_parallel_test_run_p ..." + # debug print-outs. + # 2. Run the testsuite with "-v" added to RUNTESTFLAGS + # 3. Extract debug print-outs with something like: + # for i in $(find -name "*.log.sep"); do + # grep gcc_parallel_test_run_p $i \ + # | sed -e "s/\([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\)/\3 \2/" \ + # | sed -e "s#\(/testsuite/[a-z+]*\)[0-9]*/#\1N/#" > $i.order + # done + # 4. Compare debug print-outs produced by individual runtest processes: + # find -name "*.log.sep.order" | xargs md5sum | sort + # 5. Check that MD5 hashes of all .order files of the same testsuite match + # and investigate if they don't. set gcc_runtest_parallelize_counter 0 set gcc_runtest_parallelize_counter_minor 0 set gcc_runtest_parallelize_enable 1 -- cgit v1.1 From ef9cc434a476954b5ef3493955d4e668338990c2 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 2 Jul 2021 10:37:52 -0400 Subject: Fix frv target specific fallout from recent int->bool changes gcc/ChangeLog * config/frv/frv-protos.h (integer_register_operand): Adjust return type. (frv_load_operand, gpr_or_fpr_operand, gpr_no_subreg_operand): Likewise. (fpr_or_int6_operand, gpr_or_int_operand); Likewise. (gpr_or_int12_operand, gpr_or_int10_operand); Likewise. (move_source_operand, move_destination_operand): Likewise. (condexec_source_operand, condexec_dest_operand): Likewise. (lr_operand, gpr_or_memory_operand, fpr_or_memory_operand): Likewise. (reg_or_0_operand, fcc_operand, icc_operand, cc_operand): Likewise. (fcr_operand, icr_operand, cr_operand, call_operand): Likewise. (fpr_operand, even_reg_operand, odd_reg_operand): Likewise. (even_gpr_operand, odd_gpr_operand, quad_fpr_operand): Likewise. (even_fpr_operand, odd_fpr_operand): Likewise. (dbl_memory_one_insn_operand, dbl_memory_two_insn_operand): Likewise. (int12_operand, int6_operand, int5_operand, uint5_operand): Likewise. (uint4_operand, uint1_operand, int_2word_operand): Likewise (upper_int16_operand, uint16_operand, symbolic_operand): Likewise. (relational_operator, float_relational_operator): Likewise. (ccr_eqne_operator, minmax_operator): Likewise. (condexec_si_binary_operator, condexec_si_media_operator): Likewise. (condexec_si_divide_operator, condexec_si_unary_operator): Likewise. (condexec_sf_conv_operator, condexec_sf_add_operator): Likewise. (intop_compare_operator, acc_operand, even_acc_operand): Likewise. (quad_acc_operand, accg_operand): Likewise. --- gcc/config/frv/frv-protos.h | 118 ++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 59 deletions(-) (limited to 'gcc') diff --git a/gcc/config/frv/frv-protos.h b/gcc/config/frv/frv-protos.h index 8d79d73..29d4425 100644 --- a/gcc/config/frv/frv-protos.h +++ b/gcc/config/frv/frv-protos.h @@ -89,73 +89,73 @@ extern int frv_adjust_field_align (tree, int); #endif #ifdef RTX_CODE -extern int integer_register_operand (rtx, machine_mode); -extern int frv_load_operand (rtx, machine_mode); -extern int gpr_or_fpr_operand (rtx, machine_mode); -extern int gpr_no_subreg_operand (rtx, machine_mode); +extern bool integer_register_operand (rtx, machine_mode); +extern bool frv_load_operand (rtx, machine_mode); +extern bool gpr_or_fpr_operand (rtx, machine_mode); +extern bool gpr_no_subreg_operand (rtx, machine_mode); extern int gpr_or_int6_operand (rtx, machine_mode); -extern int fpr_or_int6_operand (rtx, machine_mode); -extern int gpr_or_int_operand (rtx, machine_mode); -extern int gpr_or_int12_operand (rtx, machine_mode); -extern int gpr_fpr_or_int12_operand (rtx, machine_mode); -extern int gpr_or_int10_operand (rtx, machine_mode); -extern int move_source_operand (rtx, machine_mode); -extern int move_destination_operand (rtx, machine_mode); -extern int condexec_source_operand (rtx, machine_mode); -extern int condexec_dest_operand (rtx, machine_mode); -extern int lr_operand (rtx, machine_mode); -extern int gpr_or_memory_operand (rtx, machine_mode); -extern int fpr_or_memory_operand (rtx, machine_mode); -extern int reg_or_0_operand (rtx, machine_mode); -extern int fcc_operand (rtx, machine_mode); -extern int icc_operand (rtx, machine_mode); -extern int cc_operand (rtx, machine_mode); -extern int fcr_operand (rtx, machine_mode); -extern int icr_operand (rtx, machine_mode); -extern int cr_operand (rtx, machine_mode); -extern int call_operand (rtx, machine_mode); -extern int fpr_operand (rtx, machine_mode); -extern int even_reg_operand (rtx, machine_mode); -extern int odd_reg_operand (rtx, machine_mode); -extern int even_gpr_operand (rtx, machine_mode); -extern int odd_gpr_operand (rtx, machine_mode); -extern int quad_fpr_operand (rtx, machine_mode); -extern int even_fpr_operand (rtx, machine_mode); -extern int odd_fpr_operand (rtx, machine_mode); -extern int dbl_memory_one_insn_operand (rtx, machine_mode); -extern int dbl_memory_two_insn_operand (rtx, machine_mode); -extern int int12_operand (rtx, machine_mode); -extern int int6_operand (rtx, machine_mode); -extern int int5_operand (rtx, machine_mode); -extern int uint5_operand (rtx, machine_mode); -extern int uint4_operand (rtx, machine_mode); -extern int uint1_operand (rtx, machine_mode); -extern int int_2word_operand (rtx, machine_mode); +extern bool fpr_or_int6_operand (rtx, machine_mode); +extern bool gpr_or_int_operand (rtx, machine_mode); +extern bool gpr_or_int12_operand (rtx, machine_mode); +extern bool gpr_fpr_or_int12_operand (rtx, machine_mode); +extern bool gpr_or_int10_operand (rtx, machine_mode); +extern bool move_source_operand (rtx, machine_mode); +extern bool move_destination_operand (rtx, machine_mode); +extern bool condexec_source_operand (rtx, machine_mode); +extern bool condexec_dest_operand (rtx, machine_mode); +extern bool lr_operand (rtx, machine_mode); +extern bool gpr_or_memory_operand (rtx, machine_mode); +extern bool fpr_or_memory_operand (rtx, machine_mode); +extern bool reg_or_0_operand (rtx, machine_mode); +extern bool fcc_operand (rtx, machine_mode); +extern bool icc_operand (rtx, machine_mode); +extern bool cc_operand (rtx, machine_mode); +extern bool fcr_operand (rtx, machine_mode); +extern bool icr_operand (rtx, machine_mode); +extern bool cr_operand (rtx, machine_mode); +extern bool call_operand (rtx, machine_mode); +extern bool fpr_operand (rtx, machine_mode); +extern bool even_reg_operand (rtx, machine_mode); +extern bool odd_reg_operand (rtx, machine_mode); +extern bool even_gpr_operand (rtx, machine_mode); +extern bool odd_gpr_operand (rtx, machine_mode); +extern bool quad_fpr_operand (rtx, machine_mode); +extern bool even_fpr_operand (rtx, machine_mode); +extern bool odd_fpr_operand (rtx, machine_mode); +extern bool dbl_memory_one_insn_operand (rtx, machine_mode); +extern bool dbl_memory_two_insn_operand (rtx, machine_mode); +extern bool int12_operand (rtx, machine_mode); +extern bool int6_operand (rtx, machine_mode); +extern bool int5_operand (rtx, machine_mode); +extern bool uint5_operand (rtx, machine_mode); +extern bool uint4_operand (rtx, machine_mode); +extern bool uint1_operand (rtx, machine_mode); +extern bool int_2word_operand (rtx, machine_mode); extern int pic_register_operand (rtx, machine_mode); extern int pic_symbolic_operand (rtx, machine_mode); extern int small_data_register_operand (rtx, machine_mode); extern int small_data_symbolic_operand (rtx, machine_mode); -extern int upper_int16_operand (rtx, machine_mode); -extern int uint16_operand (rtx, machine_mode); -extern int symbolic_operand (rtx, machine_mode); -extern int relational_operator (rtx, machine_mode); +extern bool upper_int16_operand (rtx, machine_mode); +extern bool uint16_operand (rtx, machine_mode); +extern bool symbolic_operand (rtx, machine_mode); +extern bool relational_operator (rtx, machine_mode); extern int signed_relational_operator (rtx, machine_mode); extern int unsigned_relational_operator (rtx, machine_mode); -extern int float_relational_operator (rtx, machine_mode); -extern int ccr_eqne_operator (rtx, machine_mode); -extern int minmax_operator (rtx, machine_mode); -extern int condexec_si_binary_operator (rtx, machine_mode); -extern int condexec_si_media_operator (rtx, machine_mode); -extern int condexec_si_divide_operator (rtx, machine_mode); -extern int condexec_si_unary_operator (rtx, machine_mode); -extern int condexec_sf_conv_operator (rtx, machine_mode); -extern int condexec_sf_add_operator (rtx, machine_mode); +extern bool float_relational_operator (rtx, machine_mode); +extern bool ccr_eqne_operator (rtx, machine_mode); +extern bool minmax_operator (rtx, machine_mode); +extern bool condexec_si_binary_operator (rtx, machine_mode); +extern bool condexec_si_media_operator (rtx, machine_mode); +extern bool condexec_si_divide_operator (rtx, machine_mode); +extern bool condexec_si_unary_operator (rtx, machine_mode); +extern bool condexec_sf_conv_operator (rtx, machine_mode); +extern bool condexec_sf_add_operator (rtx, machine_mode); extern int condexec_memory_operand (rtx, machine_mode); -extern int intop_compare_operator (rtx, machine_mode); -extern int acc_operand (rtx, machine_mode); -extern int even_acc_operand (rtx, machine_mode); -extern int quad_acc_operand (rtx, machine_mode); -extern int accg_operand (rtx, machine_mode); +extern bool intop_compare_operator (rtx, machine_mode); +extern bool acc_operand (rtx, machine_mode); +extern bool even_acc_operand (rtx, machine_mode); +extern bool quad_acc_operand (rtx, machine_mode); +extern bool accg_operand (rtx, machine_mode); extern rtx frv_matching_accg_for_acc (rtx); extern void frv_expand_fdpic_call (rtx *, bool, bool); extern rtx frv_gen_GPsym2reg (rtx, rtx); -- cgit v1.1 From f6aa1c34e4a89c8c93518c49a108f3c43b78ea47 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 2 Jul 2021 10:48:26 -0400 Subject: Fix m32r target specific fallout from recent int->bool changes gcc/ChangeLog * config/m32r/m32r-protos.h (call_operand): Adjust return type. (small_data_operand, memreg_operand, small_insn_p): Likewise. * config/m32r/m32r.c (call_operand): Adjust return type. (small_data_operand, memreg_operand): Likewise. --- gcc/config/m32r/m32r-protos.h | 8 ++++---- gcc/config/m32r/m32r.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/config/m32r/m32r-protos.h b/gcc/config/m32r/m32r-protos.h index 23313fb..82b2c70 100644 --- a/gcc/config/m32r/m32r-protos.h +++ b/gcc/config/m32r/m32r-protos.h @@ -49,13 +49,13 @@ extern rtx m32r_return_addr (int); extern rtx m32r_function_symbol (const char *); #ifdef HAVE_MACHINE_MODES -extern int call_operand (rtx, machine_mode); -extern int small_data_operand (rtx, machine_mode); +extern bool call_operand (rtx, machine_mode); +extern bool small_data_operand (rtx, machine_mode); extern int addr24_operand (rtx, machine_mode); extern int addr32_operand (rtx, machine_mode); extern int call26_operand (rtx, machine_mode); -extern int memreg_operand (rtx, machine_mode); -extern int small_insn_p (rtx, machine_mode); +extern bool memreg_operand (rtx, machine_mode); +extern bool small_insn_p (rtx, machine_mode); #endif /* HAVE_MACHINE_MODES */ diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index 3444ed4..1aaba94 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -532,7 +532,7 @@ m32r_init_expanders (void) to make it easy to experiment. */ } -int +bool call_operand (rtx op, machine_mode mode) { if (!MEM_P (op)) @@ -543,7 +543,7 @@ call_operand (rtx op, machine_mode mode) /* Return 1 if OP is a reference to an object in .sdata/.sbss. */ -int +bool small_data_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED) { if (! TARGET_SDATA_USE) @@ -674,7 +674,7 @@ easy_df_const (rtx op) /* Return 1 if OP is (mem (reg ...)). This is used in insn length calcs. */ -int +bool memreg_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED) { return MEM_P (op) && REG_P (XEXP (op, 0)); -- cgit v1.1 From eb817f27e82769aef545d580a0c47a3aa50d1ec4 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Fri, 2 Jul 2021 09:44:59 +0100 Subject: Darwin, BTF: Provide a suitable section name for BTF [PR101283]. In a similar manner to r12-1960-gcc8453012f75d, this provides a placeholder section name for BTF data. This change groups BTF and CTF debug formats in the same segment, but keeps them in separate sections. As per the CTF section designation, this should be agreed or amended to an agreed form before GCC 12 ships. Signed-off-by: Iain Sandoe PR debug/101283 - Several tests fail on Darwin with -gctf/gbtf PR debug/101283 gcc/ChangeLog: * config/darwin.h (CTF_INFO_SECTION_NAME): Update the segment to include BTF. (BTF_INFO_SECTION_NAME): New. --- gcc/config/darwin.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index b7c3af3..6840aeb 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -1115,8 +1115,10 @@ extern void darwin_driver_init (unsigned int *,struct cl_decoded_option **); # endif #endif -/* CTF support. */ +/* CTF and BTF support. */ #undef CTF_INFO_SECTION_NAME -#define CTF_INFO_SECTION_NAME "__CTF,__ctf,regular,debug" +#define CTF_INFO_SECTION_NAME "__CTF_BTF,__ctf,regular,debug" +#undef BTF_INFO_SECTION_NAME +#define BTF_INFO_SECTION_NAME "__CTF_BTF,__btf,regular,debug" #endif /* CONFIG_DARWIN_H */ -- cgit v1.1 From 85017431068251628478f38346c273418c71209b Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Fri, 2 Jul 2021 09:51:57 +0100 Subject: Darwin, CTF, BTF: Do not run the DWARF debug link for BTF/CTF [PR101283]. Darwin uses an efficient two-stage process for debug linking. The static linker (ld64) notes the inputs required but does not link the debug. When required / on demand the debug is linked into a separate package by the debug linker (dsymutil). At present none of the Darwin tools consume or understand BTF/CTF. The static linker silently accepts the sections (but will not act on them as containing anything to be processed). However, the debug linker produces a warning that it has been presented with input with no [DWARF] debug content: warning: no debug symbols in executable (-arch x86_64). This causes several testsuite fails with excess errors. Signed-off-by: Iain Sandoe PR debug/101283 - Several tests fail on Darwin with -gctf/gbtf PR debug/101283 gcc/ChangeLog: * config/darwin.h (DSYMUTIL_SPEC): Do not try to run dsymutil for BTF/CTF. --- gcc/config/darwin.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index 6840aeb..5f11978 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -250,10 +250,10 @@ extern GTY(()) int darwin_ms_struct; #define DSYMUTIL_SPEC \ "%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\ %{v} \ - %{g*:%{!gstabs*:%{%:debug-level-gt(0): -idsym}}}\ + %{g*:%{!gctf:%{!gbtf:%{!gstabs*:%{%:debug-level-gt(0): -idsym}}}}}\ %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm|.s|.f|.f90|\ .f95|.f03|.f77|.for|.F|.F90|.F95|.F03: \ - %{g*:%{!gstabs*:%{%:debug-level-gt(0): -dsym}}}}}}}}}}}" + %{g*:%{!gctf:%{!gbtf:%{!gstabs*:%{%:debug-level-gt(0): -dsym}}}}}}}}}}}}}" #define LINK_COMMAND_SPEC LINK_COMMAND_SPEC_A DSYMUTIL_SPEC -- cgit v1.1 From b60761baa6fd6acf3200e732283d133f4ce0f0e9 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 2 Jul 2021 11:07:37 -0400 Subject: Preparing to use shifts to eliminate redundant test/compare insns on H8 * config/h8300/h8300-protos.h (output_a_shift): Make first argument an array of rtx rather than a pointer to rtx. Add code argument. (compute_a_shift_length): Similarly. * config/h8300/h8300.c (h8300_shift_costs): Adjust now that the shift itself isn't an operand. Create dummy operand[0] to carry a mode and pass a suitable rtx code to compute_a_shift_length. (get_shift_alg): Adjust operand number of clobber in output templates. (output_a_shift): Make first argument an array of rtx rather than a pointer to rtx. Add code argument for the type of shift. Adjust now that the shift itself is no longer an operand. (compute_a_shift_length): Similarly. * config/h8300/shiftrotate.md (shiftqi, shifthi, shiftsi): Use an iterator rather than nshift_operator. (shiftqi_noscratch, shifthi_noscratch, shiftsi_noscratch): Likewise. (shiftqi_clobber_flags): Adjust to API changes in output_a_shift and compute_a_shift_length. (shiftqi_noscratch_clobber_flags): Likewise. (shifthi_noscratch_clobber_flags): Likewise. (shiftsi_noscratch_clobber_flags): Likewise. --- gcc/config/h8300/h8300-protos.h | 4 +- gcc/config/h8300/h8300.c | 33 ++++------ gcc/config/h8300/shiftrotate.md | 143 +++++++++++++++++++--------------------- 3 files changed, 85 insertions(+), 95 deletions(-) (limited to 'gcc') diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index d7efa97..86bcc3f 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -28,8 +28,8 @@ along with GCC; see the file COPYING3. If not see extern unsigned int compute_mov_length (rtx *); extern const char *output_plussi (rtx *, bool); extern unsigned int compute_plussi_length (rtx *, bool); -extern const char *output_a_shift (rtx *); -extern unsigned int compute_a_shift_length (rtx *); +extern const char *output_a_shift (rtx[4], rtx_code); +extern unsigned int compute_a_shift_length (rtx[4], rtx_code); extern const char *output_a_rotate (enum rtx_code, rtx *); extern unsigned int compute_a_rotate_length (rtx *); extern const char *output_simode_bld (int, rtx[]); diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index d8b4bfc..0fdc68b 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -1108,18 +1108,17 @@ h8300_and_costs (rtx x) static int h8300_shift_costs (rtx x) { - rtx operands[4]; + rtx operands[3]; if (GET_MODE (x) != QImode && GET_MODE (x) != HImode && GET_MODE (x) != SImode) return 100; - operands[0] = NULL; + operands[0] = gen_rtx_REG (GET_MODE (x), 0); operands[1] = NULL; operands[2] = XEXP (x, 1); - operands[3] = x; - return compute_a_shift_length (operands) / 2; + return compute_a_shift_length (operands, GET_CODE (x)) / 2; } /* Worker function for TARGET_RTX_COSTS. */ @@ -3759,13 +3758,13 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode, switch (shift_type) { case SHIFT_ASHIFT: - info->special = "mov.w\t%e0,%f4\n\tmov.b\t%s4,%t4\n\tmov.b\t%t0,%s4\n\tmov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tmov.w\t%f4,%e0"; + info->special = "mov.w\t%e0,%f3\n\tmov.b\t%s3,%t3\n\tmov.b\t%t0,%s3\n\tmov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tmov.w\t%f3,%e0"; goto end; case SHIFT_LSHIFTRT: - info->special = "mov.w\t%e0,%f4\n\tmov.b\t%t0,%s0\n\tmov.b\t%s4,%t0\n\tmov.b\t%t4,%s4\n\textu.w\t%f4\n\tmov.w\t%f4,%e0"; + info->special = "mov.w\t%e0,%f3\n\tmov.b\t%t0,%s0\n\tmov.b\t%s3,%t0\n\tmov.b\t%t3,%s3\n\textu.w\t%f3\n\tmov.w\t%f3,%e0"; goto end; case SHIFT_ASHIFTRT: - info->special = "mov.w\t%e0,%f4\n\tmov.b\t%t0,%s0\n\tmov.b\t%s4,%t0\n\tmov.b\t%t4,%s4\n\texts.w\t%f4\n\tmov.w\t%f4,%e0"; + info->special = "mov.w\t%e0,%f3\n\tmov.b\t%t0,%s0\n\tmov.b\t%s3,%t0\n\tmov.b\t%t3,%s3\n\texts.w\t%f3\n\tmov.w\t%f3,%e0"; goto end; } } @@ -3985,12 +3984,10 @@ h8300_shift_needs_scratch_p (int count, machine_mode mode, enum rtx_code type) /* Output the assembler code for doing shifts. */ const char * -output_a_shift (rtx *operands) +output_a_shift (rtx operands[4], rtx_code code) { static int loopend_lab; - rtx shift = operands[3]; - machine_mode mode = GET_MODE (shift); - enum rtx_code code = GET_CODE (shift); + machine_mode mode = GET_MODE (operands[0]); enum shift_type shift_type; enum shift_mode shift_mode; struct shift_info info; @@ -4114,10 +4111,10 @@ output_a_shift (rtx *operands) if (info.shift2 != NULL) { fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n / 2, - names_big[REGNO (operands[4])]); + names_big[REGNO (operands[3])]); fprintf (asm_out_file, ".Llt%d:\n", loopend_lab); output_asm_insn (info.shift2, operands); - output_asm_insn ("add #0xff,%X4", operands); + output_asm_insn ("add #0xff,%X3", operands); fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab); if (n % 2) output_asm_insn (info.shift1, operands); @@ -4125,10 +4122,10 @@ output_a_shift (rtx *operands) else { fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n, - names_big[REGNO (operands[4])]); + names_big[REGNO (operands[3])]); fprintf (asm_out_file, ".Llt%d:\n", loopend_lab); output_asm_insn (info.shift1, operands); - output_asm_insn ("add #0xff,%X4", operands); + output_asm_insn ("add #0xff,%X3", operands); fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab); } return ""; @@ -4155,11 +4152,9 @@ h8300_asm_insn_count (const char *templ) /* Compute the length of a shift insn. */ unsigned int -compute_a_shift_length (rtx *operands) +compute_a_shift_length (rtx operands[3], rtx_code code) { - rtx shift = operands[3]; - machine_mode mode = GET_MODE (shift); - enum rtx_code code = GET_CODE (shift); + enum machine_mode mode = GET_MODE (operands[0]); enum shift_type shift_type; enum shift_mode shift_mode; struct shift_info info; diff --git a/gcc/config/h8300/shiftrotate.md b/gcc/config/h8300/shiftrotate.md index 23140d9a..c5d32cd 100644 --- a/gcc/config/h8300/shiftrotate.md +++ b/gcc/config/h8300/shiftrotate.md @@ -152,168 +152,163 @@ (define_insn_and_split "*shiftqi" [(set (match_operand:QI 0 "register_operand" "=r,r") - (match_operator:QI 3 "nshift_operator" - [(match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "R,rn")])) - (clobber (match_scratch:QI 4 "=X,&r"))] + (shifts:QI + (match_operand:QI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "R,rn"))) + (clobber (match_scratch:QI 3 "=X,&r"))] "" "#" "&& reload_completed" - [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) - (clobber (match_dup 4)) + [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2))) + (clobber (match_dup 3)) (clobber (reg:CC CC_REG))])]) (define_insn "*shiftqi_clobber_flags" [(set (match_operand:QI 0 "register_operand" "=r,r") - (match_operator:QI 3 "nshift_operator" - [(match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "R,rn")])) - (clobber (match_scratch:QI 4 "=X,&r")) + (shifts:QI + (match_operand:QI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "R,rn"))) + (clobber (match_scratch:QI 3 "=X,&r")) (clobber (reg:CC CC_REG))] "" { - return output_a_shift (operands); + return output_a_shift (operands, ); } [(set (attr "length") - (symbol_ref "compute_a_shift_length (operands)"))]) + (symbol_ref "compute_a_shift_length (operands, )"))]) (define_insn_and_split "*shiftqi_noscratch" [(set (match_operand:QI 0 "register_operand" "=r,r") - (match_operator:QI 3 "nshift_operator" - [(match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "R,rn")]))] + (shifts:QI + (match_operand:QI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "R,rn")))] "(GET_CODE (operands[2]) == CONST_INT && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, - GET_CODE (operands[3])))" + ))" "#" "&& reload_completed" - [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) + [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) (define_insn "*shiftqi_noscratch_clobber_flags" [(set (match_operand:QI 0 "register_operand" "=r,r") - (match_operator:QI 3 "nshift_operator" - [(match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "R,rn")])) + (shifts:QI + (match_operand:QI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "R,rn"))) (clobber (reg:CC CC_REG))] "(GET_CODE (operands[2]) == CONST_INT - && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, - GET_CODE (operands[3])))" + && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, ))" { - return output_a_shift (operands); + return output_a_shift (operands, ); } [(set (attr "length") - (symbol_ref "compute_a_shift_length (operands)"))]) + (symbol_ref "compute_a_shift_length (operands, )"))]) (define_insn_and_split "*shifthi" [(set (match_operand:HI 0 "register_operand" "=r,r") - (match_operator:HI 3 "nshift_operator" - [(match_operand:HI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "S,rn")])) - (clobber (match_scratch:QI 4 "=X,&r"))] + (shifts:HI + (match_operand:HI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "S,rn"))) + (clobber (match_scratch:QI 3 "=X,&r"))] "" "#" "&& reload_completed" - [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) - (clobber (match_dup 4)) + [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2))) + (clobber (match_dup 3)) (clobber (reg:CC CC_REG))])]) (define_insn "*shifthi_clobber_flags" [(set (match_operand:HI 0 "register_operand" "=r,r") - (match_operator:HI 3 "nshift_operator" - [(match_operand:HI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "S,rn")])) - (clobber (match_scratch:QI 4 "=X,&r")) + (shifts:HI + (match_operand:HI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "S,rn"))) + (clobber (match_scratch:QI 3 "=X,&r")) (clobber (reg:CC CC_REG))] "" { - return output_a_shift (operands); + return output_a_shift (operands, ); } [(set (attr "length") - (symbol_ref "compute_a_shift_length (operands)"))]) + (symbol_ref "compute_a_shift_length (operands, )"))]) (define_insn_and_split "*shifthi_noscratch" [(set (match_operand:HI 0 "register_operand" "=r,r") - (match_operator:HI 3 "nshift_operator" - [(match_operand:HI 1 "register_operand" "0,0") - (match_operand:HI 2 "nonmemory_operand" "S,rn")]))] + (shifts:HI + (match_operand:HI 1 "register_operand" "0,0") + (match_operand:HI 2 "nonmemory_operand" "S,rn")))] "(GET_CODE (operands[2]) == CONST_INT - && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, - GET_CODE (operands[3])))" + && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, ))" "#" "&& reload_completed" - [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) + [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) (define_insn "*shifthi_noscratch_clobber_flags" [(set (match_operand:HI 0 "register_operand" "=r,r") - (match_operator:HI 3 "nshift_operator" - [(match_operand:HI 1 "register_operand" "0,0") - (match_operand:HI 2 "nonmemory_operand" "S,rn")])) + (shifts:HI + (match_operand:HI 1 "register_operand" "0,0") + (match_operand:HI 2 "nonmemory_operand" "S,rn"))) (clobber (reg:CC CC_REG))] "(GET_CODE (operands[2]) == CONST_INT - && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, - GET_CODE (operands[3])))" + && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, ))" { - return output_a_shift (operands); + return output_a_shift (operands, ); } [(set (attr "length") - (symbol_ref "compute_a_shift_length (operands)"))]) + (symbol_ref "compute_a_shift_length (operands, )"))]) (define_insn_and_split "*shiftsi" [(set (match_operand:SI 0 "register_operand" "=r,r") - (match_operator:SI 3 "nshift_operator" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "T,rn")])) - (clobber (match_scratch:QI 4 "=X,&r"))] + (shifts:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "T,rn"))) + (clobber (match_scratch:QI 3 "=X,&r"))] "" "#" "&& reload_completed" - [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) - (clobber (match_dup 4)) + [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2))) + (clobber (match_dup 3)) (clobber (reg:CC CC_REG))])]) (define_insn "*shiftsi_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r") - (match_operator:SI 3 "nshift_operator" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "T,rn")])) - (clobber (match_scratch:QI 4 "=X,&r")) + (shifts:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "T,rn"))) + (clobber (match_scratch:QI 3 "=X,&r")) (clobber (reg:CC CC_REG))] "" { - return output_a_shift (operands); + return output_a_shift (operands, ); } [(set (attr "length") - (symbol_ref "compute_a_shift_length (operands)"))]) + (symbol_ref "compute_a_shift_length (operands, )"))]) (define_insn_and_split "*shiftsi_noscratch" [(set (match_operand:SI 0 "register_operand" "=r,r") - (match_operator:SI 3 "nshift_operator" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "T,rn")]))] + (shifts:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "T,rn")))] "(GET_CODE (operands[2]) == CONST_INT - && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, - GET_CODE (operands[3])))" + && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, ))" "#" "&& reload_completed" - [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)])) + [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) (define_insn "*shiftsi_noscratch_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r") - (match_operator:SI 3 "nshift_operator" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "T,rn")])) + (shifts:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "T,rn"))) (clobber (reg:CC CC_REG))] "(GET_CODE (operands[2]) == CONST_INT - && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, - GET_CODE (operands[3])))" + && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, ))" { - return output_a_shift (operands); + return output_a_shift (operands, ); } [(set (attr "length") - (symbol_ref "compute_a_shift_length (operands)"))]) + (symbol_ref "compute_a_shift_length (operands, )"))]) ;; Split a variable shift into a loop. If the register containing ;; the shift count dies, then we just use that register. -- cgit v1.1 From 18d0fad77b580d1ac64ed04d94fd3c9795687b91 Mon Sep 17 00:00:00 2001 From: David Faust Date: Tue, 1 Jun 2021 09:22:59 -0700 Subject: BTF: Support for BTF_KIND_FLOAT Add BTF_KIND_FLOAT, a new BTF type kind which has recently stabilized in the linux kernel [1]. This kind is used for encoding floating point types, and is of particular use when generating BTF for some s390 arch-specific kernel headers. Also update some BTF tests which previously used floating point types to check correct behavior for types with no BTF representation. [1]: https://github.com/torvalds/linux/commit/b1828f0b04828aa8cccadf00a702f459caefeed9 include/ChangeLog: * btf.h (struct btf_type): Update bit usage comment. (BTF_INFO_KIND): Update bit mask. (BTF_KIND_FLOAT): New define. (BTF_KIND_MAX): Update. gcc/ChangeLog: * btfout.c (get_btf_kind): Support BTF_KIND_FLOAT. (btf_asm_type): Likewise. gcc/testsuite/ChangeLog: * gcc.dg/debug/btf/btf-float-1.c: New test. * gcc.dg/debug/btf/btf-function-3.c: Use different unrepresentable type. * gcc.dg/debug/btf/btf-struct-2.c: Likewise. * gcc.dg/debug/btf/btf-variables-2.c: Likewise. --- gcc/btfout.c | 2 ++ gcc/testsuite/gcc.dg/debug/btf/btf-float-1.c | 20 ++++++++++++++++++++ gcc/testsuite/gcc.dg/debug/btf/btf-function-3.c | 2 +- gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c | 2 +- gcc/testsuite/gcc.dg/debug/btf/btf-variables-2.c | 2 +- 5 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-float-1.c (limited to 'gcc') diff --git a/gcc/btfout.c b/gcc/btfout.c index e58c969..8cdd990 100644 --- a/gcc/btfout.c +++ b/gcc/btfout.c @@ -124,6 +124,7 @@ get_btf_kind (uint32_t ctf_kind) switch (ctf_kind) { case CTF_K_INTEGER: return BTF_KIND_INT; + case CTF_K_FLOAT: return BTF_KIND_FLOAT; case CTF_K_POINTER: return BTF_KIND_PTR; case CTF_K_ARRAY: return BTF_KIND_ARRAY; case CTF_K_FUNCTION: return BTF_KIND_FUNC_PROTO; @@ -627,6 +628,7 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd) switch (btf_kind) { case BTF_KIND_INT: + case BTF_KIND_FLOAT: case BTF_KIND_STRUCT: case BTF_KIND_UNION: case BTF_KIND_ENUM: diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-float-1.c b/gcc/testsuite/gcc.dg/debug/btf/btf-float-1.c new file mode 100644 index 0000000..6876df0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-float-1.c @@ -0,0 +1,20 @@ +/* Tests for BTF floating point type kinds. We expect a single record for each + of the base types: float, double and long double. */ + +/* { dg-do compile } */ +/* { dg-options "-O0 -gbtf -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x10000000\[\t \]+\[^\n\]*btt_info" 3 } } */ + +/* { dg-final { scan-assembler-times "ascii \"float.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"double.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"long double.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ + +float a; +float b = 1.5f; + +double c; +double d = -99.9; + +long double e; +long double f = 1000.01; diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-function-3.c b/gcc/testsuite/gcc.dg/debug/btf/btf-function-3.c index 35f96a2..c83b823 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf-function-3.c +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-function-3.c @@ -16,7 +16,7 @@ /* Exactly one function parameter should have type_id=0. */ /* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*farg_type" 1 } } */ -int foo (int a, float f, long b) +int foo (int a, float __attribute__((__vector_size__(16))) f, long b) { return 0; } diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c b/gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c index 24514fc..c3aff09 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c @@ -14,6 +14,6 @@ struct with_float { int a; - float f; + float __attribute__((__vector_size__(16))) f; char c; } instance; diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-variables-2.c b/gcc/testsuite/gcc.dg/debug/btf/btf-variables-2.c index 0f9742e..db0bdd7 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf-variables-2.c +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-variables-2.c @@ -16,7 +16,7 @@ /* { dg-final { scan-assembler-times "ascii \"myst.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ int foo; -float bar; +float __attribute__((__vector_size__(16))) bar; int baz[10]; struct st -- cgit v1.1 From 84f7bab89279ca1234fef88929c74caeda8cb55e Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Wed, 30 Jun 2021 14:15:53 -0400 Subject: Fix build_gt and build_lt for signed 1 bit values. Signed 1 bit values have a range of [-1, 0] but neither (0 - 1) nor (-1 + 1) can be represented. For signed values, add or subtract -1 as appropriate. PR tree-optimization/101223 gcc/ * range-op.cc (build_lt): Add -1 for signed values. (built_gt): Subtract -1 for signed values. gcc/testsuite/ * gcc.dg/pr101223.c: New. --- gcc/range-op.cc | 18 +++++++++++++++-- gcc/testsuite/gcc.dg/pr101223.c | 44 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr101223.c (limited to 'gcc') diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 97b9843..f8e4c6d 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -687,7 +687,14 @@ static void build_lt (irange &r, tree type, const wide_int &val) { wi::overflow_type ov; - wide_int lim = wi::sub (val, 1, TYPE_SIGN (type), &ov); + wide_int lim; + signop sgn = TYPE_SIGN (type); + + // Signed 1 bit cannot represent 1 for subtraction. + if (sgn == SIGNED) + lim = wi::add (val, -1, sgn, &ov); + else + lim = wi::sub (val, 1, sgn, &ov); // If val - 1 underflows, check if X < MIN, which is an empty range. if (ov) @@ -710,7 +717,14 @@ static void build_gt (irange &r, tree type, const wide_int &val) { wi::overflow_type ov; - wide_int lim = wi::add (val, 1, TYPE_SIGN (type), &ov); + wide_int lim; + signop sgn = TYPE_SIGN (type); + + // Signed 1 bit cannot represent 1 for addition. + if (sgn == SIGNED) + lim = wi::sub (val, -1, sgn, &ov); + else + lim = wi::add (val, 1, sgn, &ov); // If val + 1 overflows, check is for X > MAX, which is an empty range. if (ov) r.set_undefined (); diff --git a/gcc/testsuite/gcc.dg/pr101223.c b/gcc/testsuite/gcc.dg/pr101223.c new file mode 100644 index 0000000..6d5a247 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101223.c @@ -0,0 +1,44 @@ +/* PR tree-optimization/101223 */ +/* { dg-do run } */ +/* { dg-options "-O2 " } */ + +struct { + int a : 1; +} b; +int c = 1, d; +int foo1() { + for (; d < 2; d++) { + int e = ~c, f = 0, g; + if (e) { + f = c; + g = b.a; + b.a = f; + if (b.a >= g) + __builtin_abort(); + } + c = f; + b.a = g; + } + return 0; +} + +int foo2() { + for (; d < 2; d++) { + int e = ~c, f = 0, g; + if (e) { + f = c; + g = b.a; + b.a = f; + if (g <= b.a) + __builtin_abort(); + } + c = f; + b.a = g; + } + return 0; +} +int main () +{ + return foo1() + foo2(); +} + -- cgit v1.1 From 7aa5fb17a30ff0ce9928e5eac35b892d95e7eba5 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 2 Jul 2021 11:58:47 -0400 Subject: Use shift instructions to eliminate redundant compare/test instructions on the H8 gcc/ChangeLog * config/h8300/h8300-protos.h (compute_a_shift_cc): Accept additional argument for the code. * config/h8300/h8300.c (compute_a_shift_cc): Accept additional argument for the code. Just return if the ZN bits are useful or not rather than the old style CC_* enums. * config/h8300/shiftrotate.md (shiftqi_noscratch): Move before more generic shiftqi patterns. (shifthi_noscratch, shiftsi_noscratch): Similarly. (shiftqi_noscratch_set_flags): New pattern. (shifthi_noscratch_set_flags, shiftsi_noscratch_set_flags): Likewise. --- gcc/config/h8300/h8300-protos.h | 2 +- gcc/config/h8300/h8300.c | 20 +++--- gcc/config/h8300/shiftrotate.md | 153 +++++++++++++++++++++++++++------------- 3 files changed, 116 insertions(+), 59 deletions(-) (limited to 'gcc') diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 86bcc3f..744337d 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -41,7 +41,7 @@ extern const char *output_logical_op (machine_mode, rtx_code code, extern unsigned int compute_logical_op_length (machine_mode, rtx_code, rtx *, rtx_insn *); -extern int compute_a_shift_cc (rtx, rtx *); +extern int compute_a_shift_cc (rtx *, rtx_code); #ifdef HAVE_ATTR_cc extern enum attr_cc compute_plussi_cc (rtx *); #endif diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 0fdc68b..d2f6548 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -4297,11 +4297,9 @@ compute_a_shift_length (rtx operands[3], rtx_code code) /* Compute which flag bits are valid after a shift insn. */ int -compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands) +compute_a_shift_cc (rtx operands[3], rtx_code code) { - rtx shift = operands[3]; - machine_mode mode = GET_MODE (shift); - enum rtx_code code = GET_CODE (shift); + machine_mode mode = GET_MODE (operands[0]); enum shift_type shift_type; enum shift_mode shift_mode; struct shift_info info; @@ -4358,16 +4356,18 @@ compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands) { case SHIFT_SPECIAL: if (info.remainder == 0) - return info.cc_special; + return (info.cc_special == OLD_CC_SET_ZN + || info.cc_special == OLD_CC_SET_ZNV); /* Fall through. */ case SHIFT_INLINE: - return info.cc_inline; + return (info.cc_inline == OLD_CC_SET_ZN + || info.cc_inline == OLD_CC_SET_ZNV); case SHIFT_ROT_AND: /* This case always ends with an and instruction. */ - return OLD_CC_SET_ZNV; + return true; case SHIFT_LOOP: /* A loop to shift by a "large" constant value. @@ -4375,9 +4375,11 @@ compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands) if (info.shift2 != NULL) { if (n % 2) - return info.cc_inline; + return (info.cc_inline == OLD_CC_SET_ZN + || info.cc_inline == OLD_CC_SET_ZNV); + } - return OLD_CC_CLOBBER; + return false; default: gcc_unreachable (); diff --git a/gcc/config/h8300/shiftrotate.md b/gcc/config/h8300/shiftrotate.md index c5d32cd..0476324 100644 --- a/gcc/config/h8300/shiftrotate.md +++ b/gcc/config/h8300/shiftrotate.md @@ -150,33 +150,6 @@ } [(set_attr "length" "4")]) -(define_insn_and_split "*shiftqi" - [(set (match_operand:QI 0 "register_operand" "=r,r") - (shifts:QI - (match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "R,rn"))) - (clobber (match_scratch:QI 3 "=X,&r"))] - "" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2))) - (clobber (match_dup 3)) - (clobber (reg:CC CC_REG))])]) - -(define_insn "*shiftqi_clobber_flags" - [(set (match_operand:QI 0 "register_operand" "=r,r") - (shifts:QI - (match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "R,rn"))) - (clobber (match_scratch:QI 3 "=X,&r")) - (clobber (reg:CC CC_REG))] - "" -{ - return output_a_shift (operands, ); -} - [(set (attr "length") - (symbol_ref "compute_a_shift_length (operands, )"))]) - (define_insn_and_split "*shiftqi_noscratch" [(set (match_operand:QI 0 "register_operand" "=r,r") (shifts:QI @@ -204,24 +177,43 @@ [(set (attr "length") (symbol_ref "compute_a_shift_length (operands, )"))]) -(define_insn_and_split "*shifthi" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (shifts:HI - (match_operand:HI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "S,rn"))) +(define_insn "*shiftqi_noscratch_set_flags" + [(set (reg:CCZN CC_REG) + (compare:CCZN + (shifts:QI + (match_operand:QI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "R,rn")) + (const_int 0))) + (set (match_operand:QI 0 "register_operand" "=r,r") + (shifts:QI (match_dup 1) (match_dup 2)))] + "(GET_CODE (operands[2]) == CONST_INT + && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, ) + && compute_a_shift_cc (operands, ))" +{ + return output_a_shift (operands, ); +} + [(set (attr "length") + (symbol_ref "compute_a_shift_length (operands, )"))]) + + +(define_insn_and_split "*shiftqi" + [(set (match_operand:QI 0 "register_operand" "=r,r") + (shifts:QI + (match_operand:QI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "R,rn"))) (clobber (match_scratch:QI 3 "=X,&r"))] "" "#" "&& reload_completed" - [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2))) + [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2))) (clobber (match_dup 3)) (clobber (reg:CC CC_REG))])]) -(define_insn "*shifthi_clobber_flags" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (shifts:HI - (match_operand:HI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "S,rn"))) +(define_insn "*shiftqi_clobber_flags" + [(set (match_operand:QI 0 "register_operand" "=r,r") + (shifts:QI + (match_operand:QI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "R,rn"))) (clobber (match_scratch:QI 3 "=X,&r")) (clobber (reg:CC CC_REG))] "" @@ -257,24 +249,41 @@ [(set (attr "length") (symbol_ref "compute_a_shift_length (operands, )"))]) -(define_insn_and_split "*shiftsi" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (shifts:SI - (match_operand:SI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "T,rn"))) +(define_insn "*shifthi_noscratch_setzn" + [(set (reg:CCZN CC_REG) + (compare:CCZN + (shifts:HI (match_operand:HI 1 "register_operand" "0,0") + (match_operand:HI 2 "nonmemory_operand" "S,rn")) + (const_int 0))) + (set (match_operand:HI 0 "register_operand" "=r,r") + (shifts:HI (match_dup 1) (match_dup 2)))] + "(GET_CODE (operands[2]) == CONST_INT + && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, ) + && compute_a_shift_cc (operands, ))" +{ + return output_a_shift (operands, ); +} + [(set (attr "length") + (symbol_ref "compute_a_shift_length (operands, )"))]) + +(define_insn_and_split "*shifthi" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (shifts:HI + (match_operand:HI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "S,rn"))) (clobber (match_scratch:QI 3 "=X,&r"))] "" "#" "&& reload_completed" - [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2))) + [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2))) (clobber (match_dup 3)) (clobber (reg:CC CC_REG))])]) -(define_insn "*shiftsi_clobber_flags" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (shifts:SI - (match_operand:SI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "T,rn"))) +(define_insn "*shifthi_clobber_flags" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (shifts:HI + (match_operand:HI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "S,rn"))) (clobber (match_scratch:QI 3 "=X,&r")) (clobber (reg:CC CC_REG))] "" @@ -310,9 +319,55 @@ [(set (attr "length") (symbol_ref "compute_a_shift_length (operands, )"))]) +(define_insn "*shiftsi_noscratch_cczn" + [(set (reg:CCZN CC_REG) + (compare:CCZN + (shifts:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "T,rn")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r,r") + (shifts:SI (match_dup 1) (match_dup 2)))] + "(GET_CODE (operands[2]) == CONST_INT + && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, ) + && compute_a_shift_cc (operands, ))" +{ + return output_a_shift (operands, ); +} + [(set (attr "length") + (symbol_ref "compute_a_shift_length (operands, )"))]) + ;; Split a variable shift into a loop. If the register containing ;; the shift count dies, then we just use that register. + +(define_insn_and_split "*shiftsi" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (shifts:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "T,rn"))) + (clobber (match_scratch:QI 3 "=X,&r"))] + "" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2))) + (clobber (match_dup 3)) + (clobber (reg:CC CC_REG))])]) + +(define_insn "*shiftsi_clobber_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (shifts:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "T,rn"))) + (clobber (match_scratch:QI 3 "=X,&r")) + (clobber (reg:CC CC_REG))] + "" +{ + return output_a_shift (operands, ); +} + [(set (attr "length") + (symbol_ref "compute_a_shift_length (operands, )"))]) + (define_split [(set (match_operand 0 "register_operand" "") (match_operator 2 "nshift_operator" -- cgit v1.1 From 42a9e4e1381ba14d8ef21b331494945c2f51e6be Mon Sep 17 00:00:00 2001 From: Peter Bergner Date: Fri, 2 Jul 2021 11:27:52 -0500 Subject: rs6000: Add MMA __builtin_vsx_lxvp and __builtin_vsx_stxvp built-ins Add support for the __builtin_vsx_lxvp and __builtin_vsx_stxvp built-ins to keep in sync with LLVM which added these earlier. 2021-07-02 Peter Bergner gcc/ * config/rs6000/rs6000-builtin.def (BU_MMA_PAIR_LD, BU_MMA_PAIR_ST): New macros. (__builtin_vsx_lxvp, __builtin_vsx_stxvp): New built-ins. * config/rs6000/rs6000-call.c (rs6000_gimple_fold_mma_builtin): Expand lxvp and stxvp built-ins. (mma_init_builtins): Handle lxvp and stxvp built-ins. (builtin_function_type): Likewise. * doc/extend.texi (__builtin_vsx_lxvp, __builtin_mma_stxvp): Document. gcc/testsuite/ * gcc.target/powerpc/mma-builtin-7.c: New test. * gcc.target/powerpc/mma-builtin-8.c: New test. --- gcc/config/rs6000/rs6000-builtin.def | 22 ++++++++++ gcc/config/rs6000/rs6000-call.c | 56 +++++++++++++++++++++++- gcc/doc/extend.texi | 3 ++ gcc/testsuite/gcc.target/powerpc/mma-builtin-7.c | 26 +++++++++++ gcc/testsuite/gcc.target/powerpc/mma-builtin-8.c | 27 ++++++++++++ 5 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/mma-builtin-7.c create mode 100644 gcc/testsuite/gcc.target/powerpc/mma-builtin-8.c (limited to 'gcc') diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def index d7ce4de..6270444 100644 --- a/gcc/config/rs6000/rs6000-builtin.def +++ b/gcc/config/rs6000/rs6000-builtin.def @@ -484,6 +484,25 @@ | RS6000_BTC_SENARY), \ CODE_FOR_ ## ICODE) /* ICODE */ +#define BU_MMA_PAIR_LD(ENUM, NAME, ATTR) \ + RS6000_BUILTIN_M (VSX_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_vsx_" NAME, /* NAME */ \ + RS6000_BTM_MMA, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_BINARY \ + | RS6000_BTC_GIMPLE), \ + CODE_FOR_nothing) /* ICODE */ + +#define BU_MMA_PAIR_ST(ENUM, NAME, ATTR) \ + RS6000_BUILTIN_M (VSX_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_vsx_" NAME, /* NAME */ \ + RS6000_BTM_MMA, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_TERNARY \ + | RS6000_BTC_VOID \ + | RS6000_BTC_GIMPLE), \ + CODE_FOR_nothing) /* ICODE */ + /* ISA 2.05 (power6) convenience macros. */ /* For functions that depend on the CMPB instruction */ #define BU_P6_2(ENUM, NAME, ATTR, ICODE) \ @@ -3253,6 +3272,9 @@ BU_SPECIAL_X (RS6000_BUILTIN_CFSTRING, "__builtin_cfstring", RS6000_BTM_ALWAYS, BU_P10V_VSX_1 (XVCVBF16SPN, "xvcvbf16spn", MISC, vsx_xvcvbf16spn) BU_P10V_VSX_1 (XVCVSPBF16, "xvcvspbf16", MISC, vsx_xvcvspbf16) +BU_MMA_PAIR_LD (LXVP, "lxvp", MISC) +BU_MMA_PAIR_ST (STXVP, "stxvp", PAIR) + BU_MMA_1 (XXMFACC, "xxmfacc", QUAD, mma_xxmfacc) BU_MMA_1 (XXMTACC, "xxmtacc", QUAD, mma_xxmtacc) BU_MMA_1 (XXSETACCZ, "xxsetaccz", MISC, mma_xxsetaccz) diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index b677898..6115e3b 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -11913,6 +11913,32 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi) gsi_replace_with_seq (gsi, new_seq, true); return true; } + else if (fncode == VSX_BUILTIN_LXVP) + { + push_gimplify_context (true); + tree offset = gimple_call_arg (stmt, 0); + tree ptr = gimple_call_arg (stmt, 1); + tree lhs = gimple_call_lhs (stmt); + tree mem = build_simple_mem_ref (build2 (POINTER_PLUS_EXPR, + TREE_TYPE (ptr), ptr, offset)); + gimplify_assign (lhs, mem, &new_seq); + pop_gimplify_context (NULL); + gsi_replace_with_seq (gsi, new_seq, true); + return true; + } + else if (fncode == VSX_BUILTIN_STXVP) + { + push_gimplify_context (true); + tree src = gimple_call_arg (stmt, 0); + tree offset = gimple_call_arg (stmt, 1); + tree ptr = gimple_call_arg (stmt, 2); + tree mem = build_simple_mem_ref (build2 (POINTER_PLUS_EXPR, + TREE_TYPE (ptr), ptr, offset)); + gimplify_assign (mem, src, &new_seq); + pop_gimplify_context (NULL); + gsi_replace_with_seq (gsi, new_seq, true); + return true; + } /* Convert this built-in into an internal version that uses pass-by-value arguments. The internal built-in follows immediately after this one. */ @@ -14264,11 +14290,14 @@ mma_init_builtins (void) if (gimple_func) { gcc_assert (icode == CODE_FOR_nothing); - op[nopnds++] = void_type_node; /* Some MMA built-ins that are expanded into gimple are converted into internal MMA built-ins that are expanded into rtl. The internal built-in follows immediately after this built-in. */ - icode = d[1].icode; + if (d[1].icode != CODE_FOR_nothing) + { + op[nopnds++] = void_type_node; + icode = d[1].icode; + } } else { @@ -14291,6 +14320,19 @@ mma_init_builtins (void) else op[nopnds++] = build_pointer_type (vector_pair_type_node); } + else if (d->code == VSX_BUILTIN_LXVP) + { + op[nopnds++] = vector_pair_type_node; + op[nopnds++] = sizetype; + op[nopnds++] = build_pointer_type (vector_pair_type_node); + } + else if (d->code == VSX_BUILTIN_STXVP) + { + op[nopnds++] = void_type_node; + op[nopnds++] = vector_pair_type_node; + op[nopnds++] = sizetype; + op[nopnds++] = build_pointer_type (vector_pair_type_node); + } else { /* This is a normal MMA built-in function. */ @@ -14781,6 +14823,16 @@ builtin_function_type (machine_mode mode_ret, machine_mode mode_arg0, h.uns_p[2] = 1; break; + case VSX_BUILTIN_LXVP: + h.uns_p[0] = 1; + h.uns_p[2] = 1; + break; + + case VSX_BUILTIN_STXVP: + h.uns_p[1] = 1; + h.uns_p[3] = 1; + break; + default: break; } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 8fc66d6..b83cd49 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -20731,6 +20731,9 @@ void __builtin_vsx_disassemble_pair (void *, __vector_pair *); vec_t __builtin_vsx_xvcvspbf16 (vec_t); vec_t __builtin_vsx_xvcvbf16spn (vec_t); + +__vector_pair __builtin_vsx_lxvp (size_t, __vector_pair *); +void __builtin_vsx_stxvp (__vector_pair, size_t, __vector_pair *); @end smallexample @node PRU Built-in Functions diff --git a/gcc/testsuite/gcc.target/powerpc/mma-builtin-7.c b/gcc/testsuite/gcc.target/powerpc/mma-builtin-7.c new file mode 100644 index 0000000..c661a4b --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mma-builtin-7.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ + +void +foo (__vector_pair *dst, __vector_pair *src, long idx) +{ + dst[0] = __builtin_vsx_lxvp (0, src); + dst[2] = __builtin_vsx_lxvp (32, src); + dst[4] = __builtin_vsx_lxvp (64, src); + /* Non-constant offset should generate a lxvpx. */ + dst[6] = __builtin_vsx_lxvp (idx, src); + /* Non-aligned offset should generate a plxvp. */ + dst[8] = __builtin_vsx_lxvp (257, src); +} + +#if !__has_builtin (__builtin_vsx_lxvp) +# error "__has_builtin (__builtin_vsx_lxvp) failed" +#endif + +/* { dg-final { scan-assembler-not {\mlxv\M} } } */ +/* { dg-final { scan-assembler-not {\mstxv\M} } } */ +/* { dg-final { scan-assembler-times {\mlxvp\M} 3 } } */ +/* { dg-final { scan-assembler-times {\mlxvpx\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mplxvp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mstxvp\M} 5 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/mma-builtin-8.c b/gcc/testsuite/gcc.target/powerpc/mma-builtin-8.c new file mode 100644 index 0000000..af29e47 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mma-builtin-8.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ + +void +foo (__vector_pair *dst, __vector_pair *src, long idx) +{ + __vector_pair pair = *src; + __builtin_vsx_stxvp (pair, 0, dst); + __builtin_vsx_stxvp (pair, 32, dst); + __builtin_vsx_stxvp (pair, 64, dst); + /* Non-constant offset should generate a stxvpx. */ + __builtin_vsx_stxvp (pair, idx, dst); + /* Non-aligned offset should generate a pstxvp. */ + __builtin_vsx_stxvp (pair, 257, dst); +} + +#if !__has_builtin (__builtin_vsx_stxvp) +# error "__has_builtin (__builtin_vsx_stxvp) failed" +#endif + +/* { dg-final { scan-assembler-not {\mlxv\M} } } */ +/* { dg-final { scan-assembler-not {\mstxv\M} } } */ +/* { dg-final { scan-assembler-times {\mlxvp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mstxvp\M} 3 } } */ +/* { dg-final { scan-assembler-times {\mstxvpx\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpstxvp\M} 1 } } */ -- cgit v1.1 From e3528ce197f8886869f95e8a8f901861a319851c Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 2 Jul 2021 13:54:57 -0400 Subject: c++: unqualified member template in constraint [PR101247] Here any_template_parm_r is failing to mark the template parameters implicitly used by the unqualified use of 'd' inside the constraint because the code to do so assumes each level of a template parameter list points to the corresponding primary template, but here the parameter level for A in the out-of-line definition of A::B does not (nor do the parameter levels for A and C in the definition of A::C), which causes us to overlook the sharing. So it seems we can't in general depend on the TREE_TYPE of a template parameter level being non-empty here. This patch partially fixes this by rewriting the relevant part of any_template_parm_r to not depend on the TREE_TYPE of outer levels. We still depend on the innermost level to point to the innermost primary template, so we still crash on the commented out line in the below testcase. PR c++/101247 gcc/cp/ChangeLog: * pt.c (any_template_parm_r) : Rewrite to use common_enclosing_class and to not depend on the TREE_TYPE of outer levels pointing to the corresponding primary template. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-memtmpl4.C: New test. --- gcc/cp/pt.c | 23 +++++---------------- gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C | 28 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C (limited to 'gcc') diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index dda6c9e..7e56ccf 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10731,24 +10731,11 @@ any_template_parm_r (tree t, void *data) { /* If T is a member template that shares template parameters with ctx_parms, we need to mark all those parameters for mapping. */ - tree dparms = DECL_TEMPLATE_PARMS (t); - tree cparms = ftpi->ctx_parms; - while (TMPL_PARMS_DEPTH (dparms) > ftpi->max_depth) - dparms = TREE_CHAIN (dparms); - while (TMPL_PARMS_DEPTH (cparms) > TMPL_PARMS_DEPTH (dparms)) - cparms = TREE_CHAIN (cparms); - while (dparms - && (TREE_TYPE (TREE_VALUE (dparms)) - != TREE_TYPE (TREE_VALUE (cparms)))) - dparms = TREE_CHAIN (dparms), - cparms = TREE_CHAIN (cparms); - if (dparms) - { - int ddepth = TMPL_PARMS_DEPTH (dparms); - tree dargs = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (t))); - for (int i = 0; i < ddepth; ++i) - WALK_SUBTREE (TMPL_ARGS_LEVEL (dargs, i+1)); - } + if (tree ctmpl = TREE_TYPE (INNERMOST_TEMPLATE_PARMS (ftpi->ctx_parms))) + if (tree com = common_enclosing_class (DECL_CONTEXT (t), + DECL_CONTEXT (ctmpl))) + if (tree ti = CLASSTYPE_TEMPLATE_INFO (com)) + WALK_SUBTREE (TI_ARGS (ti)); } break; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C new file mode 100644 index 0000000..625149e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C @@ -0,0 +1,28 @@ +// PR c++/101247 +// { dg-do compile { target concepts } } +// A variant of concepts-memtmpl3.C where f is defined outside A's definition. + +template struct A { + template static constexpr bool d = true; + struct B; + template struct C; +}; + +template +struct A::B { + template static void f(c) requires d; +}; + +template +template +struct A::C { + template static void f(c) requires d; + static void g() requires d; +}; + +int main() +{ + A::B::f(0); + A::C::f(0); + // A::C::g(); +} -- cgit v1.1 From 2ca89394280da4afad6074ec3cb7136b6142af7b Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 2 Jul 2021 21:57:24 +0200 Subject: openmp: Reject #pragma omp atomic update, [PR101297] I've noticed that we allow a trailing comma on OpenMP atomic construct if there is at least one clause. Commas should be only allowed to separate the clauses (or in OpenMP 5.1 to separate directive name from the clauses). 2021-07-02 Jakub Jelinek PR c/101297 * c-parser.c (c_parser_omp_atomic): Consume comma only if it appears before a CPP_NAME. * parser.c (cp_parser_omp_atomic): Consume comma only if it appears before a CPP_NAME. * c-c++-common/gomp/atomic-24.c: New test. --- gcc/c/c-parser.c | 4 +++- gcc/cp/parser.c | 4 +++- gcc/testsuite/c-c++-common/gomp/atomic-24.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/atomic-24.c (limited to 'gcc') diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 3922b56..9a56e0c 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -17533,7 +17533,9 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc) while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) { - if (!first && c_parser_next_token_is (parser, CPP_COMMA)) + if (!first + && c_parser_next_token_is (parser, CPP_COMMA) + && c_parser_peek_2nd_token (parser)->type == CPP_NAME) c_parser_consume_token (parser); first = false; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 02daa7a..3550cd0 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -39171,7 +39171,9 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { - if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + if (!first + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); first = false; diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-24.c b/gcc/testsuite/c-c++-common/gomp/atomic-24.c new file mode 100644 index 0000000..f70c805 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/atomic-24.c @@ -0,0 +1,12 @@ +/* PR c/101297 */ + +int i; + +void +foo (void) +{ + #pragma omp atomic update, /* { dg-error "expected end of line before ',' token" } */ + i++; + #pragma omp atomic update,, /* { dg-error "expected end of line before ',' token" } */ + i++; +} -- cgit v1.1 From 9984f63aab93a370101966b7eb198dc61130b3c8 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 2 Jul 2021 21:59:21 +0200 Subject: openmp: Initial support for OpenMP directives expressed as C++11 attributes This is an OpenMP 5.1 feature, but I think it is something very useful for OpenMP users, so I'm committing it now instead of waiting until all 5.0 work is done. The support is incomplete, only attributes on statements (or block local declarations) are supported right now, while for non-executable directives they should be also supported at namespace scope and at class scope, and for declarations in all places that appertain to the declarations rather than e.g. types. I need to also fix up handling of C++11 non-OpenMP attributes mixed with OpenMP attributes before block local declarations (currently it throws them away), probably reject if the directives appertain to labels etc. In order not to complicate all the OpenMP directive parsing, it is done by remembering the tokens from the attribute, slightly adjusting them and feeding them through a temporary new lexer to cp_parse_pragma. 2021-07-02 Jakub Jelinek gcc/c-family/ * c-common.h (enum c_omp_directive_kind): New enum. (struct c_omp_directive): New type. (c_omp_categorize_directive): Declare. * c-omp.c (omp_directives): New variable. (c_omp_categorize_directive): New function. gcc/cp/ * parser.h (struct cp_lexer): Add in_omp_attribute_pragma member. (struct cp_omp_declare_simd_data): Likewise. * cp-tree.h (enum cp_tree_index): Add CPTI_OMP_IDENTIFIER. (omp_identifier): Define. * parser.c (cp_parser_skip_to_pragma_eol): Handle in_omp_attribute_pragma CPP_PRAGMA_EOL followed by CPP_EOF. (cp_parser_require_pragma_eol): Likewise. (struct cp_omp_attribute_data): New type. (cp_parser_handle_statement_omp_attributes): New function. (cp_parser_statement): Handle OpenMP directives in statement's attribute-specifier-seq. (cp_parser_omp_directive_args, cp_parser_omp_sequence_args): New functions. (cp_parser_std_attribute): Handle omp::directive and omp::sequence attributes. (cp_parser_omp_all_clauses): If in_omp_attribute_pragma, allow a comma also before the first clause. (cp_parser_omp_allocate): Likewise. (cp_parser_omp_atomic): Likewise. (cp_parser_omp_depobj): Likewise. (cp_parser_omp_flush): Likewise. (cp_parser_omp_ordered): Likewise. (cp_parser_omp_declare_simd): Save in_omp_attribute_pragma into struct cp_omp_declare_simd_data. (cp_finish_omp_declare_variant): Add in_omp_attribute_pragma argument. If set, allow a comma also before match clause. (cp_parser_late_parsing_omp_declare_simd): If in_omp_attribute_pragma, allow a comma also before the first clause. Adjust cp_finish_omp_declare_variant caller. (cp_parser_omp_declare_target): If in_omp_attribute_pragma, allow a comma also before the first clause. (cp_parser_omp_declare_reduction_exprs): Likewise. (cp_parser_omp_requires): Likewise. * decl.c (initialize_predefined_identifiers): Initialize omp_identifier. * decl2.c (cplus_decl_attributes): Reject omp::directive and omp::sequence attributes. gcc/testsuite/ * g++.dg/gomp/attrs-1.C: New test. * g++.dg/gomp/attrs-2.C: New test. * g++.dg/gomp/attrs-3.C: New test. --- gcc/c-family/c-common.h | 19 ++ gcc/c-family/c-omp.c | 151 ++++++++++ gcc/cp/cp-tree.h | 2 + gcc/cp/decl.c | 1 + gcc/cp/decl2.c | 25 ++ gcc/cp/parser.c | 399 +++++++++++++++++++++++++- gcc/cp/parser.h | 6 + gcc/testsuite/g++.dg/gomp/attrs-1.C | 553 ++++++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/gomp/attrs-2.C | 553 ++++++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/gomp/attrs-3.C | 40 +++ 10 files changed, 1739 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gomp/attrs-1.C create mode 100644 gcc/testsuite/g++.dg/gomp/attrs-2.C create mode 100644 gcc/testsuite/g++.dg/gomp/attrs-3.C (limited to 'gcc') diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 88022d0..50ca8fb 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1246,6 +1246,25 @@ extern void c_omp_mark_declare_variant (location_t, tree, tree); extern const char *c_omp_map_clause_name (tree, bool); extern void c_omp_adjust_map_clauses (tree, bool); +enum c_omp_directive_kind { + C_OMP_DIR_STANDALONE, + C_OMP_DIR_CONSTRUCT, + C_OMP_DIR_DECLARATIVE, + C_OMP_DIR_UTILITY, + C_OMP_DIR_INFORMATIONAL +}; + +struct c_omp_directive { + const char *first, *second, *third; + unsigned int id; + enum c_omp_directive_kind kind; + bool simd; +}; + +extern const struct c_omp_directive *c_omp_categorize_directive (const char *, + const char *, + const char *); + /* Return next tree in the chain for chain_next walking of tree nodes. */ static inline tree c_tree_chain_next (tree t) diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index cd81a08..e70974d 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -2912,3 +2912,154 @@ c_omp_adjust_map_clauses (tree clauses, bool is_target) } } } + +static const struct c_omp_directive omp_directives[] = { + /* Keep this alphabetically sorted by the first word. Non-null second/third + if any should precede null ones. */ + { "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE, + C_OMP_DIR_DECLARATIVE, false }, + /* { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME, + C_OMP_DIR_INFORMATIONAL, false }, */ + /* { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES, + C_OMP_DIR_INFORMATIONAL, false }, */ + { "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC, + C_OMP_DIR_CONSTRUCT, false }, + { "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER, + C_OMP_DIR_STANDALONE, false }, + /* { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN, + C_OMP_DIR_INFORMATIONAL, false }, */ + /* { "begin", "declare", "target", PRAGMA_OMP_BEGIN, + C_OMP_DIR_DECLARATIVE, false }, */ + /* { "begin", "declare", "variant", PRAGMA_OMP_BEGIN, + C_OMP_DIR_DECLARATIVE, false }, */ + /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN, + C_OMP_DIR_???, ??? }, */ + { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL, + C_OMP_DIR_STANDALONE, false }, + { "cancellation", "point", nullptr, PRAGMA_OMP_CANCELLATION_POINT, + C_OMP_DIR_STANDALONE, false }, + { "critical", nullptr, nullptr, PRAGMA_OMP_CRITICAL, + C_OMP_DIR_CONSTRUCT, false }, + /* { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, false }, */ + { "declare", "reduction", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, true }, + { "declare", "simd", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, true }, + { "declare", "target", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, false }, + { "declare", "variant", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, false }, + { "depobj", nullptr, nullptr, PRAGMA_OMP_DEPOBJ, + C_OMP_DIR_STANDALONE, false }, + /* { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH, + C_OMP_DIR_CONSTRUCT, false }, */ + { "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE, + C_OMP_DIR_CONSTRUCT, true }, + /* { "end", "assumes", nullptr, PRAGMA_OMP_END, + C_OMP_DIR_INFORMATIONAL, false }, */ + { "end", "declare", "target", PRAGMA_OMP_END_DECLARE_TARGET, + C_OMP_DIR_DECLARATIVE, false }, + /* { "end", "declare", "variant", PRAGMA_OMP_END, + C_OMP_DIR_DECLARATIVE, false }, */ + /* { "end", "metadirective", nullptr, PRAGMA_OMP_END, + C_OMP_DIR_???, ??? }, */ + /* error with at(execution) is C_OMP_DIR_STANDALONE. */ + /* { "error", nullptr, nullptr, PRAGMA_OMP_ERROR, + C_OMP_DIR_UTILITY, false }, */ + { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH, + C_OMP_DIR_STANDALONE, false }, + { "for", nullptr, nullptr, PRAGMA_OMP_FOR, + C_OMP_DIR_CONSTRUCT, true }, + /* { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP, + C_OMP_DIR_STANDALONE, false }, */ + { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP, + C_OMP_DIR_CONSTRUCT, true }, + /* { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED, + C_OMP_DIR_CONSTRUCT, true }, */ + { "master", nullptr, nullptr, PRAGMA_OMP_MASTER, + C_OMP_DIR_CONSTRUCT, true }, + /* { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE, + C_OMP_DIR_???, ??? }, */ + /* { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING, + C_OMP_DIR_UTILITY, false }, */ + /* ordered with depend clause is C_OMP_DIR_STANDALONE. */ + { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED, + C_OMP_DIR_CONSTRUCT, true }, + { "parallel", nullptr, nullptr, PRAGMA_OMP_PARALLEL, + C_OMP_DIR_CONSTRUCT, true }, + { "requires", nullptr, nullptr, PRAGMA_OMP_REQUIRES, + C_OMP_DIR_INFORMATIONAL, false }, + { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN, + C_OMP_DIR_CONSTRUCT, true }, + /* { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE, + C_OMP_DIR_CONSTRUCT, false }, */ + { "section", nullptr, nullptr, PRAGMA_OMP_SECTION, + C_OMP_DIR_CONSTRUCT, false }, + { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS, + C_OMP_DIR_CONSTRUCT, false }, + { "simd", nullptr, nullptr, PRAGMA_OMP_SIMD, + C_OMP_DIR_CONSTRUCT, true }, + { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE, + C_OMP_DIR_CONSTRUCT, false }, + { "target", "data", nullptr, PRAGMA_OMP_TARGET, + C_OMP_DIR_CONSTRUCT, false }, + { "target", "enter", "data", PRAGMA_OMP_TARGET, + C_OMP_DIR_STANDALONE, false }, + { "target", "exit", "data", PRAGMA_OMP_TARGET, + C_OMP_DIR_STANDALONE, false }, + { "target", "update", nullptr, PRAGMA_OMP_TARGET, + C_OMP_DIR_STANDALONE, false }, + { "target", nullptr, nullptr, PRAGMA_OMP_TARGET, + C_OMP_DIR_CONSTRUCT, true }, + { "task", nullptr, nullptr, PRAGMA_OMP_TASK, + C_OMP_DIR_CONSTRUCT, false }, + { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP, + C_OMP_DIR_CONSTRUCT, false }, + { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP, + C_OMP_DIR_CONSTRUCT, true }, + { "taskwait", nullptr, nullptr, PRAGMA_OMP_TASKWAIT, + C_OMP_DIR_STANDALONE, false }, + { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD, + C_OMP_DIR_STANDALONE, false }, + /* { "tile", nullptr, nullptr, PRAGMA_OMP_TILE, + C_OMP_DIR_CONSTRUCT, false }, */ + { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS, + C_OMP_DIR_CONSTRUCT, true }, + { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE, + C_OMP_DIR_DECLARATIVE, false } + /* { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL, + C_OMP_DIR_CONSTRUCT, false }, */ +}; + +/* Find (non-combined/composite) OpenMP directive (if any) which starts + with FIRST keyword and for multi-word directives has SECOND and + THIRD keyword after it. */ + +const struct c_omp_directive * +c_omp_categorize_directive (const char *first, const char *second, + const char *third) +{ + const size_t n_omp_directives = ARRAY_SIZE (omp_directives); + for (size_t i = 0; i < n_omp_directives; i++) + { + if ((unsigned char) omp_directives[i].first[0] + < (unsigned char) first[0]) + continue; + if ((unsigned char) omp_directives[i].first[0] + > (unsigned char) first[0]) + break; + if (strcmp (omp_directives[i].first, first)) + continue; + if (!omp_directives[i].second) + return &omp_directives[i]; + if (!second || strcmp (omp_directives[i].second, second)) + continue; + if (!omp_directives[i].third) + return &omp_directives[i]; + if (!third || strcmp (omp_directives[i].third, third)) + continue; + return &omp_directives[i]; + } + return NULL; +} diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 58da746..b450157 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -176,6 +176,7 @@ enum cp_tree_index CPTI_HEAP_DELETED_IDENTIFIER, CPTI_HEAP_VEC_UNINIT_IDENTIFIER, CPTI_HEAP_VEC_IDENTIFIER, + CPTI_OMP_IDENTIFIER, CPTI_LANG_NAME_C, CPTI_LANG_NAME_CPLUSPLUS, @@ -337,6 +338,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; #define heap_deleted_identifier cp_global_trees[CPTI_HEAP_DELETED_IDENTIFIER] #define heap_vec_uninit_identifier cp_global_trees[CPTI_HEAP_VEC_UNINIT_IDENTIFIER] #define heap_vec_identifier cp_global_trees[CPTI_HEAP_VEC_IDENTIFIER] +#define omp_identifier cp_global_trees[CPTI_OMP_IDENTIFIER] #define lang_name_c cp_global_trees[CPTI_LANG_NAME_C] #define lang_name_cplusplus cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS] diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7672947..ebe1318 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4387,6 +4387,7 @@ initialize_predefined_identifiers (void) {"heap deleted", &heap_deleted_identifier, cik_normal}, {"heap [] uninit", &heap_vec_uninit_identifier, cik_normal}, {"heap []", &heap_vec_identifier, cik_normal}, + {"omp", &omp_identifier, cik_normal}, {NULL, NULL, cik_normal} }; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 090a83b..9564b0d 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1584,6 +1584,31 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags) cp_check_const_attributes (attributes); + if ((flag_openmp || flag_openmp_simd) && attributes != error_mark_node) + { + bool diagnosed = false; + for (tree *pa = &attributes; *pa; ) + { + if (get_attribute_namespace (*pa) == omp_identifier) + { + tree name = get_attribute_name (*pa); + if (is_attribute_p ("directive", name) + || is_attribute_p ("sequence", name)) + { + if (!diagnosed) + { + error ("% not allowed to be specified in this " + "context", name); + diagnosed = true; + } + *pa = TREE_CHAIN (*pa); + continue; + } + } + pa = &TREE_CHAIN (*pa); + } + } + if (TREE_CODE (*decl) == TEMPLATE_DECL) decl = &DECL_TEMPLATE_RESULT (*decl); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 3550cd0..93698aa 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1,4 +1,3 @@ - /* -*- C++ -*- Parser. Copyright (C) 2000-2021 Free Software Foundation, Inc. Written by Mark Mitchell . @@ -4061,6 +4060,14 @@ cp_parser_skip_to_pragma_eol (cp_parser* parser, cp_token *pragma_tok) /* Ensure that the pragma is not parsed again. */ cp_lexer_purge_tokens_after (parser->lexer, pragma_tok); parser->lexer->in_pragma = false; + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_EOF)) + { + parser->lexer = parser->lexer->next; + /* Put the current source position back where it was before this + lexer was pushed. */ + cp_lexer_set_source_position_from_token (parser->lexer->next_token); + } } } @@ -4073,6 +4080,14 @@ cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok) parser->lexer->in_pragma = false; if (!cp_parser_require (parser, CPP_PRAGMA_EOL, RT_PRAGMA_EOL)) cp_parser_skip_to_pragma_eol (parser, pragma_tok); + else if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_EOF)) + { + parser->lexer = parser->lexer->next; + /* Put the current source position back where it was before this + lexer was pushed. */ + cp_lexer_set_source_position_from_token (parser->lexer->next_token); + } } /* This is a simple wrapper around make_typename_type. When the id is @@ -11631,6 +11646,187 @@ add_debug_begin_stmt (location_t loc) add_stmt (stmt); } +struct cp_omp_attribute_data +{ + cp_token_cache *tokens; + const c_omp_directive *dir; + c_omp_directive_kind kind; +}; + +/* Handle omp::directive and omp::sequence attributes in ATTRS + (if any) at the start of a statement. */ + +static tree +cp_parser_handle_statement_omp_attributes (cp_parser *parser, tree attrs) +{ + if (!flag_openmp && !flag_openmp_simd) + return attrs; + + auto_vec vec; + int cnt = 0; + int tokens = 0; + for (tree *pa = &attrs; *pa; ) + if (get_attribute_namespace (*pa) == omp_identifier + && is_attribute_p ("directive", get_attribute_name (*pa))) + { + cnt++; + for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a)) + { + tree d = TREE_VALUE (a); + gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); + cp_token *first = DEFPARSE_TOKENS (d)->first; + cp_token *last = DEFPARSE_TOKENS (d)->last; + const char *directive[3] = {}; + for (int i = 0; i < 3; i++) + { + tree id = NULL_TREE; + if (first + i == last) + break; + if (first[i].type == CPP_NAME) + id = first[i].u.value; + else if (first[i].type == CPP_KEYWORD) + id = ridpointers[(int) first[i].keyword]; + else + break; + directive[i] = IDENTIFIER_POINTER (id); + } + const c_omp_directive *dir = NULL; + if (directive[0]) + dir = c_omp_categorize_directive (directive[0], directive[1], + directive[2]); + if (dir == NULL) + { + error_at (first->location, + "unknown OpenMP directive name in %" + " attribute argument"); + continue; + } + c_omp_directive_kind kind = dir->kind; + if (dir->id == PRAGMA_OMP_ORDERED) + { + /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain + depend clause. */ + if (directive[1] && strcmp (directive[1], "depend") == 0) + kind = C_OMP_DIR_STANDALONE; + else if (first + 2 < last + && first[1].type == CPP_COMMA + && first[2].type == CPP_NAME + && strcmp (IDENTIFIER_POINTER (first[2].u.value), + "depend") == 0) + kind = C_OMP_DIR_STANDALONE; + } + /* else if (dir->id == PRAGMA_OMP_ERROR) + { + error with at(execution) clause is C_OMP_DIR_STANDALONE. + } */ + cp_omp_attribute_data v = { DEFPARSE_TOKENS (d), dir, kind }; + vec.safe_push (v); + if (flag_openmp || dir->simd) + tokens += (last - first) + 1; + } + cp_omp_attribute_data v = {}; + vec.safe_push (v); + *pa = TREE_CHAIN (*pa); + } + else + pa = &TREE_CHAIN (*pa); + + unsigned int i; + cp_omp_attribute_data *v; + cp_omp_attribute_data *construct_seen = nullptr; + cp_omp_attribute_data *standalone_seen = nullptr; + cp_omp_attribute_data *prev_standalone_seen = nullptr; + FOR_EACH_VEC_ELT (vec, i, v) + if (v->tokens) + { + if (v->kind == C_OMP_DIR_CONSTRUCT && !construct_seen) + construct_seen = v; + else if (v->kind == C_OMP_DIR_STANDALONE && !standalone_seen) + standalone_seen = v; + } + else + { + if (standalone_seen && !prev_standalone_seen) + { + prev_standalone_seen = standalone_seen; + standalone_seen = nullptr; + } + } + + if (cnt > 1 && construct_seen) + { + error_at (construct_seen->tokens->first->location, + "OpenMP construct among % attributes" + " requires all % attributes on the" + " same statement to be in the same %"); + return attrs; + } + if (cnt > 1 && standalone_seen && prev_standalone_seen) + { + error_at (standalone_seen->tokens->first->location, + "multiple OpenMP standalone directives among" + " % attributes must be all within the" + " same %"); + return attrs; + } + + if (prev_standalone_seen) + standalone_seen = prev_standalone_seen; + if (standalone_seen + && !cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + { + error_at (standalone_seen->tokens->first->location, + "standalone OpenMP directives in % attribute" + " can only appear on an empty statement"); + return attrs; + } + + if (!tokens) + return attrs; + tokens++; + cp_lexer *lexer = cp_lexer_alloc (); + lexer->debugging_p = parser->lexer->debugging_p; + vec_safe_reserve (lexer->buffer, tokens, true); + FOR_EACH_VEC_ELT (vec, i, v) + { + if (!v->tokens) + continue; + if (!flag_openmp && !v->dir->simd) + continue; + cp_token *first = v->tokens->first; + cp_token *last = v->tokens->last; + cp_token tok = {}; + tok.type = CPP_PRAGMA; + tok.keyword = RID_MAX; + tok.u.value = build_int_cst (NULL, v->dir->id); + tok.location = first->location; + lexer->buffer->quick_push (tok); + while (++first < last) + lexer->buffer->quick_push (*first); + tok = {}; + tok.type = CPP_PRAGMA_EOL; + tok.keyword = RID_MAX; + tok.location = last->location; + lexer->buffer->quick_push (tok); + } + cp_token tok = {}; + tok.type = CPP_EOF; + tok.keyword = RID_MAX; + tok.location = lexer->buffer->last ().location; + lexer->buffer->quick_push (tok); + lexer->next = parser->lexer; + lexer->next_token = lexer->buffer->address (); + lexer->last_token = lexer->next_token + + lexer->buffer->length () + - 1; + lexer->in_omp_attribute_pragma = true; + parser->lexer = lexer; + /* Move the current source position to that of the first token in the + new lexer. */ + cp_lexer_set_source_position_from_token (lexer->next_token); + return attrs; +} + /* Parse a statement. statement: @@ -11681,8 +11877,10 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, tree statement, std_attrs = NULL_TREE; cp_token *token; location_t statement_location, attrs_loc; + bool in_omp_attribute_pragma; restart: + in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; if (if_p != NULL) *if_p = false; /* There is no statement yet. */ @@ -11704,6 +11902,9 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, std_attrs = NULL_TREE; } + if (std_attrs && (flag_openmp || flag_openmp_simd)) + std_attrs = cp_parser_handle_statement_omp_attributes (parser, std_attrs); + /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* Remember the location of the first token in the statement. */ @@ -11821,6 +12022,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, a statement all its own. */ else if (token->type == CPP_PRAGMA) { + cp_lexer *lexer = parser->lexer; + bool do_restart = false; /* Only certain OpenMP pragmas are attached to statements, and thus are considered statements themselves. All others are not. In the context of a compound, accept the pragma as a "statement" and @@ -11829,6 +12032,13 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, if (in_compound) cp_parser_pragma (parser, pragma_compound, if_p); else if (!cp_parser_pragma (parser, pragma_stmt, if_p)) + do_restart = true; + if (lexer->in_omp_attribute_pragma && !in_omp_attribute_pragma) + { + gcc_assert (parser->lexer != lexer); + cp_lexer_destroy (lexer); + } + if (do_restart) goto restart; return; } @@ -27935,6 +28145,92 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */) return nreverse (attribute_list); } +/* Parse arguments of omp::directive attribute. + + ( directive-name ,[opt] clause-list[opt] ) + + For directive just remember the first/last tokens for subsequent + parsing. */ + +static void +cp_parser_omp_directive_args (cp_parser *parser, tree attribute) +{ + cp_token *first = cp_lexer_peek_nth_token (parser->lexer, 2); + if (first->type == CPP_CLOSE_PAREN) + { + cp_lexer_consume_token (parser->lexer); + error_at (first->location, "expected OpenMP directive name"); + cp_lexer_consume_token (parser->lexer); + TREE_VALUE (attribute) = NULL_TREE; + return; + } + for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 2; n; --n) + cp_lexer_consume_token (parser->lexer); + cp_token *last = cp_lexer_peek_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + tree arg = make_node (DEFERRED_PARSE); + DEFPARSE_TOKENS (arg) = cp_token_cache_new (first, last); + DEFPARSE_INSTANTIATIONS (arg) = nullptr; + TREE_VALUE (attribute) = tree_cons (NULL_TREE, arg, TREE_VALUE (attribute)); +} + +/* Parse arguments of omp::sequence attribute. + + ( omp::[opt] directive-attr [ , omp::[opt] directive-attr ]... ) */ + +static void +cp_parser_omp_sequence_args (cp_parser *parser, tree attribute) +{ + matching_parens parens; + parens.consume_open (parser); + do + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_NAME + && token->u.value == omp_identifier + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_SCOPE)) + { + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + token = cp_lexer_peek_token (parser->lexer); + } + bool directive = false; + const char *p; + if (token->type != CPP_NAME) + p = ""; + else + p = IDENTIFIER_POINTER (token->u.value); + if (strcmp (p, "directive") == 0) + directive = true; + else if (strcmp (p, "sequence") != 0) + { + error_at (token->location, "expected % or %"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/true, + /*consume_paren=*/false); + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) + break; + cp_lexer_consume_token (parser->lexer); + } + cp_lexer_consume_token (parser->lexer); + if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) + cp_parser_required_error (parser, RT_OPEN_PAREN, false, + UNKNOWN_LOCATION); + else if (directive) + cp_parser_omp_directive_args (parser, attribute); + else + cp_parser_omp_sequence_args (parser, attribute); + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) + break; + cp_lexer_consume_token (parser->lexer); + } + while (1); + if (!parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, true, false, + /*consume_paren=*/true); +} + /* Parse a standard C++11 attribute. The returned representation is a TREE_LIST which TREE_PURPOSE is @@ -28066,7 +28362,18 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) /* Now parse the optional argument clause of the attribute. */ if (token->type != CPP_OPEN_PAREN) - return attribute; + { + if ((flag_openmp || flag_openmp_simd) + && attr_ns == omp_identifier + && (is_attribute_p ("directive", attr_id) + || is_attribute_p ("sequence", attr_id))) + { + error_at (token->location, "% attribute requires argument", + attr_id); + return NULL_TREE; + } + return attribute; + } { vec *vec; @@ -28093,6 +28400,23 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) if (as == NULL) { + if ((flag_openmp || flag_openmp_simd) && attr_ns == omp_identifier) + { + if (is_attribute_p ("directive", attr_id)) + { + cp_parser_omp_directive_args (parser, attribute); + return attribute; + } + else if (is_attribute_p ("sequence", attr_id)) + { + TREE_VALUE (TREE_PURPOSE (attribute)) + = get_identifier ("directive"); + cp_parser_omp_sequence_args (parser, attribute); + TREE_VALUE (attribute) = nreverse (TREE_VALUE (attribute)); + return attribute; + } + } + /* For unknown attributes, just skip balanced tokens instead of trying to parse the arguments. */ for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; n; --n) @@ -38675,7 +38999,12 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, if (nested && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) break; - if (!first) + if (!first + /* OpenMP 5.1 allows optional comma in between directive-name and + clauses everywhere, but as we aren't done with OpenMP 5.0 + implementation yet, let's allow it for now only in C++11 + attributes. */ + || (parser->lexer->in_omp_attribute_pragma && nested != 2)) { if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) cp_lexer_consume_token (parser->lexer); @@ -39080,6 +39409,12 @@ cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok) location_t loc = pragma_tok->location; tree nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE); + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { matching_parens parens; @@ -39171,7 +39506,8 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { - if (!first + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if ((!first || parser->lexer->in_omp_attribute_pragma) && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); @@ -39735,6 +40071,10 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) tree clause = NULL_TREE; enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE; location_t c_loc = cp_lexer_peek_token (parser->lexer)->location; + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -39815,6 +40155,11 @@ static void cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok) { enum memmodel mo = MEMMODEL_LAST; + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -41175,10 +41520,16 @@ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, enum pragma_context context, bool *if_p) { location_t loc = pragma_tok->location; + int n = 1; - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + n = 2; + + if (cp_lexer_nth_token_is (parser->lexer, n, CPP_NAME)) { - tree id = cp_lexer_peek_token (parser->lexer)->u.value; + tree id = cp_lexer_peek_nth_token (parser->lexer, n)->u.value; const char *p = IDENTIFIER_POINTER (id); if (strcmp (p, "depend") == 0) @@ -43020,6 +43371,7 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok, data.error_seen = false; data.fndecl_seen = false; data.variant_p = variant_p; + data.in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; data.tokens = vNULL; data.clauses = NULL_TREE; /* It is safe to take the address of a local variable; it will only be @@ -43458,7 +43810,7 @@ cp_parser_omp_context_selector_specification (cp_parser *parser, static tree cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, - tree attrs) + tree attrs, bool in_omp_attribute_pragma) { matching_parens parens; if (!parens.require_open (parser)) @@ -43516,6 +43868,12 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, location_t finish_loc = get_finish (varid.get_location ()); location_t varid_loc = make_location (caret_loc, start_loc, finish_loc); + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); + const char *clause = ""; location_t match_loc = cp_lexer_peek_token (parser->lexer)->location; if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) @@ -43588,6 +43946,12 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs) cp_lexer_consume_token (parser->lexer); if (strcmp (kind, "simd") == 0) { + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (data->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); + cl = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, "#pragma omp declare simd", pragma_tok); @@ -43602,7 +43966,9 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs) else { gcc_assert (strcmp (kind, "variant") == 0); - attrs = cp_finish_omp_declare_variant (parser, pragma_tok, attrs); + attrs + = cp_finish_omp_declare_variant (parser, pragma_tok, attrs, + data->in_omp_attribute_pragma); } cp_parser_pop_lexer (parser); } @@ -43633,7 +43999,11 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) tree clauses = NULL_TREE; int device_type = 0; bool only_device_type = true; - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME) + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + || (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))) clauses = cp_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK, "#pragma omp declare target", pragma_tok); @@ -43812,6 +44182,12 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser) if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) return false; + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); + const char *p = ""; if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { @@ -44246,7 +44622,10 @@ cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok) location_t loc = pragma_tok->location; while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { - if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if ((!first || parser->lexer->in_omp_attribute_pragma) + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); first = false; diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index a468b69..5ef7047 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -113,6 +113,10 @@ struct GTY (()) cp_lexer { /* True if we're in the context of parsing a pragma, and should not increment past the end-of-line marker. */ bool in_pragma; + + /* True if we're in the context of OpenMP directives written as C++11 + attributes turned into pragma. */ + bool in_omp_attribute_pragma; }; @@ -208,6 +212,8 @@ struct cp_omp_declare_simd_data { bool error_seen; /* Set if error has been reported. */ bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */ bool variant_p; /* Set for #pragma omp declare variant. */ + bool in_omp_attribute_pragma; /* True if declare simd/variant comes from + C++11 attribute rather than pragma. */ vec tokens; tree clauses; }; diff --git a/gcc/testsuite/g++.dg/gomp/attrs-1.C b/gcc/testsuite/g++.dg/gomp/attrs-1.C new file mode 100644 index 0000000..c2734a1 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/attrs-1.C @@ -0,0 +1,553 @@ +// { dg-do compile { target c++11 } } + +typedef enum omp_allocator_handle_t +: __UINTPTR_TYPE__ +{ + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, + omp_low_lat_mem_alloc = 5, + omp_cgroup_mem_alloc = 6, + omp_pteam_mem_alloc = 7, + omp_thread_mem_alloc = 8, + __omp_allocator_handle_t_max__ = __UINTPTR_MAX__ +} omp_allocator_handle_t; + +typedef enum omp_sync_hint_t { +omp_sync_hint_none = 0x0, +omp_lock_hint_none = omp_sync_hint_none, +omp_sync_hint_uncontended = 0x1, +omp_lock_hint_uncontended = omp_sync_hint_uncontended, +omp_sync_hint_contended = 0x2, +omp_lock_hint_contended = omp_sync_hint_contended, +omp_sync_hint_nonspeculative = 0x4, +omp_lock_hint_nonspeculative = omp_sync_hint_nonspeculative, +omp_sync_hint_speculative = 0x8, +omp_lock_hint_speculative = omp_sync_hint_speculative +} omp_sync_hint_t; + +typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t { + char __omp_depend_t__[2 * sizeof (void *)]; +} omp_depend_t; + +int t; +#pragma omp threadprivate (t) + +#pragma omp declare target +int f, l, ll, r, r2; + +void +foo (int d, int m, int i1, int i2, int p, int *idp, int s, + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int ntm) +{ + [[omp::directive (distribute parallel for + private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) schedule(static, 4) order(concurrent) allocate (omp_default_mem_alloc:f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (distribute parallel for simd + private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) + if (parallel: i2) if(simd: i1) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) schedule(static, 4) nontemporal(ntm) + safelen(8) simdlen(4) aligned(q: 32) order(concurrent) allocate (omp_default_mem_alloc:f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (distribute simd + private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) + safelen(8) simdlen(4) aligned(q: 32) reduction(+:r) if(i1) nontemporal(ntm) + order(concurrent) allocate (omp_default_mem_alloc:f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (distribute + private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) + allocate (omp_default_mem_alloc:f))]] + for (int i = 0; i < 64; i++) + ll++; +} + +void +qux (int p) +{ + [[omp::directive (loop bind(teams) order(concurrent) + private (p) lastprivate (l) collapse(1) reduction(+:r))]] + for (l = 0; l < 64; ++l) + ll++; +} +#pragma omp end declare target + +void +baz (int d, int m, int i1, int i2, int p, int *idp, int s, + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int ntm) +{ + [[omp::directive (distribute parallel for + private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) schedule(static, 4) copyin(t) order(concurrent) allocate (p))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (distribute parallel for simd + private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) + if (parallel: i2) if(simd: i1) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) schedule(static, 4) nontemporal(ntm) + safelen(8) simdlen(4) aligned(q: 32) copyin(t) order(concurrent) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (distribute simd + private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) + safelen(8) simdlen(4) aligned(q: 32) reduction(+:r) if(i1) nontemporal(ntm) + order(concurrent) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (loop bind(parallel) order(concurrent) + private (p) lastprivate (l) collapse(1) reduction(+:r))]] + for (l = 0; l < 64; ++l) + ll++; +} + +void +bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm) +{ + [[omp::directive (for simd + private (p) firstprivate (f) lastprivate (l) linear (ll:1) reduction(+:r) schedule(static, 4) collapse(1) nowait + safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) if(i1) order(concurrent) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (for + private (p) firstprivate (f) lastprivate (l) linear (ll:1) reduction(+:r) schedule(static, 4) collapse(1) nowait + order(concurrent) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (simd + private (p) lastprivate (l) linear (ll:1) reduction(+:r) collapse(1) safelen(8) simdlen(4) aligned(q: 32) + nontemporal(ntm) if(i1) order(concurrent))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel for + private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) linear (ll:1) ordered schedule(static, 4) collapse(1) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel for + private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) order(concurrent) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel for simd + private (p) firstprivate (f) if (i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) + safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) order(concurrent) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel sections + private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) allocate (f))]] + { + #pragma omp section + {} + #pragma omp section + {} + } + [[omp::directive (sections private (p) firstprivate (f) reduction(+:r) lastprivate (l) allocate (f) nowait)]] + { + ; + #pragma omp section + ; + #pragma omp section + {} + } + [[omp::directive (barrier)]]; + [[omp::sequence (omp::directive (single private (p) firstprivate (f) allocate (f) nowait))]] + ; + [[omp::sequence (directive (barrier))]]; + [[omp::sequence (directive (parallel private (p)), + omp::directive (single copyprivate (p) firstprivate (f) allocate (f)))]] + p = 6; + [[omp::directive (target parallel + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) + nowait depend(inout: dd[0]) allocate (omp_default_mem_alloc:f) in_reduction(+:r2))]] + ; + [[omp::directive (target parallel for + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) linear (ll:1) ordered schedule(static, 4) collapse(1) nowait depend(inout: dd[0]) + allocate (omp_default_mem_alloc:f) in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (target parallel for + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) nowait depend(inout: dd[0]) order(concurrent) + allocate (omp_default_mem_alloc:f) in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (omp::directive (target parallel for simd + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) + safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) if (simd: i3) order(concurrent) + allocate (omp_default_mem_alloc:f) in_reduction(+:r2)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (target teams + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) nowait depend(inout: dd[0]) + allocate (omp_default_mem_alloc:f) in_reduction(+:r2)))]] + ; + [[omp::sequence (directive (target + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + nowait depend(inout: dd[0]) allocate (omp_default_mem_alloc:f) in_reduction(+:r2)))]] + ; + [[omp::sequence (omp::directive (target teams distribute + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) dist_schedule(static, 16) nowait depend(inout: dd[0]) allocate (omp_default_mem_alloc:f) in_reduction(+:r2)))]] + for (int i = 0; i < 64; i++) + ; + [[omp::directive (target teams distribute parallel for + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) dist_schedule(static, 16) + if (parallel: i2) num_threads (nth) proc_bind(spread) + lastprivate (l) schedule(static, 4) nowait depend(inout: dd[0]) order(concurrent) + allocate (omp_default_mem_alloc:f) in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (target teams distribute parallel for simd + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) dist_schedule(static, 16) + if (parallel: i2) num_threads (nth) proc_bind(spread) + lastprivate (l) schedule(static, 4) order(concurrent) + safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) if (simd: i3) + allocate (omp_default_mem_alloc:f) in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (target teams distribute simd + device(d) map (tofrom: m) if (i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) dist_schedule(static, 16) order(concurrent) + safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) + allocate (omp_default_mem_alloc:f) in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (target simd + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + safelen(8) simdlen(4) lastprivate (l) linear(ll: 1) aligned(q: 32) reduction(+:r) + nowait depend(inout: dd[0]) nontemporal(ntm) if(simd:i3) order(concurrent) + allocate (omp_default_mem_alloc:f) in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (taskgroup task_reduction(+:r2) allocate (r2)), + omp::directive (taskloop simd + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) + order(concurrent) allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (omp::directive (taskgroup task_reduction(+:r) allocate (r)), + directive (taskloop simd + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(i1) final(fi) mergeable nogroup priority (pp) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) in_reduction(+:r) nontemporal(ntm) + order(concurrent) allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (taskwait)]]; + [[omp::directive (taskloop simd + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) if(taskloop: i1) final(fi) priority (pp) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(+:r) if (simd: i3) nontemporal(ntm) + order(concurrent) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (taskgroup task_reduction(+:r2) allocate (r2)), + omp::directive (taskloop + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) final(fi) mergeable priority (pp) + reduction(default, +:r) in_reduction(+:r2) allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (taskgroup task_reduction(+:r2) allocate (r2)), + omp::directive (task + private (p) firstprivate (f) shared (s) default(shared) untied if(task: i1) final(fi) mergeable priority (pp) + in_reduction(+:r2) allocate (f)))]] + ; + [[omp::directive (taskyield)]]; + [[omp::directive (target data if (target data: i1) device(d) map (tofrom: m) use_device_ptr (q) use_device_addr (p))]] + ; + [[omp::directive (target enter data if (target enter data: i1) device(d) map (to: m) depend(inout: dd[0]) nowait)]] + ; + [[omp::directive (target exit data if (target exit data: i1) device(d) map (from: m) depend(inout: dd[0]) nowait)]] + ; + [[omp::directive (target update if (target update: i1) device(d) to (m) depend(inout: dd[0]) nowait)]] + ; + [[omp::directive (target update if (target update: i1) device(d) from (m) depend(inout: dd[0]) nowait)]] + ; + [[omp::directive (taskwait)]]; + [[omp::sequence (directive (target nowait depend(inout: dd[0]) in_reduction(+:r2)), + directive (teams distribute + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) dist_schedule(static, 16) allocate (omp_default_mem_alloc: f)))]] + for (int i = 0; i < 64; i++) + ; + [[omp::directive (teams + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + allocate (omp_default_mem_alloc: f))]] + ; + [[omp::sequence (omp::directive (target), + omp::directive (teams distribute parallel for + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) dist_schedule(static, 16) + if (parallel: i2) num_threads (nth) proc_bind(spread) + lastprivate (l) schedule(static, 4) order(concurrent) allocate (omp_default_mem_alloc: f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (target), + directive (teams distribute parallel for simd + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) dist_schedule(static, 16) + if (parallel: i2) num_threads (nth) proc_bind(spread) + lastprivate (l) schedule(static, 4) order(concurrent) + safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm) + allocate (omp_default_mem_alloc: f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (target), + directive (teams distribute simd + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) dist_schedule(static, 16) order(concurrent) + safelen(8) simdlen(4) aligned(q: 32) if(i3) nontemporal(ntm) + allocate (omp_default_mem_alloc: f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (teams distribute parallel for + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) dist_schedule(static, 16) order(concurrent) + if (parallel: i2) num_threads (nth) proc_bind(spread) + lastprivate (l) schedule(static, 4) copyin(t) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (teams distribute parallel for simd + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) dist_schedule(static, 16) + if (parallel: i2) num_threads (nth) proc_bind(spread) + lastprivate (l) schedule(static, 4) order(concurrent) + safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm) copyin(t) + allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (teams distribute simd + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) dist_schedule(static, 16) order(concurrent) + safelen(8) simdlen(4) aligned(q: 32) if(i3) nontemporal(ntm) allocate(f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel master + private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) reduction(+:r) + num_threads (nth) proc_bind(spread) copyin(t) allocate (f))]] + ; + [[omp::directive (parallel + private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) reduction(+:r) + num_threads (nth) proc_bind(spread) copyin(t) allocate (f))]] + ; + [[omp::sequence (directive (taskgroup task_reduction (+:r2) allocate (r2)), + omp::directive (master taskloop + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) final(fi) mergeable priority (pp) + reduction(default, +:r) in_reduction(+:r2) allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (master)]]; + [[omp::sequence (omp::directive (taskgroup task_reduction (+:r2) allocate (r2)), + directive (master taskloop simd + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) + order(concurrent) allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel master taskloop + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) final(fi) mergeable priority (pp) + reduction(default, +:r) if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel master taskloop simd + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) nontemporal(ntm) if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t) + order(concurrent) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (taskgroup task_reduction (+:r2) allocate (r2)), + directive (master taskloop + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) + reduction(default, +:r) in_reduction(+:r2)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (omp::directive (taskgroup task_reduction (+:r2) allocate (r2)), + omp::directive (master taskloop simd + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) + order(concurrent) allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel master taskloop + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) + reduction(default, +:r) num_threads (nth) proc_bind(spread) copyin(t) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel master taskloop simd + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) nontemporal(ntm) num_threads (nth) proc_bind(spread) copyin(t) + order(concurrent) allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (loop bind(thread) order(concurrent) + private (p) lastprivate (l) collapse(1) reduction(+:r))]] + for (l = 0; l < 64; ++l) + ll++; + [[omp::directive (parallel loop + private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) collapse(1) bind(parallel) order(concurrent) allocate (f))]] + for (l = 0; l < 64; l++) + ll++; + [[omp::directive (parallel loop + private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) + lastprivate (l) collapse(1) allocate (f))]] + for (l = 0; l < 64; l++) + ll++; + [[omp::directive (teams loop + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) lastprivate (l) bind(teams) allocate (f))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (teams loop + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) + collapse(1) lastprivate (l) order(concurrent) allocate (f))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (target parallel loop + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) + nowait depend(inout: dd[0]) lastprivate (l) bind(parallel) order(concurrent) collapse(1) + allocate (omp_default_mem_alloc: f) in_reduction(+:r2))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (target parallel loop + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) + nowait depend(inout: dd[0]) lastprivate (l) order(concurrent) collapse(1) + allocate (omp_default_mem_alloc: f) in_reduction(+:r2))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (target teams loop + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) nowait depend(inout: dd[0]) + lastprivate (l) bind(teams) collapse(1) + allocate (omp_default_mem_alloc: f) in_reduction(+:r2))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (target teams loop + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) + shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) nowait depend(inout: dd[0]) + lastprivate (l) order(concurrent) collapse(1) + allocate (omp_default_mem_alloc: f) in_reduction(+:r2))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (critical)]] { + } + [[omp::directive (critical (foobar) hint(omp_sync_hint_none))]] + ; + [[omp::directive (taskwait depend (inout: dd[0]))]] + ; + [[omp::directive (taskgroup task_reduction(+:r2) allocate (r2))]] + ; + [[omp::directive (atomic update seq_cst hint(omp_sync_hint_none))]] + p++; + [[omp::directive (atomic read hint(omp_sync_hint_none) relaxed)]] + f = p; + [[omp::directive (atomic write release hint(omp_sync_hint_none))]] + p = f; + [[omp::directive (flush)]] + ; + [[omp::directive (flush acq_rel)]] + ; + [[omp::directive (flush (p, f))]] + ; + [[omp::directive (simd + private (p) lastprivate (l) linear (ll:1) reduction(+:r) collapse(1) safelen(8) simdlen(4) aligned(q: 32) + nontemporal(ntm) if(i1))]] + for (int i = 0; i < 64; i++) + [[omp::directive (ordered simd)]] + ll++; + [[omp::directive (for + private (p) firstprivate (f) lastprivate (l) linear (ll:1) reduction(+:r) schedule(static, 4) collapse(1) nowait + ordered allocate (f))]] + for (int i = 0; i < 64; i++) + [[omp::directive (ordered threads)]] + ll++; + [[omp::directive(for ordered (1))]] + for (l = 0; l < 64; l++) + { + [[omp::directive(ordered depend (sink: l - 1))]]; + [[omp::directive(ordered depend (source))]]; + } + extern omp_depend_t depobj; + [[omp::directive (depobj(depobj) depend(in : dd[0]))]]; + [[omp::directive (parallel)]] { + if (p) { + [[omp::directive (cancel parallel)]]; + } else { + [[omp::directive (cancellation point parallel)]]; + } + } + extern int t2; + [[omp::directive (threadprivate (t2))]] + extern int t2; + [[omp::directive (declare reduction (dr: int: omp_out += omp_in) initializer (omp_priv = 0))]] + ; +} + +void corge1 (); + +void +corge () +{ + [[omp::directive (declare variant (corge1) match (construct={parallel,for}))]] + extern void corge2 (); + [[omp::sequence (directive (parallel), directive (for))]] + for (int i = 0; i < 5; i++) + corge2 (); + [[omp::directive (declare simd simdlen(4) linear(l) aligned(p:4) uniform(p) inbranch), + omp::directive (declare simd simdlen(8) notinbranch)]] + extern int corge3 (int l, int *p); + [[omp::directive (declare simd simdlen(4) linear(l) aligned(p:4) uniform(p) inbranch), + directive (declare simd simdlen(8) notinbranch)]] + extern int corge4 (int l, int *p); + [[omp::sequence (directive (declare simd simdlen(4) linear(l) aligned(p:4) uniform(p) inbranch), + omp::directive (declare simd simdlen(8) notinbranch))]] + extern int corge5 (int l, int *p); + [[omp::directive (declare target)]]; + extern void corge6 (); + [[omp::directive (end declare target)]]; +} + +int +garply (int a, int *c, int *d, int *e, int *f) +{ + int i; + [[omp::directive (simd reduction (inscan, +: a))]] + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan exclusive (a) + a += c[i]; + } + [[omp::directive (simd reduction (inscan, +: a))]] + for (i = 0; i < 64; i++) + { + a += c[i]; + #pragma omp scan inclusive (a) + d[i] = a; + } + return a; +} diff --git a/gcc/testsuite/g++.dg/gomp/attrs-2.C b/gcc/testsuite/g++.dg/gomp/attrs-2.C new file mode 100644 index 0000000..1eb6263 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/attrs-2.C @@ -0,0 +1,553 @@ +// { dg-do compile { target c++17 } } + +typedef enum omp_allocator_handle_t +: __UINTPTR_TYPE__ +{ + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, + omp_low_lat_mem_alloc = 5, + omp_cgroup_mem_alloc = 6, + omp_pteam_mem_alloc = 7, + omp_thread_mem_alloc = 8, + __omp_allocator_handle_t_max__ = __UINTPTR_MAX__ +} omp_allocator_handle_t; + +typedef enum omp_sync_hint_t { +omp_sync_hint_none = 0x0, +omp_lock_hint_none = omp_sync_hint_none, +omp_sync_hint_uncontended = 0x1, +omp_lock_hint_uncontended = omp_sync_hint_uncontended, +omp_sync_hint_contended = 0x2, +omp_lock_hint_contended = omp_sync_hint_contended, +omp_sync_hint_nonspeculative = 0x4, +omp_lock_hint_nonspeculative = omp_sync_hint_nonspeculative, +omp_sync_hint_speculative = 0x8, +omp_lock_hint_speculative = omp_sync_hint_speculative +} omp_sync_hint_t; + +typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t { + char __omp_depend_t__[2 * sizeof (void *)]; +} omp_depend_t; + +int t; +#pragma omp threadprivate (t) + +#pragma omp declare target +int f, l, ll, r, r2; + +void +foo (int d, int m, int i1, int i2, int p, int *idp, int s, + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int ntm) +{ + [[omp::directive (distribute parallel for, + private (p),firstprivate (f),collapse(1),dist_schedule(static, 16), + if (parallel: i2),default(shared),shared(s),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),schedule(static, 4),order(concurrent),allocate (omp_default_mem_alloc:f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (distribute parallel for simd, + private (p),firstprivate (f),collapse(1),dist_schedule(static, 16), + if (parallel: i2),if(simd: i1),default(shared),shared(s),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),schedule(static, 4),nontemporal(ntm), + safelen(8),simdlen(4),aligned(q: 32),order(concurrent),allocate (omp_default_mem_alloc:f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (distribute simd, + private (p),firstprivate (f),collapse(1),dist_schedule(static, 16), + safelen(8),simdlen(4),aligned(q: 32),reduction(+:r),if(i1),nontemporal(ntm), + order(concurrent),allocate (omp_default_mem_alloc:f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (distribute, + private (p),firstprivate (f),collapse(1),dist_schedule(static, 16), + allocate (omp_default_mem_alloc:f))]] + for (int i = 0; i < 64; i++) + ll++; +} + +void +qux (int p) +{ + [[omp::directive (loop, bind(teams),order(concurrent), + private (p),lastprivate (l),collapse(1),reduction(+:r))]] + for (l = 0; l < 64; ++l) + ll++; +} +#pragma omp end declare target + +void +baz (int d, int m, int i1, int i2, int p, int *idp, int s, + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int ntm) +{ + [[omp::directive (distribute parallel for, + private (p),firstprivate (f),collapse(1),dist_schedule(static, 16), + if (parallel: i2),default(shared),shared(s),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),schedule(static, 4),copyin(t),order(concurrent),allocate (p))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (distribute parallel for simd, + private (p),firstprivate (f),collapse(1),dist_schedule(static, 16), + if (parallel: i2),if(simd: i1),default(shared),shared(s),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),schedule(static, 4),nontemporal(ntm), + safelen(8),simdlen(4),aligned(q: 32),copyin(t),order(concurrent),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (distribute simd, + private (p),firstprivate (f),collapse(1),dist_schedule(static, 16), + safelen(8),simdlen(4),aligned(q: 32),reduction(+:r),if(i1),nontemporal(ntm), + order(concurrent),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (loop, bind(parallel),order(concurrent), + private (p),lastprivate (l),collapse(1),reduction(+:r))]] + for (l = 0; l < 64; ++l) + ll++; +} + +void +bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm) +{ + [[omp::directive (for simd, + private (p),firstprivate (f),lastprivate (l),linear (ll:1),reduction(+:r),schedule(static, 4),collapse(1),nowait, + safelen(8),simdlen(4),aligned(q: 32),nontemporal(ntm),if(i1),order(concurrent),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (for, + private (p),firstprivate (f),lastprivate (l),linear (ll:1),reduction(+:r),schedule(static, 4),collapse(1),nowait, + order(concurrent),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (simd, + private (p),lastprivate (l),linear (ll:1),reduction(+:r),collapse(1),safelen(8),simdlen(4),aligned(q: 32), + nontemporal(ntm),if(i1),order(concurrent))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel for, + private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),copyin(t),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),linear (ll:1),ordered schedule(static, 4),collapse(1),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel for, + private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),copyin(t),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),linear (ll:1),schedule(static, 4),collapse(1),order(concurrent),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel for simd, + private (p),firstprivate (f),if (i2),default(shared),shared(s),copyin(t),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),linear (ll:1),schedule(static, 4),collapse(1), + safelen(8),simdlen(4),aligned(q: 32),nontemporal(ntm),order(concurrent),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel sections, + private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),copyin(t),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),allocate (f))]] + { + #pragma omp section + {} + #pragma omp section + {} + } + [[omp::directive (sections, private (p),firstprivate (f),reduction(+:r),lastprivate (l),allocate (f),nowait)]] + { + ; + #pragma omp section + ; + #pragma omp section + {} + } + [[omp::directive (barrier)]]; + [[using omp:sequence (omp::directive (single, private (p),firstprivate (f),allocate (f),nowait))]] + ; + [[omp::sequence (directive (barrier))]]; + [[using omp:sequence (directive (parallel, private (p)), + omp::directive (single, copyprivate (p),firstprivate (f),allocate (f)))]] + p = 6; + [[omp::directive (target parallel, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + if (parallel: i2),default(shared),shared(s),reduction(+:r),num_threads (nth),proc_bind(spread) + nowait depend(inout: dd[0]),allocate (omp_default_mem_alloc:f),in_reduction(+:r2))]] + ; + [[omp::directive (target parallel for, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + if (parallel: i2),default(shared),shared(s),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),linear (ll:1),ordered schedule(static, 4),collapse(1),nowait depend(inout: dd[0]), + allocate (omp_default_mem_alloc:f),in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[using omp:directive (target parallel for, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + if (parallel: i2),default(shared),shared(s),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),linear (ll:1),schedule(static, 4),collapse(1),nowait depend(inout: dd[0]),order(concurrent), + allocate (omp_default_mem_alloc:f),in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (omp::directive (target parallel for simd, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + if (parallel: i2),default(shared),shared(s),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),linear (ll:1),schedule(static, 4),collapse(1), + safelen(8),simdlen(4),aligned(q: 32),nowait depend(inout: dd[0]),nontemporal(ntm),if (simd: i3),order(concurrent), + allocate (omp_default_mem_alloc:f),in_reduction(+:r2)))]] + for (int i = 0; i < 64; i++) + ll++; + [[using omp:sequence (directive (target teams, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl),nowait, depend(inout: dd[0]), + allocate (omp_default_mem_alloc:f) in_reduction(+:r2)))]] + ; + [[using omp:sequence (directive (target, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + nowait depend(inout: dd[0]),allocate (omp_default_mem_alloc:f),in_reduction(+:r2)))]] + ; + [[omp::sequence (omp::directive (target teams distribute, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),dist_schedule(static, 16),nowait depend(inout: dd[0]),allocate (omp_default_mem_alloc:f),in_reduction(+:r2)))]] + for (int i = 0; i < 64; i++) + ; + [[omp::directive (target teams distribute parallel for, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),dist_schedule(static, 16), + if (parallel: i2),num_threads (nth),proc_bind(spread), + lastprivate (l),schedule(static, 4),nowait depend(inout: dd[0]),order(concurrent), + allocate (omp_default_mem_alloc:f),in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (target teams distribute parallel for simd, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),dist_schedule(static, 16), + if (parallel: i2),num_threads (nth),proc_bind(spread), + lastprivate (l),schedule(static, 4),order(concurrent), + safelen(8),simdlen(4),aligned(q: 32),nowait depend(inout: dd[0]),nontemporal(ntm),if (simd: i3), + allocate (omp_default_mem_alloc:f),in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (target teams distribute simd, + device(d),map (tofrom: m),if (i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),dist_schedule(static, 16),order(concurrent), + safelen(8),simdlen(4),aligned(q: 32),nowait depend(inout: dd[0]),nontemporal(ntm), + allocate (omp_default_mem_alloc:f),in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (target simd, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + safelen(8),simdlen(4),lastprivate (l),linear(ll: 1),aligned(q: 32),reduction(+:r), + nowait depend(inout: dd[0]),nontemporal(ntm),if(simd:i3),order(concurrent), + allocate (omp_default_mem_alloc:f),in_reduction(+:r2))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (taskgroup, task_reduction(+:r2), allocate (r2)), + omp::directive (taskloop simd, + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),grainsize (g),collapse(1),untied,if(taskloop: i1),if(simd: i2),final(fi),mergeable,priority (pp), + safelen(8),simdlen(4),linear(ll: 1),aligned(q: 32),reduction(default, +:r),in_reduction(+:r2),nontemporal(ntm), + order(concurrent),allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[using omp:sequence (omp::directive (taskgroup, task_reduction(+:r), allocate (r)), + directive (taskloop simd, + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),grainsize (g),collapse(1),untied,if(i1),final(fi),mergeable,nogroup,priority (pp), + safelen(8),simdlen(4),linear(ll: 1),aligned(q: 32),in_reduction(+:r),nontemporal(ntm), + order(concurrent),allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (taskwait)]]; + [[omp::directive (taskloop simd, + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),num_tasks (nta),collapse(1),if(taskloop: i1),final(fi),priority (pp) + safelen(8),simdlen(4),linear(ll: 1),aligned(q: 32),reduction(+:r),if (simd: i3),nontemporal(ntm), + order(concurrent),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (taskgroup, task_reduction(+:r2), allocate (r2)), + omp::directive (taskloop + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),grainsize (g),collapse(1),untied, if(taskloop: i1),final(fi),mergeable, priority (pp), + reduction(default, +:r),in_reduction(+:r2),allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (taskgroup, task_reduction(+:r2),allocate (r2)), + omp::directive (task, + private (p),firstprivate (f),shared (s),default(shared),untied,if(task: i1),final(fi),mergeable,priority (pp), + in_reduction(+:r2),allocate (f)))]] + ; + [[omp::directive (taskyield)]]; + [[omp::directive (target data, if (target data: i1),device(d),map (tofrom: m),use_device_ptr (q),use_device_addr (p))]] + ; + [[omp::directive (target enter data, if (target enter data: i1),device(d),map (to: m),depend(inout: dd[0]),nowait)]] + ; + [[omp::directive (target exit data, if (target exit data: i1),device(d),map (from: m),depend(inout: dd[0]),nowait)]] + ; + [[omp::directive (target update, if (target update: i1),device(d),to (m),depend(inout: dd[0]),nowait)]] + ; + [[omp::directive (target update, if (target update: i1),device(d),from (m),depend(inout: dd[0]),nowait)]] + ; + [[omp::directive (taskwait)]]; + [[omp::sequence (directive (target, nowait,depend(inout: dd[0]),in_reduction(+:r2)), + directive (teams distribute, + private(p),firstprivate (f),shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),dist_schedule(static, 16),allocate (omp_default_mem_alloc: f)))]] + for (int i = 0; i < 64; i++) + ; + [[omp::directive (teams, + private(p),firstprivate (f),shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + allocate (omp_default_mem_alloc: f))]] + ; + [[omp::sequence (omp::directive (target), + omp::directive (teams distribute parallel for, + private(p),firstprivate (f),shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),dist_schedule(static, 16), + if (parallel: i2),num_threads (nth),proc_bind(spread), + lastprivate (l),schedule(static, 4),order(concurrent),allocate (omp_default_mem_alloc: f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[using omp:sequence (directive (target), + directive (teams distribute parallel for simd, + private(p),firstprivate (f),shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),dist_schedule(static, 16), + if (parallel: i2),num_threads (nth),proc_bind(spread), + lastprivate (l),schedule(static, 4),order(concurrent), + safelen(8),simdlen(4),aligned(q: 32),if (simd: i3),nontemporal(ntm), + allocate (omp_default_mem_alloc: f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (target), + directive (teams distribute simd, + private(p),firstprivate (f),shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),dist_schedule(static, 16),order(concurrent), + safelen(8),simdlen(4),aligned(q: 32),if(i3),nontemporal(ntm), + allocate (omp_default_mem_alloc: f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (teams distribute parallel for, + private(p),firstprivate (f),shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),dist_schedule(static, 16),order(concurrent), + if (parallel: i2),num_threads (nth),proc_bind(spread), + lastprivate (l),schedule(static, 4),copyin(t),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (teams distribute parallel for simd, + private(p),firstprivate (f),shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),dist_schedule(static, 16), + if (parallel: i2),num_threads (nth),proc_bind(spread), + lastprivate (l),schedule(static, 4),order(concurrent), + safelen(8),simdlen(4),aligned(q: 32),if (simd: i3),nontemporal(ntm),copyin(t), + allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (teams distribute simd, + private(p),firstprivate (f),shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),dist_schedule(static, 16),order(concurrent), + safelen(8),simdlen(4),aligned(q: 32),if(i3),nontemporal(ntm),allocate(f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel master, + private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),reduction(+:r), + num_threads (nth),proc_bind(spread),copyin(t),allocate (f))]] + ; + [[omp::directive (parallel, + private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),reduction(+:r), + num_threads (nth),proc_bind(spread),copyin(t),allocate (f))]] + ; + [[using omp:sequence (directive (taskgroup, task_reduction (+:r2),allocate (r2)), + omp::directive (master taskloop, + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),grainsize (g),collapse(1),untied, if(taskloop: i1),final(fi),mergeable, priority (pp), + reduction(default, +:r),in_reduction(+:r2),allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[using omp:directive (master)]]; + [[omp::sequence (omp::directive (taskgroup task_reduction (+:r2),allocate (r2)), + directive (master taskloop simd, + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),grainsize (g),collapse(1),untied,if(taskloop: i1),if(simd: i2),final(fi),mergeable,priority (pp), + safelen(8),simdlen(4),linear(ll: 1),aligned(q: 32),reduction(default, +:r),in_reduction(+:r2),nontemporal(ntm), + order(concurrent),allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel master taskloop, + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),grainsize (g),collapse(1),untied,if(taskloop: i1),final(fi),mergeable,priority (pp), + reduction(default, +:r),if (parallel: i2),num_threads (nth),proc_bind(spread),copyin(t),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel master taskloop simd, + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),grainsize (g),collapse(1),untied,if(taskloop: i1),if(simd: i2),final(fi),mergeable,priority (pp), + safelen(8),simdlen(4),linear(ll: 1),aligned(q: 32),reduction(default, +:r),nontemporal(ntm),if (parallel: i2),num_threads (nth),proc_bind(spread),copyin(t), + order(concurrent),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (directive (taskgroup,task_reduction (+:r2),allocate (r2)), + directive (master taskloop, + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),num_tasks (nta),collapse(1),untied,if(i1),final(fi),mergeable,priority (pp), + reduction(default, +:r),in_reduction(+:r2)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::sequence (omp::directive (taskgroup,task_reduction (+:r2),allocate (r2)), + omp::directive (master taskloop simd, + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),num_tasks (nta),collapse(1),untied,if(i1),final(fi),mergeable,priority (pp), + safelen(8),simdlen(4),linear(ll: 1),aligned(q: 32),reduction(default, +:r),in_reduction(+:r2),nontemporal(ntm), + order(concurrent),allocate (f)))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel master taskloop, + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),num_tasks (nta),collapse(1),untied if(i1),final(fi),mergeable priority (pp), + reduction(default, +:r),num_threads (nth),proc_bind(spread),copyin(t),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (parallel master taskloop simd, + private (p),firstprivate (f),lastprivate (l),shared (s),default(shared),num_tasks (nta),collapse(1),untied if(i1),final(fi),mergeable priority (pp), + safelen(8),simdlen(4),linear(ll: 1),aligned(q: 32),reduction(default, +:r),nontemporal(ntm),num_threads (nth),proc_bind(spread),copyin(t), + order(concurrent),allocate (f))]] + for (int i = 0; i < 64; i++) + ll++; + [[omp::directive (loop, bind(thread),order(concurrent), + private (p),lastprivate (l),collapse(1),reduction(+:r))]] + for (l = 0; l < 64; ++l) + ll++; + [[omp::directive (parallel loop, + private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),copyin(t),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),collapse(1),bind(parallel),order(concurrent),allocate (f))]] + for (l = 0; l < 64; l++) + ll++; + [[omp::directive (parallel loop, + private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),copyin(t),reduction(+:r),num_threads (nth),proc_bind(spread), + lastprivate (l),collapse(1),allocate (f))]] + for (l = 0; l < 64; l++) + ll++; + [[omp::directive (teams loop, + private(p),firstprivate (f),shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),lastprivate (l),bind(teams),allocate (f))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (teams loop, + private(p),firstprivate (f),shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl), + collapse(1),lastprivate (l),order(concurrent),allocate (f))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (target parallel loop, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + if (parallel: i2),default(shared),shared(s),reduction(+:r),num_threads (nth),proc_bind(spread), + nowait depend(inout: dd[0]),lastprivate (l),bind(parallel),order(concurrent),collapse(1), + allocate (omp_default_mem_alloc: f),in_reduction(+:r2))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (target parallel loop, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + if (parallel: i2),default(shared),shared(s),reduction(+:r),num_threads (nth),proc_bind(spread), + nowait depend(inout: dd[0]),lastprivate (l),order(concurrent),collapse(1), + allocate (omp_default_mem_alloc: f),in_reduction(+:r2))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (target teams loop, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl),nowait,depend(inout: dd[0]), + lastprivate (l),bind(teams),collapse(1), + allocate (omp_default_mem_alloc: f),in_reduction(+:r2))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (target teams loop, + device(d),map (tofrom: m),if (target: i1),private (p),firstprivate (f),defaultmap(tofrom: scalar),is_device_ptr (idp), + shared(s),default(shared),reduction(+:r),num_teams(nte),thread_limit(tl),nowait,depend(inout: dd[0]), + lastprivate (l),order(concurrent),collapse(1) + allocate (omp_default_mem_alloc: f),in_reduction(+:r2))]] + for (l = 0; l < 64; ++l) + ; + [[omp::directive (critical)]] { + } + [[omp::directive (critical (foobar),hint(omp_sync_hint_none))]] + ; + [[using omp:directive (taskwait, depend (inout: dd[0]))]] + ; + [[omp::directive (taskgroup, task_reduction(+:r2),allocate (r2))]] + ; + [[omp::directive (atomic, update,seq_cst,hint(omp_sync_hint_none))]] + p++; + [[omp::directive (atomic, read, hint(omp_sync_hint_none),relaxed)]] + f = p; + [[omp::directive (atomic,write, release hint(omp_sync_hint_none))]] + p = f; + [[omp::directive (flush)]] + ; + [[omp::directive (flush, acq_rel)]] + ; + [[omp::directive (flush (p, f))]] + ; + [[omp::directive (simd, + private (p),lastprivate (l),linear (ll:1),reduction(+:r),collapse(1),safelen(8),simdlen(4),aligned(q: 32), + nontemporal(ntm),if(i1))]] + for (int i = 0; i < 64; i++) + [[omp::directive (ordered, simd)]] + ll++; + [[omp::directive (for, + private (p),firstprivate (f),lastprivate (l),linear (ll:1),reduction(+:r),schedule(static, 4),collapse(1),nowait, + ordered, allocate (f))]] + for (int i = 0; i < 64; i++) + [[omp::directive (ordered, threads)]] + ll++; + [[omp::directive(for, ordered (1))]] + for (l = 0; l < 64; l++) + { + [[omp::directive(ordered, depend (sink: l - 1))]]; + [[omp::directive(ordered, depend (source))]]; + } + extern omp_depend_t depobj; + [[omp::directive (depobj(depobj),depend(in : dd[0]))]]; + [[omp::directive (parallel)]] { + if (p) { + [[omp::directive (cancel, parallel)]]; + } else { + [[omp::directive (cancellation point, parallel)]]; + } + } + extern int t2; + [[omp::directive (threadprivate (t2))]] + extern int t2; + [[omp::directive (declare reduction (dr: int: omp_out += omp_in),initializer (omp_priv = 0))]] + ; +} + +void corge1 (); + +void +corge () +{ + [[omp::directive (declare variant (corge1),match (construct={parallel,for}))]] + extern void corge2 (); + [[omp::sequence (directive (parallel), directive (for))]] + for (int i = 0; i < 5; i++) + corge2 (); + [[omp::directive (declare simd, simdlen(4),linear(l),aligned(p:4),uniform(p),inbranch), + omp::directive (declare simd,simdlen(8),notinbranch)]] + extern int corge3 (int l, int *p); + [[using omp:directive (declare simd, simdlen(4),linear(l),aligned(p:4),uniform(p),inbranch), + directive (declare simd, simdlen(8),notinbranch)]] + extern int corge4 (int l, int *p); + [[omp::sequence (directive (declare simd, simdlen(4),linear(l),aligned(p:4),uniform(p),inbranch), + omp::directive (declare simd, simdlen(8),notinbranch))]] + extern int corge5 (int l, int *p); + [[omp::directive (declare target)]]; + extern void corge6 (); + [[omp::directive (end declare target)]]; +} + +int +garply (int a, int *c, int *d, int *e, int *f) +{ + int i; + [[omp::directive (simd, reduction (inscan, +: a))]] + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan exclusive (a) + a += c[i]; + } + [[omp::directive (simd, reduction (inscan, +: a))]] + for (i = 0; i < 64; i++) + { + a += c[i]; + #pragma omp scan inclusive (a) + d[i] = a; + } + return a; +} diff --git a/gcc/testsuite/g++.dg/gomp/attrs-3.C b/gcc/testsuite/g++.dg/gomp/attrs-3.C new file mode 100644 index 0000000..7aab637 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/attrs-3.C @@ -0,0 +1,40 @@ +// { dg-do compile { target c++11 } } + +int i; +int t1, t2, t3, t4, t5, t6, t7; + +void +foo () +{ + [[omp::directive]]; // { dg-error "'omp::directive' attribute requires argument" } + [[omp::directive ()]]; // { dg-error "expected OpenMP directive name" } + [[omp::directive (nonexistent foobar)]]; // { dg-error "unknown OpenMP directive name in 'omp::directive' attribute argument" } + [[omp::sequence]]; // { dg-error "'omp::sequence' attribute requires argument" } + [[omp::sequence()]]; // { dg-error "expected 'directive' or 'sequence'" } + [[omp::sequence(foobar())]]; // { dg-error "expected 'directive' or 'sequence'" } + [[omp::sequence(omp::foobar())]]; // { dg-error "expected 'directive' or 'sequence'" } + [[omp::sequence(directive(taskwait), foobar())]]; // { dg-error "expected 'directive' or 'sequence'" } + [[omp::sequence(omp::directive(taskwait), omp::foobar())]]; // { dg-error "expected 'directive' or 'sequence'" } + [[omp::sequence(directive(taskwait) foobar())]]; // { dg-error "expected '\\\)' before 'foobar'" } + [[omp::sequence(directive)]]; // { dg-error "expected '\\\(' before '\\\)' token" } + [[omp::sequence(omp::sequence)]]; // { dg-error "expected '\\\(' before '\\\)' token" } + [[omp::directive (parallel), omp::directive (single)]] // { dg-error "OpenMP construct among 'omp::directive' attributes requires all 'omp::directive' attributes on the same statement to be in the same 'omp::sequence'" } + ; + [[omp::directive (parallel)]] // { dg-error "OpenMP construct among 'omp::directive' attributes requires all 'omp::directive' attributes on the same statement to be in the same 'omp::sequence'" } + [[omp::directive (single)]] + ; + [[omp::directive (taskwait), omp::directive (taskyield)]] // { dg-error "multiple OpenMP standalone directives among 'omp::directive' attributes must be all within the same 'omp::sequence'" } + ; + [[omp::directive (taskwait)]] + [[omp::directive (taskyield)]] // { dg-error "multiple OpenMP standalone directives among 'omp::directive' attributes must be all within the same 'omp::sequence'" } + ; + [[omp::directive (flush)]] // { dg-error "standalone OpenMP directives in 'omp::directive' attribute can only appear on an empty statement" } + i++; + auto a = [] () [[omp::directive (threadprivate (t1))]] {}; // { dg-error "'omp::directive' not allowed to be specified in this context" } + int [[omp::directive (threadprivate (t2))]] b; // { dg-warning "attribute ignored" } + int *[[omp::directive (threadprivate (t3))]] c; // { dg-warning "'omp::directive' scoped attribute directive ignored" } + int &[[omp::directive (threadprivate (t4))]] d = b; // { dg-warning "'omp::directive' scoped attribute directive ignored" } + typedef int T [[omp::directive (threadprivate (t5))]]; // { dg-error "'omp::directive' not allowed to be specified in this context" } + int e[10] [[omp::directive (threadprivate (t6))]]; // { dg-error "'omp::directive' not allowed to be specified in this context" } + struct [[omp::directive (threadprivate (t7))]] S {}; // { dg-error "'omp::directive' not allowed to be specified in this context" } +} -- cgit v1.1 From 6feb628a706e86eb3f303aff388c74bdb29e7381 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 2 Jul 2021 16:16:31 -0600 Subject: Improve warning suppression for inlined functions [PR98512]. Resolves: PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute gcc/ChangeLog: PR middle-end/98871 PR middle-end/98512 * diagnostic.c (get_any_inlining_info): New. (update_effective_level_from_pragmas): Handle inlining context. (diagnostic_enabled): Same. (diagnostic_report_diagnostic): Same. * diagnostic.h (struct diagnostic_info): Add ctor. (struct diagnostic_context): Add new member. * tree-diagnostic.c (set_inlining_locations): New. (tree_diagnostics_defaults): Set new callback pointer. --- gcc/diagnostic.c | 122 ++++++++++++++++++++++++++++++++++++-------------- gcc/diagnostic.h | 23 ++++++++++ gcc/tree-diagnostic.c | 68 ++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+), 33 deletions(-) (limited to 'gcc') diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index d58586f..8361f68 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -991,51 +991,88 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc, pp_set_prefix (pp, saved_prefix); } -/* Update the diag_class of DIAGNOSTIC based on its location - relative to any +/* Update the inlining info in CONTEXT for a DIAGNOSTIC. */ + +static void +get_any_inlining_info (diagnostic_context *context, + diagnostic_info *diagnostic) +{ + auto &ilocs = diagnostic->m_iinfo.m_ilocs; + + if (context->set_locations_cb) + /* Retrieve the locations into which the expression about to be + diagnosed has been inlined, including those of all the callers + all the way down the inlining stack. */ + context->set_locations_cb (context, diagnostic); + else + { + /* When there's no callback use just the one location provided + by the caller of the diagnostic function. */ + location_t loc = diagnostic_location (diagnostic); + ilocs.safe_push (loc); + diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc); + } +} + +/* Update the kind of DIAGNOSTIC based on its location(s), including + any of those in its inlining stack, relative to any #pragma GCC diagnostic directives recorded within CONTEXT. - Return the new diag_class of DIAGNOSTIC if it was updated, or - DK_UNSPECIFIED otherwise. */ + Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED + otherwise. */ static diagnostic_t update_effective_level_from_pragmas (diagnostic_context *context, diagnostic_info *diagnostic) { - diagnostic_t diag_class = DK_UNSPECIFIED; - - if (context->n_classification_history > 0) + if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers) { - location_t location = diagnostic_location (diagnostic); + /* Ignore the diagnostic if all the inlined locations are + in system headers and -Wno-system-headers is in effect. */ + diagnostic->kind = DK_IGNORED; + return DK_IGNORED; + } + + if (context->n_classification_history <= 0) + return DK_UNSPECIFIED; + /* Iterate over the locations, checking the diagnostic disposition + for the diagnostic at each. If it's explicitly set as opposed + to unspecified, update the disposition for this instance of + the diagnostic and return it. */ + for (location_t loc: diagnostic->m_iinfo.m_ilocs) + { /* FIXME: Stupid search. Optimize later. */ for (int i = context->n_classification_history - 1; i >= 0; i --) { - if (linemap_location_before_p - (line_table, - context->classification_history[i].location, - location)) + const diagnostic_classification_change_t &hist + = context->classification_history[i]; + + location_t pragloc = hist.location; + if (!linemap_location_before_p (line_table, pragloc, loc)) + continue; + + if (hist.kind == (int) DK_POP) { - if (context->classification_history[i].kind == (int) DK_POP) - { - i = context->classification_history[i].option; - continue; - } - int option = context->classification_history[i].option; - /* The option 0 is for all the diagnostics. */ - if (option == 0 || option == diagnostic->option_index) - { - diag_class = context->classification_history[i].kind; - if (diag_class != DK_UNSPECIFIED) - diagnostic->kind = diag_class; - break; - } + /* Move on to the next region. */ + i = hist.option; + continue; + } + + int option = hist.option; + /* The option 0 is for all the diagnostics. */ + if (option == 0 || option == diagnostic->option_index) + { + diagnostic_t kind = hist.kind; + if (kind != DK_UNSPECIFIED) + diagnostic->kind = kind; + return kind; } } } - return diag_class; + return DK_UNSPECIFIED; } /* Generate a URL string describing CWE. The caller is responsible for @@ -1129,6 +1166,9 @@ static bool diagnostic_enabled (diagnostic_context *context, diagnostic_info *diagnostic) { + /* Update the inlining stack for this diagnostic. */ + get_any_inlining_info (context, diagnostic); + /* Diagnostics with no option or -fpermissive are always enabled. */ if (!diagnostic->option_index || diagnostic->option_index == permissive_error_option (context)) @@ -1194,9 +1234,17 @@ diagnostic_report_diagnostic (diagnostic_context *context, /* Give preference to being able to inhibit warnings, before they get reclassified to something else. */ - if ((diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN) - && !diagnostic_report_warnings_p (context, location)) - return false; + bool report_warning_p = true; + if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN) + { + if (context->dc_inhibit_warnings) + return false; + /* Remember the result of the overall system header warning setting + but proceed to also check the inlining context. */ + report_warning_p = diagnostic_report_warnings_p (context, location); + if (!report_warning_p && diagnostic->kind == DK_PEDWARN) + return false; + } if (diagnostic->kind == DK_PEDWARN) { @@ -1204,7 +1252,7 @@ diagnostic_report_diagnostic (diagnostic_context *context, /* We do this to avoid giving the message for -pedantic-errors. */ orig_diag_kind = diagnostic->kind; } - + if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p) return false; @@ -1228,9 +1276,19 @@ diagnostic_report_diagnostic (diagnostic_context *context, && diagnostic->kind == DK_WARNING) diagnostic->kind = DK_ERROR; + diagnostic->message.x_data = &diagnostic->x_data; + + /* Check to see if the diagnostic is enabled at the location and + not disabled by #pragma GCC diagnostic anywhere along the inlining + stack. . */ if (!diagnostic_enabled (context, diagnostic)) return false; + if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs) + /* Bail if the warning is not to be reported because all locations + in the inlining stack (if there is one) are in system headers. */ + return false; + if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE) diagnostic_check_max_errors (context); @@ -1270,8 +1328,6 @@ diagnostic_report_diagnostic (diagnostic_context *context, } context->diagnostic_group_emission_count++; - diagnostic->message.x_data = &diagnostic->x_data; - diagnostic->x_data = NULL; pp_format (context->printer, &diagnostic->message); (*diagnostic_starter (context)) (context, diagnostic); pp_output_formatted_text (context->printer); diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 086bc4f..7227dae 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -87,6 +87,11 @@ enum diagnostics_extra_output_kind list in diagnostic.def. */ struct diagnostic_info { + diagnostic_info () + : message (), richloc (), metadata (), x_data (), kind (), option_index (), + m_iinfo () + { } + /* Text to be formatted. */ text_info message; @@ -103,6 +108,18 @@ struct diagnostic_info diagnostic_t kind; /* Which OPT_* directly controls this diagnostic. */ int option_index; + + /* Inlining context containing locations for each call site along + the inlining stack. */ + struct inlining_info + { + /* Locations along the inlining stack. */ + auto_vec m_ilocs; + /* The abstract origin of the location. */ + void *m_ao; + /* Set if every M_ILOCS element is in a system header. */ + bool m_allsyslocs; + } m_iinfo; }; /* Each time a diagnostic's classification is changed with a pragma, @@ -346,6 +363,12 @@ struct diagnostic_context /* Callback for final cleanup. */ void (*final_cb) (diagnostic_context *context); + + /* Callback to set the locations of call sites along the inlining + stack corresponding to a diagnostic location. Needed to traverse + the BLOCK_SUPERCONTEXT() chain hanging off the LOCATION_BLOCK() + of a diagnostic's location. */ + void (*set_locations_cb)(diagnostic_context *, diagnostic_info *); }; static inline void diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c index 95b8ef3..1b636d7 100644 --- a/gcc/tree-diagnostic.c +++ b/gcc/tree-diagnostic.c @@ -305,6 +305,73 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec, return true; } +/* Set the locations of call sites along the inlining stack corresponding + to the DIAGNOSTIC location. */ + +static void +set_inlining_locations (diagnostic_context *, + diagnostic_info *diagnostic) +{ + location_t loc = diagnostic_location (diagnostic); + tree block = LOCATION_BLOCK (loc); + + /* Count the number of locations in system headers. When all are, + warnings are suppressed by -Wno-system-headers. Otherwise, they + involve some user code, possibly inlined into a function in a system + header, and are not treated as coming from system headers. */ + unsigned nsyslocs = 0; + + /* Use a reference to the vector of locations for convenience. */ + auto &ilocs = diagnostic->m_iinfo.m_ilocs; + + while (block && TREE_CODE (block) == BLOCK + && BLOCK_ABSTRACT_ORIGIN (block)) + { + tree ao = BLOCK_ABSTRACT_ORIGIN (block); + if (TREE_CODE (ao) == FUNCTION_DECL) + { + if (!diagnostic->m_iinfo.m_ao) + diagnostic->m_iinfo.m_ao = block; + + location_t bsloc = BLOCK_SOURCE_LOCATION (block); + ilocs.safe_push (bsloc); + if (in_system_header_at (bsloc)) + ++nsyslocs; + } + else if (TREE_CODE (ao) != BLOCK) + break; + + block = BLOCK_SUPERCONTEXT (block); + } + + if (ilocs.length ()) + { + /* When there is an inlining context use the macro expansion + location for the original location and bump up NSYSLOCS if + it's in a system header since it's not counted above. */ + location_t sysloc = expansion_point_location_if_in_system_header (loc); + if (sysloc != loc) + { + loc = sysloc; + ++nsyslocs; + } + } + else + { + /* When there's no inlining context use the original location + and set NSYSLOCS accordingly. */ + nsyslocs = in_system_header_at (loc) != 0; + } + + ilocs.safe_push (loc); + + /* Set if all locations are in a system header. */ + diagnostic->m_iinfo.m_allsyslocs = nsyslocs == ilocs.length (); + + if (tree *ao = pp_ti_abstract_origin (&diagnostic->message)) + *ao = (tree)diagnostic->m_iinfo.m_ao; +} + /* Sets CONTEXT to use language independent diagnostics. */ void tree_diagnostics_defaults (diagnostic_context *context) @@ -314,4 +381,5 @@ tree_diagnostics_defaults (diagnostic_context *context) diagnostic_format_decoder (context) = default_tree_printer; context->print_path = default_tree_diagnostic_path_printer; context->make_json_for_path = default_tree_make_json_for_path; + context->set_locations_cb = set_inlining_locations; } -- cgit v1.1 From c77230856eac2d28eb7bf10985846885c3c8727b Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sat, 3 Jul 2021 00:13:29 +0200 Subject: d: RHS value lost when a target_expr modifies LHS in a cond_expr To prevent the RHS of an assignment modifying the LHS before the assignment proper, a target_expr is forced so that function calls that return with slot optimization modify the temporary instead. This did not work for conditional expressions however, to give one example. So now the RHS is always forced to a temporary. PR d/101282 gcc/d/ChangeLog: * d-codegen.cc (build_assign): Force target_expr on RHS for non-POD assignment expressions. gcc/testsuite/ChangeLog: * gdc.dg/torture/pr101282.d: New test. --- gcc/d/d-codegen.cc | 7 +++++++ gcc/testsuite/gdc.dg/torture/pr101282.d | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 gcc/testsuite/gdc.dg/torture/pr101282.d (limited to 'gcc') diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index 9a94473..ce7c17b 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -1344,6 +1344,13 @@ build_assign (tree_code code, tree lhs, tree rhs) d_mark_addressable (lhs); CALL_EXPR_RETURN_SLOT_OPT (rhs) = true; } + /* If modifying an LHS whose type is marked TREE_ADDRESSABLE. */ + else if (code == MODIFY_EXPR && TREE_ADDRESSABLE (TREE_TYPE (lhs)) + && TREE_SIDE_EFFECTS (rhs) && TREE_CODE (rhs) != TARGET_EXPR) + { + /* LHS may be referenced by the RHS expression, so force a temporary. */ + rhs = force_target_expr (rhs); + } /* The LHS assignment replaces the temporary in TARGET_EXPR_SLOT. */ if (TREE_CODE (rhs) == TARGET_EXPR) diff --git a/gcc/testsuite/gdc.dg/torture/pr101282.d b/gcc/testsuite/gdc.dg/torture/pr101282.d new file mode 100644 index 0000000..b75d5fc --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/pr101282.d @@ -0,0 +1,23 @@ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101282 +// { dg-do run } + +void main() +{ + struct S101282 + { + int impl; + S101282 opUnary(string op : "-")() + { + return S101282(-impl); + } + int opCmp(int i) + { + return (impl < i) ? -1 : (impl > i) ? 1 : 0; + } + } + auto a = S101282(120); + a = -a; + assert(a.impl == -120); + a = a >= 0 ? a : -a; + assert(a.impl == 120); +} -- cgit v1.1 From 7a60a6e8b36dec960939494baef0f1f15dbfc450 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 3 Jul 2021 00:16:31 +0000 Subject: Daily bump. --- gcc/ChangeLog | 170 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/c-family/ChangeLog | 8 +++ gcc/c/ChangeLog | 6 ++ gcc/cp/ChangeLog | 53 +++++++++++++++ gcc/d/ChangeLog | 6 ++ gcc/testsuite/ChangeLog | 63 ++++++++++++++++++ 7 files changed, 307 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b514c21..8b003c6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,173 @@ +2021-07-02 Martin Sebor + + PR middle-end/98871 + PR middle-end/98512 + * diagnostic.c (get_any_inlining_info): New. + (update_effective_level_from_pragmas): Handle inlining context. + (diagnostic_enabled): Same. + (diagnostic_report_diagnostic): Same. + * diagnostic.h (struct diagnostic_info): Add ctor. + (struct diagnostic_context): Add new member. + * tree-diagnostic.c (set_inlining_locations): New. + (tree_diagnostics_defaults): Set new callback pointer. + +2021-07-02 Peter Bergner + + * config/rs6000/rs6000-builtin.def (BU_MMA_PAIR_LD, BU_MMA_PAIR_ST): + New macros. + (__builtin_vsx_lxvp, __builtin_vsx_stxvp): New built-ins. + * config/rs6000/rs6000-call.c (rs6000_gimple_fold_mma_builtin): Expand + lxvp and stxvp built-ins. + (mma_init_builtins): Handle lxvp and stxvp built-ins. + (builtin_function_type): Likewise. + * doc/extend.texi (__builtin_vsx_lxvp, __builtin_mma_stxvp): Document. + +2021-07-02 Jeff Law + + * config/h8300/h8300-protos.h (compute_a_shift_cc): Accept + additional argument for the code. + * config/h8300/h8300.c (compute_a_shift_cc): Accept additional + argument for the code. Just return if the ZN bits are useful or + not rather than the old style CC_* enums. + * config/h8300/shiftrotate.md (shiftqi_noscratch): Move before + more generic shiftqi patterns. + (shifthi_noscratch, shiftsi_noscratch): Similarly. + (shiftqi_noscratch_set_flags): New pattern. + (shifthi_noscratch_set_flags, shiftsi_noscratch_set_flags): Likewise. + +2021-07-02 Andrew MacLeod + + PR tree-optimization/101223 + * range-op.cc (build_lt): Add -1 for signed values. + (built_gt): Subtract -1 for signed values. + +2021-07-02 David Faust + + * btfout.c (get_btf_kind): Support BTF_KIND_FLOAT. + (btf_asm_type): Likewise. + +2021-07-02 Jeff Law + + * config/h8300/h8300-protos.h (output_a_shift): Make first argument + an array of rtx rather than a pointer to rtx. Add code argument. + (compute_a_shift_length): Similarly. + * config/h8300/h8300.c (h8300_shift_costs): Adjust now that the + shift itself isn't an operand. Create dummy operand[0] to carry + a mode and pass a suitable rtx code to compute_a_shift_length. + (get_shift_alg): Adjust operand number of clobber in output templates. + (output_a_shift): Make first argument an array of rtx rather than + a pointer to rtx. Add code argument for the type of shift. + Adjust now that the shift itself is no longer an operand. + (compute_a_shift_length): Similarly. + * config/h8300/shiftrotate.md (shiftqi, shifthi, shiftsi): Use an + iterator rather than nshift_operator. + (shiftqi_noscratch, shifthi_noscratch, shiftsi_noscratch): Likewise. + (shiftqi_clobber_flags): Adjust to API changes in output_a_shift + and compute_a_shift_length. + (shiftqi_noscratch_clobber_flags): Likewise. + (shifthi_noscratch_clobber_flags): Likewise. + (shiftsi_noscratch_clobber_flags): Likewise. + +2021-07-02 Iain Sandoe + + PR debug/101283 + * config/darwin.h (DSYMUTIL_SPEC): Do not try to run + dsymutil for BTF/CTF. + +2021-07-02 Iain Sandoe + + PR debug/101283 + * config/darwin.h (CTF_INFO_SECTION_NAME): Update the + segment to include BTF. + (BTF_INFO_SECTION_NAME): New. + +2021-07-02 Jeff Law + + * config/m32r/m32r-protos.h (call_operand): Adjust return type. + (small_data_operand, memreg_operand, small_insn_p): Likewise. + * config/m32r/m32r.c (call_operand): Adjust return type. + (small_data_operand, memreg_operand): Likewise. + +2021-07-02 Jeff Law + + * config/frv/frv-protos.h (integer_register_operand): Adjust return + type. + (frv_load_operand, gpr_or_fpr_operand, gpr_no_subreg_operand): Likewise. + (fpr_or_int6_operand, gpr_or_int_operand); Likewise. + (gpr_or_int12_operand, gpr_or_int10_operand); Likewise. + (move_source_operand, move_destination_operand): Likewise. + (condexec_source_operand, condexec_dest_operand): Likewise. + (lr_operand, gpr_or_memory_operand, fpr_or_memory_operand): Likewise. + (reg_or_0_operand, fcc_operand, icc_operand, cc_operand): Likewise. + (fcr_operand, icr_operand, cr_operand, call_operand): Likewise. + (fpr_operand, even_reg_operand, odd_reg_operand): Likewise. + (even_gpr_operand, odd_gpr_operand, quad_fpr_operand): Likewise. + (even_fpr_operand, odd_fpr_operand): Likewise. + (dbl_memory_one_insn_operand, dbl_memory_two_insn_operand): Likewise. + (int12_operand, int6_operand, int5_operand, uint5_operand): Likewise. + (uint4_operand, uint1_operand, int_2word_operand): Likewise + (upper_int16_operand, uint16_operand, symbolic_operand): Likewise. + (relational_operator, float_relational_operator): Likewise. + (ccr_eqne_operator, minmax_operator): Likewise. + (condexec_si_binary_operator, condexec_si_media_operator): Likewise. + (condexec_si_divide_operator, condexec_si_unary_operator): Likewise. + (condexec_sf_conv_operator, condexec_sf_add_operator): Likewise. + (intop_compare_operator, acc_operand, even_acc_operand): Likewise. + (quad_acc_operand, accg_operand): Likewise. + +2021-07-02 Jeff Law + + * config/stormy16/stormy16-protos.h (xstormy16_below_100_symbol): Change + return type to a bool. + (nonimmediate_nonstack_operand): Likewise. + (xstormy16_splittable_below100_operand): Likewise. + * config/stormy16/stormy16.c (xstormy16_below_100_symbol): Fix + return type. + (xstormy16_splittable_below100_operand): Likewise. + +2021-07-02 Richard Biener + + PR tree-optimization/101293 + * tree-ssa-loop-im.c (mem_ref_hasher::equal): Compare MEM_REF bases + with combined offsets. + (gather_mem_refs_stmt): Hash MEM_REFs as if their offset were + combined with the rest of the offset. + +2021-07-02 Eric Botcazou + + * config/i386/i386.c (asm_preferred_eh_data_format): Always use the + PIC encodings for PE-COFF targets. + +2021-07-02 Jakub Jelinek + + PR target/101286 + * config/i386/i386-expand.c (ix86_broadcast_from_integer_constant): + Return nullptr for TImode inner mode. + +2021-07-02 Richard Biener + + PR tree-optimization/101280 + PR tree-optimization/101173 + * gimple-loop-interchange.cc + (tree_loop_interchange::valid_data_dependences): Properly + guard all dependence checks with DDR_REVERSED_P or its + inverse. + +2021-07-02 Hongyu Wang + + * config/i386/i386-expand.c (ix86_expand_builtin): + Add branch to clear odata when ZF is set for asedecenc_expand + and wideaesdecenc_expand. + +2021-07-02 Eugene Rozenfeld + + * config/i386/gcc-auto-profile: regenerate + +2021-07-02 liuhongt + + * config/i386/sse.md (trunc2): Refined to .. + (trunc2): this. + 2021-07-01 David Malcolm * diagnostic.h (diagnostic_context::m_file_cache): New field. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7369508..7693fe4 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210702 +20210703 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index ae7cafc..cd01f5c 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,11 @@ +2021-07-02 Jakub Jelinek + + * c-common.h (enum c_omp_directive_kind): New enum. + (struct c_omp_directive): New type. + (c_omp_categorize_directive): Declare. + * c-omp.c (omp_directives): New variable. + (c_omp_categorize_directive): New function. + 2021-07-01 Eric Botcazou * c-ada-spec.c (packed_layout): New global variable. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index ba53da8..27d6e89 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2021-07-02 Jakub Jelinek + + PR c/101297 + * c-parser.c (c_parser_omp_atomic): Consume comma only if it + appears before a CPP_NAME. + 2021-06-25 Martin Sebor * c-decl.c (pop_scope): Replace direct uses of TREE_NO_WARNING with diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 13b009e..90a2d2a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,56 @@ +2021-07-02 Jakub Jelinek + + * parser.h (struct cp_lexer): Add in_omp_attribute_pragma member. + (struct cp_omp_declare_simd_data): Likewise. + * cp-tree.h (enum cp_tree_index): Add CPTI_OMP_IDENTIFIER. + (omp_identifier): Define. + * parser.c (cp_parser_skip_to_pragma_eol): Handle + in_omp_attribute_pragma CPP_PRAGMA_EOL followed by CPP_EOF. + (cp_parser_require_pragma_eol): Likewise. + (struct cp_omp_attribute_data): New type. + (cp_parser_handle_statement_omp_attributes): New function. + (cp_parser_statement): Handle OpenMP directives in statement's + attribute-specifier-seq. + (cp_parser_omp_directive_args, cp_parser_omp_sequence_args): New + functions. + (cp_parser_std_attribute): Handle omp::directive and omp::sequence + attributes. + (cp_parser_omp_all_clauses): If in_omp_attribute_pragma, allow + a comma also before the first clause. + (cp_parser_omp_allocate): Likewise. + (cp_parser_omp_atomic): Likewise. + (cp_parser_omp_depobj): Likewise. + (cp_parser_omp_flush): Likewise. + (cp_parser_omp_ordered): Likewise. + (cp_parser_omp_declare_simd): Save in_omp_attribute_pragma + into struct cp_omp_declare_simd_data. + (cp_finish_omp_declare_variant): Add in_omp_attribute_pragma + argument. If set, allow a comma also before match clause. + (cp_parser_late_parsing_omp_declare_simd): If in_omp_attribute_pragma, + allow a comma also before the first clause. Adjust + cp_finish_omp_declare_variant caller. + (cp_parser_omp_declare_target): If in_omp_attribute_pragma, allow + a comma also before the first clause. + (cp_parser_omp_declare_reduction_exprs): Likewise. + (cp_parser_omp_requires): Likewise. + * decl.c (initialize_predefined_identifiers): Initialize + omp_identifier. + * decl2.c (cplus_decl_attributes): Reject omp::directive and + omp::sequence attributes. + +2021-07-02 Jakub Jelinek + + PR c/101297 + * parser.c (cp_parser_omp_atomic): Consume comma only if it + appears before a CPP_NAME. + +2021-07-02 Patrick Palka + + PR c++/101247 + * pt.c (any_template_parm_r) : Rewrite to + use common_enclosing_class and to not depend on the TREE_TYPE + of outer levels pointing to the corresponding primary template. + 2021-07-01 Patrick Palka PR c++/101194 diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index eb17034..b6ace1e 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,9 @@ +2021-07-02 Iain Buclaw + + PR d/101282 + * d-codegen.cc (build_assign): Force target_expr on RHS for non-POD + assignment expressions. + 2021-06-11 Iain Buclaw PR d/100999 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fd699df..e18f267 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,66 @@ +2021-07-02 Iain Buclaw + + PR d/101282 + * gdc.dg/torture/pr101282.d: New test. + +2021-07-02 Jakub Jelinek + + * g++.dg/gomp/attrs-1.C: New test. + * g++.dg/gomp/attrs-2.C: New test. + * g++.dg/gomp/attrs-3.C: New test. + +2021-07-02 Jakub Jelinek + + PR c/101297 + * c-c++-common/gomp/atomic-24.c: New test. + +2021-07-02 Patrick Palka + + PR c++/101247 + * g++.dg/cpp2a/concepts-memtmpl4.C: New test. + +2021-07-02 Peter Bergner + + * gcc.target/powerpc/mma-builtin-7.c: New test. + * gcc.target/powerpc/mma-builtin-8.c: New test. + +2021-07-02 Andrew MacLeod + + PR tree-optimization/101223 + * gcc.dg/pr101223.c: New. + +2021-07-02 David Faust + + * gcc.dg/debug/btf/btf-float-1.c: New test. + * gcc.dg/debug/btf/btf-function-3.c: Use different unrepresentable type. + * gcc.dg/debug/btf/btf-struct-2.c: Likewise. + * gcc.dg/debug/btf/btf-variables-2.c: Likewise. + +2021-07-02 Maxim Kuvyrkov + + * lib/gcc-defs.exp: Add a comment. + +2021-07-02 Richard Biener + + PR tree-optimization/101293 + * gcc.dg/tree-ssa/ssa-lim-15.c: New testcase. + +2021-07-02 Jakub Jelinek + + PR target/101286 + * gcc.target/i386/avx2-pr101286.c: New test. + +2021-07-02 Hongyu Wang + + * gcc.target/i386/keylocker-aesdec128kl.c: Update test. + * gcc.target/i386/keylocker-aesdec256kl.c: Likewise. + * gcc.target/i386/keylocker-aesdecwide128kl.c: Likewise. + * gcc.target/i386/keylocker-aesdecwide256kl.c: Likewise. + * gcc.target/i386/keylocker-aesenc128kl.c: Likewise. + * gcc.target/i386/keylocker-aesenc256kl.c: Likewise. + * gcc.target/i386/keylocker-aesencwide128kl.c: Likewise. + * gcc.target/i386/keylocker-aesencwide256kl.c: Likewise. + 2021-07-01 Michael Meissner * gcc.target/powerpc/float128-cmove.c: New test. -- cgit v1.1 From 152f4d0e4d3b524ce30d05f20e23a44b0dd29765 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sat, 3 Jul 2021 02:42:14 +0200 Subject: d: Missed RVO optimization with non-POD structs The D front-end semantic pass sometimes declares a temporary inside a return expression. This is now detected with the RESULT_DECL replacing the temporary, allowing for RVO to be done. PR d/101273 gcc/d/ChangeLog: * toir.cc (IRVisitor::visit (ReturnStatement *)): Detect returns that use a temporary, and replace with return value. gcc/testsuite/ChangeLog: * gdc.dg/torture/pr101273.d: New test. --- gcc/d/toir.cc | 32 +++++++++++++++++++++++++-- gcc/testsuite/gdc.dg/torture/pr101273.d | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gdc.dg/torture/pr101273.d (limited to 'gcc') diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc index 41d07a7..eaee6f7 100644 --- a/gcc/d/toir.cc +++ b/gcc/d/toir.cc @@ -1034,14 +1034,37 @@ public: /* Detect a call to a constructor function, or if returning a struct literal, write result directly into the return value. */ StructLiteralExp *sle = NULL; + bool using_rvo_p = false; if (DotVarExp *dve = (s->exp->op == TOKcall && s->exp->isCallExp ()->e1->op == TOKdotvar ? s->exp->isCallExp ()->e1->isDotVarExp () : NULL)) { - sle = (dve->var->isCtorDeclaration () - ? dve->e1->isStructLiteralExp () : NULL); + if (dve->var->isCtorDeclaration ()) + { + if (CommaExp *ce = dve->e1->isCommaExp ()) + { + /* Temporary initialized inside a return expression, and + used as the return value. Replace it with the hidden + reference to allow RVO return. */ + DeclarationExp *de = ce->e1->isDeclarationExp (); + VarExp *ve = ce->e2->isVarExp (); + if (de != NULL && ve != NULL + && ve->var == de->declaration + && ve->var->storage_class & STCtemp) + { + tree var = get_symbol_decl (ve->var); + TREE_ADDRESSABLE (var) = 1; + SET_DECL_VALUE_EXPR (var, decl); + DECL_HAS_VALUE_EXPR_P (var) = 1; + SET_DECL_LANG_NRVO (var, this->func_->shidden); + using_rvo_p = true; + } + } + else + sle = dve->e1->isStructLiteralExp (); + } } else sle = s->exp->isStructLiteralExp (); @@ -1050,11 +1073,16 @@ public: { StructDeclaration *sd = type->baseElemOf ()->isTypeStruct ()->sym; sle->sym = build_address (this->func_->shidden); + using_rvo_p = true; /* Fill any alignment holes in the return slot using memset. */ if (!identity_compare_p (sd) || sd->isUnionDeclaration ()) add_stmt (build_memset_call (this->func_->shidden)); + } + if (using_rvo_p == true) + { + /* Generate: (expr, return ); */ add_stmt (build_expr_dtor (s->exp)); } else diff --git a/gcc/testsuite/gdc.dg/torture/pr101273.d b/gcc/testsuite/gdc.dg/torture/pr101273.d new file mode 100644 index 0000000..e300e03 --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/pr101273.d @@ -0,0 +1,39 @@ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101273 +// { dg-do run } + +struct S101273 +{ + int x; + S101273* impl; + this(int x) + { + this.x = x; + this.impl = &this; + } + ~this() { } +} + +S101273 makeS101273() +{ + return S101273(2); +} + +S101273 nrvo101273() +{ + S101273 ret = makeS101273(); + return ret; +} + +S101273 rvo101273() +{ + return makeS101273(); +} + +void main() +{ + auto nrvo = nrvo101273(); + assert(&nrvo is nrvo.impl); + + auto rvo = rvo101273(); + assert(&rvo is rvo.impl); +} -- cgit v1.1 From 52c3fdf3e4780f75297515d3c2a3dae9b36586ba Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Fri, 2 Jul 2021 10:03:48 -0700 Subject: Don't use vec_duplicate on vector in CTOR expansion Since vec_duplicate only works on scalar, don't use it on vector in store constructor expansion. gcc/ PR middle-end/101294 * expr.c (store_constructor): Don't use vec_duplicate on vector. gcc/testsuite/ PR middle-end/101294 * gcc.dg/pr101294.c: New test. --- gcc/expr.c | 3 ++- gcc/testsuite/gcc.dg/pr101294.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/pr101294.c (limited to 'gcc') diff --git a/gcc/expr.c b/gcc/expr.c index 025033c..bd85bbf 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -7078,7 +7078,8 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size, && eltmode == GET_MODE_INNER (mode) && ((icode = optab_handler (vec_duplicate_optab, mode)) != CODE_FOR_nothing) - && (elt = uniform_vector_p (exp))) + && (elt = uniform_vector_p (exp)) + && !VECTOR_TYPE_P (TREE_TYPE (elt))) { class expand_operand ops[2]; create_output_operand (&ops[0], target, mode); diff --git a/gcc/testsuite/gcc.dg/pr101294.c b/gcc/testsuite/gcc.dg/pr101294.c new file mode 100644 index 0000000..ca59b35 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101294.c @@ -0,0 +1,15 @@ +/* PR middle-end/101294 */ +/* { dg-do compile } */ +/* { dg-options "-O0" } */ +/* { dg-additional-options "-mavx" { target avx } } */ + +typedef __attribute__((__vector_size__ (sizeof (unsigned long long)))) unsigned long long U; +typedef __attribute__((__vector_size__ (4 * sizeof (unsigned long long)))) unsigned long long V; + +extern U x; + +void +foo (void) +{ + x = __builtin_shufflevector ((U){}, (V){}, 3); +} -- cgit v1.1 From 981351e87b7ad7a0660d4f3a34614172f3d8376b Mon Sep 17 00:00:00 2001 From: David Edelsohn Date: Thu, 1 Jul 2021 10:49:27 -0400 Subject: testsuite: Disable BTF and CTF testsuite on AIX. CTF utilizes DWARF sections, but it is a distinct debugging format. The CTF support in GCC is not implemented as a separate debugging format. AIX supports DWARF but not CTF section. The GCC testsuite test for target support of a debugging format checks if GCC itself emits an error message, not if the debugging output compiles correctly. Because CTF is not a distinct debugging format, GCC does not distinguish support for targets and does not have the ability to produce an error message. This patch skips the CTF and BTF debug directories, and explicitly reports that AIX doesn't support CTF. Currently the dejagnu code to skip multiple debugging levels for CTF does not ensure that CTF is a supported debugging format. The patch also shifts the CTF options logic to within the test that CTF debug format is supported. Bootstrapped on powerpc-ibm-aix7.2.3.0 and powerpc64le-linux. gcc/testsuite/ChangeLog: * gcc.dg/debug/btf/btf.exp: Skip on AIX. * gcc.dg/debug/ctf/ctf.exp: Skip on AIX. * lib/gcc-dg.exp (gcc-dg-target-supports-debug-format): AIX doesn't support CTF. (gcc-dg-debug-runtest): Move CTF support within target support format test. --- gcc/testsuite/gcc.dg/debug/btf/btf.exp | 5 ++++ gcc/testsuite/gcc.dg/debug/ctf/ctf.exp | 5 ++++ gcc/testsuite/lib/gcc-dg.exp | 45 +++++++++++++++++----------------- 3 files changed, 33 insertions(+), 22 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf.exp b/gcc/testsuite/gcc.dg/debug/btf/btf.exp index e72a2be..e173515 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf.exp +++ b/gcc/testsuite/gcc.dg/debug/btf/btf.exp @@ -24,6 +24,11 @@ if { [istarget nvptx-*-*] } { return } +if { [istarget "powerpc-ibm-aix*"] } { + set torture_execute_xfail "powerpc-ibm-aix*" + return +} + # If a testcase doesn't have special options, use these. global DEFAULT_CFLAGS if ![info exists DEFAULT_CFLAGS] then { diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp b/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp index 46055f8..0b650ed 100644 --- a/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp @@ -24,6 +24,11 @@ if { [istarget nvptx-*-*] } { return } +if { [istarget "powerpc-ibm-aix*"] } { + set torture_execute_xfail "powerpc-ibm-aix*" + return +} + # If a testcase doesn't have special options, use these. global DEFAULT_CFLAGS if ![info exists DEFAULT_CFLAGS] then { diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index 51d8a11..81f4bb2 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -641,6 +641,7 @@ proc gcc-dg-frontend-supports-ctf { target_compile trivial } { proc gcc-dg-target-supports-debug-format { target_compile trivial type } { global srcdir subdir + if {$type == "-gctf" && [istarget *-*-aix*]} { return 0 } set comp_output [$target_compile \ "$srcdir/$subdir/$trivial" "trivial.S" assembly \ "additional_flags=$type"] @@ -656,29 +657,29 @@ proc gcc-dg-debug-runtest { target_compile trivial opt_opts testcases } { if ![info exists DEBUG_TORTURE_OPTIONS] { set DEBUG_TORTURE_OPTIONS "" foreach type {-gctf -gdwarf-2 -gstabs -gstabs+ -gxcoff -gxcoff+} { - if { $type == "-gctf" } { - if [expr [gcc-dg-frontend-supports-ctf \ - $target_compile $trivial]] { - # At this time, running tests with various opt levels or - # ctf debug info levels does not add value. - lappend DEBUG_TORTURE_OPTIONS [list "${type}"] + if [expr [gcc-dg-target-supports-debug-format \ + $target_compile $trivial $type]] { + if { $type == "-gctf" } { + if [expr [gcc-dg-frontend-supports-ctf \ + $target_compile $trivial]] { + # At this time, running tests with various opt levels or + # ctf debug info levels does not add value. + lappend DEBUG_TORTURE_OPTIONS [list "${type}"] + } + continue } - } else { - if [expr [gcc-dg-target-supports-debug-format \ - $target_compile $trivial $type]] { - foreach level {1 "" 3} { - if { ($type == "-gdwarf-2") && ($level != "") } { - lappend DEBUG_TORTURE_OPTIONS [list "${type}" "-g${level}"] - foreach opt $opt_opts { - lappend DEBUG_TORTURE_OPTIONS \ - [list "${type}" "-g${level}" "$opt" ] - } - } else { - lappend DEBUG_TORTURE_OPTIONS [list "${type}${level}"] - foreach opt $opt_opts { - lappend DEBUG_TORTURE_OPTIONS \ - [list "${type}${level}" "$opt" ] - } + foreach level {1 "" 3} { + if { ($type == "-gdwarf-2") && ($level != "") } { + lappend DEBUG_TORTURE_OPTIONS [list "${type}" "-g${level}"] + foreach opt $opt_opts { + lappend DEBUG_TORTURE_OPTIONS \ + [list "${type}" "-g${level}" "$opt" ] + } + } else { + lappend DEBUG_TORTURE_OPTIONS [list "${type}${level}"] + foreach opt $opt_opts { + lappend DEBUG_TORTURE_OPTIONS \ + [list "${type}${level}" "$opt" ] } } } -- cgit v1.1 From e6f3adc899aa9c4d925406974b446634e0db9cd2 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sun, 4 Jul 2021 00:16:25 +0000 Subject: Daily bump. --- gcc/ChangeLog | 5 +++++ gcc/DATESTAMP | 2 +- gcc/d/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 19 +++++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8b003c6..d7a3b12 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2021-07-03 H.J. Lu + + PR middle-end/101294 + * expr.c (store_constructor): Don't use vec_duplicate on vector. + 2021-07-02 Martin Sebor PR middle-end/98871 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7693fe4..ea1d54a 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210703 +20210704 diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index b6ace1e..f0489c2 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,9 @@ +2021-07-03 Iain Buclaw + + PR d/101273 + * toir.cc (IRVisitor::visit (ReturnStatement *)): Detect returns that + use a temporary, and replace with return value. + 2021-07-02 Iain Buclaw PR d/101282 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e18f267..187a6ef 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,22 @@ +2021-07-03 David Edelsohn + + * gcc.dg/debug/btf/btf.exp: Skip on AIX. + * gcc.dg/debug/ctf/ctf.exp: Skip on AIX. + * lib/gcc-dg.exp (gcc-dg-target-supports-debug-format): AIX + doesn't support CTF. + (gcc-dg-debug-runtest): Move CTF support within + target support format test. + +2021-07-03 H.J. Lu + + PR middle-end/101294 + * gcc.dg/pr101294.c: New test. + +2021-07-03 Iain Buclaw + + PR d/101273 + * gdc.dg/torture/pr101273.d: New test. + 2021-07-02 Iain Buclaw PR d/101282 -- cgit v1.1 From d07092a61d5a6907b2d92563e810bf5bb8e61c01 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Fri, 30 Apr 2021 16:20:42 +0100 Subject: Darwin, config : Adjust X86 biarch definitions ordering [PR100269]. This reorganises the biarch definitions to cater for the macro changes and removals at r12-36. Signed-off-by: Iain Sandoe PR target/100269 - [12 Regression] i686 biarch compiler fails for Darwin after r12-36. PR target/100269 gcc/ChangeLog: PR target/100269 * config.gcc: Ensure that Darwin biarch definitions are added before i386.h. * config/i386/darwin.h (TARGET_64BIT): Remove. (PR80556_WORKAROUND): New. (REAL_LIBGCC_SPEC): Amend to use PR80556_WORKAROUND. (DARWIN_SUBARCH_SPEC): New. * config/i386/darwin32-biarch.h (TARGET_64BIT_DEFAULT, TARGET_BI_ARCH, PR80556_WORKAROUND): New. (REAL_LIBGCC_SPEC): Remove. * config/i386/darwin64-biarch.h (TARGET_64BIT_DEFAULT, TARGET_BI_ARCH, PR80556_WORKAROUND): New. (REAL_LIBGCC_SPEC): Remove. --- gcc/config.gcc | 10 +++++++--- gcc/config/i386/darwin.h | 22 ++++++++++------------ gcc/config/i386/darwin32-biarch.h | 22 ++++++---------------- gcc/config/i386/darwin64-biarch.h | 22 ++++++---------------- 4 files changed, 29 insertions(+), 47 deletions(-) (limited to 'gcc') diff --git a/gcc/config.gcc b/gcc/config.gcc index 0230bb8..f3e94f7 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -591,6 +591,8 @@ i[34567]86-*-*) exit 1 fi ;; +x86_64-*-darwin*) + ;; x86_64-*-*) case ${with_abi} in "") @@ -1837,7 +1839,7 @@ hppa[12]*-*-hpux11*) dwarf2=no fi ;; -i[34567]86-*-darwin1[89]*) +i[34567]86-*-darwin1[89]* | i[34567]86-*-darwin2[0-9]*) echo "Error: 32bit target is not supported after Darwin17" 1>&2 ;; i[34567]86-*-darwin*) @@ -1845,17 +1847,19 @@ i[34567]86-*-darwin*) # Baseline choice for a machine that allows m64 support. with_cpu=${with_cpu:-core2} tmake_file="${tmake_file} ${cpu_type}/t-darwin32-biarch t-slibgcc" - tm_file="${tm_file} ${cpu_type}/darwin32-biarch.h" + tm_file="${cpu_type}/darwin32-biarch.h ${tm_file} " ;; x86_64-*-darwin1[89]* | x86_64-*-darwin2[01]*) # Only 64b from now + tm_defines="${tm_defines} TARGET_64BIT_DEFAULT=(OPTION_MASK_ISA_64BIT|OPTION_MASK_ABI_64)" + tm_defines="${tm_defines} TARGET_BI_ARCH=0" with_cpu=${with_cpu:-core2} tmake_file="${tmake_file} t-slibgcc" ;; x86_64-*-darwin*) with_cpu=${with_cpu:-core2} tmake_file="${tmake_file} ${cpu_type}/t-darwin64-biarch t-slibgcc" - tm_file="${tm_file} ${cpu_type}/darwin64-biarch.h" + tm_file="${cpu_type}/darwin64-biarch.h ${tm_file} " ;; i[34567]86-*-elfiamcu) tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/iamcu.h" diff --git a/gcc/config/i386/darwin.h b/gcc/config/i386/darwin.h index 5312003..bac3219 100644 --- a/gcc/config/i386/darwin.h +++ b/gcc/config/i386/darwin.h @@ -25,15 +25,6 @@ along with GCC; see the file COPYING3. If not see #undef DARWIN_X86 #define DARWIN_X86 1 -#ifdef IN_LIBGCC2 -#undef TARGET_64BIT -#ifdef __x86_64__ -#define TARGET_64BIT 1 -#else -#define TARGET_64BIT 0 -#endif -#endif - /* WORKAROUND pr80556: For x86_64 Darwin10 and later, the unwinder is in libunwind (redirected from libSystem). This doesn't use the keymgr (see keymgr.c) and therefore @@ -44,11 +35,15 @@ along with GCC; see the file COPYING3. If not see even when static-libgcc is specified. We put libSystem first so that unwinder symbols are satisfied from there. We default to 64b for single-arch builds, so apply this unconditionally. */ +#ifndef PR80556_WORKAROUND +#define PR80556_WORKAROUND \ +" %:version-compare(>= 10.6 mmacosx-version-min= -lSystem) " +#endif #undef REAL_LIBGCC_SPEC #define REAL_LIBGCC_SPEC \ - "%{static-libgcc|static: \ - %:version-compare(>= 10.6 mmacosx-version-min= -lSystem) \ - -lgcc_eh -lgcc; \ + "%{static-libgcc|static: " \ + PR80556_WORKAROUND \ + " -lgcc_eh -lgcc; \ shared-libgcc|fexceptions|fgnu-runtime: \ %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_s.10.4) \ %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \ @@ -142,8 +137,11 @@ along with GCC; see the file COPYING3. If not see %{mpc64:crtprec64.o%s} \ %{mpc80:crtprec80.o%s}" TM_DESTRUCTOR +#ifndef DARWIN_ARCH_SPEC /* We default to x86_64 for single-arch builds, bi-arch overrides. */ #define DARWIN_ARCH_SPEC "x86_64" +#define DARWIN_SUBARCH_SPEC DARWIN_ARCH_SPEC +#endif #undef SUBTARGET_EXTRA_SPECS #define SUBTARGET_EXTRA_SPECS \ diff --git a/gcc/config/i386/darwin32-biarch.h b/gcc/config/i386/darwin32-biarch.h index 73b83eb..5470edf 100644 --- a/gcc/config/i386/darwin32-biarch.h +++ b/gcc/config/i386/darwin32-biarch.h @@ -21,6 +21,9 @@ along with GCC; see the file COPYING3. If not see #undef DARWIN_ARCH_SPEC #define DARWIN_ARCH_SPEC "%{m64:x86_64;:i386}" +#define TARGET_64BIT_DEFAULT 0 +#define TARGET_BI_ARCH 1 + /* WORKAROUND pr80556: For x86_64 Darwin10 and later, the unwinder is in libunwind (redirected from libSystem). This doesn't use the keymgr (see keymgr.c) and therefore @@ -30,22 +33,9 @@ along with GCC; see the file COPYING3. If not see Therefore, for 64b exes at least, we must use the libunwind implementation, even when static-libgcc is specified. We put libSystem first so that unwinder symbols are satisfied from there. */ -#undef REAL_LIBGCC_SPEC -#define REAL_LIBGCC_SPEC \ - "%{static-libgcc|static: \ - %{m64:%:version-compare(>= 10.6 mmacosx-version-min= -lSystem)} \ - -lgcc_eh -lgcc; \ - shared-libgcc|fexceptions|fgnu-runtime: \ - %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_s.10.4) \ - %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \ - %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4) \ - %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \ - -lgcc ; \ - :%:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4) \ - %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \ - %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4) \ - %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \ - -lgcc }" +#undef PR80556_WORKAROUND +#define PR80556_WORKAROUND \ +" %{m64:%:version-compare(>= 10.6 mmacosx-version-min= -lSystem)} " #undef DARWIN_SUBARCH_SPEC #define DARWIN_SUBARCH_SPEC DARWIN_ARCH_SPEC diff --git a/gcc/config/i386/darwin64-biarch.h b/gcc/config/i386/darwin64-biarch.h index 1ae76b8..f5bc3d6 100644 --- a/gcc/config/i386/darwin64-biarch.h +++ b/gcc/config/i386/darwin64-biarch.h @@ -22,6 +22,9 @@ along with GCC; see the file COPYING3. If not see #undef DARWIN_ARCH_SPEC #define DARWIN_ARCH_SPEC "%{m32:i386;:x86_64}" +#define TARGET_64BIT_DEFAULT (OPTION_MASK_ISA_64BIT | OPTION_MASK_ABI_64) +#define TARGET_BI_ARCH 1 + /* WORKAROUND pr80556: For x86_64 Darwin10 and later, the unwinder is in libunwind (redirected from libSystem). This doesn't use the keymgr (see keymgr.c) and therefore @@ -31,22 +34,9 @@ along with GCC; see the file COPYING3. If not see Therefore, for 64b exes at least, we must use the libunwind implementation, even when static-libgcc is specified. We put libSystem first so that unwinder symbols are satisfied from there. */ -#undef REAL_LIBGCC_SPEC -#define REAL_LIBGCC_SPEC \ - "%{static-libgcc|static: \ - %{!m32:%:version-compare(>= 10.6 mmacosx-version-min= -lSystem)} \ - -lgcc_eh -lgcc; \ - shared-libgcc|fexceptions|fgnu-runtime: \ - %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_s.10.4) \ - %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \ - %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4) \ - %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \ - -lgcc ; \ - :%:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4) \ - %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \ - %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4) \ - %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \ - -lgcc }" +#undef PR80556_WORKAROUND +#define PR80556_WORKAROUND \ +" %{!m32:%:version-compare(>= 10.6 mmacosx-version-min= -lSystem)} " #undef DARWIN_SUBARCH_SPEC #define DARWIN_SUBARCH_SPEC DARWIN_ARCH_SPEC -- cgit v1.1 From 65b8273cc0fd0e8c093e481fb0c6dc84a99ccf80 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Mon, 5 Jul 2021 00:16:28 +0000 Subject: Daily bump. --- gcc/ChangeLog | 16 ++++++++++++++++ gcc/DATESTAMP | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d7a3b12..88620d1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2021-07-04 Iain Sandoe + + PR target/100269 + * config.gcc: Ensure that Darwin biarch definitions are + added before i386.h. + * config/i386/darwin.h (TARGET_64BIT): Remove. + (PR80556_WORKAROUND): New. + (REAL_LIBGCC_SPEC): Amend to use PR80556_WORKAROUND. + (DARWIN_SUBARCH_SPEC): New. + * config/i386/darwin32-biarch.h (TARGET_64BIT_DEFAULT, + TARGET_BI_ARCH, PR80556_WORKAROUND): New. + (REAL_LIBGCC_SPEC): Remove. + * config/i386/darwin64-biarch.h (TARGET_64BIT_DEFAULT, + TARGET_BI_ARCH, PR80556_WORKAROUND): New. + (REAL_LIBGCC_SPEC): Remove. + 2021-07-03 H.J. Lu PR middle-end/101294 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ea1d54a..7596b54 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210704 +20210705 -- cgit v1.1 From 9c6ce6b04cf7119e8405e3de60967858f1cc9570 Mon Sep 17 00:00:00 2001 From: liuhongt Date: Mon, 5 Jul 2021 12:55:57 +0800 Subject: Remove xfail for pr92658-avx512vl.c Typo of standard pattern name has been fixed by r12-1970, remove those xfails. gcc/testsuite/ChangeLog * gcc.target/i386/pr92658-avx512vl.c: Refine testcase. --- gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c b/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c index a9f7d7e..7ff9c19 100644 --- a/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c +++ b/gcc/testsuite/gcc.target/i386/pr92658-avx512vl.c @@ -122,8 +122,7 @@ truncdb_128 (v16qi * dst, v4si * __restrict src) } /* { dg-final { scan-assembler-times "vpmovqd" 2 } } */ -/* { dg-final { scan-assembler-times "vpmovqw" 2 { xfail *-*-* } } } */ +/* { dg-final { scan-assembler-times "vpmovqw" 2 } } */ /* { dg-final { scan-assembler-times "vpmovqb" 2 { xfail *-*-* } } } */ -/* { dg-final { scan-assembler-times "vpmovdw" 1 } } */ -/* { dg-final { scan-assembler-times "vpmovdw" 2 { xfail *-*-* } } } */ +/* { dg-final { scan-assembler-times "vpmovdw" 2 } } */ /* { dg-final { scan-assembler-times "vpmovdb" 2 } } */ -- cgit v1.1 From ccb4e0774b3e5859ea1d7f1864b02fa5826c4a79 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 5 Jul 2021 08:38:29 +0200 Subject: testsuite/101299 - add missing vect_double requires to bb-slp-74.c This should fix the FAIL of gcc.dg/vect/bb-slp-74.c on arm. 2021-07-05 Richard Biener PR testsuite/101299 * gcc.dg/vect/bb-slp-74.c: Add vect_double requires. --- gcc/testsuite/gcc.dg/vect/bb-slp-74.c | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-74.c b/gcc/testsuite/gcc.dg/vect/bb-slp-74.c index d3d5a02..9c1ebb7 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-74.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-74.c @@ -1,4 +1,5 @@ /* { dg-do run } */ +/* { dg-require-effective-target vect_double } */ #include "tree-vect.h" -- cgit v1.1 From 38872c6c0db1b10b17d3913b277c499913208d0b Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 5 Jul 2021 11:53:07 +0200 Subject: middle-end/101291 - set loop copy of versioned loop This fixes the vectorizer loop versioning code failing to clear niter related info on the scalar loop as it assumed get_loop_copy would work even for the outermost loop. The patch makes that assumption hold by adjusting the loop versioning code. 2021-07-05 Richard Biener PR middle-end/101291 * cfgloopmanip.c (loop_version): Set the loop copy of the versioned loop to the new loop. --- gcc/cfgloopmanip.c | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index e6df280..2af59fe 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -1731,6 +1731,7 @@ loop_version (class loop *loop, then_scale, else_scale); copy_loop_info (loop, nloop); + set_loop_copy (loop, nloop); /* loopify redirected latch_edge. Update its PENDING_STMTS. */ lv_flush_pending_stmts (latch_edge); -- cgit v1.1 From 88ada5c051c49a1f03602df747a9e6dae675c68e Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 5 Jul 2021 12:00:17 +0200 Subject: Do not set both LOOP_C_INFINITE and LOOP_C_FINITE on vectorized loop The setting is likely a typo and was meant to affect the scalar version but even there LOOP_C_INFINITE is at most an optimization to the niter analysis. Clearly setting it on the vectorized loop which we just versioned to be _not_ infinite is bogus so the following change removes this. 2021-07-05 Richard Biener * tree-vect-loop-manip.c (vect_loop_versioning): Do not set LOOP_C_INFINITE on the vectorized loop. --- gcc/tree-vect-loop-manip.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'gcc') diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index 012f48b..2909e8a 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -3597,8 +3597,6 @@ vect_loop_versioning (loop_vec_info loop_vinfo, niter information which is copied from the original loop. */ gcc_assert (loop_constraint_set_p (loop, LOOP_C_FINITE)); vect_free_loop_info_assumptions (nloop); - /* And set constraint LOOP_C_INFINITE for niter analyzer. */ - loop_constraint_set (loop, LOOP_C_INFINITE); } if (LOCATION_LOCUS (vect_location.get_location_t ()) != UNKNOWN_LOCATION -- cgit v1.1 From 0ea47850bbb38ea81a34c503533d4dd0f3391f19 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Mon, 5 Jul 2021 11:33:45 +0000 Subject: testsuite: gcc.dg/debug/btf/btf-bitfields-3.c requires -fno-short-enums PR debug/101321 arm-eabi uses -fshort-enums by default while arm-linux-gnueabi* do not, like most (all?) other targets, but this test relies -fno-short-enums. Fix it by forcing -fno-short-enums. 2021-07-05 Christophe Lyon PR debug/101321 gcc/testsuite/ * gcc.dg/debug/btf/btf-bitfields-3.c: Add -fno-short-enums. --- gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c b/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c index 440623c3..5e68416 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c @@ -15,7 +15,7 @@ */ /* { dg-do compile } */ -/* { dg-options "-O0 -gbtf -dA" } */ +/* { dg-options "-O0 -gbtf -dA -fno-short-enums" } */ /* Enum with 4 members. */ /* { dg-final { scan-assembler-times "\[\t \]0x6000004\[\t \]+\[^\n\]*btt_info" 1 } } */ -- cgit v1.1 From afe5959e11727f6ff276bc1a7c62181306157504 Mon Sep 17 00:00:00 2001 From: Boris Yakobowski Date: Wed, 21 Apr 2021 14:49:15 +0200 Subject: [Ada] Do not catch 'N rem -1' in CodePeer_Mode gcc/ada/ * exp_ch4.adb (Expand_N_Op_Rem): Remove special case for rem -1 in CodePeer_Mode. --- gcc/ada/exp_ch4.adb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index a9fc2705..54e91b2 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -10393,7 +10393,9 @@ package body Exp_Ch4 is -- types and this is really marginal). We will just assume that we need -- the test if the left operand can be negative at all. - if Lneg and Rneg then + if (Lneg and Rneg) + and then not CodePeer_Mode + then Rewrite (N, Make_If_Expression (Loc, Expressions => New_List ( -- cgit v1.1 From 767f9cb1f81bdeb55a7b5fbbccb3c057f37e2fae Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Thu, 22 Apr 2021 17:13:19 +0200 Subject: [Ada] Fix overriding subprogram being incorrectly seen as returning gcc/ada/ * sem_ch3.adb (Check_Abstract_Overriding): Check for renamings. --- gcc/ada/sem_ch3.adb | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 7dfb5c8..7a24298 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -11149,12 +11149,28 @@ package body Sem_Ch3 is if Present (Overridden_Operation (Subp)) and then No_Return (Overridden_Operation (Subp)) - and then not No_Return (Subp) then - Error_Msg_N ("overriding subprogram & must be No_Return", Subp); - Error_Msg_N - ("\since overridden subprogram is No_Return (RM 6.5.1(6/2))", - Subp); + + -- If the subprogram is a renaming, check that the renamed + -- subprogram is No_Return. + + if Present (Renamed_Or_Alias (Subp)) then + if not No_Return (Renamed_Or_Alias (Subp)) then + Error_Msg_N ("subprogram & must be No_Return", + Renamed_Or_Alias (Subp)); + Error_Msg_N ("\since renaming & overrides No_Return " + & "subprogram (RM 6.5.1(6/2))", + Subp); + end if; + + -- Make sure that the subprogram itself is No_Return. + + elsif not No_Return (Subp) then + Error_Msg_N ("overriding subprogram & must be No_Return", Subp); + Error_Msg_N + ("\since overridden subprogram is No_Return (RM 6.5.1(6/2))", + Subp); + end if; end if; -- If the operation is a wrapper for a synchronized primitive, it -- cgit v1.1 From 8926c29c5f512203b6ed6e1e944738fc0a6f0c4c Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Thu, 22 Apr 2021 14:07:34 -0400 Subject: [Ada] Refactoring related to Returns_By_Ref gcc/ada/ * sem_util.ads, sem_util.adb (Compute_Returns_By_Ref): New procedure to compute Returns_By_Ref, to avoid some code duplication. This will likely change soon, so it's good to have the code in one place. (CW_Or_Has_Controlled_Part): Move here from Exp_Ch7, because it's called by Compute_Returns_By_Ref, and this is a better place for it anyway. (Needs_Finalization): Fix comment to be vague instead of wrong. * exp_ch6.adb (Expand_N_Subprogram_Body, Freeze_Subprogram): Call Compute_Returns_By_Ref. * sem_ch6.adb (Check_Delayed_Subprogram): Call Compute_Returns_By_Ref. * exp_ch7.ads, exp_ch7.adb (CW_Or_Has_Controlled_Part): Move to Sem_Util. (Has_New_Controlled_Component): Remove unused function. --- gcc/ada/exp_ch6.adb | 26 ++------------------------ gcc/ada/exp_ch7.adb | 40 ---------------------------------------- gcc/ada/exp_ch7.ads | 11 ----------- gcc/ada/sem_ch6.adb | 14 +------------- gcc/ada/sem_util.adb | 26 ++++++++++++++++++++++++++ gcc/ada/sem_util.ads | 12 ++++++++++-- 6 files changed, 39 insertions(+), 90 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index b81216f..3542411 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -6431,18 +6431,7 @@ package body Exp_Ch6 is -- Returns_By_Ref flag is normally set when the subprogram is frozen but -- subprograms with no specs are not frozen. - declare - Typ : constant Entity_Id := Etype (Spec_Id); - Utyp : constant Entity_Id := Underlying_Type (Typ); - - begin - if Is_Limited_View (Typ) then - Set_Returns_By_Ref (Spec_Id); - - elsif Present (Utyp) and then CW_Or_Has_Controlled_Part (Utyp) then - Set_Returns_By_Ref (Spec_Id); - end if; - end; + Compute_Returns_By_Ref (Spec_Id); -- For a procedure, we add a return for all possible syntactic ends of -- the subprogram. @@ -7851,18 +7840,7 @@ package body Exp_Ch6 is -- of the normal semantic analysis of the spec since the underlying -- returned type may not be known yet (for private types). - declare - Typ : constant Entity_Id := Etype (Subp); - Utyp : constant Entity_Id := Underlying_Type (Typ); - - begin - if Is_Limited_View (Typ) then - Set_Returns_By_Ref (Subp); - - elsif Present (Utyp) and then CW_Or_Has_Controlled_Part (Utyp) then - Set_Returns_By_Ref (Subp); - end if; - end; + Compute_Returns_By_Ref (Subp); -- Wnen freezing a null procedure, analyze its delayed aspects now -- because we may not have reached the end of the declarative list when diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index a534370..469c9fb 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -5118,15 +5118,6 @@ package body Exp_Ch7 is end if; end Convert_View; - ------------------------------- - -- CW_Or_Has_Controlled_Part -- - ------------------------------- - - function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean is - begin - return Is_Class_Wide_Type (T) or else Needs_Finalization (T); - end CW_Or_Has_Controlled_Part; - ------------------------ -- Enclosing_Function -- ------------------------ @@ -6130,37 +6121,6 @@ package body Exp_Ch7 is return Empty; end Find_Transient_Context; - ---------------------------------- - -- Has_New_Controlled_Component -- - ---------------------------------- - - function Has_New_Controlled_Component (E : Entity_Id) return Boolean is - Comp : Entity_Id; - - begin - if not Is_Tagged_Type (E) then - return Has_Controlled_Component (E); - elsif not Is_Derived_Type (E) then - return Has_Controlled_Component (E); - end if; - - Comp := First_Component (E); - while Present (Comp) loop - if Chars (Comp) = Name_uParent then - null; - - elsif Scope (Original_Record_Component (Comp)) = E - and then Needs_Finalization (Etype (Comp)) - then - return True; - end if; - - Next_Component (Comp); - end loop; - - return False; - end Has_New_Controlled_Component; - --------------------------------- -- Has_Simple_Protected_Object -- --------------------------------- diff --git a/gcc/ada/exp_ch7.ads b/gcc/ada/exp_ch7.ads index 62fdb8a..ef1bf67 100644 --- a/gcc/ada/exp_ch7.ads +++ b/gcc/ada/exp_ch7.ads @@ -153,17 +153,6 @@ package Exp_Ch7 is -- triggered by an abort, E_Id denotes the defining identifier of a local -- exception occurrence, Raised_Id is the entity of a local boolean flag. - function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean; - -- True if T is a class-wide type, or if it has controlled parts ("part" - -- means T or any of its subcomponents). Same as Needs_Finalization, except - -- when pragma Restrictions (No_Finalization) applies, in which case we - -- know that class-wide objects do not contain controlled parts. - - function Has_New_Controlled_Component (E : Entity_Id) return Boolean; - -- E is a type entity. Give the same result as Has_Controlled_Component - -- except for tagged extensions where the result is True only if the - -- latest extension contains a controlled component. - function Make_Adjust_Call (Obj_Ref : Node_Id; Typ : Entity_Id; diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index c361acc..ffab332 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -36,7 +36,6 @@ with Errout; use Errout; with Expander; use Expander; with Exp_Ch3; use Exp_Ch3; with Exp_Ch6; use Exp_Ch6; -with Exp_Ch7; use Exp_Ch7; with Exp_Ch9; use Exp_Ch9; with Exp_Dbug; use Exp_Dbug; with Exp_Tss; use Exp_Tss; @@ -6748,18 +6747,7 @@ package body Sem_Ch6 is -- may not be known yet (for private types). if not Has_Delayed_Freeze (Designator) and then Expander_Active then - declare - Typ : constant Entity_Id := Etype (Designator); - Utyp : constant Entity_Id := Underlying_Type (Typ); - - begin - if Is_Limited_View (Typ) then - Set_Returns_By_Ref (Designator); - - elsif Present (Utyp) and then CW_Or_Has_Controlled_Part (Utyp) then - Set_Returns_By_Ref (Designator); - end if; - end; + Compute_Returns_By_Ref (Designator); end if; end Check_Delayed_Subprogram; diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index a543268..e7e0c84 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -6672,6 +6672,23 @@ package body Sem_Util is return N; end Compile_Time_Constraint_Error; + ---------------------------- + -- Compute_Returns_By_Ref -- + ---------------------------- + + procedure Compute_Returns_By_Ref (Func : Entity_Id) is + Typ : constant Entity_Id := Etype (Func); + Utyp : constant Entity_Id := Underlying_Type (Typ); + + begin + if Is_Limited_View (Typ) then + Set_Returns_By_Ref (Func); + + elsif Present (Utyp) and then CW_Or_Has_Controlled_Part (Utyp) then + Set_Returns_By_Ref (Func); + end if; + end Compute_Returns_By_Ref; + -------------------------------- -- Collect_Types_In_Hierarchy -- -------------------------------- @@ -7073,6 +7090,15 @@ package body Sem_Util is end Current_Subprogram; ------------------------------- + -- CW_Or_Has_Controlled_Part -- + ------------------------------- + + function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean is + begin + return Is_Class_Wide_Type (T) or else Needs_Finalization (T); + end CW_Or_Has_Controlled_Part; + + ------------------------------- -- Deepest_Type_Access_Level -- ------------------------------- diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index 10375ff..9f15f44 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -582,6 +582,9 @@ package Sem_Util is -- emitted immediately after the main message (and before output of any -- message indicating that Constraint_Error will be raised). + procedure Compute_Returns_By_Ref (Func : Entity_Id); + -- Set the Returns_By_Ref flag on Func if appropriate + generic with function Predicate (Typ : Entity_Id) return Boolean; function Collect_Types_In_Hierarchy @@ -653,6 +656,12 @@ package Sem_Util is -- Current_Scope is returned. The returned value is Empty if this is called -- from a library package which is not within any subprogram. + function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean; + -- True if T is a class-wide type, or if it has controlled parts ("part" + -- means T or any of its subcomponents). Same as Needs_Finalization, except + -- when pragma Restrictions (No_Finalization) applies, in which case we + -- know that class-wide objects do not contain controlled parts. + function Deepest_Type_Access_Level (Typ : Entity_Id) return Uint; -- Same as Type_Access_Level, except that if the type is the type of an Ada -- 2012 stand-alone object of an anonymous access type, then return the @@ -2556,8 +2565,7 @@ package Sem_Util is -- entity E. If no such instance exits, return Empty. function Needs_Finalization (Typ : Entity_Id) return Boolean; - -- Determine whether type Typ is controlled and thus requires finalization - -- actions. + -- True if Typ requires finalization actions function Needs_One_Actual (E : Entity_Id) return Boolean; -- Returns True if a function has defaults for all but its first formal, -- cgit v1.1 From 7c4f32677bb64c3423893441541d520097f238c5 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Fri, 23 Apr 2021 08:17:28 -0400 Subject: [Ada] Clean up Get_Index_Bounds gcc/ada/ * checks.adb, exp_aggr.adb, exp_ch5.adb, freeze.adb, sem_util.adb, sem_util.ads: Change L and H to be First and Last, to match the attributes in the RM. Change calls from procedure to function where appropriate. --- gcc/ada/checks.adb | 69 +++++----- gcc/ada/exp_aggr.adb | 381 ++++++++++++++++++++++++++------------------------- gcc/ada/exp_ch5.adb | 43 +++--- gcc/ada/freeze.adb | 10 +- gcc/ada/sem_util.adb | 4 +- gcc/ada/sem_util.ads | 4 +- 6 files changed, 266 insertions(+), 245 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 1a39a82..6c49e67 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -9931,8 +9931,7 @@ package body Checks is declare Indx_Type : Node_Id; - Lo : Node_Id; - Hi : Node_Id; + Bounds : Range_Nodes; Do_Expand : Boolean := False; begin @@ -9942,37 +9941,38 @@ package body Checks is Next_Index (Indx_Type); end loop; - Get_Index_Bounds (Indx_Type, Lo, Hi); + Bounds := Get_Index_Bounds (Indx_Type); - if Nkind (Lo) = N_Identifier - and then Ekind (Entity (Lo)) = E_In_Parameter + if Nkind (Bounds.First) = N_Identifier + and then Ekind (Entity (Bounds.First)) = E_In_Parameter then - Lo := Get_Discriminal (E, Lo); + Bounds.First := Get_Discriminal (E, Bounds.First); Do_Expand := True; end if; - if Nkind (Hi) = N_Identifier - and then Ekind (Entity (Hi)) = E_In_Parameter + if Nkind (Bounds.Last) = N_Identifier + and then Ekind (Entity (Bounds.Last)) = E_In_Parameter then - Hi := Get_Discriminal (E, Hi); + Bounds.Last := Get_Discriminal (E, Bounds.Last); Do_Expand := True; end if; if Do_Expand then - if not Is_Entity_Name (Lo) then - Lo := Duplicate_Subexpr_No_Checks (Lo); + if not Is_Entity_Name (Bounds.First) then + Bounds.First := + Duplicate_Subexpr_No_Checks (Bounds.First); end if; - if not Is_Entity_Name (Hi) then - Lo := Duplicate_Subexpr_No_Checks (Hi); + if not Is_Entity_Name (Bounds.Last) then + Bounds.First := Duplicate_Subexpr_No_Checks (Bounds.Last); end if; N := Make_Op_Add (Loc, Left_Opnd => Make_Op_Subtract (Loc, - Left_Opnd => Hi, - Right_Opnd => Lo), + Left_Opnd => Bounds.Last, + Right_Opnd => Bounds.First), Right_Opnd => Make_Integer_Literal (Loc, 1)); return N; @@ -10215,10 +10215,8 @@ package body Checks is L_Index : Node_Id; R_Index : Node_Id; - L_Low : Node_Id; - L_High : Node_Id; - R_Low : Node_Id; - R_High : Node_Id; + L_Bounds : Range_Nodes; + R_Bounds : Range_Nodes; L_Length : Uint; R_Length : Uint; Ref_Node : Node_Id; @@ -10250,29 +10248,33 @@ package body Checks is or else Nkind (R_Index) = N_Raise_Constraint_Error) then - Get_Index_Bounds (L_Index, L_Low, L_High); - Get_Index_Bounds (R_Index, R_Low, R_High); + L_Bounds := Get_Index_Bounds (L_Index); + R_Bounds := Get_Index_Bounds (R_Index); -- Deal with compile time length check. Note that we -- skip this in the access case, because the access -- value may be null, so we cannot know statically. if not Do_Access - and then Compile_Time_Known_Value (L_Low) - and then Compile_Time_Known_Value (L_High) - and then Compile_Time_Known_Value (R_Low) - and then Compile_Time_Known_Value (R_High) + and then Compile_Time_Known_Value (L_Bounds.First) + and then Compile_Time_Known_Value (L_Bounds.Last) + and then Compile_Time_Known_Value (R_Bounds.First) + and then Compile_Time_Known_Value (R_Bounds.Last) then - if Expr_Value (L_High) >= Expr_Value (L_Low) then - L_Length := Expr_Value (L_High) - - Expr_Value (L_Low) + 1; + if Expr_Value (L_Bounds.Last) >= + Expr_Value (L_Bounds.First) + then + L_Length := Expr_Value (L_Bounds.Last) - + Expr_Value (L_Bounds.First) + 1; else L_Length := UI_From_Int (0); end if; - if Expr_Value (R_High) >= Expr_Value (R_Low) then - R_Length := Expr_Value (R_High) - - Expr_Value (R_Low) + 1; + if Expr_Value (R_Bounds.Last) >= + Expr_Value (R_Bounds.First) + then + R_Length := Expr_Value (R_Bounds.Last) - + Expr_Value (R_Bounds.First) + 1; else R_Length := UI_From_Int (0); end if; @@ -10304,8 +10306,9 @@ package body Checks is (Etype (L_Index), Etype (R_Index)) and then not - (Same_Bounds (L_Low, R_Low) - and then Same_Bounds (L_High, R_High)) + (Same_Bounds (L_Bounds.First, R_Bounds.First) + and then + Same_Bounds (L_Bounds.Last, R_Bounds.Last)) then Evolve_Or_Else (Cond, Length_E_Cond (Exptyp, T_Typ, Indx)); diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 56ec1be..7978b1c 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -375,15 +375,6 @@ package body Exp_Aggr is -- specifically optimized for the target. function Aggr_Assignment_OK_For_Backend (N : Node_Id) return Boolean is - Csiz : Uint := No_Uint; - Ctyp : Entity_Id; - Expr : Node_Id; - High : Node_Id; - Index : Entity_Id; - Low : Node_Id; - Nunits : Int; - Remainder : Uint; - Value : Uint; function Is_OK_Aggregate (Aggr : Node_Id) return Boolean; -- Return true if Aggr is suitable for back-end assignment @@ -422,6 +413,15 @@ package body Exp_Aggr is return Nkind (First (Assoc)) /= N_Iterated_Component_Association; end Is_OK_Aggregate; + Bounds : Range_Nodes; + Csiz : Uint := No_Uint; + Ctyp : Entity_Id; + Expr : Node_Id; + Index : Entity_Id; + Nunits : Int; + Remainder : Uint; + Value : Uint; + -- Start of processing for Aggr_Assignment_OK_For_Backend begin @@ -444,9 +444,9 @@ package body Exp_Aggr is Index := First_Index (Ctyp); while Present (Index) loop - Get_Index_Bounds (Index, Low, High); + Bounds := Get_Index_Bounds (Index); - if Is_Null_Range (Low, High) then + if Is_Null_Range (Bounds.First, Bounds.Last) then return False; end if; @@ -2282,10 +2282,12 @@ package body Exp_Aggr is Assoc : Node_Id; Choice : Node_Id; Expr : Node_Id; - High : Node_Id; - Low : Node_Id; Typ : Entity_Id; + Bounds : Range_Nodes; + Low : Node_Id renames Bounds.First; + High : Node_Id renames Bounds.Last; + Nb_Choices : Nat := 0; Table : Case_Table_Type (1 .. Number_Of_Choices (N)); -- Used to sort all the different choice values @@ -2347,7 +2349,7 @@ package body Exp_Aggr is exit; end if; - Get_Index_Bounds (Choice, Low, High); + Bounds := Get_Index_Bounds (Choice); if Low /= High then Set_Loop_Actions (Assoc, New_List); @@ -4508,11 +4510,9 @@ package body Exp_Aggr is Is_Array : constant Boolean := Is_Array_Type (Etype (N)); Aggr_In : Node_Id; - Aggr_Lo : Node_Id; - Aggr_Hi : Node_Id; + Aggr_Bounds : Range_Nodes; Obj_In : Node_Id; - Obj_Lo : Node_Id; - Obj_Hi : Node_Id; + Obj_Bounds : Range_Nodes; Parent_Kind : Node_Kind; Parent_Node : Node_Id; @@ -4823,16 +4823,17 @@ package body Exp_Aggr is end if; while Present (Aggr_In) loop - Get_Index_Bounds (Aggr_In, Aggr_Lo, Aggr_Hi); - Get_Index_Bounds (Obj_In, Obj_Lo, Obj_Hi); + Aggr_Bounds := Get_Index_Bounds (Aggr_In); + Obj_Bounds := Get_Index_Bounds (Obj_In); -- We require static bounds for the target and a static matching -- of low bound for the aggregate. - if not Compile_Time_Known_Value (Obj_Lo) - or else not Compile_Time_Known_Value (Obj_Hi) - or else not Compile_Time_Known_Value (Aggr_Lo) - or else Expr_Value (Aggr_Lo) /= Expr_Value (Obj_Lo) + if not Compile_Time_Known_Value (Obj_Bounds.First) + or else not Compile_Time_Known_Value (Obj_Bounds.Last) + or else not Compile_Time_Known_Value (Aggr_Bounds.First) + or else Expr_Value (Aggr_Bounds.First) /= + Expr_Value (Obj_Bounds.First) then return False; @@ -4848,8 +4849,9 @@ package body Exp_Aggr is elsif Parent_Kind = N_Assignment_Statement or else Is_Constrained (Etype (Parent_Node)) then - if not Compile_Time_Known_Value (Aggr_Hi) - or else Expr_Value (Aggr_Hi) /= Expr_Value (Obj_Hi) + if not Compile_Time_Known_Value (Aggr_Bounds.Last) + or else Expr_Value (Aggr_Bounds.Last) /= + Expr_Value (Obj_Bounds.Last) then return False; end if; @@ -5692,7 +5694,7 @@ package body Exp_Aggr is -- type using the computable sizes of the aggregate and its sub- -- aggregates. - procedure Check_Bounds (Aggr_Bounds : Node_Id; Index_Bounds : Node_Id); + procedure Check_Bounds (Aggr_Bounds_Node, Index_Bounds_Node : Node_Id); -- Checks that the bounds of Aggr_Bounds are within the bounds defined -- by Index_Bounds. @@ -5792,55 +5794,58 @@ package body Exp_Aggr is -- Check_Bounds -- ------------------ - procedure Check_Bounds (Aggr_Bounds : Node_Id; Index_Bounds : Node_Id) is - Aggr_Lo : Node_Id; - Aggr_Hi : Node_Id; - - Ind_Lo : Node_Id; - Ind_Hi : Node_Id; + procedure Check_Bounds (Aggr_Bounds_Node, Index_Bounds_Node : Node_Id) is + Aggr_Bounds : constant Range_Nodes := + Get_Index_Bounds (Aggr_Bounds_Node); + Ind_Bounds : constant Range_Nodes := + Get_Index_Bounds (Index_Bounds_Node); - Cond : Node_Id := Empty; + Cond : Node_Id := Empty; begin - Get_Index_Bounds (Aggr_Bounds, Aggr_Lo, Aggr_Hi); - Get_Index_Bounds (Index_Bounds, Ind_Lo, Ind_Hi); - -- Generate the following test: -- [constraint_error when - -- Aggr_Lo <= Aggr_Hi and then - -- (Aggr_Lo < Ind_Lo or else Aggr_Hi > Ind_Hi)] + -- Aggr_Bounds.First <= Aggr_Bounds.Last and then + -- (Aggr_Bounds.First < Ind_Bounds.First + -- or else Aggr_Bounds.Last > Ind_Bounds.Last)] -- As an optimization try to see if some tests are trivially vacuous -- because we are comparing an expression against itself. - if Aggr_Lo = Ind_Lo and then Aggr_Hi = Ind_Hi then + if Aggr_Bounds.First = Ind_Bounds.First + and then Aggr_Bounds.Last = Ind_Bounds.Last + then Cond := Empty; - elsif Aggr_Hi = Ind_Hi then + elsif Aggr_Bounds.Last = Ind_Bounds.Last then Cond := Make_Op_Lt (Loc, - Left_Opnd => Duplicate_Subexpr_Move_Checks (Aggr_Lo), - Right_Opnd => Duplicate_Subexpr_Move_Checks (Ind_Lo)); + Left_Opnd => + Duplicate_Subexpr_Move_Checks (Aggr_Bounds.First), + Right_Opnd => + Duplicate_Subexpr_Move_Checks (Ind_Bounds.First)); - elsif Aggr_Lo = Ind_Lo then + elsif Aggr_Bounds.First = Ind_Bounds.First then Cond := Make_Op_Gt (Loc, - Left_Opnd => Duplicate_Subexpr_Move_Checks (Aggr_Hi), - Right_Opnd => Duplicate_Subexpr_Move_Checks (Ind_Hi)); + Left_Opnd => Duplicate_Subexpr_Move_Checks (Aggr_Bounds.Last), + Right_Opnd => Duplicate_Subexpr_Move_Checks (Ind_Bounds.Last)); else Cond := Make_Or_Else (Loc, Left_Opnd => Make_Op_Lt (Loc, - Left_Opnd => Duplicate_Subexpr_Move_Checks (Aggr_Lo), - Right_Opnd => Duplicate_Subexpr_Move_Checks (Ind_Lo)), + Left_Opnd => + Duplicate_Subexpr_Move_Checks (Aggr_Bounds.First), + Right_Opnd => + Duplicate_Subexpr_Move_Checks (Ind_Bounds.First)), Right_Opnd => Make_Op_Gt (Loc, - Left_Opnd => Duplicate_Subexpr (Aggr_Hi), - Right_Opnd => Duplicate_Subexpr (Ind_Hi))); + Left_Opnd => Duplicate_Subexpr (Aggr_Bounds.Last), + Right_Opnd => Duplicate_Subexpr (Ind_Bounds.Last))); end if; if Present (Cond) then @@ -5848,8 +5853,10 @@ package body Exp_Aggr is Make_And_Then (Loc, Left_Opnd => Make_Op_Le (Loc, - Left_Opnd => Duplicate_Subexpr_Move_Checks (Aggr_Lo), - Right_Opnd => Duplicate_Subexpr_Move_Checks (Aggr_Hi)), + Left_Opnd => + Duplicate_Subexpr_Move_Checks (Aggr_Bounds.First), + Right_Opnd => + Duplicate_Subexpr_Move_Checks (Aggr_Bounds.Last)), Right_Opnd => Cond); @@ -6116,8 +6123,6 @@ package body Exp_Aggr is -- Used to sort all the different choice values J : Pos := 1; - Low : Node_Id; - High : Node_Id; begin Assoc := First (Component_Associations (Sub_Aggr)); @@ -6128,9 +6133,13 @@ package body Exp_Aggr is exit; end if; - Get_Index_Bounds (Choice, Low, High); - Table (J).Choice_Lo := Low; - Table (J).Choice_Hi := High; + declare + Bounds : constant Range_Nodes := + Get_Index_Bounds (Choice); + begin + Table (J).Choice_Lo := Bounds.First; + Table (J).Choice_Hi := Bounds.Last; + end; J := J + 1; Next (Choice); @@ -9144,14 +9153,6 @@ package body Exp_Aggr is declare Csiz : constant Nat := UI_To_Int (Component_Size (Typ)); - Lo : Node_Id; - Hi : Node_Id; - -- Bounds of index type - - Lob : Uint; - Hib : Uint; - -- Values of bounds if compile time known - function Get_Component_Val (N : Node_Id) return Uint; -- Given a expression value N of the component type Ctyp, returns a -- value of Csiz (component size) bits representing this value. If @@ -9193,147 +9194,154 @@ package body Exp_Aggr is return Val mod Uint_2 ** Csiz; end Get_Component_Val; + Bounds : constant Range_Nodes := Get_Index_Bounds (First_Index (Typ)); + -- Here we know we have a one dimensional bit packed array begin - Get_Index_Bounds (First_Index (Typ), Lo, Hi); - -- Cannot do anything if bounds are dynamic - if not Compile_Time_Known_Value (Lo) - or else - not Compile_Time_Known_Value (Hi) + if not (Compile_Time_Known_Value (Bounds.First) + and then + Compile_Time_Known_Value (Bounds.Last)) then return False; end if; - -- Or are silly out of range of int bounds - - Lob := Expr_Value (Lo); - Hib := Expr_Value (Hi); - - if not UI_Is_In_Int_Range (Lob) - or else - not UI_Is_In_Int_Range (Hib) - then - return False; - end if; + declare + Bounds_Vals : Range_Values; + -- Compile-time known values of bounds + begin + -- Or are silly out of range of int bounds - -- At this stage we have a suitable aggregate for handling at compile - -- time. The only remaining checks are that the values of expressions - -- in the aggregate are compile-time known (checks are performed by - -- Get_Component_Val), and that any subtypes or ranges are statically - -- known. + Bounds_Vals.First := Expr_Value (Bounds.First); + Bounds_Vals.Last := Expr_Value (Bounds.Last); - -- If the aggregate is not fully positional at this stage, then - -- convert it to positional form. Either this will fail, in which - -- case we can do nothing, or it will succeed, in which case we have - -- succeeded in handling the aggregate and transforming it into a - -- modular value, or it will stay an aggregate, in which case we - -- have failed to create a packed value for it. + if not UI_Is_In_Int_Range (Bounds_Vals.First) + or else + not UI_Is_In_Int_Range (Bounds_Vals.Last) + then + return False; + end if; - if Present (Component_Associations (N)) then - Convert_To_Positional (N, Handle_Bit_Packed => True); - return Nkind (N) /= N_Aggregate; - end if; + -- At this stage we have a suitable aggregate for handling at + -- compile time. The only remaining checks are that the values of + -- expressions in the aggregate are compile-time known (checks are + -- performed by Get_Component_Val), and that any subtypes or + -- ranges are statically known. - -- Otherwise we are all positional, so convert to proper value + -- If the aggregate is not fully positional at this stage, then + -- convert it to positional form. Either this will fail, in which + -- case we can do nothing, or it will succeed, in which case we + -- have succeeded in handling the aggregate and transforming it + -- into a modular value, or it will stay an aggregate, in which + -- case we have failed to create a packed value for it. - declare - Lov : constant Int := UI_To_Int (Lob); - Hiv : constant Int := UI_To_Int (Hib); + if Present (Component_Associations (N)) then + Convert_To_Positional (N, Handle_Bit_Packed => True); + return Nkind (N) /= N_Aggregate; + end if; - Len : constant Nat := Int'Max (0, Hiv - Lov + 1); - -- The length of the array (number of elements) + -- Otherwise we are all positional, so convert to proper value - Aggregate_Val : Uint; - -- Value of aggregate. The value is set in the low order bits of - -- this value. For the little-endian case, the values are stored - -- from low-order to high-order and for the big-endian case the - -- values are stored from high-order to low-order. Note that gigi - -- will take care of the conversions to left justify the value in - -- the big endian case (because of left justified modular type - -- processing), so we do not have to worry about that here. + declare + Len : constant Nat := + Int'Max (0, UI_To_Int (Bounds_Vals.Last) - + UI_To_Int (Bounds_Vals.First) + 1); + -- The length of the array (number of elements) - Lit : Node_Id; - -- Integer literal for resulting constructed value + Aggregate_Val : Uint; + -- Value of aggregate. The value is set in the low order bits + -- of this value. For the little-endian case, the values are + -- stored from low-order to high-order and for the big-endian + -- case the values are stored from high order to low order. + -- Note that gigi will take care of the conversions to left + -- justify the value in the big endian case (because of left + -- justified modular type processing), so we do not have to + -- worry about that here. - Shift : Nat; - -- Shift count from low order for next value + Lit : Node_Id; + -- Integer literal for resulting constructed value - Incr : Int; - -- Shift increment for loop + Shift : Nat; + -- Shift count from low order for next value - Expr : Node_Id; - -- Next expression from positional parameters of aggregate + Incr : Int; + -- Shift increment for loop - Left_Justified : Boolean; - -- Set True if we are filling the high order bits of the target - -- value (i.e. the value is left justified). + Expr : Node_Id; + -- Next expression from positional parameters of aggregate - begin - -- For little endian, we fill up the low order bits of the target - -- value. For big endian we fill up the high order bits of the - -- target value (which is a left justified modular value). + Left_Justified : Boolean; + -- Set True if we are filling the high order bits of the target + -- value (i.e. the value is left justified). - Left_Justified := Bytes_Big_Endian; + begin + -- For little endian, we fill up the low order bits of the + -- target value. For big endian we fill up the high order bits + -- of the target value (which is a left justified modular + -- value). - -- Switch justification if using -gnatd8 + Left_Justified := Bytes_Big_Endian; - if Debug_Flag_8 then - Left_Justified := not Left_Justified; - end if; + -- Switch justification if using -gnatd8 - -- Switch justfification if reverse storage order + if Debug_Flag_8 then + Left_Justified := not Left_Justified; + end if; - if Reverse_Storage_Order (Base_Type (Typ)) then - Left_Justified := not Left_Justified; - end if; + -- Switch justfification if reverse storage order - if Left_Justified then - Shift := Csiz * (Len - 1); - Incr := -Csiz; - else - Shift := 0; - Incr := +Csiz; - end if; + if Reverse_Storage_Order (Base_Type (Typ)) then + Left_Justified := not Left_Justified; + end if; - -- Loop to set the values + if Left_Justified then + Shift := Csiz * (Len - 1); + Incr := -Csiz; + else + Shift := 0; + Incr := +Csiz; + end if; - if Len = 0 then - Aggregate_Val := Uint_0; - else - Expr := First (Expressions (N)); - Aggregate_Val := Get_Component_Val (Expr) * Uint_2 ** Shift; + -- Loop to set the values - for J in 2 .. Len loop - Shift := Shift + Incr; - Next (Expr); - Aggregate_Val := - Aggregate_Val + Get_Component_Val (Expr) * Uint_2 ** Shift; - end loop; - end if; + if Len = 0 then + Aggregate_Val := Uint_0; + else + Expr := First (Expressions (N)); + Aggregate_Val := Get_Component_Val (Expr) * Uint_2 ** Shift; + + for J in 2 .. Len loop + Shift := Shift + Incr; + Next (Expr); + Aggregate_Val := + Aggregate_Val + + Get_Component_Val (Expr) * Uint_2 ** Shift; + end loop; + end if; - -- Now we can rewrite with the proper value + -- Now we can rewrite with the proper value - Lit := Make_Integer_Literal (Loc, Intval => Aggregate_Val); - Set_Print_In_Hex (Lit); + Lit := Make_Integer_Literal (Loc, Intval => Aggregate_Val); + Set_Print_In_Hex (Lit); - -- Construct the expression using this literal. Note that it is - -- important to qualify the literal with its proper modular type - -- since universal integer does not have the required range and - -- also this is a left justified modular type, which is important - -- in the big-endian case. + -- Construct the expression using this literal. Note that it + -- is important to qualify the literal with its proper modular + -- type since universal integer does not have the required + -- range and also this is a left justified modular type, + -- which is important in the big-endian case. - Rewrite (N, - Unchecked_Convert_To (Typ, - Make_Qualified_Expression (Loc, - Subtype_Mark => - New_Occurrence_Of (Packed_Array_Impl_Type (Typ), Loc), - Expression => Lit))); + Rewrite (N, + Unchecked_Convert_To (Typ, + Make_Qualified_Expression (Loc, + Subtype_Mark => + New_Occurrence_Of (Packed_Array_Impl_Type (Typ), Loc), + Expression => Lit))); - Analyze_And_Resolve (N, Typ); - return True; + Analyze_And_Resolve (N, Typ); + return True; + end; end; end; @@ -9408,8 +9416,6 @@ package body Exp_Aggr is (Obj_Type : Entity_Id; Typ : Entity_Id) return Boolean is - L1, L2, H1, H2 : Node_Id; - begin -- No sliding if the type of the object is not established yet, if it is -- an unconstrained type whose actual subtype comes from the aggregate, @@ -9427,20 +9433,25 @@ package body Exp_Aggr is else -- Sliding can only occur along the first dimension - Get_Index_Bounds (First_Index (Typ), L1, H1); - Get_Index_Bounds (First_Index (Obj_Type), L2, H2); + declare + Bounds1 : constant Range_Nodes := + Get_Index_Bounds (First_Index (Typ)); + Bounds2 : constant Range_Nodes := + Get_Index_Bounds (First_Index (Obj_Type)); - if not Is_OK_Static_Expression (L1) or else - not Is_OK_Static_Expression (L2) or else - not Is_OK_Static_Expression (H1) or else - not Is_OK_Static_Expression (H2) - then - return False; - else - return Expr_Value (L1) /= Expr_Value (L2) - or else - Expr_Value (H1) /= Expr_Value (H2); - end if; + begin + if not Is_OK_Static_Expression (Bounds1.First) or else + not Is_OK_Static_Expression (Bounds2.First) or else + not Is_OK_Static_Expression (Bounds1.Last) or else + not Is_OK_Static_Expression (Bounds2.Last) + then + return False; + else + return Expr_Value (Bounds1.First) /= Expr_Value (Bounds2.First) + or else + Expr_Value (Bounds1.Last) /= Expr_Value (Bounds2.Last); + end if; + end; end if; end Must_Slide; diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 0070706..4eba6fb 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -1500,12 +1500,13 @@ package body Exp_Ch5 is (if Nkind (Name (N)) = N_Slice then Get_Index_Bounds (Discrete_Range (Name (N))) else Larray_Bounds); - -- If the left-hand side is A (L..H), Larray_Bounds is A'Range, and - -- L_Bounds is L..H. If it's not a slice, we treat it like a slice - -- starting at A'First. + -- If the left-hand side is A (First..Last), Larray_Bounds is A'Range, + -- and L_Bounds is First..Last. If it's not a slice, we treat it like + -- a slice starting at A'First. L_Bit : constant Node_Id := - Make_Integer_Literal (Loc, (L_Bounds.L - Larray_Bounds.L) * C_Size); + Make_Integer_Literal + (Loc, (L_Bounds.First - Larray_Bounds.First) * C_Size); Rarray_Bounds : constant Range_Values := Get_Index_Bounds (First_Index (R_Typ)); @@ -1515,7 +1516,8 @@ package body Exp_Ch5 is else Rarray_Bounds); R_Bit : constant Node_Id := - Make_Integer_Literal (Loc, (R_Bounds.L - Rarray_Bounds.L) * C_Size); + Make_Integer_Literal + (Loc, (R_Bounds.First - Rarray_Bounds.First) * C_Size); Size : constant Node_Id := Make_Op_Multiply (Loc, @@ -1594,17 +1596,21 @@ package body Exp_Ch5 is Rev : Boolean) return Node_Id is + L : constant Node_Id := Name (N); + R : constant Node_Id := Expression (N); + -- Left- and right-hand sides of the assignment statement + Slices : constant Boolean := - Nkind (Name (N)) = N_Slice or else Nkind (Expression (N)) = N_Slice; + Nkind (L) = N_Slice or else Nkind (R) = N_Slice; L_Prefix_Comp : constant Boolean := -- True if the left-hand side is a slice of a component or slice - Nkind (Name (N)) = N_Slice - and then Nkind (Prefix (Name (N))) in + Nkind (L) = N_Slice + and then Nkind (Prefix (L)) in N_Selected_Component | N_Indexed_Component | N_Slice; R_Prefix_Comp : constant Boolean := -- Likewise for the right-hand side - Nkind (Expression (N)) = N_Slice - and then Nkind (Prefix (Expression (N))) in + Nkind (R) = N_Slice + and then Nkind (Prefix (R)) in N_Selected_Component | N_Indexed_Component | N_Slice; begin @@ -1664,27 +1670,28 @@ package body Exp_Ch5 is Get_Index_Bounds (Right_Base_Index); Known_Left_Slice_Low : constant Boolean := - (if Nkind (Name (N)) = N_Slice + (if Nkind (L) = N_Slice then Compile_Time_Known_Value - (Get_Index_Bounds (Discrete_Range (Name (N))).L)); + (Get_Index_Bounds (Discrete_Range (L)).First)); Known_Right_Slice_Low : constant Boolean := - (if Nkind (Expression (N)) = N_Slice + (if Nkind (R) = N_Slice then Compile_Time_Known_Value - (Get_Index_Bounds (Discrete_Range (Expression (N))).H)); + (Get_Index_Bounds (Discrete_Range (R)).Last)); Val_Bits : constant Pos := Standard_Long_Long_Integer_Size / 2; begin - if Left_Base_Range.H - Left_Base_Range.L < Val_Bits - and then Right_Base_Range.H - Right_Base_Range.L < Val_Bits + if Left_Base_Range.Last - Left_Base_Range.First < Val_Bits + and then Right_Base_Range.Last - Right_Base_Range.First < + Val_Bits and then Known_Esize (L_Type) and then Known_Esize (R_Type) and then Known_Left_Slice_Low and then Known_Right_Slice_Low and then Compile_Time_Known_Value - (Get_Index_Bounds (First_Index (Etype (Larray))).L) + (Get_Index_Bounds (First_Index (Etype (Larray))).First) and then Compile_Time_Known_Value - (Get_Index_Bounds (First_Index (Etype (Rarray))).L) + (Get_Index_Bounds (First_Index (Etype (Rarray))).First) and then not (Is_Enumeration_Type (Etype (Left_Base_Index)) and then Has_Enumeration_Rep_Clause diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 81e0e87..23b64a0 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -867,11 +867,8 @@ package body Freeze is ---------------- function Size_Known (T : Entity_Id) return Boolean is - Index : Entity_Id; Comp : Entity_Id; Ctyp : Entity_Id; - Low : Node_Id; - High : Node_Id; begin if Size_Known_At_Compile_Time (T) then @@ -918,8 +915,11 @@ package body Freeze is -- thus may be packable). declare - Size : Uint := Component_Size (T); - Dim : Uint; + Index : Entity_Id; + Low : Node_Id; + High : Node_Id; + Size : Uint := Component_Size (T); + Dim : Uint; begin Index := First_Index (T); diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index e7e0c84..c0bc4b7 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -10978,7 +10978,7 @@ package body Sem_Util is Use_Full_View : Boolean := False) return Range_Nodes is Result : Range_Nodes; begin - Get_Index_Bounds (N, Result.L, Result.H, Use_Full_View); + Get_Index_Bounds (N, Result.First, Result.Last, Use_Full_View); return Result; end Get_Index_Bounds; @@ -10987,7 +10987,7 @@ package body Sem_Util is Use_Full_View : Boolean := False) return Range_Values is Nodes : constant Range_Nodes := Get_Index_Bounds (N, Use_Full_View); begin - return (Expr_Value (Nodes.L), Expr_Value (Nodes.H)); + return (Expr_Value (Nodes.First), Expr_Value (Nodes.Last)); end Get_Index_Bounds; ----------------------------- diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index 9f15f44..10f1ba5 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -1177,11 +1177,11 @@ package Sem_Util is -- arise during normal compilation of semantically correct programs. type Range_Nodes is record - L, H : Node_Id; -- First and Last nodes of a discrete_range + First, Last : Node_Id; -- First and Last nodes of a discrete_range end record; type Range_Values is record - L, H : Uint; -- First and Last values of a discrete_range + First, Last : Uint; -- First and Last values of a discrete_range end record; function Get_Index_Bounds -- cgit v1.1 From b9713be32ba408b1d8002d92c589c6c3ed8f8831 Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Thu, 8 Apr 2021 10:44:19 +0200 Subject: [Ada] Fix crash when printing error message gcc/ada/ * freeze.adb (Freeze_Profile): Use N's Sloc, F_type's chars. --- gcc/ada/freeze.adb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 23b64a0..21d24cd 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -4141,9 +4141,10 @@ package body Freeze is elsif not After_Last_Declaration and then not Freezing_Library_Level_Tagged_Type then - Error_Msg_Node_1 := F_Type; - Error_Msg_N - ("type & must be fully defined before this point", N); + Error_Msg_NE + ("type & must be fully defined before this point", + N, + F_Type); end if; end if; -- cgit v1.1 From b4b023c4267801dce118923421124e0d9f65075f Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Fri, 16 Apr 2021 16:07:31 -0700 Subject: [Ada] Add Ada 2022 Image and Put_Image support for tagged types gcc/ada/ * debug.adb: Remove comments about -gnatd_z switch. * exp_ch3.adb (Make_Predefined_Primitive_Specs): A one-line fix for a subtle bug that took some effort to debug. Append a new Put_Image procedure for a type extension even if it seems to already have one, just as is done for (for example) the streaming-related Read procedure. * exp_put_image.adb: (Build_Record_Put_Image_Procedure.Make_Component_Attributes): Do not treat _Parent component like just another component, for two reasons. 1. If the _parent component's type has a user-specified Put_Image procedure, then we want to generate a call to that procedure and then generate extension aggregate syntax. 2. Otherwise, we still don't want to see any mention of "_parent" in the generated image text. (Build_Record_Put_Image_Procedure.Make_Component_Name): Add assertion that we are not generating a reference to an "_parent" component. (Build_Record_Put_Image_Procedure): Add special treatment for null records. Add call to Duplicate_Subexpr for image attribute prefix in order to help with expansion needed in the class-wide case (where the prefix is also referenced in the call to Wide_Wide_Expanded_Name) if evaluation of the prefix has side effects. Add new local helper function, Put_String_Exp. Add support for case where prefix type is class-wide. (Enable_Put_Image, Preload_Root_Buffer_Type): Query Ada_Version > Ada_2022 instead of (indirectly) querying -gnatd_z switch. * freeze.adb (In_Expanded_Body): A one-line change to add TSS_Put_Image to the list of subprograms that have expander-created bodies. * rtsfind.ads: Add support for accessing Ada.Tags.Wide_Wide_Expanded_Name. * sem_ch3.ads, sem_ch3.adb: Delete Is_Null_Extension function, as part of moving it to Sem_Util. * sem_ch13.adb (Analyze_Put_Image_TSS_Definition.Has_Good_Profile): Improve diagnostic messages in cases where the result is going to be False and the Report parameter is True. Relax overly-restrictive checks in order to implement mode conformance. (Analyze_Stream_TSS_Definition.Has_Good_Profile): Add similar relaxation of parameter subtype checking for the Stream parameter of user-defined streaming subprograms. * sem_disp.adb (Check_Dispatching_Operation): A one-line change (and an accompanying comment change) to add TSS_Put_Image to the list of compiler-generated dispatching primitive operations. * sem_util.ads, sem_util.adb: Add Ignore_Privacy Boolean parameter to Is_Null_Record_Type function (typically the parameter will be False when the function is being used in the implementation of static semantics and True for dynamic semantics; the parameter might make a difference in the case of, for example, a private type that is implemented as a null record type). Add related new routines Is_Null_Extension (formerly declared in Sem_Ch3), Is_Null_Extension_Of, and Is_Null_Record_Definition. --- gcc/ada/debug.adb | 5 +- gcc/ada/exp_ch3.adb | 4 +- gcc/ada/exp_put_image.adb | 286 ++++++++++++++++++++++++++++++++++++---------- gcc/ada/freeze.adb | 1 + gcc/ada/rtsfind.ads | 2 + gcc/ada/sem_ch13.adb | 54 ++++++--- gcc/ada/sem_ch3.adb | 50 -------- gcc/ada/sem_ch3.ads | 5 - gcc/ada/sem_disp.adb | 4 +- gcc/ada/sem_util.adb | 143 +++++++++++++++++++++-- gcc/ada/sem_util.ads | 25 +++- 11 files changed, 425 insertions(+), 154 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index 3f1fa55..978f333 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -164,7 +164,7 @@ package body Debug is -- d_w -- d_x Disable inline expansion of Image attribute for enumeration types -- d_y - -- d_z Enable Put_Image on tagged types + -- d_z -- d_A Stop generation of ALI file -- d_B Warn on build-in-place function calls @@ -993,9 +993,6 @@ package body Debug is -- d_x The compiler does not expand in line the Image attribute for user- -- defined enumeration types and the standard boolean type. - -- d_z Enable the default Put_Image on tagged types that are not - -- predefined. - -- d_A Do not generate ALI files by setting Opt.Disable_ALI_File. -- d_B Warn on build-in-place function calls. This allows users to diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 4dbaadd..ce6d294 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -10345,9 +10345,7 @@ package body Exp_Ch3 is -- Spec of Put_Image - if Enable_Put_Image (Tag_Typ) - and then No (TSS (Tag_Typ, TSS_Put_Image)) - then + if Enable_Put_Image (Tag_Typ) then Append_To (Res, Predef_Spec_Or_Body (Loc, Tag_Typ => Tag_Typ, Name => Make_TSS_Name (Tag_Typ, TSS_Put_Image), diff --git a/gcc/ada/exp_put_image.adb b/gcc/ada/exp_put_image.adb index 33c72c3..3a9751b 100644 --- a/gcc/ada/exp_put_image.adb +++ b/gcc/ada/exp_put_image.adb @@ -23,13 +23,14 @@ -- -- ------------------------------------------------------------------------------ +with Aspects; use Aspects; with Atree; use Atree; +with Csets; use Csets; with Einfo; use Einfo; with Einfo.Entities; use Einfo.Entities; with Einfo.Utils; use Einfo.Utils; with Exp_Tss; use Exp_Tss; -with Exp_Util; -with Debug; use Debug; +with Exp_Util; use Exp_Util; with Lib; use Lib; with Namet; use Namet; with Nlists; use Nlists; @@ -49,9 +50,6 @@ with Uintp; use Uintp; package body Exp_Put_Image is - Tagged_Put_Image_Enabled : Boolean renames Debug_Flag_Underscore_Z; - -- ???Set True to enable Put_Image for at least some tagged types - ----------------------- -- Local Subprograms -- ----------------------- @@ -649,32 +647,90 @@ package body Exp_Put_Image is -- Loop through components, skipping all internal components, -- which are not part of the value (e.g. _Tag), except that we -- don't skip the _Parent, since we do want to process that - -- recursively. If _Parent is an interface type, being abstract - -- with no components there is no need to handle it. + -- recursively. while Present (Item) loop if Nkind (Item) in N_Component_Declaration | N_Discriminant_Specification - and then - ((Chars (Defining_Identifier (Item)) = Name_uParent - and then not Is_Interface - (Etype (Defining_Identifier (Item)))) - or else - not Is_Internal_Name (Chars (Defining_Identifier (Item)))) then - if First_Time then - First_Time := False; - else - Append_To (Result, - Make_Procedure_Call_Statement (Loc, - Name => - New_Occurrence_Of (RTE (RE_Record_Between), Loc), - Parameter_Associations => New_List - (Make_Identifier (Loc, Name_S)))); + if Chars (Defining_Identifier (Item)) = Name_uParent then + declare + Parent_Type : constant Entity_Id := + Underlying_Type (Base_Type ( + (Etype (Defining_Identifier (Item))))); + + Parent_Aspect_Spec : constant Node_Id := + Find_Aspect (Parent_Type, Aspect_Put_Image); + + Parent_Type_Decl : constant Node_Id := + Declaration_Node (Parent_Type); + + Parent_Rdef : Node_Id := + Type_Definition (Parent_Type_Decl); + begin + -- If parent type has an noninherited + -- explicitly-specified Put_Image aspect spec, then + -- display parent part by calling specified procedure, + -- and then use extension-aggregate syntax for the + -- remaining components as per RM 4.10(15/5); + -- otherwise, "look through" the parent component + -- to its components - we don't want the image text + -- to include mention of an "_parent" component. + + if Present (Parent_Aspect_Spec) and then + Entity (Parent_Aspect_Spec) = Parent_Type + then + Append_Component_Attr + (Result, Defining_Identifier (Item)); + + -- Omit the " with " if no subsequent components. + + if not Is_Null_Extension_Of + (Descendant => Typ, + Ancestor => Parent_Type) + then + Append_To (Result, + Make_Procedure_Call_Statement (Loc, + Name => + New_Occurrence_Of + (RTE (RE_Put_UTF_8), Loc), + Parameter_Associations => New_List + (Make_Identifier (Loc, Name_S), + Make_String_Literal (Loc, " with ")))); + end if; + else + if Nkind (Parent_Rdef) = N_Derived_Type_Definition + then + Parent_Rdef := + Record_Extension_Part (Parent_Rdef); + end if; + + if Present (Component_List (Parent_Rdef)) then + Append_List_To (Result, + Make_Component_List_Attributes + (Component_List (Parent_Rdef))); + end if; + end if; + end; + + elsif not Is_Internal_Name + (Chars (Defining_Identifier (Item))) + then + if First_Time then + First_Time := False; + else + Append_To (Result, + Make_Procedure_Call_Statement (Loc, + Name => + New_Occurrence_Of (RTE (RE_Record_Between), Loc), + Parameter_Associations => New_List + (Make_Identifier (Loc, Name_S)))); + end if; + + Append_To (Result, Make_Component_Name (Item)); + Append_Component_Attr + (Result, Defining_Identifier (Item)); end if; - - Append_To (Result, Make_Component_Name (Item)); - Append_Component_Attr (Result, Defining_Identifier (Item)); end if; Next (Item); @@ -690,13 +746,35 @@ package body Exp_Put_Image is function Make_Component_Name (C : Entity_Id) return Node_Id is Name : constant Name_Id := Chars (Defining_Identifier (C)); + pragma Assert (Name /= Name_uParent); + + function To_Upper (S : String) return String; + -- Same as Ada.Characters.Handling.To_Upper, but withing + -- Ada.Characters.Handling seems to cause mailserver problems. + + -------------- + -- To_Upper -- + -------------- + + function To_Upper (S : String) return String is + begin + return Result : String := S do + for Char of Result loop + Char := Fold_Upper (Char); + end loop; + end return; + end To_Upper; + + -- Start of processing for Make_Component_Name + begin return Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Put_UTF_8), Loc), Parameter_Associations => New_List (Make_Identifier (Loc, Name_S), - Make_String_Literal (Loc, Get_Name_String (Name) & " => "))); + Make_String_Literal (Loc, + To_Upper (Get_Name_String (Name)) & " => "))); end Make_Component_Name; Stms : constant List_Id := New_List; @@ -707,38 +785,47 @@ package body Exp_Put_Image is -- Start of processing for Build_Record_Put_Image_Procedure begin - Append_To (Stms, - Make_Procedure_Call_Statement (Loc, - Name => New_Occurrence_Of (RTE (RE_Record_Before), Loc), - Parameter_Associations => New_List - (Make_Identifier (Loc, Name_S)))); + if Is_Null_Record_Type (Btyp, Ignore_Privacy => True) then + Append_To (Stms, + Make_Procedure_Call_Statement (Loc, + Name => New_Occurrence_Of (RTE (RE_Put_UTF_8), Loc), + Parameter_Associations => New_List + (Make_Identifier (Loc, Name_S), + Make_String_Literal (Loc, "(NULL RECORD)")))); + else + Append_To (Stms, + Make_Procedure_Call_Statement (Loc, + Name => New_Occurrence_Of (RTE (RE_Record_Before), Loc), + Parameter_Associations => New_List + (Make_Identifier (Loc, Name_S)))); - -- Generate Put_Images for the discriminants of the type + -- Generate Put_Images for the discriminants of the type - Append_List_To (Stms, - Make_Component_Attributes (Discriminant_Specifications (Type_Decl))); + Append_List_To (Stms, + Make_Component_Attributes + (Discriminant_Specifications (Type_Decl))); - Rdef := Type_Definition (Type_Decl); + Rdef := Type_Definition (Type_Decl); - -- In the record extension case, the components we want, including the - -- _Parent component representing the parent type, are to be found in - -- the extension. We will process the _Parent component using the type - -- of the parent. + -- In the record extension case, the components we want are to be + -- found in the extension (although we have to process the + -- _Parent component to find inherited components). - if Nkind (Rdef) = N_Derived_Type_Definition then - Rdef := Record_Extension_Part (Rdef); - end if; + if Nkind (Rdef) = N_Derived_Type_Definition then + Rdef := Record_Extension_Part (Rdef); + end if; - if Present (Component_List (Rdef)) then - Append_List_To (Stms, - Make_Component_List_Attributes (Component_List (Rdef))); - end if; + if Present (Component_List (Rdef)) then + Append_List_To (Stms, + Make_Component_List_Attributes (Component_List (Rdef))); + end if; - Append_To (Stms, - Make_Procedure_Call_Statement (Loc, - Name => New_Occurrence_Of (RTE (RE_Record_After), Loc), - Parameter_Associations => New_List - (Make_Identifier (Loc, Name_S)))); + Append_To (Stms, + Make_Procedure_Call_Statement (Loc, + Name => New_Occurrence_Of (RTE (RE_Record_After), Loc), + Parameter_Associations => New_List + (Make_Identifier (Loc, Name_S)))); + end if; Pnam := Make_Put_Image_Name (Loc, Btyp); Build_Put_Image_Proc (Loc, Btyp, Decl, Pnam, Stms); @@ -843,9 +930,9 @@ package body Exp_Put_Image is -- -- Put_Image on tagged types triggers some bugs. - if Is_Remote_Types (Scope (Typ)) + if Ada_Version < Ada_2022 + or else Is_Remote_Types (Scope (Typ)) or else (Is_Tagged_Type (Typ) and then In_Predefined_Unit (Typ)) - or else (Is_Tagged_Type (Typ) and then not Tagged_Put_Image_Enabled) then return False; end if; @@ -952,7 +1039,7 @@ package body Exp_Put_Image is -- For T'Image (X) Generate an Expression_With_Actions node: -- -- do - -- S : Buffer := New_Buffer; + -- S : Buffer; -- U_Type'Put_Image (S, X); -- Result : constant String := Get (S); -- Destroy (S); @@ -970,13 +1057,16 @@ package body Exp_Put_Image is Object_Definition => New_Occurrence_Of (RTE (RE_Buffer_Type), Loc)); + Image_Prefix : constant Node_Id := + Duplicate_Subexpr (First (Expressions (N))); + Put_Im : constant Node_Id := Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (U_Type, Loc), Attribute_Name => Name_Put_Image, Expressions => New_List ( New_Occurrence_Of (Sink_Entity, Loc), - New_Copy_Tree (First (Expressions (N))))); + Image_Prefix)); Result_Entity : constant Entity_Id := Make_Defining_Identifier (Loc, Chars => New_Internal_Name ('R')); Result_Decl : constant Node_Id := @@ -989,12 +1079,86 @@ package body Exp_Put_Image is Name => New_Occurrence_Of (RTE (RE_Get), Loc), Parameter_Associations => New_List ( New_Occurrence_Of (Sink_Entity, Loc)))); - Image : constant Node_Id := - Make_Expression_With_Actions (Loc, - Actions => New_List (Sink_Decl, Put_Im, Result_Decl), - Expression => New_Occurrence_Of (Result_Entity, Loc)); + Actions : List_Id; + + function Put_String_Exp (String_Exp : Node_Id; + Wide_Wide : Boolean := False) return Node_Id; + -- Generate a call to evaluate a String (or Wide_Wide_String, depending + -- on the Wide_Wide Boolean parameter) expression and output it into + -- the buffer. + + -------------------- + -- Put_String_Exp -- + -------------------- + + function Put_String_Exp (String_Exp : Node_Id; + Wide_Wide : Boolean := False) return Node_Id is + Put_Id : constant RE_Id := + (if Wide_Wide then RE_Wide_Wide_Put else RE_Put_UTF_8); + + -- We could build a nondispatching call here, but to make + -- that work we'd have to change Rtsfind spec to make available + -- corresponding callees out of Ada.Strings.Text_Buffers.Unbounded + -- (as opposed to from Ada.Strings.Text_Buffers). Seems simpler to + -- introduce a type conversion and leave it to the optimizer to + -- eliminate the dispatching. This does not *introduce* any problems + -- if a no-dispatching-allowed restriction is in effect, since we + -- are already in the middle of generating a call to T'Class'Image. + + Sink_Exp : constant Node_Id := + Make_Type_Conversion (Loc, + Subtype_Mark => + New_Occurrence_Of + (Class_Wide_Type (RTE (RE_Root_Buffer_Type)), Loc), + Expression => New_Occurrence_Of (Sink_Entity, Loc)); + begin + return + Make_Procedure_Call_Statement (Loc, + Name => New_Occurrence_Of (RTE (Put_Id), Loc), + Parameter_Associations => New_List (Sink_Exp, String_Exp)); + end Put_String_Exp; + + -- Start of processing for Build_Image_Call + begin - return Image; + if Is_Class_Wide_Type (U_Type) then + -- Generate qualified-expression syntax; qualification name comes + -- from calling Ada.Tags.Wide_Wide_Expanded_Name. + + declare + -- The copy of Image_Prefix will be evaluated before the + -- original, which is ok if no side effects are involved. + + pragma Assert (Side_Effect_Free (Image_Prefix)); + + Specific_Type_Name : constant Node_Id := + Put_String_Exp + (Make_Function_Call (Loc, + Name => New_Occurrence_Of + (RTE (RE_Wide_Wide_Expanded_Name), Loc), + Parameter_Associations => New_List ( + Make_Attribute_Reference (Loc, + Prefix => Duplicate_Subexpr (Image_Prefix), + Attribute_Name => Name_Tag))), + Wide_Wide => True); + + Qualification : constant Node_Id := + Put_String_Exp (Make_String_Literal (Loc, "'")); + begin + Actions := New_List + (Sink_Decl, + Specific_Type_Name, + Qualification, + Put_Im, + Result_Decl); + end; + else + Actions := New_List (Sink_Decl, Put_Im, Result_Decl); + end if; + + return Make_Expression_With_Actions (Loc, + Actions => Actions, + Expression => New_Occurrence_Of (Result_Entity, Loc)); end Build_Image_Call; ------------------------------ @@ -1023,7 +1187,7 @@ package body Exp_Put_Image is -- Don't do it if type Root_Buffer_Type is unavailable in the runtime. if not In_Predefined_Unit (Compilation_Unit) - and then Tagged_Put_Image_Enabled + and then Ada_Version >= Ada_2022 and then Tagged_Seen and then not No_Run_Time_Mode and then RTE_Available (RE_Root_Buffer_Type) diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 21d24cd..fa16887 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -7591,6 +7591,7 @@ package body Freeze is or else Is_TSS (Id, TSS_Stream_Output) or else Is_TSS (Id, TSS_Stream_Read) or else Is_TSS (Id, TSS_Stream_Write) + or else Is_TSS (Id, TSS_Put_Image) or else Nkind (Original_Node (P)) = N_Subprogram_Renaming_Declaration) then diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads index ad84e9e..6bec611 100644 --- a/gcc/ada/rtsfind.ads +++ b/gcc/ada/rtsfind.ads @@ -708,6 +708,7 @@ package Rtsfind is RE_TK_Tagged, -- Ada.Tags RE_TK_Task, -- Ada.Tags RE_Unregister_Tag, -- Ada.Tags + RE_Wide_Wide_Expanded_Name, -- Ada.Tags RE_Set_Specific_Handler, -- Ada.Task_Termination RE_Specific_Handler, -- Ada.Task_Termination @@ -2389,6 +2390,7 @@ package Rtsfind is RE_TK_Tagged => Ada_Tags, RE_TK_Task => Ada_Tags, RE_Unregister_Tag => Ada_Tags, + RE_Wide_Wide_Expanded_Name => Ada_Tags, RE_Set_Specific_Handler => Ada_Task_Termination, RE_Specific_Handler => Ada_Task_Termination, diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index dcd5954..83d7d3c 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -5230,44 +5230,64 @@ package body Sem_Ch13 is F := First_Formal (Subp); - if No (F) - or else Etype (F) /= Class_Wide_Type (RTE (RE_Root_Buffer_Type)) + if No (F) then + return False; + end if; + + if Base_Type (Etype (F)) + /= Class_Wide_Type (RTE (RE_Root_Buffer_Type)) then + if Report then + Error_Msg_N + ("wrong type for Put_Image procedure''s first parameter", + Parameter_Type (Parent (F))); + end if; + return False; end if; - Next_Formal (F); + if Parameter_Mode (F) /= E_In_Out_Parameter then + if Report then + Error_Msg_N + ("wrong mode for Put_Image procedure''s first parameter", + Parent (F)); + end if; - if Parameter_Mode (F) /= E_In_Parameter then return False; end if; + Next_Formal (F); + Typ := Etype (F); -- Verify that the prefix of the attribute and the local name for -- the type of the formal match. - if Typ /= Ent then - return False; - end if; + if Base_Type (Typ) /= Base_Type (Ent) then + if Report then + Error_Msg_N + ("wrong type for Put_Image procedure''s second parameter", + Parameter_Type (Parent (F))); + end if; - if Present (Next_Formal (F)) then return False; + end if; - elsif not Is_Scalar_Type (Typ) - and then not Is_First_Subtype (Typ) - then - if Report and not Is_First_Subtype (Typ) then + if Parameter_Mode (F) /= E_In_Parameter then + if Report then Error_Msg_N - ("subtype of formal in Put_Image operation must be a " - & "first subtype", Parameter_Type (Parent (F))); + ("wrong mode for Put_Image procedure''s second parameter", + Parent (F)); end if; return False; + end if; - else - return True; + if Present (Next_Formal (F)) then + return False; end if; + + return True; end Has_Good_Profile; -- Start of processing for Analyze_Put_Image_TSS_Definition @@ -5386,7 +5406,7 @@ package body Sem_Ch13 is if No (F) or else Ekind (Etype (F)) /= E_Anonymous_Access_Type - or else Designated_Type (Etype (F)) /= + or else Base_Type (Designated_Type (Etype (F))) /= Class_Wide_Type (RTE (RE_Root_Stream_Type)) then return False; diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 7a24298..4250483 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -19013,56 +19013,6 @@ package body Sem_Ch3 is return False; end Is_EVF_Procedure; - ----------------------- - -- Is_Null_Extension -- - ----------------------- - - function Is_Null_Extension (T : Entity_Id) return Boolean is - Type_Decl : constant Node_Id := Parent (Base_Type (T)); - Comp_List : Node_Id; - Comp : Node_Id; - - begin - if Nkind (Type_Decl) /= N_Full_Type_Declaration - or else not Is_Tagged_Type (T) - or else Nkind (Type_Definition (Type_Decl)) /= - N_Derived_Type_Definition - or else No (Record_Extension_Part (Type_Definition (Type_Decl))) - then - return False; - end if; - - Comp_List := - Component_List (Record_Extension_Part (Type_Definition (Type_Decl))); - - if Present (Discriminant_Specifications (Type_Decl)) then - return False; - - elsif Present (Comp_List) - and then Is_Non_Empty_List (Component_Items (Comp_List)) - then - Comp := First (Component_Items (Comp_List)); - - -- Only user-defined components are relevant. The component list - -- may also contain a parent component and internal components - -- corresponding to secondary tags, but these do not determine - -- whether this is a null extension. - - while Present (Comp) loop - if Comes_From_Source (Comp) then - return False; - end if; - - Next (Comp); - end loop; - - return True; - - else - return True; - end if; - end Is_Null_Extension; - -------------------------- -- Is_Private_Primitive -- -------------------------- diff --git a/gcc/ada/sem_ch3.ads b/gcc/ada/sem_ch3.ads index dcd4a34..eedb98c 100644 --- a/gcc/ada/sem_ch3.ads +++ b/gcc/ada/sem_ch3.ads @@ -176,11 +176,6 @@ package Sem_Ch3 is -- corresponding to that discriminant in the constraint that specifies its -- value. - function Is_Null_Extension (T : Entity_Id) return Boolean; - -- Returns True if the tagged type T has an N_Full_Type_Declaration that - -- is a null extension, meaning that it has an extension part without any - -- components and does not have a known discriminant part. - function Is_Visible_Component (C : Entity_Id; N : Node_Id := Empty) return Boolean; diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb index 15b700fa..06c4b07 100644 --- a/gcc/ada/sem_disp.adb +++ b/gcc/ada/sem_disp.adb @@ -45,7 +45,6 @@ with Restrict; use Restrict; with Rident; use Rident; with Sem; use Sem; with Sem_Aux; use Sem_Aux; -with Sem_Ch3; use Sem_Ch3; with Sem_Ch6; use Sem_Ch6; with Sem_Ch8; use Sem_Ch8; with Sem_Eval; use Sem_Eval; @@ -1209,7 +1208,7 @@ package body Sem_Disp is -- primitives. -- 3. Subprograms associated with stream attributes (built by - -- New_Stream_Subprogram) + -- New_Stream_Subprogram) or with the Put_Image attribute. -- 4. Wrappers built for inherited operations with inherited class- -- wide conditions, where the conditions include calls to other @@ -1238,6 +1237,7 @@ package body Sem_Disp is or else Get_TSS_Name (Subp) = TSS_Stream_Read or else Get_TSS_Name (Subp) = TSS_Stream_Write + or else Get_TSS_Name (Subp) = TSS_Put_Image or else (Is_Wrapper (Subp) diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index c0bc4b7..e5b76f3 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -712,7 +712,7 @@ package body Sem_Util is return Make_Level_Literal (Type_Access_Level (Etype (E))); - -- A non-discriminant selected component where the component + -- A nondiscriminant selected component where the component -- is an anonymous access type means that its associated -- level is that of the containing type - see RM 3.10.2 (16). @@ -18576,18 +18576,143 @@ package body Sem_Util is return False; end Is_Nontrivial_DIC_Procedure; + ----------------------- + -- Is_Null_Extension -- + ----------------------- + + function Is_Null_Extension + (T : Entity_Id; Ignore_Privacy : Boolean := False) return Boolean + is + Type_Decl : Node_Id; + Type_Def : Node_Id; + begin + if Ignore_Privacy then + Type_Decl := Parent (Underlying_Type (Base_Type (T))); + else + Type_Decl := Parent (Base_Type (T)); + if Nkind (Type_Decl) /= N_Full_Type_Declaration then + return False; + end if; + end if; + pragma Assert (Nkind (Type_Decl) = N_Full_Type_Declaration); + Type_Def := Type_Definition (Type_Decl); + if Present (Discriminant_Specifications (Type_Decl)) + or else Nkind (Type_Def) /= N_Derived_Type_Definition + or else not Is_Tagged_Type (T) + or else No (Record_Extension_Part (Type_Def)) + then + return False; + end if; + + return Is_Null_Record_Definition (Record_Extension_Part (Type_Def)); + end Is_Null_Extension; + + -------------------------- + -- Is_Null_Extension_Of -- + -------------------------- + + function Is_Null_Extension_Of + (Descendant, Ancestor : Entity_Id) return Boolean + is + Ancestor_Type : constant Entity_Id + := Underlying_Type (Base_Type (Ancestor)); + Descendant_Type : Entity_Id := Underlying_Type (Base_Type (Descendant)); + begin + pragma Assert (Descendant_Type /= Ancestor_Type); + while Descendant_Type /= Ancestor_Type loop + if not Is_Null_Extension + (Descendant_Type, Ignore_Privacy => True) + then + return False; + end if; + Descendant_Type := Etype (Subtype_Indication + (Type_Definition (Parent (Descendant_Type)))); + Descendant_Type := Underlying_Type (Base_Type (Descendant_Type)); + end loop; + return True; + end Is_Null_Extension_Of; + + ------------------------------- + -- Is_Null_Record_Definition -- + ------------------------------- + + function Is_Null_Record_Definition (Record_Def : Node_Id) return Boolean is + Item : Node_Id; + begin + -- Testing Null_Present is just an optimization, not required. + + if Null_Present (Record_Def) then + return True; + elsif Present (Variant_Part (Component_List (Record_Def))) then + return False; + elsif not Present (Component_List (Record_Def)) then + return True; + end if; + + Item := First (Component_Items (Component_List (Record_Def))); + + while Present (Item) loop + if Nkind (Item) = N_Component_Declaration + and then Is_Internal_Name (Chars (Defining_Identifier (Item))) + then + null; + elsif Nkind (Item) = N_Pragma then + null; + else + return False; + end if; + Item := Next (Item); + end loop; + + return True; + end Is_Null_Record_Definition; + ------------------------- -- Is_Null_Record_Type -- ------------------------- - function Is_Null_Record_Type (T : Entity_Id) return Boolean is - Decl : constant Node_Id := Parent (T); + function Is_Null_Record_Type + (T : Entity_Id; Ignore_Privacy : Boolean := False) return Boolean + is + Decl : Node_Id; + Type_Def : Node_Id; begin - return Nkind (Decl) = N_Full_Type_Declaration - and then Nkind (Type_Definition (Decl)) = N_Record_Definition - and then - (No (Component_List (Type_Definition (Decl))) - or else Null_Present (Component_List (Type_Definition (Decl)))); + if not Is_Record_Type (T) then + return False; + end if; + + if Ignore_Privacy then + Decl := Parent (Underlying_Type (Base_Type (T))); + else + Decl := Parent (Base_Type (T)); + if Nkind (Decl) /= N_Full_Type_Declaration then + return False; + end if; + end if; + pragma Assert (Nkind (Decl) = N_Full_Type_Declaration); + Type_Def := Type_Definition (Decl); + + if Has_Discriminants (Defining_Identifier (Decl)) then + return False; + end if; + + case Nkind (Type_Def) is + when N_Record_Definition => + return Is_Null_Record_Definition (Type_Def); + when N_Derived_Type_Definition => + if not Is_Null_Record_Type + (Etype (Subtype_Indication (Type_Def)), + Ignore_Privacy => Ignore_Privacy) + then + return False; + elsif not Is_Tagged_Type (T) then + return True; + else + return Is_Null_Extension (T, Ignore_Privacy => Ignore_Privacy); + end if; + when others => + return False; + end case; end Is_Null_Record_Type; --------------------- @@ -19183,7 +19308,7 @@ package body Sem_Util is elsif Is_Tagged_Type (Typ) then return True; - -- Case of non-discriminated record + -- Case of nondiscriminated record else declare diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index 10f1ba5..0894d03 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -2126,9 +2126,28 @@ package Sem_Util is -- assertion expression of pragma Default_Initial_Condition and if it does, -- the encapsulated expression is nontrivial. - function Is_Null_Record_Type (T : Entity_Id) return Boolean; - -- Determine whether T is declared with a null record definition or a - -- null component list. + function Is_Null_Extension + (T : Entity_Id; Ignore_Privacy : Boolean := False) return Boolean; + -- Given a tagged type, returns True if argument is a type extension + -- that introduces no new components (discriminant or nondiscriminant). + -- Ignore_Privacy should be True for use in implementing dynamic semantics. + + function Is_Null_Extension_Of + (Descendant, Ancestor : Entity_Id) return Boolean; + -- Given two tagged types, the first a descendant of the second, + -- returns True if every component of Descendant is inherited + -- (directly or indirectly) from Ancestor. Privacy is ignored. + + function Is_Null_Record_Definition (Record_Def : Node_Id) return Boolean; + -- Returns True for an N_Record_Definition node that has no user-defined + -- components (and no variant part). + + function Is_Null_Record_Type + (T : Entity_Id; Ignore_Privacy : Boolean := False) return Boolean; + -- Determine whether T is declared with a null record definition, a + -- null component list, or as a type derived from a null record type + -- (with a null extension if tagged). Returns True for interface types, + -- False for discriminated types. function Is_Object_Image (Prefix : Node_Id) return Boolean; -- Returns True if an 'Img, 'Image, 'Wide_Image, or 'Wide_Wide_Image -- cgit v1.1 From 243573ff080ed436d8cd9a3273e509ee436434d9 Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Fri, 23 Apr 2021 16:02:19 +0200 Subject: [Ada] Print JSON continuation messages as separate messages gcc/ada/ * errout.adb (Output_JSON_Message): Recursively call Output_JSON_Message for continuation messages instead of appending their content to the initial message. --- gcc/ada/errout.adb | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/errout.adb b/gcc/ada/errout.adb index 8fd2076..0122304 100644 --- a/gcc/ada/errout.adb +++ b/gcc/ada/errout.adb @@ -2079,6 +2079,9 @@ package body Errout is procedure Output_JSON_Message (Error_Id : Error_Msg_Id) is + function Is_Continuation (E : Error_Msg_Id) return Boolean; + -- Return True if E is a continuation message. + procedure Write_JSON_Escaped_String (Str : String_Ptr); -- Write each character of Str, taking care of preceding each quote and -- backslash with a backslash. Note that this escaping differs from what @@ -2099,6 +2102,15 @@ package body Errout is -- Span.Last are different from Span.Ptr, they will be printed as JSON -- locations under the names "start" and "finish". + ----------------------- + -- Is_Continuation -- + ----------------------- + + function Is_Continuation (E : Error_Msg_Id) return Boolean is + begin + return E <= Last_Error_Msg and then Errors.Table (E).Msg_Cont; + end Is_Continuation; + ------------------------------- -- Write_JSON_Escaped_String -- ------------------------------- @@ -2155,6 +2167,10 @@ package body Errout is E : Error_Msg_Id := Error_Id; + Print_Continuations : constant Boolean := not Is_Continuation (E); + -- Do not print continuations messages as children of the current + -- message if the current message is a continuation message. + -- Start of processing for Output_JSON_Message begin @@ -2186,18 +2202,27 @@ package body Errout is Write_Str ("],""message"":"""); Write_JSON_Escaped_String (Errors.Table (E).Text); - - -- Print message continuations if present + Write_Str (""""); E := E + 1; - while E <= Last_Error_Msg and then Errors.Table (E).Msg_Cont loop - Write_Str (", "); - Write_JSON_Escaped_String (Errors.Table (E).Text); + if Print_Continuations and then Is_Continuation (E) then + + Write_Str (",""children"": ["); + Output_JSON_Message (E); E := E + 1; - end loop; - Write_Str ("""}"); + while Is_Continuation (E) loop + Write_Str (", "); + Output_JSON_Message (E); + E := E + 1; + end loop; + + Write_Str ("]"); + + end if; + + Write_Str ("}"); end Output_JSON_Message; --------------------- -- cgit v1.1 From 0b8880428c4da92886b069af714365019f660ade Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 26 Apr 2021 13:32:06 -0400 Subject: [Ada] Spurious error in instantiation with aggregate and private ancestor gcc/ada/ * sem_aggr.adb (Resolve_Record_Aggregate, Step_5): Do not check for the need to use an extension aggregate for a given component when within an instance and the type of the component hss a private ancestor: the instantiation is legal if the generic compiles, and spurious errors may be generated otherwise. --- gcc/ada/sem_aggr.adb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb index d189ab7..9ad9629 100644 --- a/gcc/ada/sem_aggr.adb +++ b/gcc/ada/sem_aggr.adb @@ -5028,12 +5028,19 @@ package body Sem_Aggr is Prepend_Elmt (Parent_Typ, To => Parent_Typ_List); Parent_Typ := Etype (Parent_Typ); + -- Check whether a private parent requires the use of + -- an extension aggregate. This test does not apply in + -- an instantiation: if the generic unit is legal so is + -- the instance. + if Nkind (Parent (Base_Type (Parent_Typ))) = N_Private_Type_Declaration or else Nkind (Parent (Base_Type (Parent_Typ))) = N_Private_Extension_Declaration then - if Nkind (N) /= N_Extension_Aggregate then + if Nkind (N) /= N_Extension_Aggregate + and then not In_Instance + then Error_Msg_NE ("type of aggregate has private ancestor&!", N, Parent_Typ); -- cgit v1.1 From 5c3bbe1d9879a92f8e301382a66749c653fa075e Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Mon, 26 Apr 2021 15:55:21 +0200 Subject: [Ada] Cleanup checking for compatible alignment gcc/ada/ * sem_util.adb (Has_Compatible_Alignment_Internal): Fix indentation of ELSIF comments; remove explicit calls to UI_To_Int; remove extra parens around the MOD operand. --- gcc/ada/sem_util.adb | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index e5b76f3..b7d84af 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -11820,22 +11820,22 @@ package body Sem_Util is Set_Result (Known_Incompatible); end if; - -- See if Expr is an object with known alignment + -- See if Expr is an object with known alignment elsif Is_Entity_Name (Expr) and then Known_Alignment (Entity (Expr)) then ExpA := Alignment (Entity (Expr)); - -- Otherwise, we can use the alignment of the type of - -- Expr given that we already checked for - -- discombobulating rep clauses for the cases of indexed - -- and selected components above. + -- Otherwise, we can use the alignment of the type of Expr + -- given that we already checked for discombobulating rep + -- clauses for the cases of indexed and selected components + -- above. elsif Known_Alignment (Etype (Expr)) then ExpA := Alignment (Etype (Expr)); - -- Otherwise the alignment is unknown + -- Otherwise the alignment is unknown else Set_Result (Default); @@ -11854,14 +11854,14 @@ package body Sem_Util is if Offs /= No_Uint then null; - -- See if Expr is an object with known size + -- See if Expr is an object with known size elsif Is_Entity_Name (Expr) and then Known_Static_Esize (Entity (Expr)) then SizA := Esize (Entity (Expr)); - -- Otherwise, we check the object size of the Expr type + -- Otherwise, we check the object size of the Expr type elsif Known_Static_Esize (Etype (Expr)) then SizA := Esize (Etype (Expr)); @@ -11906,25 +11906,24 @@ package body Sem_Util is -- where we do not know the alignment of Obj. if Known_Alignment (Entity (Expr)) - and then UI_To_Int (Alignment (Entity (Expr))) < - Ttypes.Maximum_Alignment + and then Alignment (Entity (Expr)) < Ttypes.Maximum_Alignment then Set_Result (Unknown); - -- Now check size of Expr object. Any size that is not an - -- even multiple of Maximum_Alignment is also worrisome - -- since it may cause the alignment of the object to be less - -- than the alignment of the type. + -- Now check size of Expr object. Any size that is not an even + -- multiple of Maximum_Alignment is also worrisome since it + -- may cause the alignment of the object to be less than the + -- alignment of the type. elsif Known_Static_Esize (Entity (Expr)) and then - (UI_To_Int (Esize (Entity (Expr))) mod - (Ttypes.Maximum_Alignment * Ttypes.System_Storage_Unit)) + Esize (Entity (Expr)) mod + (Ttypes.Maximum_Alignment * Ttypes.System_Storage_Unit) /= 0 then Set_Result (Unknown); - -- Otherwise same type is decisive + -- Otherwise same type is decisive else Set_Result (Known_Compatible); -- cgit v1.1 From 22c0e0cabd0d9c1f100e7a5f43c8781198e3448e Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Mon, 26 Apr 2021 16:09:49 +0200 Subject: [Ada] Fix comment about the debug flag for strict alignment gcc/ada/ * ttypes.ads (Target_Strict_Alignment): Fix comment. --- gcc/ada/ttypes.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ttypes.ads b/gcc/ada/ttypes.ads index ee0c1d3..5f59607 100644 --- a/gcc/ada/ttypes.ads +++ b/gcc/ada/ttypes.ads @@ -210,7 +210,7 @@ package Ttypes is Set_Targ.Strict_Alignment /= 0; -- True if instructions will fail if data is misaligned. Note that this -- is a variable rather than a constant since it can be modified (set to - -- True) if the debug flag -gnatd.A is used. + -- True) if the debug flag -gnatd.a is used. Target_Double_Float_Alignment : constant Nat := Set_Targ.Double_Float_Alignment; -- cgit v1.1 From 36d4f97d589085ddb0abccf3e0f76a3a1c8045c2 Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Wed, 17 Mar 2021 18:33:34 +0100 Subject: [Ada] Turn GNAT_Annotate into its own pragma gcc/ada/ * aspects.ads: Add GNAT_Annotate aspect. * gnat1drv.adb (Adjust_Global_Switches): Stop defining Name_Gnat_Annotate as an alias of Name_Annotate. * snames.ads-tmpl: Define Gnat_Annotate. * par-prag.adb, sem_prag.ads: Add Pragma_Gnat_Annotate to list of pragmas. * lib-writ.adb, sem_ch13.adb, sem_prag.adb: Handle Gnat_Annotate like Aspect_Annotate. --- gcc/ada/aspects.ads | 13 ++++++++++--- gcc/ada/gnat1drv.adb | 7 ------- gcc/ada/lib-writ.adb | 2 +- gcc/ada/par-prag.adb | 1 + gcc/ada/sem_ch13.adb | 3 ++- gcc/ada/sem_prag.adb | 3 ++- gcc/ada/sem_prag.ads | 1 + gcc/ada/snames.ads-tmpl | 3 ++- 8 files changed, 19 insertions(+), 14 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads index 2cbb2da..0f9ed23 100644 --- a/gcc/ada/aspects.ads +++ b/gcc/ada/aspects.ads @@ -100,6 +100,7 @@ package Aspects is Aspect_External_Tag, Aspect_Ghost, -- GNAT Aspect_Global, -- GNAT + Aspect_GNAT_Annotate, -- GNAT Aspect_Implicit_Dereference, Aspect_Initial_Condition, -- GNAT Aspect_Initializes, -- GNAT @@ -269,6 +270,7 @@ package Aspects is Aspect_Favor_Top_Level => True, Aspect_Ghost => True, Aspect_Global => True, + Aspect_GNAT_Annotate => True, Aspect_Inline_Always => True, Aspect_Invariant => True, Aspect_Lock_Free => True, @@ -318,9 +320,10 @@ package Aspects is -- the same aspect attached to the same declaration are allowed. No_Duplicates_Allowed : constant array (Aspect_Id) of Boolean := - (Aspect_Annotate => False, - Aspect_Test_Case => False, - others => True); + (Aspect_Annotate => False, + Aspect_GNAT_Annotate => False, + Aspect_Test_Case => False, + others => True); -- The following subtype defines aspects corresponding to library unit -- pragmas, these can only validly appear as aspects for library units, @@ -387,6 +390,7 @@ package Aspects is Aspect_External_Tag => Expression, Aspect_Ghost => Optional_Expression, Aspect_Global => Expression, + Aspect_GNAT_Annotate => Expression, Aspect_Implicit_Dereference => Name, Aspect_Initial_Condition => Expression, Aspect_Initializes => Expression, @@ -491,6 +495,7 @@ package Aspects is Aspect_External_Tag => False, Aspect_Ghost => False, Aspect_Global => False, + Aspect_GNAT_Annotate => False, Aspect_Implicit_Dereference => False, Aspect_Initial_Condition => False, Aspect_Initializes => False, @@ -647,6 +652,7 @@ package Aspects is Aspect_Full_Access_Only => Name_Full_Access_Only, Aspect_Ghost => Name_Ghost, Aspect_Global => Name_Global, + Aspect_GNAT_Annotate => Name_GNAT_Annotate, Aspect_Implicit_Dereference => Name_Implicit_Dereference, Aspect_Import => Name_Import, Aspect_Independent => Name_Independent, @@ -957,6 +963,7 @@ package Aspects is Aspect_Extensions_Visible => Never_Delay, Aspect_Ghost => Never_Delay, Aspect_Global => Never_Delay, + Aspect_GNAT_Annotate => Never_Delay, Aspect_Import => Never_Delay, Aspect_Initial_Condition => Never_Delay, Aspect_Initializes => Never_Delay, diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb index 59b9595..22c9311 100644 --- a/gcc/ada/gnat1drv.adb +++ b/gcc/ada/gnat1drv.adb @@ -67,7 +67,6 @@ with Sem_Type; with Set_Targ; with Sinfo; use Sinfo; with Sinfo.Nodes; use Sinfo.Nodes; -with Sinfo.Utils; use Sinfo.Utils; with Sinput; use Sinput; with Sinput.L; use Sinput.L; with Snames; use Snames; @@ -146,12 +145,6 @@ procedure Gnat1drv is -- Start of processing for Adjust_Global_Switches begin - -- Define pragma GNAT_Annotate as an alias of pragma Annotate, to be - -- able to work around bootstrap limitations with the old syntax of - -- pragma Annotate, and use pragma GNAT_Annotate in compiler sources - -- when needed. - - Map_Pragma_Name (From => Name_Gnat_Annotate, To => Name_Annotate); -- -gnatd_U disables prepending error messages with "error:" diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb index 4dfb68e..16993dd 100644 --- a/gcc/ada/lib-writ.adb +++ b/gcc/ada/lib-writ.adb @@ -709,7 +709,7 @@ package body Lib.Writ is Write_Info_Char (' '); case Pragma_Name (N) is - when Name_Annotate => + when Name_Annotate | Name_GNAT_Annotate => C := 'A'; when Name_Comment => C := 'C'; diff --git a/gcc/ada/par-prag.adb b/gcc/ada/par-prag.adb index d701c2c..06c7d87 100644 --- a/gcc/ada/par-prag.adb +++ b/gcc/ada/par-prag.adb @@ -1389,6 +1389,7 @@ begin | Pragma_Finalize_Storage_Only | Pragma_Ghost | Pragma_Global + | Pragma_GNAT_Annotate | Pragma_Ident | Pragma_Implementation_Defined | Pragma_Implemented diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 83d7d3c..cdc0083 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -4199,7 +4199,7 @@ package body Sem_Ch13 is -- Case 2e: Annotate aspect - when Aspect_Annotate => + when Aspect_Annotate | Aspect_GNAT_Annotate => declare Args : List_Id; Pargs : List_Id; @@ -11117,6 +11117,7 @@ package body Sem_Ch13 is | Aspect_Extensions_Visible | Aspect_Ghost | Aspect_Global + | Aspect_GNAT_Annotate | Aspect_Implicit_Dereference | Aspect_Initial_Condition | Aspect_Initializes diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 14351b3..36b305e 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -12688,7 +12688,7 @@ package body Sem_Prag is -- external tool and a tool-specific function. These arguments are -- not analyzed. - when Pragma_Annotate => Annotate : declare + when Pragma_Annotate | Pragma_GNAT_Annotate => Annotate : declare Arg : Node_Id; Expr : Node_Id; Nam_Arg : Node_Id; @@ -31246,6 +31246,7 @@ package body Sem_Prag is Pragma_Finalize_Storage_Only => 0, Pragma_Ghost => 0, Pragma_Global => -1, + Pragma_GNAT_Annotate => 93, Pragma_Ident => -1, Pragma_Ignore_Pragma => 0, Pragma_Implementation_Defined => -1, diff --git a/gcc/ada/sem_prag.ads b/gcc/ada/sem_prag.ads index c620beb..e166481 100644 --- a/gcc/ada/sem_prag.ads +++ b/gcc/ada/sem_prag.ads @@ -63,6 +63,7 @@ package Sem_Prag is Pragma_Favor_Top_Level => True, Pragma_Ghost => True, Pragma_Global => True, + Pragma_GNAT_Annotate => True, Pragma_Import => True, Pragma_Independent => True, Pragma_Independent_Components => True, diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl index b9ca607..837a878 100644 --- a/gcc/ada/snames.ads-tmpl +++ b/gcc/ada/snames.ads-tmpl @@ -439,6 +439,7 @@ package Snames is -- correctly recognize and process Fast_Math. Name_Favor_Top_Level : constant Name_Id := N + $; -- GNAT + Name_GNAT_Annotate : constant Name_Id := N + $; -- GNAT Name_Ignore_Pragma : constant Name_Id := N + $; -- GNAT Name_Implicit_Packing : constant Name_Id := N + $; -- GNAT Name_Initialize_Scalars : constant Name_Id := N + $; -- GNAT @@ -796,7 +797,6 @@ package Snames is Name_Gcc : constant Name_Id := N + $; Name_General : constant Name_Id := N + $; Name_Gnat : constant Name_Id := N + $; - Name_Gnat_Annotate : constant Name_Id := N + $; Name_Gnat_Extended_Ravenscar : constant Name_Id := N + $; Name_Gnat_Ravenscar_EDF : constant Name_Id := N + $; Name_Gnatprove : constant Name_Id := N + $; @@ -1767,6 +1767,7 @@ package Snames is Pragma_Extensions_Allowed, Pragma_External_Name_Casing, Pragma_Favor_Top_Level, + Pragma_GNAT_Annotate, Pragma_Ignore_Pragma, Pragma_Implicit_Packing, Pragma_Initialize_Scalars, -- cgit v1.1 From f7b2ce2f53b18c9770a5caae42e58791d41ae522 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Wed, 7 Apr 2021 12:15:04 +0200 Subject: [Ada] Adapt SPARK checking after change in rules regarding heap modeling gcc/ada/ * libgnat/a-uncdea.ads: Add Depends/Post to Ada.Unchecked_Deallocation. * sem_ch4.adb (Analyze_Allocator): Remove checking of allocator placement. * sem_res.adb (Flag_Object): Same. --- gcc/ada/libgnat/a-uncdea.ads | 5 ++++- gcc/ada/sem_ch4.adb | 10 ---------- gcc/ada/sem_res.adb | 12 ------------ 3 files changed, 4 insertions(+), 23 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/a-uncdea.ads b/gcc/ada/libgnat/a-uncdea.ads index a61cd50..439fa61 100644 --- a/gcc/ada/libgnat/a-uncdea.ads +++ b/gcc/ada/libgnat/a-uncdea.ads @@ -17,7 +17,10 @@ generic type Object (<>) is limited private; type Name is access Object; -procedure Ada.Unchecked_Deallocation (X : in out Name); +procedure Ada.Unchecked_Deallocation (X : in out Name) with + Depends => (X => null, -- X on exit does not depend on its input value + null => X), -- X's input value has no effect + Post => X = null; -- X's output value is null pragma Preelaborate (Unchecked_Deallocation); pragma Import (Intrinsic, Ada.Unchecked_Deallocation); diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index ede257b..d849834 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -889,16 +889,6 @@ package body Sem_Ch4 is Check_Restriction (No_Local_Allocators, N); end if; - if SPARK_Mode = On - and then Comes_From_Source (N) - and then not Is_OK_Volatile_Context (Context => Parent (N), - Obj_Ref => N, - Check_Actuals => False) - then - Error_Msg_N - ("allocator cannot appear in this context (SPARK RM 7.1.3(10))", N); - end if; - if Serious_Errors_Detected > Sav_Errs then Set_Error_Posted (N); Set_Etype (N, Any_Type); diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index e639fab..b6a9b1d 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -3753,18 +3753,6 @@ package body Sem_Res is begin case Nkind (N) is - when N_Allocator => - if not Is_OK_Volatile_Context (Context => Parent (N), - Obj_Ref => N, - Check_Actuals => True) - then - Error_Msg_N - ("allocator cannot appear in this context" - & " (SPARK RM 7.1.3(10))", N); - end if; - - return Skip; - -- Do not consider nested function calls because they have -- already been processed during their own resolution. -- cgit v1.1 From e7b17be97330d2e42dd7e8e84a5b16a167241931 Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Tue, 27 Apr 2021 13:30:34 +0200 Subject: [Ada] Move overriding rename error message from declaration to use gcc/ada/ * sem_ch3.adb (Check_Abstract_Overriding): Post error message on renaming node. --- gcc/ada/sem_ch3.adb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 4250483..aa73f3a 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -11156,7 +11156,8 @@ package body Sem_Ch3 is if Present (Renamed_Or_Alias (Subp)) then if not No_Return (Renamed_Or_Alias (Subp)) then - Error_Msg_N ("subprogram & must be No_Return", + Error_Msg_NE ("subprogram & must be No_Return", + Subp, Renamed_Or_Alias (Subp)); Error_Msg_N ("\since renaming & overrides No_Return " & "subprogram (RM 6.5.1(6/2))", -- cgit v1.1 From a0bdd4b03b87a01a5984aa5c7ad94f66b2a7bc9e Mon Sep 17 00:00:00 2001 From: Doug Rupp Date: Sun, 25 Apr 2021 21:52:09 -0700 Subject: [Ada] The Unix Epochalyse of 2038 - OS_Time gcc/ada/ * adaint.h (OS_Time): typedef as long long. * osint.adb (Underlying_OS_Time): Declare as 64-bit signed type. * libgnat/s-os_lib.adb ("<"): Compare OS_Time as Long_Long_Integer. ("<="): Likewise. (">"): Likewise. (">="): Likewise. * libgnat/s-os_lib.ads (OS_Time): Declare as 64-bit signed type. --- gcc/ada/adaint.h | 4 ---- gcc/ada/libgnat/s-os_lib.adb | 8 ++++---- gcc/ada/libgnat/s-os_lib.ads | 3 +-- gcc/ada/osint.adb | 3 +-- 4 files changed, 6 insertions(+), 12 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/adaint.h b/gcc/ada/adaint.h index 6ef61e7..b03294f 100644 --- a/gcc/ada/adaint.h +++ b/gcc/ada/adaint.h @@ -101,11 +101,7 @@ extern "C" { #endif /* Type corresponding to GNAT.OS_Lib.OS_Time */ -#if defined (_WIN64) typedef long long OS_Time; -#else -typedef long OS_Time; -#endif #define __int64 long long GNAT_STRUCT_STAT; diff --git a/gcc/ada/libgnat/s-os_lib.adb b/gcc/ada/libgnat/s-os_lib.adb index 5c02b2d..7591f27 100644 --- a/gcc/ada/libgnat/s-os_lib.adb +++ b/gcc/ada/libgnat/s-os_lib.adb @@ -139,7 +139,7 @@ package body System.OS_Lib is function "<" (X, Y : OS_Time) return Boolean is begin - return Long_Integer (X) < Long_Integer (Y); + return Long_Long_Integer (X) < Long_Long_Integer (Y); end "<"; ---------- @@ -148,7 +148,7 @@ package body System.OS_Lib is function "<=" (X, Y : OS_Time) return Boolean is begin - return Long_Integer (X) <= Long_Integer (Y); + return Long_Long_Integer (X) <= Long_Long_Integer (Y); end "<="; --------- @@ -157,7 +157,7 @@ package body System.OS_Lib is function ">" (X, Y : OS_Time) return Boolean is begin - return Long_Integer (X) > Long_Integer (Y); + return Long_Long_Integer (X) > Long_Long_Integer (Y); end ">"; ---------- @@ -166,7 +166,7 @@ package body System.OS_Lib is function ">=" (X, Y : OS_Time) return Boolean is begin - return Long_Integer (X) >= Long_Integer (Y); + return Long_Long_Integer (X) >= Long_Long_Integer (Y); end ">="; ----------------- diff --git a/gcc/ada/libgnat/s-os_lib.ads b/gcc/ada/libgnat/s-os_lib.ads index 42ac488..1d0af9b 100644 --- a/gcc/ada/libgnat/s-os_lib.ads +++ b/gcc/ada/libgnat/s-os_lib.ads @@ -1098,8 +1098,7 @@ private pragma Import (C, Current_Process_Id, "__gnat_current_process_id"); type OS_Time is - range -(2 ** (Standard'Address_Size - Integer'(1))) .. - +(2 ** (Standard'Address_Size - Integer'(1)) - 1); + range -(2 ** 63) .. +(2 ** 63 - 1); -- Type used for timestamps in the compiler. This type is used to hold -- time stamps, but may have a different representation than C's time_t. -- This type needs to match the declaration of OS_Time in adaint.h. diff --git a/gcc/ada/osint.adb b/gcc/ada/osint.adb index d47eaa5..3e5db36 100644 --- a/gcc/ada/osint.adb +++ b/gcc/ada/osint.adb @@ -2191,8 +2191,7 @@ package body Osint is GNAT_Time : Time_Stamp_Type; type Underlying_OS_Time is - range -(2 ** (Standard'Address_Size - Integer'(1))) .. - +(2 ** (Standard'Address_Size - Integer'(1)) - 1); + range -(2 ** 63) .. +(2 ** 63 - 1); -- Underlying_OS_Time is a redeclaration of OS_Time to allow integer -- manipulation. Remove this in favor of To_Ada/To_C once newer -- GNAT releases are available with these functions. -- cgit v1.1 From 35d721c09a5c8e4fb48d0a7a07da9220915bf0c1 Mon Sep 17 00:00:00 2001 From: Doug Rupp Date: Mon, 26 Apr 2021 10:14:37 -0700 Subject: [Ada] The Unix Epochalypse of 2038 - Use OS_Time gcc/ada/ * adaint.h (__gnat_set_file_time_name): Use OS_Time. * adaint.c (__gnat_set_file_time_name): Likewise. --- gcc/ada/adaint.c | 4 ++-- gcc/ada/adaint.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c index b2d4de6..26be260 100644 --- a/gcc/ada/adaint.c +++ b/gcc/ada/adaint.c @@ -1570,7 +1570,7 @@ extern long long __gnat_file_time(char* name) /* Set the file time stamp. */ void -__gnat_set_file_time_name (char *name, time_t time_stamp) +__gnat_set_file_time_name (char *name, OS_Time time_stamp) { #if defined (__vxworks) @@ -1606,7 +1606,7 @@ __gnat_set_file_time_name (char *name, time_t time_stamp) time_t t; /* Set modification time to requested time. */ - utimbuf.modtime = time_stamp; + utimbuf.modtime = (time_t) time_stamp; /* Set access time to now in local time. */ t = time (NULL); diff --git a/gcc/ada/adaint.h b/gcc/ada/adaint.h index b03294f..a63ceef 100644 --- a/gcc/ada/adaint.h +++ b/gcc/ada/adaint.h @@ -201,7 +201,7 @@ extern OS_Time __gnat_file_time_name (char *); extern OS_Time __gnat_file_time_fd (int); /* return -1 in case of error */ -extern void __gnat_set_file_time_name (char *, time_t); +extern void __gnat_set_file_time_name (char *, OS_Time); extern int __gnat_dup (int); extern int __gnat_dup2 (int, int); -- cgit v1.1 From bcb8c3bba756feb252340757e0944956684b7cfb Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Mon, 29 Mar 2021 08:46:02 -0400 Subject: [Ada] INOX: prototype alternative accessibility model gcc/ada/ * checks.adb (Accessibility_Checks_Suppressed): Add check against restriction No_Dynamic_Accessibility_Checks. (Apply_Accessibility_Check): Add assertion to check restriction No_Dynamic_Accessibility_Checks is not active. * debug.adb: Add documentation for new debugging switch to control which accessibility model gets employed under restriction No_Dynamic_Accessibility_Checks. * exp_attr.adb (Expand_N_Attribute_Reference): Disable dynamic accessibility check generation when No_Dynamic_Accessibility_Checks is active. * exp_ch4.adb (Apply_Accessibility_Check): Skip check generation when restriction No_Dynamic_Accessibility_Checks is active. (Expand_N_Allocator): Disable dynamic accessibility checks when No_Dynamic_Accessibility_Checks is active. (Expand_N_In): Disable dynamic accessibility checks when No_Dynamic_Accessibility_Checks is active. (Expand_N_Type_Conversion): Disable dynamic accessibility checks when No_Dynamic_Accessibility_Checks is active. * exp_ch5.adb (Expand_N_Assignment_Statement): Disable alternative accessibility model calculations when computing a dynamic level for a SAOAAT. * exp_ch6.adb (Add_Call_By_Copy_Code): Disable dynamic accessibility check generation when No_Dynamic_Accessibility_Checks is active. (Expand_Branch): Disable alternative accessibility model calculations. (Expand_Call_Helper): Disable alternative accessibility model calculations. * restrict.adb, restrict.ads: Add new restriction No_Dynamic_Accessibility_Checks. (No_Dynamic_Accessibility_Checks_Enabled): Created to test when experimental features (which are generally incompatible with standard Ada) can be enabled. * sem_attr.adb (Safe_Value_Conversions): Add handling of new accessibility model under the restriction No_Dynamic_Accessibility_Checks. * sem_prag.adb (Process_Restrictions_Or_Restriction_Warnings): Disallow new restriction No_Dynamic_Accessibility_Checks from being exclusively specified within a body or subunit without being present in a specification. * sem_res.adb (Check_Fully_Declared_Prefix): Minor comment fixup. (Valid_Conversion): Omit implicit conversion checks on anonymous access types and perform static checking instead when No_Dynamic_Accessibility_Checks is active. * sem_util.adb, sem_util.ads (Accessibility_Level): Add special handling of anonymous access objects, formal parameters, anonymous access components, and function return objects. (Deepest_Type_Access_Level): When No_Dynamic_Accessibility_Checks is active employ an alternative model. Add paramter Allow_Alt_Model to override the new behavior in certain cases. (Type_Access_Level): When No_Dynamic_Accessibility_Checks is active employ an alternative model. Add parameter Allow_Alt_Model to override the new behavior in certain cases. (Typ_Access_Level): Created within Accessibility_Level for convenience. * libgnat/s-rident.ads, snames.ads-tmpl: Add handing for No_Dynamic_Accessibility_Checks. --- gcc/ada/checks.adb | 11 ++- gcc/ada/debug.adb | 2 +- gcc/ada/exp_attr.adb | 1 + gcc/ada/exp_ch4.adb | 5 + gcc/ada/exp_ch5.adb | 4 +- gcc/ada/exp_ch6.adb | 29 ++++-- gcc/ada/libgnat/s-rident.ads | 1 + gcc/ada/restrict.adb | 15 +++ gcc/ada/restrict.ads | 10 ++ gcc/ada/sem_attr.adb | 13 ++- gcc/ada/sem_prag.adb | 35 +++++++ gcc/ada/sem_res.adb | 22 ++++- gcc/ada/sem_util.adb | 215 ++++++++++++++++++++++++++++++++++++------- gcc/ada/sem_util.ads | 23 ++++- gcc/ada/snames.ads-tmpl | 1 + 15 files changed, 332 insertions(+), 55 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 6c49e67..96a2a3f 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -379,8 +379,12 @@ package body Checks is function Accessibility_Checks_Suppressed (E : Entity_Id) return Boolean is begin - if Present (E) and then Checks_May_Be_Suppressed (E) then + if No_Dynamic_Accessibility_Checks_Enabled (E) then + return True; + + elsif Present (E) and then Checks_May_Be_Suppressed (E) then return Is_Check_Suppressed (E, Accessibility_Check); + else return Scope_Suppress.Suppress (Accessibility_Check); end if; @@ -582,6 +586,11 @@ package body Checks is Type_Level : Node_Id; begin + -- Verify we haven't tried to add a dynamic accessibility check when we + -- shouldn't. + + pragma Assert (not No_Dynamic_Accessibility_Checks_Enabled (N)); + if Ada_Version >= Ada_2012 and then not Present (Param_Ent) and then Is_Entity_Name (N) diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index 978f333..5a4d1d3 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -140,7 +140,7 @@ package body Debug is -- d.Z Do not enable expansion in configurable run-time mode -- d_a Stop elaboration checks on accept or select statement - -- d_b + -- d_b Use compatibility model under No_Dynamic_Accessibility_Checks -- d_c CUDA compilation : compile for the host -- d_d -- d_e Ignore entry calls and requeue statements for elaboration diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index af7f205d..067e7ed 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -2366,6 +2366,7 @@ package body Exp_Attr is = E_Anonymous_Access_Type and then Present (Extra_Accessibility (Entity (Prefix (Enc_Object)))) + and then not No_Dynamic_Accessibility_Checks_Enabled (Enc_Object) then Apply_Accessibility_Check (Prefix (Enc_Object), Typ, N); diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 54e91b2..d608a30 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -615,6 +615,7 @@ package body Exp_Ch4 is and then Is_Class_Wide_Type (DesigT) and then Tagged_Type_Expansion and then not Scope_Suppress.Suppress (Accessibility_Check) + and then not No_Dynamic_Accessibility_Checks_Enabled (Ref) and then (Type_Access_Level (Etype (Exp)) > Type_Access_Level (PtrT) or else @@ -5277,6 +5278,8 @@ package body Exp_Ch4 is if Ada_Version >= Ada_2005 and then Ekind (Etype (Nod)) = E_Anonymous_Access_Type + and then not + No_Dynamic_Accessibility_Checks_Enabled (Nod) then Apply_Accessibility_Check (Nod, Typ, Insert_Node => Nod); @@ -6865,6 +6868,7 @@ package body Exp_Ch4 is if Ada_Version >= Ada_2012 and then Is_Acc and then Ekind (Ltyp) = E_Anonymous_Access_Type + and then not No_Dynamic_Accessibility_Checks_Enabled (Lop) then declare Expr_Entity : Entity_Id := Empty; @@ -12333,6 +12337,7 @@ package body Exp_Ch4 is and then Ekind (Etype (Operand_Acc)) = E_Anonymous_Access_Type and then (Nkind (Original_Node (N)) /= N_Attribute_Reference or else Attribute_Name (Original_Node (N)) = Name_Access) + and then not No_Dynamic_Accessibility_Checks_Enabled (N) then if not Comes_From_Source (N) and then Nkind (Parent (N)) in N_Function_Call diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 4eba6fb..2cc8b64 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -2771,7 +2771,9 @@ package body Exp_Ch5 is (Entity (Lhs)), Loc), Expression => Accessibility_Level - (Rhs, Dynamic_Level)); + (Expr => Rhs, + Level => Dynamic_Level, + Allow_Alt_Model => False)); begin if not Accessibility_Checks_Suppressed (Entity (Lhs)) then diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 3542411..80ed21b 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -1803,6 +1803,7 @@ package body Exp_Ch6 is and then Is_Entity_Name (Lhs) and then Present (Effective_Extra_Accessibility (Entity (Lhs))) + and then not No_Dynamic_Accessibility_Checks_Enabled (Lhs) then -- Copyback target is an Ada 2012 stand-alone object of an -- anonymous access type. @@ -2929,7 +2930,9 @@ package body Exp_Ch6 is Name => New_Occurrence_Of (Lvl, Loc), Expression => Accessibility_Level - (Expression (Res_Assn), Dynamic_Level))); + (Expr => Expression (Res_Assn), + Level => Dynamic_Level, + Allow_Alt_Model => False))); end if; end Expand_Branch; @@ -3857,9 +3860,10 @@ package body Exp_Ch6 is end if; Add_Extra_Actual - (Expr => - New_Occurrence_Of - (Get_Dynamic_Accessibility (Parm_Ent), Loc), + (Expr => Accessibility_Level + (Expr => Parm_Ent, + Level => Dynamic_Level, + Allow_Alt_Model => False), EF => Extra_Accessibility (Formal)); end; @@ -3890,15 +3894,20 @@ package body Exp_Ch6 is Add_Extra_Actual (Expr => Accessibility_Level - (Expr => Expression (Parent (Entity (Prev))), - Level => Dynamic_Level), + (Expr => Expression + (Parent (Entity (Prev))), + Level => Dynamic_Level, + Allow_Alt_Model => False), EF => Extra_Accessibility (Formal)); -- Normal case else Add_Extra_Actual - (Expr => Accessibility_Level (Prev, Dynamic_Level), + (Expr => Accessibility_Level + (Expr => Prev, + Level => Dynamic_Level, + Allow_Alt_Model => False), EF => Extra_Accessibility (Formal)); end if; end if; @@ -4142,8 +4151,10 @@ package body Exp_Ch6 is -- Otherwise get the level normally based on the call node else - Level := Accessibility_Level (Call_Node, Dynamic_Level); - + Level := Accessibility_Level + (Expr => Call_Node, + Level => Dynamic_Level, + Allow_Alt_Model => False); end if; -- It may be possible that we are re-expanding an already diff --git a/gcc/ada/libgnat/s-rident.ads b/gcc/ada/libgnat/s-rident.ads index 7d0a384..10d374e 100644 --- a/gcc/ada/libgnat/s-rident.ads +++ b/gcc/ada/libgnat/s-rident.ads @@ -103,6 +103,7 @@ package System.Rident is No_Direct_Boolean_Operators, -- GNAT No_Dispatch, -- (RM H.4(19)) No_Dispatching_Calls, -- GNAT + No_Dynamic_Accessibility_Checks, -- GNAT No_Dynamic_Attachment, -- Ada 2012 (RM E.7(10/3)) No_Dynamic_CPU_Assignment, -- Ada 202x (RM D.7(10/3)) No_Dynamic_Priorities, -- (RM D.9(9)) diff --git a/gcc/ada/restrict.adb b/gcc/ada/restrict.adb index 3592230..4f1dea4 100644 --- a/gcc/ada/restrict.adb +++ b/gcc/ada/restrict.adb @@ -924,6 +924,21 @@ package body Restrict is or else Targparm.Restrictions_On_Target.Set (No_Tasking); end Global_No_Tasking; + --------------------------------------------- + -- No_Dynamic_Accessibility_Checks_Enabled -- + --------------------------------------------- + + function No_Dynamic_Accessibility_Checks_Enabled + (N : Node_Id) return Boolean + is + pragma Unreferenced (N); + -- N is currently unreferenced but present for debugging purposes and + -- potential future use. + + begin + return Restrictions.Set (No_Dynamic_Accessibility_Checks); + end No_Dynamic_Accessibility_Checks_Enabled; + ------------------------------- -- No_Exception_Handlers_Set -- ------------------------------- diff --git a/gcc/ada/restrict.ads b/gcc/ada/restrict.ads index 806195e..eec85c2 100644 --- a/gcc/ada/restrict.ads +++ b/gcc/ada/restrict.ads @@ -114,6 +114,7 @@ package Restrict is No_Default_Initialization => True, No_Direct_Boolean_Operators => True, No_Dispatching_Calls => True, + No_Dynamic_Accessibility_Checks => True, No_Dynamic_Attachment => True, No_Elaboration_Code => True, No_Enumeration_Maps => True, @@ -377,6 +378,15 @@ package Restrict is -- pragma Restrictions_Warning, or attribute Restriction_Set. Returns -- True if N has the proper form for an entity name, False otherwise. + function No_Dynamic_Accessibility_Checks_Enabled + (N : Node_Id) return Boolean; + -- Test to see if the current restrictions settings specify that + -- No_Dynamic_Accessibility_Checks is activated. + + -- N is currently unused, but is reserved for future use and debugging + -- purposes to provide more context on a node for which an accessibility + -- check is being performed or generated (e.g. is N in a predefined unit). + function No_Exception_Handlers_Set return Boolean; -- Test to see if current restrictions settings specify that no exception -- handlers are present. This function is called by Gigi when it needs to diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb index b7297e5..e0b2072 100644 --- a/gcc/ada/sem_attr.adb +++ b/gcc/ada/sem_attr.adb @@ -11290,7 +11290,11 @@ package body Sem_Attr is -- this kind of warning is an error in SPARK mode. if In_Instance_Body then - Error_Msg_Warn := SPARK_Mode /= On; + Error_Msg_Warn := + SPARK_Mode /= On + and then + not No_Dynamic_Accessibility_Checks_Enabled (P); + Error_Msg_F ("non-local pointer cannot point to local object<<", P); Error_Msg_F ("\Program_Error [<<", P); @@ -11422,10 +11426,13 @@ package body Sem_Attr is -- Check the static accessibility rule of 3.10.2(28). Note that -- this check is not performed for the case of an anonymous -- access type, since the access attribute is always legal - -- in such a context. + -- in such a context - unless the restriction + -- No_Dynamic_Accessibility_Checks is active. if Attr_Id /= Attribute_Unchecked_Access - and then Ekind (Btyp) = E_General_Access_Type + and then + (Ekind (Btyp) = E_General_Access_Type + or else No_Dynamic_Accessibility_Checks_Enabled (Btyp)) -- Call Accessibility_Level directly to avoid returning zero -- on cases where the prefix is an explicitly aliased diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 36b305e..fa63fda 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -10483,6 +10483,41 @@ package body Sem_Prag is Add_To_Config_Boolean_Restrictions (No_Elaboration_Code); end if; + -- Special processing for No_Dynamic_Accessibility_Checks to + -- disallow exclusive specification in a body or subunit. + + elsif R_Id = No_Dynamic_Accessibility_Checks + -- Check if the restriction is within configuration pragma + -- in a similar way to No_Elaboration_Code. + + and then not (Current_Sem_Unit = Main_Unit + or else In_Extended_Main_Source_Unit (N)) + + and then Nkind (Unit (Parent (N))) = N_Compilation_Unit + + and then (Nkind (Unit (Parent (N))) = N_Package_Body + or else Nkind (Unit (Parent (N))) = N_Subunit) + + and then not Restriction_Active + (No_Dynamic_Accessibility_Checks) + then + Error_Msg_N + ("invalid specification of " & + """No_Dynamic_Accessibility_Checks""", N); + + if Nkind (Unit (Parent (N))) = N_Package_Body then + Error_Msg_N + ("\restriction cannot be specified in a package " & + "body", N); + + elsif Nkind (Unit (Parent (N))) = N_Subunit then + Error_Msg_N + ("\restriction cannot be specified in a subunit", N); + end if; + + Error_Msg_N + ("\unless also specified in spec", N); + -- Special processing for No_Tasking restriction (not just a -- warning) when it appears as a configuration pragma. diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index b6a9b1d..fb40484 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -654,9 +654,9 @@ package body Sem_Res is end if; end Check_For_Visible_Operator; - ---------------------------------- - -- Check_Fully_Declared_Prefix -- - ---------------------------------- + --------------------------------- + -- Check_Fully_Declared_Prefix -- + --------------------------------- procedure Check_Fully_Declared_Prefix (Typ : Entity_Id; @@ -13676,12 +13676,24 @@ package body Sem_Res is then if Is_Itype (Opnd_Type) then + -- When applying restriction No_Dynamic_Accessibility_Check, + -- implicit conversions are allowed when the operand type is + -- not deeper than the target type. + + if No_Dynamic_Accessibility_Checks_Enabled (N) then + if Type_Access_Level (Opnd_Type) + > Deepest_Type_Access_Level (Target_Type) + then + Conversion_Error_N + ("operand has deeper level than target", Operand); + end if; + -- Implicit conversions aren't allowed for objects of an -- anonymous access type, since such objects have nonstatic -- levels in Ada 2012. - if Nkind (Associated_Node_For_Itype (Opnd_Type)) = - N_Object_Declaration + elsif Nkind (Associated_Node_For_Itype (Opnd_Type)) + = N_Object_Declaration then Conversion_Error_N ("implicit conversion of stand-alone anonymous " diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index b7d84af..e0a12bd 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -177,9 +177,9 @@ package body Sem_Util is -- "subp:file:line:col", corresponding to the source location of the -- body of the subprogram. - ------------------------------ - -- Abstract_Interface_List -- - ------------------------------ + ----------------------------- + -- Abstract_Interface_List -- + ----------------------------- function Abstract_Interface_List (Typ : Entity_Id) return List_Id is Nod : Node_Id; @@ -260,7 +260,8 @@ package body Sem_Util is function Accessibility_Level (Expr : Node_Id; Level : Accessibility_Level_Kind; - In_Return_Context : Boolean := False) return Node_Id + In_Return_Context : Boolean := False; + Allow_Alt_Model : Boolean := True) return Node_Id is Loc : constant Source_Ptr := Sloc (Expr); @@ -281,6 +282,11 @@ package body Sem_Util is -- Centralized processing of subprogram calls which may appear in -- prefix notation. + function Typ_Access_Level (Typ : Entity_Id) return Uint + is (Type_Access_Level (Typ, Allow_Alt_Model)); + -- Renaming of Type_Access_Level with Allow_Alt_Model specified to avoid + -- passing the parameter specifically in every call. + ---------------------------------- -- Innermost_Master_Scope_Depth -- ---------------------------------- @@ -375,7 +381,7 @@ package body Sem_Util is (Subprogram_Access_Level (Entity (Name (N)))); else return Make_Level_Literal - (Type_Access_Level (Etype (Prefix (Name (N))))); + (Typ_Access_Level (Etype (Prefix (Name (N))))); end if; -- We ignore coextensions as they cannot be implemented under the @@ -392,19 +398,39 @@ package body Sem_Util is -- Named access types have a designated level if Is_Named_Access_Type (Etype (N)) then - return Make_Level_Literal (Type_Access_Level (Etype (N))); + return Make_Level_Literal (Typ_Access_Level (Etype (N))); -- Otherwise, the level is dictated by RM 3.10.2 (10.7/3) else + -- Check No_Dynamic_Accessibility_Checks restriction override for + -- alternative accessibility model. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (N) + and then Is_Anonymous_Access_Type (Etype (N)) + then + -- In the alternative model the level is that of the subprogram + + if Debug_Flag_Underscore_B then + return Make_Level_Literal + (Subprogram_Access_Level (Current_Subprogram)); + end if; + + -- Otherwise the level is that of the designated type + + return Make_Level_Literal + (Typ_Access_Level (Etype (N))); + end if; + if Nkind (N) = N_Function_Call then -- Dynamic checks are generated when we are within a return -- value or we are in a function call within an anonymous -- access discriminant constraint of a return object (signified -- by In_Return_Context) on the side of the callee. - -- So, in this case, return library accessibility level to null - -- out the check on the side of the caller. + -- So, in this case, return accessibility level of the + -- enclosing subprogram. if In_Return_Value (N) or else In_Return_Context @@ -414,6 +440,17 @@ package body Sem_Util is end if; end if; + -- When the call is being dereferenced the level is that of the + -- enclosing master of the dereferenced call. + + if Nkind (Parent (N)) in N_Explicit_Dereference + | N_Indexed_Component + | N_Selected_Component + then + return Make_Level_Literal + (Innermost_Master_Scope_Depth (Expr)); + end if; + -- Find any relevant enclosing parent nodes that designate an -- object being initialized. @@ -434,7 +471,7 @@ package body Sem_Util is and then Is_Named_Access_Type (Etype (Par)) then return Make_Level_Literal - (Type_Access_Level (Etype (Par))); + (Typ_Access_Level (Etype (Par))); end if; -- Jump out when we hit an object declaration or the right-hand @@ -551,7 +588,7 @@ package body Sem_Util is if Is_Named_Access_Type (Etype (Pre)) then return Make_Level_Literal - (Type_Access_Level (Etype (Pre))); + (Typ_Access_Level (Etype (Pre))); -- Anonymous access types @@ -616,8 +653,36 @@ package body Sem_Util is (Scope_Depth (Standard_Standard)); end if; - return - New_Occurrence_Of (Get_Dynamic_Accessibility (E), Loc); + -- No_Dynamic_Accessibility_Checks restriction override for + -- alternative accessibility model. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (E) + then + -- In the alternative model the level depends on the + -- entity's context. + + if Debug_Flag_Underscore_B then + if Is_Formal (E) then + return Make_Level_Literal + (Subprogram_Access_Level + (Enclosing_Subprogram (E))); + end if; + + return Make_Level_Literal + (Scope_Depth (Enclosing_Dynamic_Scope (E))); + end if; + + -- Otherwise the level is that of the designated type + + return Make_Level_Literal + (Typ_Access_Level (Etype (E))); + end if; + + -- Return the dynamic level in the normal case + + return New_Occurrence_Of + (Get_Dynamic_Accessibility (E), Loc); -- Initialization procedures have a special extra accessitility -- parameter associated with the level at which the object @@ -635,8 +700,18 @@ package body Sem_Util is -- according to RM 3.10.2 (21). elsif Is_Type (E) then - return Make_Level_Literal - (Type_Access_Level (E) + 1); + -- When restriction No_Dynamic_Accessibility_Checks is active + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (E) + and then not Debug_Flag_Underscore_B + then + return Make_Level_Literal (Typ_Access_Level (E)); + end if; + + -- Normal path + + return Make_Level_Literal (Typ_Access_Level (E) + 1); -- Move up the renamed entity if it came from source since -- expansion may have created a dummy renaming under certain @@ -651,7 +726,7 @@ package body Sem_Util is elsif Is_Named_Access_Type (Etype (E)) then return Make_Level_Literal - (Type_Access_Level (Etype (E))); + (Typ_Access_Level (Etype (E))); -- When E is a component of the current instance of a -- protected type, we assume the level to be deeper than that of @@ -702,7 +777,7 @@ package body Sem_Util is elsif Is_Named_Access_Type (Etype (Pre)) then return Make_Level_Literal - (Type_Access_Level (Etype (Pre))); + (Typ_Access_Level (Etype (Pre))); -- The current expression is a named access type, so there is no -- reason to look at the prefix. Instead obtain the level of E's @@ -710,7 +785,7 @@ package body Sem_Util is elsif Is_Named_Access_Type (Etype (E)) then return Make_Level_Literal - (Type_Access_Level (Etype (E))); + (Typ_Access_Level (Etype (E))); -- A nondiscriminant selected component where the component -- is an anonymous access type means that its associated @@ -723,8 +798,21 @@ package body Sem_Util is and then Ekind (Entity (Selector_Name (E))) = E_Discriminant) then + -- When restriction No_Dynamic_Accessibility_Checks is active + -- the level is that of the designated type. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (E) + and then not Debug_Flag_Underscore_B + then + return Make_Level_Literal + (Typ_Access_Level (Etype (E))); + end if; + + -- Otherwise proceed normally + return Make_Level_Literal - (Type_Access_Level (Etype (Prefix (E)))); + (Typ_Access_Level (Etype (Prefix (E)))); -- Similar to the previous case - arrays featuring components of -- anonymous access components get their corresponding level from @@ -736,8 +824,21 @@ package body Sem_Util is and then Ekind (Component_Type (Base_Type (Etype (Pre)))) = E_Anonymous_Access_Type then + -- When restriction No_Dynamic_Accessibility_Checks is active + -- the level is that of the designated type. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (E) + and then not Debug_Flag_Underscore_B + then + return Make_Level_Literal + (Typ_Access_Level (Etype (E))); + end if; + + -- Otherwise proceed normally + return Make_Level_Literal - (Type_Access_Level (Etype (Prefix (E)))); + (Typ_Access_Level (Etype (Prefix (E)))); -- The accessibility calculation routine that handles function -- calls (Function_Call_Level) assumes, in the case the @@ -785,7 +886,7 @@ package body Sem_Util is when N_Qualified_Expression => if Is_Named_Access_Type (Etype (E)) then return Make_Level_Literal - (Type_Access_Level (Etype (E))); + (Typ_Access_Level (Etype (E))); else return Accessibility_Level (Expression (E)); end if; @@ -804,7 +905,7 @@ package body Sem_Util is -- its type. if Is_Named_Access_Type (Etype (Pre)) then - return Make_Level_Literal (Type_Access_Level (Etype (Pre))); + return Make_Level_Literal (Typ_Access_Level (Etype (Pre))); -- Otherwise, recurse deeper @@ -831,7 +932,7 @@ package body Sem_Util is elsif Is_Named_Access_Type (Etype (E)) then return Make_Level_Literal - (Type_Access_Level (Etype (E))); + (Typ_Access_Level (Etype (E))); -- In section RM 3.10.2 (10/4) the accessibility rules for -- aggregates and value conversions are outlined. Are these @@ -847,7 +948,7 @@ package body Sem_Util is -- expression's entity. when others => - return Make_Level_Literal (Type_Access_Level (Etype (E))); + return Make_Level_Literal (Typ_Access_Level (Etype (E))); end case; end Accessibility_Level; @@ -7102,12 +7203,25 @@ package body Sem_Util is -- Deepest_Type_Access_Level -- ------------------------------- - function Deepest_Type_Access_Level (Typ : Entity_Id) return Uint is + function Deepest_Type_Access_Level + (Typ : Entity_Id; + Allow_Alt_Model : Boolean := True) return Uint + is begin if Ekind (Typ) = E_Anonymous_Access_Type and then not Is_Local_Anonymous_Access (Typ) and then Nkind (Associated_Node_For_Itype (Typ)) = N_Object_Declaration then + -- No_Dynamic_Accessibility_Checks override for alternative + -- accessibility model. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (Typ) + and then Debug_Flag_Underscore_B + then + return Type_Access_Level (Typ, Allow_Alt_Model); + end if; + -- Typ is the type of an Ada 2012 stand-alone object of an anonymous -- access type. @@ -7123,7 +7237,7 @@ package body Sem_Util is return UI_From_Int (Int'Last); else - return Type_Access_Level (Typ); + return Type_Access_Level (Typ, Allow_Alt_Model); end if; end Deepest_Type_Access_Level; @@ -28982,12 +29096,14 @@ package body Sem_Util is -- Type_Access_Level -- ----------------------- - function Type_Access_Level (Typ : Entity_Id) return Uint is - Btyp : Entity_Id; + function Type_Access_Level + (Typ : Entity_Id; + Allow_Alt_Model : Boolean := True) return Uint + is + Btyp : Entity_Id := Base_Type (Typ); + Def_Ent : Entity_Id; begin - Btyp := Base_Type (Typ); - -- Ada 2005 (AI-230): For most cases of anonymous access types, we -- simply use the level where the type is declared. This is true for -- stand-alone object declarations, and for anonymous access types @@ -28998,13 +29114,50 @@ package body Sem_Util is if Is_Access_Type (Btyp) then if Ekind (Btyp) = E_Anonymous_Access_Type then + -- No_Dynamic_Accessibility_Checks restriction override for + -- alternative accessibility model. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (Btyp) + then + -- In the normal model, the level of an anonymous access + -- type is always that of the designated type. + + if not Debug_Flag_Underscore_B then + return Type_Access_Level + (Designated_Type (Btyp), Allow_Alt_Model); + end if; + + -- Otherwise the secondary model dictates special handling + -- depending on the context of the anonymous access type. + + -- Obtain the defining entity for the internally generated + -- anonymous access type. + + Def_Ent := Defining_Entity_Or_Empty + (Associated_Node_For_Itype (Typ)); + + if Present (Def_Ent) then + -- When the type comes from an anonymous access parameter, + -- the level is that of the subprogram declaration. + + if Ekind (Def_Ent) in Subprogram_Kind then + return Scope_Depth (Def_Ent); + + -- When the type is an access discriminant, the level is + -- that of the type. + + elsif Ekind (Def_Ent) = E_Discriminant then + return Scope_Depth (Scope (Def_Ent)); + end if; + end if; -- If the type is a nonlocal anonymous access type (such as for -- an access parameter) we treat it as being declared at the -- library level to ensure that names such as X.all'access don't -- fail static accessibility checks. - if not Is_Local_Anonymous_Access (Typ) then + elsif not Is_Local_Anonymous_Access (Typ) then return Scope_Depth (Standard_Standard); -- If this is a return object, the accessibility level is that of @@ -29038,7 +29191,7 @@ package body Sem_Util is -- Treat the return object's type as having the level of the -- function's result subtype (as per RM05-6.5(5.3/2)). - return Type_Access_Level (Etype (Scop)); + return Type_Access_Level (Etype (Scop), Allow_Alt_Model); end; end if; end if; diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index 0894d03..a49272e 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -65,15 +65,19 @@ package Sem_Util is function Accessibility_Level (Expr : Node_Id; Level : Accessibility_Level_Kind; - In_Return_Context : Boolean := False) return Node_Id; + In_Return_Context : Boolean := False; + Allow_Alt_Model : Boolean := True) return Node_Id; -- Centralized accessibility level calculation routine for finding the -- accessibility level of a given expression Expr. - -- In_Return_Context forcing the Accessibility_Level calculations to be + -- In_Return_Context forces the Accessibility_Level calculations to be -- carried out "as if" Expr existed in a return value. This is useful for -- calculating the accessibility levels for discriminant associations -- and return aggregates. + -- The Allow_Alt_Model parameter allows the alternative level calculation + -- under the restriction No_Dynamic_Accessibility_Checks to be performed. + function Acquire_Warning_Match_String (Str_Lit : Node_Id) return String; -- Used by pragma Warnings (Off, string), and Warn_As_Error (string) to get -- the given string argument, adding leading and trailing asterisks if they @@ -662,7 +666,10 @@ package Sem_Util is -- when pragma Restrictions (No_Finalization) applies, in which case we -- know that class-wide objects do not contain controlled parts. - function Deepest_Type_Access_Level (Typ : Entity_Id) return Uint; + function Deepest_Type_Access_Level + (Typ : Entity_Id; + Allow_Alt_Model : Boolean := True) return Uint; + -- Same as Type_Access_Level, except that if the type is the type of an Ada -- 2012 stand-alone object of an anonymous access type, then return the -- static accessibility level of the object. In that case, the dynamic @@ -672,6 +679,9 @@ package Sem_Util is -- in the case of a descendant of a generic formal type (returns Int'Last -- instead of 0). + -- The Allow_Alt_Model parameter allows the alternative level calculation + -- under the restriction No_Dynamic_Accessibility_Checks to be performed. + function Defining_Entity (N : Node_Id) return Entity_Id; -- Given a declaration N, returns the associated defining entity. If the -- declaration has a specification, the entity is obtained from the @@ -3246,9 +3256,14 @@ package Sem_Util is -- returned, i.e. Traverse_More_Func is called and the result is simply -- discarded. - function Type_Access_Level (Typ : Entity_Id) return Uint; + function Type_Access_Level + (Typ : Entity_Id; + Allow_Alt_Model : Boolean := True) return Uint; -- Return the accessibility level of Typ + -- The Allow_Alt_Model parameter allows the alternative level calculation + -- under the restriction No_Dynamic_Accessibility_Checks to be performed. + function Type_Without_Stream_Operation (T : Entity_Id; Op : TSS_Name_Type := TSS_Null) return Entity_Id; diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl index 837a878..a67623b 100644 --- a/gcc/ada/snames.ads-tmpl +++ b/gcc/ada/snames.ads-tmpl @@ -827,6 +827,7 @@ package Snames is Name_No_Access_Parameter_Allocators : constant Name_Id := N + $; Name_No_Coextensions : constant Name_Id := N + $; Name_No_Dependence : constant Name_Id := N + $; + Name_No_Dynamic_Accessibility_Checks : constant Name_Id := N + $; Name_No_Dynamic_Attachment : constant Name_Id := N + $; Name_No_Dynamic_Interrupts : constant Name_Id := N + $; Name_No_Elaboration_Code : constant Name_Id := N + $; -- cgit v1.1 From 74895b63549a064f2de8de8bd66e7c0bdbff7076 Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Tue, 27 Apr 2021 13:57:36 -0700 Subject: [Ada] Temporarily disable Ada 2022 Image and Put_Image support for tagged types gcc/ada/ * exp_put_image.adb: (Enable_Put_Image, Preload_Root_Buffer_Type): Revert to querying the -gnatd_z switch, as opposed to testing whether Ada_Version >= Ada_2022. --- gcc/ada/exp_put_image.adb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/exp_put_image.adb b/gcc/ada/exp_put_image.adb index 3a9751b..0cf38ac 100644 --- a/gcc/ada/exp_put_image.adb +++ b/gcc/ada/exp_put_image.adb @@ -26,6 +26,7 @@ with Aspects; use Aspects; with Atree; use Atree; with Csets; use Csets; +with Debug; use Debug; with Einfo; use Einfo; with Einfo.Entities; use Einfo.Entities; with Einfo.Utils; use Einfo.Utils; @@ -50,6 +51,9 @@ with Uintp; use Uintp; package body Exp_Put_Image is + Tagged_Put_Image_Enabled : Boolean renames Debug_Flag_Underscore_Z; + -- Temporary until we resolve mixing Ada 2012 and 2022 code + ----------------------- -- Local Subprograms -- ----------------------- @@ -933,6 +937,7 @@ package body Exp_Put_Image is if Ada_Version < Ada_2022 or else Is_Remote_Types (Scope (Typ)) or else (Is_Tagged_Type (Typ) and then In_Predefined_Unit (Typ)) + or else (Is_Tagged_Type (Typ) and then not Tagged_Put_Image_Enabled) then return False; end if; @@ -1188,6 +1193,7 @@ package body Exp_Put_Image is if not In_Predefined_Unit (Compilation_Unit) and then Ada_Version >= Ada_2022 + and then Tagged_Put_Image_Enabled and then Tagged_Seen and then not No_Run_Time_Mode and then RTE_Available (RE_Root_Buffer_Type) -- cgit v1.1 From 2644eaa0b91e25d01b5c847131bf7caafc7c4588 Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Wed, 28 Apr 2021 11:03:03 +0200 Subject: [Ada] Fix missing minus sign in literal translation gcc/ada/ * sem_res.adb (Resolve): Insert minus sign if needed. --- gcc/ada/sem_res.adb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index fb40484..494904f 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -2934,6 +2934,11 @@ package body Sem_Res is else UI_Image (Norm_Num (Expr_Value_R (Expr)), Decimal); Start_String; + + if UR_Is_Negative (Expr_Value_R (Expr)) then + Store_String_Chars ("-"); + end if; + Store_String_Chars (UI_Image_Buffer (1 .. UI_Image_Length)); Param1 := Make_String_Literal (Loc, End_String); -- cgit v1.1 From cee731748f23f6cbdcd7baf8102ac4dc87ca5c52 Mon Sep 17 00:00:00 2001 From: Doug Rupp Date: Wed, 28 Apr 2021 07:46:12 -0700 Subject: [Ada] The Unix Epochalypse of 2038 (Warn about time_t in the compiler) gcc/ada/ * libgnat/s-os_lib.ads: Add some comments about time_t. * libgnat/s-os_lib.adb (GM_Split/To_GM_Time): Rename formal to P_OS_Time. (GM_Time_Of/To_OS_Time): Likewise. --- gcc/ada/libgnat/s-os_lib.adb | 56 ++++++++++++++++++++++---------------------- gcc/ada/libgnat/s-os_lib.ads | 8 +++++++ 2 files changed, 36 insertions(+), 28 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/s-os_lib.adb b/gcc/ada/libgnat/s-os_lib.adb index 7591f27..d338450 100644 --- a/gcc/ada/libgnat/s-os_lib.adb +++ b/gcc/ada/libgnat/s-os_lib.adb @@ -1347,13 +1347,13 @@ package body System.OS_Lib is Second : out Second_Type) is procedure To_GM_Time - (P_Time_T : Address; - P_Year : Address; - P_Month : Address; - P_Day : Address; - P_Hours : Address; - P_Mins : Address; - P_Secs : Address); + (P_OS_Time : Address; + P_Year : Address; + P_Month : Address; + P_Day : Address; + P_Hours : Address; + P_Mins : Address; + P_Secs : Address); pragma Import (C, To_GM_Time, "__gnat_to_gm_time"); T : OS_Time := Date; @@ -1385,13 +1385,13 @@ package body System.OS_Lib is Locked_Processing : begin SSL.Lock_Task.all; To_GM_Time - (P_Time_T => T'Address, - P_Year => Y'Address, - P_Month => Mo'Address, - P_Day => D'Address, - P_Hours => H'Address, - P_Mins => Mn'Address, - P_Secs => S'Address); + (P_OS_Time => T'Address, + P_Year => Y'Address, + P_Month => Mo'Address, + P_Day => D'Address, + P_Hours => H'Address, + P_Mins => Mn'Address, + P_Secs => S'Address); SSL.Unlock_Task.all; exception @@ -1429,26 +1429,26 @@ package body System.OS_Lib is Second : Second_Type) return OS_Time is procedure To_OS_Time - (P_Time_T : Address; - P_Year : Integer; - P_Month : Integer; - P_Day : Integer; - P_Hours : Integer; - P_Mins : Integer; - P_Secs : Integer); + (P_OS_Time : Address; + P_Year : Integer; + P_Month : Integer; + P_Day : Integer; + P_Hours : Integer; + P_Mins : Integer; + P_Secs : Integer); pragma Import (C, To_OS_Time, "__gnat_to_os_time"); Result : OS_Time; begin To_OS_Time - (P_Time_T => Result'Address, - P_Year => Year - 1900, - P_Month => Month - 1, - P_Day => Day, - P_Hours => Hour, - P_Mins => Minute, - P_Secs => Second); + (P_OS_Time => Result'Address, + P_Year => Year - 1900, + P_Month => Month - 1, + P_Day => Day, + P_Hours => Hour, + P_Mins => Minute, + P_Secs => Second); return Result; end GM_Time_Of; diff --git a/gcc/ada/libgnat/s-os_lib.ads b/gcc/ada/libgnat/s-os_lib.ads index 1d0af9b..8770d94 100644 --- a/gcc/ada/libgnat/s-os_lib.ads +++ b/gcc/ada/libgnat/s-os_lib.ads @@ -164,6 +164,14 @@ package System.OS_Lib is -- component parts to be interpreted in the local time zone, and returns -- an OS_Time. Returns Invalid_Time if the creation fails. + ------------------ + -- Time_t Stuff -- + ------------------ + + -- Note: Do not use time_t in the compiler and host based tools, + -- instead use OS_Time. These 3 declarations are indended for use only + -- by consumers of the GNAT.OS_Lib renaming of this package. + subtype time_t is Long_Integer; -- C time_t type of the time representation -- cgit v1.1 From 63b43535dc775883436ac5c8445522e34e373efc Mon Sep 17 00:00:00 2001 From: Doug Rupp Date: Wed, 28 Apr 2021 08:48:52 -0700 Subject: [Ada] The Unix Epochalyse of 2038 - OS_Time comparison gcc/ada/ * libgnat/s-os_lib.ads: Import OS_Time comparison ops as intrinsic. * libgnat/s-os_lib.adb: Remove OS_TIme comparison ops implementation. --- gcc/ada/libgnat/s-os_lib.adb | 36 ------------------------------------ gcc/ada/libgnat/s-os_lib.ads | 13 ++++--------- 2 files changed, 4 insertions(+), 45 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/s-os_lib.adb b/gcc/ada/libgnat/s-os_lib.adb index d338450..19f4cf7 100644 --- a/gcc/ada/libgnat/s-os_lib.adb +++ b/gcc/ada/libgnat/s-os_lib.adb @@ -133,42 +133,6 @@ package body System.OS_Lib is -- Converts a C String to an Ada String. We could do this making use of -- Interfaces.C.Strings but we prefer not to import that entire package - --------- - -- "<" -- - --------- - - function "<" (X, Y : OS_Time) return Boolean is - begin - return Long_Long_Integer (X) < Long_Long_Integer (Y); - end "<"; - - ---------- - -- "<=" -- - ---------- - - function "<=" (X, Y : OS_Time) return Boolean is - begin - return Long_Long_Integer (X) <= Long_Long_Integer (Y); - end "<="; - - --------- - -- ">" -- - --------- - - function ">" (X, Y : OS_Time) return Boolean is - begin - return Long_Long_Integer (X) > Long_Long_Integer (Y); - end ">"; - - ---------- - -- ">=" -- - ---------- - - function ">=" (X, Y : OS_Time) return Boolean is - begin - return Long_Long_Integer (X) >= Long_Long_Integer (Y); - end ">="; - ----------------- -- Args_Length -- ----------------- diff --git a/gcc/ada/libgnat/s-os_lib.ads b/gcc/ada/libgnat/s-os_lib.ads index 8770d94..d4911d9 100644 --- a/gcc/ada/libgnat/s-os_lib.ads +++ b/gcc/ada/libgnat/s-os_lib.ads @@ -1111,18 +1111,13 @@ private -- time stamps, but may have a different representation than C's time_t. -- This type needs to match the declaration of OS_Time in adaint.h. - -- Add pragma Inline statements for comparison operations on OS_Time. It - -- would actually be nice to use pragma Import (Intrinsic) here, but this - -- was not properly supported till GNAT 3.15a, so that would cause - -- bootstrap path problems. To be changed later ??? - Invalid_Time : constant OS_Time := -1; -- This value should match the return value from __gnat_file_time_* - pragma Inline ("<"); - pragma Inline (">"); - pragma Inline ("<="); - pragma Inline (">="); + pragma Import (Intrinsic, "<"); + pragma Import (Intrinsic, ">"); + pragma Import (Intrinsic, "<="); + pragma Import (Intrinsic, ">="); pragma Inline (To_C); pragma Inline (To_Ada); -- cgit v1.1 From 1d1e91f4c3f74bfa4d106d184ca206b5abccec4f Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Thu, 29 Apr 2021 11:39:24 +0200 Subject: [Ada] Fix excessive check for alignment of overlaying objects gcc/ada/ * sem_util.adb (Has_Compatible_Alignment_Internal): If the prefix of the Address expression is an entire object with a known alignment, then skip checks related to its size. --- gcc/ada/sem_util.adb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index e0a12bd..25060cc 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -11939,6 +11939,7 @@ package body Sem_Util is elsif Is_Entity_Name (Expr) and then Known_Alignment (Entity (Expr)) then + Offs := Uint_0; ExpA := Alignment (Entity (Expr)); -- Otherwise, we can use the alignment of the type of Expr @@ -11961,9 +11962,9 @@ package body Sem_Util is Set_Result (Known_Incompatible); end if; - -- If Expr is not a piece of a larger object, see if size - -- is given. If so, check that it is not too small for the - -- required alignment. + -- If Expr is a component or an entire object with a known + -- alignment, then we are fine. Otherwise, if its size is + -- known, it must be big enough for the required alignment. if Offs /= No_Uint then null; @@ -11982,7 +11983,7 @@ package body Sem_Util is end if; -- If we got a size, see if it is a multiple of the Obj - -- alignment, if not, then the alignment cannot be + -- alignment; if not, then the alignment cannot be -- acceptable, since the size is always a multiple of the -- alignment. -- cgit v1.1 From 7e7397265c805a8d6623aadc039e898fea4a4be0 Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Thu, 29 Apr 2021 14:54:54 -0700 Subject: [Ada] Remove Ada.Strings.Text_Output and child units gcc/ada/ * libgnat/a-stobbu.adb, libgnat/a-stobbu.ads, libgnat/a-stobfi.adb, libgnat/a-stobfi.ads, libgnat/a-stoubu.adb, libgnat/a-stoubu.ads, libgnat/a-stoufi.adb, libgnat/a-stoufi.ads, libgnat/a-stoufo.adb, libgnat/a-stoufo.ads, libgnat/a-stouut.adb, libgnat/a-stouut.ads, libgnat/a-stteou.ads: Delete files. * Makefile.rtl, impunit.adb: Remove references to deleted files. --- gcc/ada/Makefile.rtl | 7 -- gcc/ada/impunit.adb | 6 - gcc/ada/libgnat/a-stobbu.adb | 53 --------- gcc/ada/libgnat/a-stobbu.ads | 34 ------ gcc/ada/libgnat/a-stobfi.adb | 118 ------------------- gcc/ada/libgnat/a-stobfi.ads | 66 ----------- gcc/ada/libgnat/a-stoubu.adb | 148 ----------------------- gcc/ada/libgnat/a-stoubu.ads | 73 ------------ gcc/ada/libgnat/a-stoufi.adb | 123 ------------------- gcc/ada/libgnat/a-stoufi.ads | 72 ------------ gcc/ada/libgnat/a-stoufo.adb | 155 ------------------------ gcc/ada/libgnat/a-stoufo.ads | 72 ------------ gcc/ada/libgnat/a-stouut.adb | 272 ------------------------------------------- gcc/ada/libgnat/a-stouut.ads | 107 ----------------- gcc/ada/libgnat/a-stteou.ads | 193 ------------------------------ 15 files changed, 1499 deletions(-) delete mode 100644 gcc/ada/libgnat/a-stobbu.adb delete mode 100644 gcc/ada/libgnat/a-stobbu.ads delete mode 100644 gcc/ada/libgnat/a-stobfi.adb delete mode 100644 gcc/ada/libgnat/a-stobfi.ads delete mode 100644 gcc/ada/libgnat/a-stoubu.adb delete mode 100644 gcc/ada/libgnat/a-stoubu.ads delete mode 100644 gcc/ada/libgnat/a-stoufi.adb delete mode 100644 gcc/ada/libgnat/a-stoufi.ads delete mode 100644 gcc/ada/libgnat/a-stoufo.adb delete mode 100644 gcc/ada/libgnat/a-stoufo.ads delete mode 100644 gcc/ada/libgnat/a-stouut.adb delete mode 100644 gcc/ada/libgnat/a-stouut.ads delete mode 100644 gcc/ada/libgnat/a-stteou.ads (limited to 'gcc') diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index ff46200..d712ab5 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -275,13 +275,7 @@ GNATRTL_NONTASKING_OBJS= \ a-stboha$(objext) \ a-stfiha$(objext) \ a-stmaco$(objext) \ - a-stobbu$(objext) \ - a-stobfi$(objext) \ a-storio$(objext) \ - a-stoubu$(objext) \ - a-stoufi$(objext) \ - a-stoufo$(objext) \ - a-stouut$(objext) \ a-strbou$(objext) \ a-stream$(objext) \ a-strsto$(objext) \ @@ -295,7 +289,6 @@ GNATRTL_NONTASKING_OBJS= \ a-strsup$(objext) \ a-strunb$(objext) \ a-ststio$(objext) \ - a-stteou$(objext) \ a-sttebu$(objext) \ a-stbuun$(objext) \ a-stbubo$(objext) \ diff --git a/gcc/ada/impunit.adb b/gcc/ada/impunit.adb index 7e4a4d9..b99f3fd 100644 --- a/gcc/ada/impunit.adb +++ b/gcc/ada/impunit.adb @@ -635,12 +635,6 @@ package body Impunit is ("a-sttebu", T), -- Ada.Strings.Text_Buffers ("a-stbuun", T), -- Ada.Strings.Text_Buffers.Unbounded ("a-stbubo", T), -- Ada.Strings.Text_Buffers.Bounded - ("a-stteou", T), -- Ada.Strings.Text_Output - ("a-stouut", T), -- Ada.Strings.Text_Output.Utils - ("a-stoufi", T), -- Ada.Strings.Text_Output.Files - ("a-stobfi", T), -- Ada.Strings.Text_Output.Basic_Files - ("a-stobbu", T), -- Ada.Strings.Text_Output.Bit_Buckets - ("a-stoufo", T), -- Ada.Strings.Text_Output.Formatting ("a-strsto", T), -- Ada.Streams.Storage ("a-ststbo", T), -- Ada.Streams.Storage.Bounded ("a-ststun", T), -- Ada.Streams.Storage.Unbounded diff --git a/gcc/ada/libgnat/a-stobbu.adb b/gcc/ada/libgnat/a-stobbu.adb deleted file mode 100644 index 560fab2..0000000 --- a/gcc/ada/libgnat/a-stobbu.adb +++ /dev/null @@ -1,53 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.BIT_BUCKETS -- --- -- --- B o d y -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package body Ada.Strings.Text_Output.Bit_Buckets is - - type Bit_Bucket_Type is new Sink with null record; - overriding procedure Full_Method (S : in out Bit_Bucket_Type); - overriding procedure Flush_Method (S : in out Bit_Bucket_Type); - - The_Bit_Bucket : aliased Bit_Bucket_Type - (Chunk_Length => Default_Chunk_Length); - function Bit_Bucket return Sink_Access is (The_Bit_Bucket'Access); - - overriding procedure Full_Method (S : in out Bit_Bucket_Type) - renames Flush_Method; - - overriding procedure Flush_Method (S : in out Bit_Bucket_Type) is - begin - S.Last := 0; - end Flush_Method; - -begin - The_Bit_Bucket.Indent_Amount := 0; - The_Bit_Bucket.Cur_Chunk := The_Bit_Bucket.Initial_Chunk'Access; -end Ada.Strings.Text_Output.Bit_Buckets; diff --git a/gcc/ada/libgnat/a-stobbu.ads b/gcc/ada/libgnat/a-stobbu.ads deleted file mode 100644 index b8710d0..0000000 --- a/gcc/ada/libgnat/a-stobbu.ads +++ /dev/null @@ -1,34 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.BIT_BUCKETS -- --- -- --- S p e c -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package Ada.Strings.Text_Output.Bit_Buckets is - function Bit_Bucket return Sink_Access; -end Ada.Strings.Text_Output.Bit_Buckets; diff --git a/gcc/ada/libgnat/a-stobfi.adb b/gcc/ada/libgnat/a-stobfi.adb deleted file mode 100644 index 942f151..0000000 --- a/gcc/ada/libgnat/a-stobfi.adb +++ /dev/null @@ -1,118 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.BASIC_FILES -- --- -- --- B o d y -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with Ada.Strings.Text_Output.Utils; use Ada.Strings.Text_Output.Utils; -package body Ada.Strings.Text_Output.Basic_Files is - use type OS.File_Descriptor; - - function Create_From_FD - (FD : OS.File_Descriptor; - Indent_Amount : Natural; - Chunk_Length : Positive) return File; - -- Create a file from an OS file descriptor - - function Create_From_FD - (FD : OS.File_Descriptor; - Indent_Amount : Natural; - Chunk_Length : Positive) return File - is - begin - if FD = OS.Invalid_FD then - raise Program_Error with OS.Errno_Message; - end if; - return Result : File (Chunk_Length) do - Result.Indent_Amount := Indent_Amount; - Result.Cur_Chunk := Result.Initial_Chunk'Unchecked_Access; - Result.FD := FD; - end return; - end Create_From_FD; - - function Create_File - (Name : String; - Indent_Amount : Natural := Default_Indent_Amount; - Chunk_Length : Positive := Default_Chunk_Length) return File - is - begin - return Create_From_FD - (OS.Create_File (Name, Fmode => OS.Binary), - Indent_Amount, Chunk_Length); - end Create_File; - - function Create_New_File - (Name : String; - Indent_Amount : Natural := Default_Indent_Amount; - Chunk_Length : Positive := Default_Chunk_Length) return File - is - begin - return Create_From_FD - (OS.Create_New_File (Name, Fmode => OS.Binary), - Indent_Amount, Chunk_Length); - end Create_New_File; - - procedure Close (S : in out File'Class) is - Status : Boolean; - begin - Flush (S); - - if S.FD not in OS.Standout | OS.Standerr then -- Don't close these - OS.Close (S.FD, Status); - if not Status then - raise Program_Error with OS.Errno_Message; - end if; - end if; - end Close; - - overriding procedure Full_Method (S : in out File) renames Flush_Method; - - overriding procedure Flush_Method (S : in out File) is - pragma Assert (S.Cur_Chunk = S.Initial_Chunk'Unchecked_Access); - Res : constant Integer := - OS.Write (S.FD, S.Cur_Chunk.Chars'Address, S.Last); - begin - if Res /= S.Last then - raise Program_Error with OS.Errno_Message; - end if; - S.Last := 0; - end Flush_Method; - - The_Stdout : aliased File := - Create_From_FD (OS.Standout, - Indent_Amount => Default_Indent_Amount, - Chunk_Length => Default_Chunk_Length); - The_Stderr : aliased File := - Create_From_FD (OS.Standerr, - Indent_Amount => Default_Indent_Amount, - Chunk_Length => Default_Chunk_Length); - - function Standard_Output return Sink_Access is (The_Stdout'Access); - function Standard_Error return Sink_Access is (The_Stderr'Access); - -end Ada.Strings.Text_Output.Basic_Files; diff --git a/gcc/ada/libgnat/a-stobfi.ads b/gcc/ada/libgnat/a-stobfi.ads deleted file mode 100644 index 89fcb4d..0000000 --- a/gcc/ada/libgnat/a-stobfi.ads +++ /dev/null @@ -1,66 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.BASIC_FILES -- --- -- --- S p e c -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -private with GNAT.OS_Lib; -package Ada.Strings.Text_Output.Basic_Files is - -- Normally, you should use Ada.Strings.Text_Output.Files, which - -- automatically Closes files via finalization. If you don't want to use - -- finalization, use this package instead. You must then Close the file by - -- hand. The semantics is otherwise the same as Files. - - function Standard_Output return Sink_Access; - function Standard_Error return Sink_Access; - - type File (<>) is new Sink with private; - - function Create_File - (Name : String; - Indent_Amount : Natural := Default_Indent_Amount; - Chunk_Length : Positive := Default_Chunk_Length) return File; - function Create_New_File - (Name : String; - Indent_Amount : Natural := Default_Indent_Amount; - Chunk_Length : Positive := Default_Chunk_Length) return File; - - procedure Close (S : in out File'Class); - -private - - package OS renames GNAT.OS_Lib; - - type File is new Sink with record - FD : OS.File_Descriptor := OS.Invalid_FD; - end record; - - overriding procedure Full_Method (S : in out File); - overriding procedure Flush_Method (S : in out File); - -end Ada.Strings.Text_Output.Basic_Files; diff --git a/gcc/ada/libgnat/a-stoubu.adb b/gcc/ada/libgnat/a-stoubu.adb deleted file mode 100644 index 3c54338..0000000 --- a/gcc/ada/libgnat/a-stoubu.adb +++ /dev/null @@ -1,148 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.BUFFERS -- --- -- --- B o d y -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with Unchecked_Deallocation; -with Ada.Strings.UTF_Encoding.Strings; -with Ada.Strings.UTF_Encoding.Wide_Strings; -with Ada.Strings.UTF_Encoding.Wide_Wide_Strings; -package body Ada.Strings.Text_Output.Buffers is - - type Chunk_Access is access all Chunk; - - function New_Buffer - (Indent_Amount : Natural := Default_Indent_Amount; - Chunk_Length : Positive := Default_Chunk_Length) return Buffer - is - begin - return Result : Buffer (Chunk_Length) do - Result.Indent_Amount := Indent_Amount; - Result.Cur_Chunk := Result.Initial_Chunk'Unchecked_Access; - end return; - end New_Buffer; - - -- We need type conversions of Chunk_Access values in the following two - -- procedures, because the one in Text_Output has Storage_Size => 0, - -- because Text_Output is Pure. We do not run afoul of 13.11.2(16/3), - -- which requires the allocation and deallocation to have the same pool, - -- because the allocation in Full_Method and the deallocation in Destroy - -- use the same access type, and therefore the same pool. - - procedure Destroy (S : in out Buffer) is - procedure Free is new Unchecked_Deallocation (Chunk, Chunk_Access); - Cur : Chunk_Access := Chunk_Access (S.Initial_Chunk.Next); - begin - while Cur /= null loop - declare - Temp : constant Chunk_Access := Chunk_Access (Cur.Next); - begin - Free (Cur); - Cur := Temp; - end; - end loop; - - S.Cur_Chunk := null; - end Destroy; - - overriding procedure Full_Method (S : in out Buffer) is - begin - pragma Assert (S.Cur_Chunk.Next = null); - pragma Assert (S.Last = S.Cur_Chunk.Chars'Length); - S.Cur_Chunk.Next := - Text_Output.Chunk_Access (Chunk_Access'(new Chunk (S.Chunk_Length))); - S.Cur_Chunk := S.Cur_Chunk.Next; - S.Num_Extra_Chunks := S.Num_Extra_Chunks + 1; - S.Last := 0; - end Full_Method; - - function UTF_8_Length (S : Buffer'Class) return Natural is - begin - return S.Num_Extra_Chunks * S.Chunk_Length + S.Last; - end UTF_8_Length; - - procedure Get_UTF_8 - (S : Buffer'Class; Result : out UTF_8_Lines) - is - Cur : access constant Chunk := S.Initial_Chunk'Access; - First : Positive := 1; - begin - loop - if Cur.Next = null then - pragma Assert (Result'Last = First + S.Last - 1); - Result (First .. Result'Last) := Cur.Chars (1 .. S.Last); - exit; - end if; - - pragma Assert (S.Chunk_Length = Cur.Chars'Length); - Result (First .. First + S.Chunk_Length - 1) := Cur.Chars; - First := First + S.Chunk_Length; - Cur := Cur.Next; - end loop; - end Get_UTF_8; - - function Get_UTF_8 (S : Buffer'Class) return UTF_8_Lines is - begin - return Result : String (1 .. UTF_8_Length (S)) do - Get_UTF_8 (S, Result); - end return; - end Get_UTF_8; - - function Get (S : Buffer'Class) return String is - begin - -- If all characters are 7 bits, we don't need to decode; - -- this is an optimization. - - -- Otherwise, if all are 8 bits, we need to decode to get Latin-1. - -- Otherwise, the result is implementation defined, so we return a - -- String encoded as UTF-8. (Note that the AI says "if any character - -- in the sequence is not defined in Character, the result is - -- implementation-defined", so we are not obliged to decode ANY - -- Latin-1 characters if ANY character is bigger than 8 bits. - - if S.All_7_Bits then - return Get_UTF_8 (S); - elsif S.All_8_Bits then - return UTF_Encoding.Strings.Decode (Get_UTF_8 (S)); - else - return Get_UTF_8 (S); - end if; - end Get; - - function Wide_Get (S : Buffer'Class) return Wide_String is - begin - return UTF_Encoding.Wide_Strings.Decode (Get_UTF_8 (S)); - end Wide_Get; - - function Wide_Wide_Get (S : Buffer'Class) return Wide_Wide_String is - begin - return UTF_Encoding.Wide_Wide_Strings.Decode (Get_UTF_8 (S)); - end Wide_Wide_Get; - -end Ada.Strings.Text_Output.Buffers; diff --git a/gcc/ada/libgnat/a-stoubu.ads b/gcc/ada/libgnat/a-stoubu.ads deleted file mode 100644 index 0370cae..0000000 --- a/gcc/ada/libgnat/a-stoubu.ads +++ /dev/null @@ -1,73 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.BUFFERS -- --- -- --- S p e c -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package Ada.Strings.Text_Output.Buffers is - - type Buffer (<>) is new Sink with private; - - function New_Buffer - (Indent_Amount : Natural := Default_Indent_Amount; - Chunk_Length : Positive := Default_Chunk_Length) return Buffer; - - procedure Destroy (S : in out Buffer); - -- Reclaim any heap-allocated data, and render the Buffer unusable. - -- It would make sense to do this via finalization, but we wish to - -- avoid controlled types in the generated code for 'Image. - - function Get_UTF_8 (S : Buffer'Class) return UTF_8_Lines; - -- Get the characters in S, encoded as UTF-8. - - function UTF_8_Length (S : Buffer'Class) return Natural; - procedure Get_UTF_8 - (S : Buffer'Class; Result : out UTF_8_Lines) with - Pre => Result'First = 1 and Result'Last = UTF_8_Length (S); - -- This is a procedure version of the Get_UTF_8 function, for - -- efficiency. The Result String must be the exact right length. - - function Get (S : Buffer'Class) return String; - function Wide_Get (S : Buffer'Class) return Wide_String; - function Wide_Wide_Get (S : Buffer'Class) return Wide_Wide_String; - -- Get the characters in S, decoded as [[Wide_]Wide_]String. - -- There is no need for procedure versions of these, because - -- they are intended primarily to implement the [[Wide_]Wide_]Image - -- attribute, which is already a function. - -private - type Chunk_Count is new Natural; - type Buffer is new Sink with record - Num_Extra_Chunks : Natural := 0; - -- Number of chunks in the linked list, not including Initial_Chunk. - end record; - - overriding procedure Full_Method (S : in out Buffer); - overriding procedure Flush_Method (S : in out Buffer) is null; - -end Ada.Strings.Text_Output.Buffers; diff --git a/gcc/ada/libgnat/a-stoufi.adb b/gcc/ada/libgnat/a-stoufi.adb deleted file mode 100644 index 3444e3b..0000000 --- a/gcc/ada/libgnat/a-stoufi.adb +++ /dev/null @@ -1,123 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.FILES -- --- -- --- B o d y -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with Ada.Strings.Text_Output.Utils; use Ada.Strings.Text_Output.Utils; -package body Ada.Strings.Text_Output.Files is - use type OS.File_Descriptor; - - function Create_From_FD - (FD : OS.File_Descriptor; - Indent_Amount : Natural; - Chunk_Length : Positive) return File; - -- Create a file from an OS file descriptor - - function Create_From_FD - (FD : OS.File_Descriptor; - Indent_Amount : Natural; - Chunk_Length : Positive) return File - is - begin - if FD = OS.Invalid_FD then - raise Program_Error; - end if; - return Result : File (Chunk_Length) do - Result.Indent_Amount := Indent_Amount; - Result.Cur_Chunk := Result.Initial_Chunk'Unchecked_Access; - Result.FD := FD; - end return; - end Create_From_FD; - - function Create_File - (Name : String; - Indent_Amount : Natural := Default_Indent_Amount; - Chunk_Length : Positive := Default_Chunk_Length) return File - is - begin - return Create_From_FD - (OS.Create_File (Name, Fmode => OS.Binary), - Indent_Amount, Chunk_Length); - end Create_File; - - function Create_New_File - (Name : String; - Indent_Amount : Natural := Default_Indent_Amount; - Chunk_Length : Positive := Default_Chunk_Length) return File - is - begin - return Create_From_FD - (OS.Create_New_File (Name, Fmode => OS.Binary), - Indent_Amount, Chunk_Length); - end Create_New_File; - - overriding procedure Finalize (Ref : in out Self_Ref) is - begin - Close (Ref.Self.all); - end Finalize; - - procedure Close (S : in out File'Class) is - Status : Boolean; - begin - Flush (S); - - if S.FD not in OS.Standout | OS.Standerr then -- Don't close these - OS.Close (S.FD, Status); - if not Status then - raise Program_Error; - end if; - end if; - end Close; - - overriding procedure Full_Method (S : in out File) renames Flush_Method; - - overriding procedure Flush_Method (S : in out File) is - pragma Assert (S.Cur_Chunk = S.Initial_Chunk'Unchecked_Access); - Res : constant Integer := - OS.Write (S.FD, S.Cur_Chunk.Chars'Address, S.Last); - begin - if Res /= S.Last then - raise Program_Error; - end if; - S.Last := 0; - end Flush_Method; - - The_Stdout : aliased File := - Create_From_FD (OS.Standout, - Indent_Amount => Default_Indent_Amount, - Chunk_Length => Default_Chunk_Length); - The_Stderr : aliased File := - Create_From_FD (OS.Standerr, - Indent_Amount => Default_Indent_Amount, - Chunk_Length => Default_Chunk_Length); - - function Standard_Output return Sink_Access is (The_Stdout'Access); - function Standard_Error return Sink_Access is (The_Stderr'Access); - -end Ada.Strings.Text_Output.Files; diff --git a/gcc/ada/libgnat/a-stoufi.ads b/gcc/ada/libgnat/a-stoufi.ads deleted file mode 100644 index 330b84f..0000000 --- a/gcc/ada/libgnat/a-stoufi.ads +++ /dev/null @@ -1,72 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.FILES -- --- -- --- S p e c -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -private with GNAT.OS_Lib; -private with Ada.Finalization; -package Ada.Strings.Text_Output.Files is - -- This package supports a Sink type that sends output to a file. The file - -- is automatically closed when finalized. - - function Standard_Output return Sink_Access; - function Standard_Error return Sink_Access; - - type File (<>) is new Sink with private; - - function Create_File - (Name : String; - Indent_Amount : Natural := Default_Indent_Amount; - Chunk_Length : Positive := Default_Chunk_Length) return File; - function Create_New_File - (Name : String; - Indent_Amount : Natural := Default_Indent_Amount; - Chunk_Length : Positive := Default_Chunk_Length) return File; - -- Create a file. Create_New_File raises an exception if the file already - -- exists; Create_File overwrites. - - procedure Close (S : in out File'Class); - -private - - package OS renames GNAT.OS_Lib; - - type Self_Ref (Self : access File) is new Finalization.Limited_Controlled - with null record; - overriding procedure Finalize (Ref : in out Self_Ref); - - type File is new Sink with record - FD : OS.File_Descriptor := OS.Invalid_FD; - Ref : Self_Ref (File'Access); - end record; - - overriding procedure Full_Method (S : in out File); - overriding procedure Flush_Method (S : in out File); - -end Ada.Strings.Text_Output.Files; diff --git a/gcc/ada/libgnat/a-stoufo.adb b/gcc/ada/libgnat/a-stoufo.adb deleted file mode 100644 index 3be8826..0000000 --- a/gcc/ada/libgnat/a-stoufo.adb +++ /dev/null @@ -1,155 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.FORMATTING -- --- -- --- B o d y -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with Ada.Strings.Text_Output.Files; -with Ada.Strings.Text_Output.Buffers; use Ada.Strings.Text_Output.Buffers; -with Ada.Strings.Text_Output.Utils; use Ada.Strings.Text_Output.Utils; -package body Ada.Strings.Text_Output.Formatting is - - procedure Put - (S : in out Sink'Class; T : Template; - X1, X2, X3, X4, X5, X6, X7, X8, X9 : UTF_8_Lines := "") - is - J : Positive := T'First; - Used : array (1 .. 9) of Boolean := (others => False); - begin - while J <= T'Last loop - if T (J) = '\' then - J := J + 1; - case T (J) is - when 'n' => - New_Line (S); - when '\' => - Put_7bit (S, '\'); - when 'i' => - Indent (S); - when 'o' => - Outdent (S); - when 'I' => - Indent (S, 1); - when 'O' => - Outdent (S, 1); - - when '1' => - Used (1) := True; - Put_UTF_8_Lines (S, X1); - when '2' => - Used (2) := True; - Put_UTF_8_Lines (S, X2); - when '3' => - Used (3) := True; - Put_UTF_8_Lines (S, X3); - when '4' => - Used (4) := True; - Put_UTF_8_Lines (S, X4); - when '5' => - Used (5) := True; - Put_UTF_8_Lines (S, X5); - when '6' => - Used (6) := True; - Put_UTF_8_Lines (S, X6); - when '7' => - Used (7) := True; - Put_UTF_8_Lines (S, X7); - when '8' => - Used (8) := True; - Put_UTF_8_Lines (S, X8); - when '9' => - Used (9) := True; - Put_UTF_8_Lines (S, X9); - - when others => - raise Program_Error; - end case; - else - Put_7bit (S, T (J)); - end if; - - J := J + 1; - end loop; - - if not Used (1) then - pragma Assert (X1 = ""); - end if; - if not Used (2) then - pragma Assert (X2 = ""); - end if; - if not Used (3) then - pragma Assert (X3 = ""); - end if; - if not Used (4) then - pragma Assert (X4 = ""); - end if; - if not Used (5) then - pragma Assert (X5 = ""); - end if; - if not Used (6) then - pragma Assert (X6 = ""); - end if; - if not Used (7) then - pragma Assert (X7 = ""); - end if; - if not Used (8) then - pragma Assert (X8 = ""); - end if; - if not Used (9) then - pragma Assert (X9 = ""); - end if; - - Flush (S); - end Put; - - procedure Put - (T : Template; - X1, X2, X3, X4, X5, X6, X7, X8, X9 : UTF_8_Lines := "") is - begin - Put (Files.Standard_Output.all, T, X1, X2, X3, X4, X5, X6, X7, X8, X9); - end Put; - - procedure Err - (T : Template; - X1, X2, X3, X4, X5, X6, X7, X8, X9 : UTF_8_Lines := "") is - begin - Put (Files.Standard_Error.all, T, X1, X2, X3, X4, X5, X6, X7, X8, X9); - end Err; - - function Format - (T : Template; - X1, X2, X3, X4, X5, X6, X7, X8, X9 : UTF_8_Lines := "") - return UTF_8_Lines - is - Buf : Buffer := New_Buffer; - begin - Put (Buf, T, X1, X2, X3, X4, X5, X6, X7, X8, X9); - return Get_UTF_8 (Buf); - end Format; - -end Ada.Strings.Text_Output.Formatting; diff --git a/gcc/ada/libgnat/a-stoufo.ads b/gcc/ada/libgnat/a-stoufo.ads deleted file mode 100644 index a03d087..0000000 --- a/gcc/ada/libgnat/a-stoufo.ads +++ /dev/null @@ -1,72 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.FORMATTING -- --- -- --- S p e c -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package Ada.Strings.Text_Output.Formatting is - - -- Template-based output, based loosely on C's printf family. Unlike - -- printf, it is type safe. We don't support myriad formatting options; the - -- caller is expected to call 'Image, or other functions that might have - -- various formatting capabilities. - -- - -- Each of the following calls Flush - - type Template is new UTF_8; - procedure Put - (S : in out Sink'Class; T : Template; - X1, X2, X3, X4, X5, X6, X7, X8, X9 : UTF_8_Lines := ""); - -- Prints the template as is, except for the following escape sequences: - -- "\n" is end of line. - -- "\i" indents by the default amount, and "\o" outdents. - -- "\I" indents by one space, and "\O" outdents. - -- "\1" is replaced with X1, and similarly for 2, 3, .... - -- "\\" is "\". - - -- Note that the template is not type String, to avoid this sort of thing: - -- - -- https://xkcd.com/327/ - - procedure Put - (T : Template; - X1, X2, X3, X4, X5, X6, X7, X8, X9 : UTF_8_Lines := ""); - -- Sends to standard output - - procedure Err - (T : Template; - X1, X2, X3, X4, X5, X6, X7, X8, X9 : UTF_8_Lines := ""); - -- Sends to standard error - - function Format - (T : Template; - X1, X2, X3, X4, X5, X6, X7, X8, X9 : UTF_8_Lines := "") - return UTF_8_Lines; - -- Returns a UTF-8-encoded String - -end Ada.Strings.Text_Output.Formatting; diff --git a/gcc/ada/libgnat/a-stouut.adb b/gcc/ada/libgnat/a-stouut.adb deleted file mode 100644 index 6b8f72b..0000000 --- a/gcc/ada/libgnat/a-stouut.adb +++ /dev/null @@ -1,272 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.UTILS -- --- -- --- B o d y -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with Ada.Strings.UTF_Encoding.Wide_Wide_Strings; - -package body Ada.Strings.Text_Output.Utils is - - procedure Put_Octet (S : in out Sink'Class; Item : Character) with Inline; - -- Send a single octet to the current Chunk - - procedure Adjust_Column (S : in out Sink'Class) with Inline; - -- Adjust the column for a non-NL character. - - procedure Put_UTF_8_Outline (S : in out Sink'Class; Item : UTF_8); - -- Out-of-line portion of Put_UTF_8. This exists solely to make Put_UTF_8 - -- small enough to reasonably inline it. - - procedure Full (S : in out Sink'Class) is - begin - pragma Assert (S.Last = S.Chunk_Length); - Full_Method (S); - pragma Assert (S.Last = 0); - end Full; - - procedure Flush (S : in out Sink'Class) is - begin - Flush_Method (S); - end Flush; - - procedure Put_Octet (S : in out Sink'Class; Item : Character) is - begin - S.Last := S.Last + 1; - S.Cur_Chunk.Chars (S.Last) := Item; - pragma Assert (S.Chunk_Length = S.Cur_Chunk.Chars'Length); - if S.Last = S.Chunk_Length then - Full (S); - end if; - end Put_Octet; - - procedure Adjust_Column (S : in out Sink'Class) is - begin - -- If we're in the first column, indent. This is handled here, rather - -- than when we see NL, because we don't want spaces in a blank line. - -- The character we're about to put is not NL; NL is handled in - -- New_Line. So after indenting, we simply increment the Column. - - if S.Column = 1 then - Tab_To_Column (S, S.Indentation + 1); - end if; - S.Column := S.Column + 1; - end Adjust_Column; - - procedure Put_7bit (S : in out Sink'Class; Item : Character_7) is - begin - Adjust_Column (S); - Put_Octet (S, Item); - end Put_7bit; - - procedure Put_7bit_NL (S : in out Sink'Class; Item : Character_7) is - begin - if Item = NL then - New_Line (S); - else - Put_7bit (S, Item); - end if; - end Put_7bit_NL; - - procedure Put_Character (S : in out Sink'Class; Item : Character) is - begin - if Character'Pos (Item) < 2**7 then - Put_7bit_NL (S, Item); - else - Put_Wide_Wide_Character (S, To_Wide_Wide (Item)); - end if; - end Put_Character; - - procedure Put_Wide_Character - (S : in out Sink'Class; Item : Wide_Character) is - begin - if Wide_Character'Pos (Item) < 2**7 then - Put_7bit_NL (S, From_Wide (Item)); - else - Put_Wide_Wide_Character (S, To_Wide_Wide (Item)); - end if; - end Put_Wide_Character; - - procedure Put_Wide_Wide_Character - (S : in out Sink'Class; Item : Wide_Wide_Character) is - begin - if Wide_Wide_Character'Pos (Item) < 2**7 then - Put_7bit_NL (S, From_Wide_Wide (Item)); - else - S.All_7_Bits := False; - if Wide_Wide_Character'Pos (Item) >= 2**8 then - S.All_8_Bits := False; - end if; - declare - Temp : constant UTF_8_Lines := - UTF_Encoding.Wide_Wide_Strings.Encode ((1 => Item)); - begin - for X of Temp loop - pragma Assert (X /= NL); - Adjust_Column (S); - Put_Octet (S, X); - end loop; - end; - end if; - end Put_Wide_Wide_Character; - - procedure Put_UTF_8_Outline (S : in out Sink'Class; Item : UTF_8) is - begin - if S.Last + Item'Length = S.Chunk_Length then - -- Item fits exactly in current chunk - - S.Cur_Chunk.Chars (S.Last + 1 .. S.Last + Item'Length) := Item; - S.Last := S.Last + Item'Length; - S.Column := S.Column + Item'Length; - Full (S); - -- ???Seems like maybe we shouldn't call Full until we have MORE - -- characters. But then we can't pass Chunk_Length => 1 to - -- Create_File to get unbuffered output. - else - -- We get here only if Item doesn't fit in the current chunk, which - -- should be fairly rare. We split Item into Left and Right, where - -- Left exactly fills the current chunk, and recurse on Left and - -- Right. Right will fit into the next chunk unless it's very long, - -- so another level of recursion will be extremely rare. - - declare - Left_Length : constant Natural := S.Chunk_Length - S.Last; - Right_First : constant Natural := Item'First + Left_Length; - Left : UTF_8 renames Item (Item'First .. Right_First - 1); - Right : UTF_8 renames Item (Right_First .. Item'Last); - pragma Assert (Left & Right = Item); - begin - Put_UTF_8 (S, Left); -- This will call Full. - Put_UTF_8 (S, Right); -- This might call Full, but probably not. - end; - end if; - end Put_UTF_8_Outline; - - procedure Put_UTF_8 (S : in out Sink'Class; Item : UTF_8) is - begin - Adjust_Column (S); - - if S.Last + Item'Length < S.Chunk_Length then - -- Item fits in current chunk - - S.Cur_Chunk.Chars (S.Last + 1 .. S.Last + Item'Length) := Item; - S.Last := S.Last + Item'Length; - S.Column := S.Column + Item'Length; - else - Put_UTF_8_Outline (S, Item); - end if; - end Put_UTF_8; - - procedure Put_UTF_8_Lines (S : in out Sink'Class; Item : UTF_8_Lines) is - Line_Start, Index : Integer := Item'First; - -- Needs to be Integer, because Item'First might be negative for empty - -- Items. - begin - while Index <= Item'Last loop - if Item (Index) = NL then - if Index > Line_Start then - Put_UTF_8 (S, Item (Line_Start .. Index - 1)); - end if; - New_Line (S); - Line_Start := Index + 1; - end if; - - Index := Index + 1; - end loop; - - if Index > Line_Start then - Put_UTF_8 (S, Item (Line_Start .. Index - 1)); - end if; - end Put_UTF_8_Lines; - - procedure Put_String (S : in out Sink'Class; Item : String) is - begin - for X of Item loop - Put_Character (S, X); - end loop; - end Put_String; - - procedure Put_Wide_String (S : in out Sink'Class; Item : Wide_String) is - begin - for X of Item loop - Put_Wide_Character (S, X); - end loop; - end Put_Wide_String; - - procedure Put_Wide_Wide_String - (S : in out Sink'Class; Item : Wide_Wide_String) is - begin - for X of Item loop - Put_Wide_Wide_Character (S, X); - end loop; - end Put_Wide_Wide_String; - - procedure New_Line (S : in out Sink'Class) is - begin - S.Column := 1; - Put_Octet (S, NL); - end New_Line; - - function Column (S : Sink'Class) return Positive is (S.Column); - - procedure Tab_To_Column (S : in out Sink'Class; Column : Positive) is - begin - if S.Column < Column then - for X in 1 .. Column - S.Column loop - Put_Octet (S, ' '); - end loop; - S.Column := Column; - end if; - end Tab_To_Column; - - procedure Set_Indentation (S : in out Sink'Class; Amount : Natural) is - begin - S.Indentation := Amount; - end Set_Indentation; - - function Indentation (S : Sink'Class) return Natural is (S.Indentation); - - procedure Indent - (S : in out Sink'Class; Amount : Optional_Indentation := Default) - is - By : constant Natural := - (if Amount = Default then S.Indent_Amount else Amount); - begin - Set_Indentation (S, Indentation (S) + By); - end Indent; - - procedure Outdent - (S : in out Sink'Class; Amount : Optional_Indentation := Default) - is - By : constant Natural := - (if Amount = Default then S.Indent_Amount else Amount); - begin - Set_Indentation (S, Indentation (S) - By); - end Outdent; - -end Ada.Strings.Text_Output.Utils; diff --git a/gcc/ada/libgnat/a-stouut.ads b/gcc/ada/libgnat/a-stouut.ads deleted file mode 100644 index 69cde55..0000000 --- a/gcc/ada/libgnat/a-stouut.ads +++ /dev/null @@ -1,107 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT.UTILS -- --- -- --- S p e c -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package Ada.Strings.Text_Output.Utils with Pure is - - -- This package provides utility functions on Sink'Class. These are - -- intended for use by Put_Image attributes, both the default versions - -- generated by the compiler, and user-defined ones. - - procedure Full (S : in out Sink'Class) with Inline; - -- Must be called when the current chunk is full. Dispatches to - -- Full_Method. - - procedure Flush (S : in out Sink'Class) with Inline; - -- Dispatches to Flush_Method - - -- Full_Method and Flush_Method should be called only via Full and Flush - - procedure Put_Character (S : in out Sink'Class; Item : Character); - procedure Put_Wide_Character (S : in out Sink'Class; Item : Wide_Character); - procedure Put_Wide_Wide_Character - (S : in out Sink'Class; Item : Wide_Wide_Character); - procedure Put_String (S : in out Sink'Class; Item : String); - procedure Put_Wide_String (S : in out Sink'Class; Item : Wide_String); - procedure Put_Wide_Wide_String - (S : in out Sink'Class; Item : Wide_Wide_String); - -- Encode characters or strings as UTF-8, and send them to S. - - subtype Character_7 is - Character range Character'Val (0) .. Character'Val (2**7 - 1); - -- 7-bit character. These are the same in both Latin-1 and UTF-8. - - procedure Put_7bit (S : in out Sink'Class; Item : Character_7) - with Inline, Pre => Item /= NL; - procedure Put_7bit_NL (S : in out Sink'Class; Item : Character_7) - with Inline; - -- Put a 7-bit character, and adjust the Column. For Put_7bit_NL, Item can - -- be NL. - - procedure Put_UTF_8 (S : in out Sink'Class; Item : UTF_8) with Inline; - procedure Put_UTF_8_Lines (S : in out Sink'Class; Item : UTF_8_Lines); - -- Send data that is already UTF-8 encoded (including 7-bit ASCII) to - -- S. These are more efficient than Put_String. - - procedure New_Line (S : in out Sink'Class) with - Inline, Post => Column (S) = 1; - -- Puts the new-line character. - - function Column (S : Sink'Class) return Positive with Inline; - -- Current output column. The Column is initially 1, and is incremented for - -- each 7-bit character output, except for the new-line character, which - -- sets Column back to 1. The next character to be output will go in this - -- column. - - procedure Tab_To_Column (S : in out Sink'Class; Column : Positive); - -- Put spaces until we're at or past Column. - - procedure Set_Indentation (S : in out Sink'Class; Amount : Natural) - with Inline; - function Indentation (S : Sink'Class) return Natural with Inline; - -- Indentation is initially 0. Set_Indentation sets it, and Indentation - -- returns it. This number of space characters are put at the start of - -- each nonempty line. - - subtype Optional_Indentation is Integer range -1 .. Natural'Last; - Default : constant Optional_Indentation := -1; - - procedure Indent - (S : in out Sink'Class; Amount : Optional_Indentation := Default) - with Inline; - procedure Outdent - (S : in out Sink'Class; Amount : Optional_Indentation := Default) - with Inline; - -- Increase/decrease Indentation by Amount. If Amount = Default, the amount - -- specified by the Indent_Amount parameter of the sink creation function - -- is used. The sink creation functions are New_Buffer, Create_File, and - -- Create_New_File. - -end Ada.Strings.Text_Output.Utils; diff --git a/gcc/ada/libgnat/a-stteou.ads b/gcc/ada/libgnat/a-stteou.ads deleted file mode 100644 index 324c9e6..0000000 --- a/gcc/ada/libgnat/a-stteou.ads +++ /dev/null @@ -1,193 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- ADA.STRINGS.TEXT_OUTPUT -- --- -- --- S p e c -- --- -- --- Copyright (C) 2020-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with Ada.Strings.UTF_Encoding; -with Ada.Strings.UTF_Encoding.Wide_Wide_Strings; - -package Ada.Strings.Text_Output with Pure is - - -- This package provides a "Sink" abstraction, to which characters of type - -- Character, Wide_Character, and Wide_Wide_Character can be sent. This - -- type is used by the Put_Image attribute. In particular, T'Put_Image has - -- the following parameter types: - -- - -- procedure T'Put_Image (S : in out Sink'Class; V : T); - -- - -- The default generated code for Put_Image of a composite type will - -- typically call Put_Image on the components. - -- - -- This is not a fully general abstraction that can be arbitrarily - -- extended. It is designed with particular extensions in mind, and these - -- extensions are declared in child packages of this package, because they - -- depend on implementation details in the private part of this - -- package. - -- - -- Users are not expected to extend type Sink. - -- - -- The primary extensions of Sink are: - -- - -- Buffer. The characters sent to a Buffer are stored in memory, and can - -- be retrieved via Get functions. This is intended for the - -- implementation of the 'Image attribute. The compiler will generate a - -- T'Image function that declares a local Buffer, sends characters to - -- it, and then returns a call to Get, Destroying the Buffer on return. - -- - -- function T'Image (V : T) return String is - -- Buf : Buffer := New_Buffer (...); - -- begin - -- T'Put_Image (Buf, V); - -- return Result : constant String := Get (Buf) do - -- Destroy (Buf); - -- end return; - -- end T'Image; - -- ????Perhaps Buffer should be controlled; if you don't like - -- controlled types, call Put_Image directly. - -- - -- File. The characters are sent to a file, possibly opened by file - -- name, or possibly standard output or standard error. 'Put_Image - -- can be called directly on a File, thus avoiding any heap allocation. - - type Sink (<>) is abstract tagged limited private; - type Sink_Access is access all Sink'Class with Storage_Size => 0; - -- Sink is a character sink; you can send characters to a Sink. - -- UTF-8 encoding is used. - - procedure Full_Method (S : in out Sink) is abstract; - procedure Flush_Method (S : in out Sink) is abstract; - -- There is an internal buffer to store the characters. Full_Method is - -- called when the buffer is full, and Flush_Method may be called to flush - -- the buffer. For Buffer, Full_Method allocates more space for more - -- characters, and Flush_Method does nothing. For File, Full_Method and - -- Flush_Method do the same thing: write the characters to the file, and - -- empty the internal buffer. - -- - -- These are the only dispatching subprograms on Sink. This is for - -- efficiency; we don't dispatch on every write to the Sink, but only when - -- the internal buffer is full (or upon client request). - -- - -- Full_Method and Flush_Method must make the current chunk empty. - -- - -- Additional operations operating on Sink'Class are declared in the Utils - -- child, including Full and Flush, which call the above. - - function To_Wide (C : Character) return Wide_Character is - (Wide_Character'Val (Character'Pos (C))); - function To_Wide_Wide (C : Character) return Wide_Wide_Character is - (Wide_Wide_Character'Val (Character'Pos (C))); - function To_Wide_Wide (C : Wide_Character) return Wide_Wide_Character is - (Wide_Wide_Character'Val (Wide_Character'Pos (C))); - -- Conversions [Wide_]Character --> [Wide_]Wide_Character. - -- These cannot fail. - - function From_Wide (C : Wide_Character) return Character is - (Character'Val (Wide_Character'Pos (C))); - function From_Wide_Wide (C : Wide_Wide_Character) return Character is - (Character'Val (Wide_Wide_Character'Pos (C))); - function From_Wide_Wide (C : Wide_Wide_Character) return Wide_Character is - (Wide_Character'Val (Wide_Wide_Character'Pos (C))); - -- Conversions [Wide_]Wide_Character --> [Wide_]Character. - -- These fail if the character is out of range. - - function NL return Character is (ASCII.LF) with Inline; - function Wide_NL return Wide_Character is (To_Wide (Character'(NL))) - with Inline; - function Wide_Wide_NL return Wide_Wide_Character is - (To_Wide_Wide (Character'(NL))) with Inline; - -- Character representing new line. There is no support for CR/LF line - -- endings. - - -- We have two subtypes of String that are encoded in UTF-8. UTF_8 cannot - -- contain newline characters; UTF_8_Lines can. Sending UTF_8 data to a - -- Sink is more efficient, because end-of-line processing is not needed. - -- Both of these are more efficient than [[Wide_]Wide_]String, because no - -- encoding is needed. - - subtype UTF_8_Lines is UTF_Encoding.UTF_8_String with - Predicate => - UTF_Encoding.Wide_Wide_Strings.Encode - (UTF_Encoding.Wide_Wide_Strings.Decode (UTF_8_Lines)) = UTF_8_Lines; - - subtype UTF_8 is UTF_8_Lines with - Predicate => (for all UTF_8_Char of UTF_8 => UTF_8_Char /= NL); - - Default_Indent_Amount : constant Natural := 4; - - Default_Chunk_Length : constant Positive := 500; - -- Experiment shows this value to be reasonably efficient; decreasing it - -- slows things down, but increasing it doesn't gain much. - -private - -- For Buffer, the "internal buffer" mentioned above is implemented as a - -- linked list of chunks. When the current chunk is full, we allocate a new - -- one. For File, there is only one chunk. When it is full, we send the - -- data to the file, and empty it. - - type Chunk; - type Chunk_Access is access all Chunk with Storage_Size => 0; - type Chunk (Length : Positive) is limited record - Next : Chunk_Access := null; - Chars : UTF_8_Lines (1 .. Length); - end record; - - type Sink (Chunk_Length : Positive) is abstract tagged limited record - Indent_Amount : Natural; - Column : Positive := 1; - Indentation : Natural := 0; - - All_7_Bits : Boolean := True; - -- For optimization of Text_Output.Buffers.Get (cf). - -- True if all characters seen so far fit in 7 bits. - -- 7-bit characters are represented the same in Character - -- and in UTF-8, so they don't need translation. - - All_8_Bits : Boolean := True; - -- True if all characters seen so far fit in 8 bits. - -- This is needed in Text_Output.Buffers.Get to distinguish - -- the case where all characters are Latin-1 (so it should - -- decode) from the case where some characters are bigger than - -- 8 bits (so the result is implementation defined). - - Cur_Chunk : Chunk_Access; - -- Points to the chunk we are currently sending characters to. - -- We want to say: - -- Cur_Chunk : Chunk_Access := Initial_Chunk'Access; - -- but that's illegal, so we have some horsing around to do. - - Last : Natural := 0; - -- Last-used character in Cur_Chunk.all. - - Initial_Chunk : aliased Chunk (Length => Chunk_Length); - -- For Buffer, this is the first chunk. Subsequent chunks are allocated - -- on the heap. For File, this is the only chunk, and there is no heap - -- allocation. - end record; - -end Ada.Strings.Text_Output; -- cgit v1.1 From 0700922ea57258870047f210c3569b5deed1bf82 Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Fri, 30 Apr 2021 10:11:25 +0200 Subject: [Ada] Fix missing error messages when returning limited type gcc/ada/ * sem_ch6.adb (Check_Limited_Return): Replace Comes_From_Source with Comes_From_Extended_Return_Statement. --- gcc/ada/sem_ch6.adb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index ffab332..3697aba 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -7008,7 +7008,8 @@ package body Sem_Ch6 is elsif Is_Limited_Type (R_Type) and then not Is_Interface (R_Type) - and then Comes_From_Source (N) + and then not (Nkind (N) = N_Simple_Return_Statement + and then Comes_From_Extended_Return_Statement (N)) and then not In_Instance_Body and then not OK_For_Limited_Init_In_05 (R_Type, Expr) then -- cgit v1.1 From 6cf7cc8ccf3a7f34c1772f8da11a1c127fee3363 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 30 Apr 2021 12:02:35 +0200 Subject: [Ada] Simplify and reuse Is_Concurrent_Interface gcc/ada/ * exp_ch3.adb (Stream_Operation_OK): Reuse Is_Concurrent_Interface. * sem_ch3.adb (Analyze_Interface_Declaration, Build_Derived_Record_Type): Likewise. * sem_ch6.adb (Check_Limited_Return): Likewise. * sem_util.adb (Is_Concurrent_Interface): Don't call Is_Interface because each of the Is_Protected_Interface, Is_Synchronized_Interface and Is_Task_Interface calls it anyway. --- gcc/ada/exp_ch3.adb | 7 +------ gcc/ada/sem_ch3.adb | 8 ++------ gcc/ada/sem_ch6.adb | 5 +---- gcc/ada/sem_util.adb | 8 +++----- 4 files changed, 7 insertions(+), 21 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index ce6d294..2f997a3 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -11251,12 +11251,7 @@ package body Exp_Ch3 is or else not Is_Abstract_Type (Typ) or else not Is_Derived_Type (Typ)) and then not Has_Unknown_Discriminants (Typ) - and then not - (Is_Interface (Typ) - and then - (Is_Task_Interface (Typ) - or else Is_Protected_Interface (Typ) - or else Is_Synchronized_Interface (Typ))) + and then not Is_Concurrent_Interface (Typ) and then not Restriction_Active (No_Streams) and then not Restriction_Active (No_Dispatch) and then No (No_Tagged_Streams_Pragma (Typ)) diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index aa73f3a..95a27a2 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -3493,9 +3493,7 @@ package body Sem_Ch3 is -- Check runtime support for synchronized interfaces - if (Is_Task_Interface (T) - or else Is_Protected_Interface (T) - or else Is_Synchronized_Interface (T)) + if Is_Concurrent_Interface (T) and then not RTE_Available (RE_Select_Specific_Data) then Error_Msg_CRT ("synchronized interfaces", T); @@ -9270,9 +9268,7 @@ package body Sem_Ch3 is and then Is_Limited_Record (Full_View (Parent_Type))) then if not Is_Interface (Parent_Type) - or else Is_Synchronized_Interface (Parent_Type) - or else Is_Protected_Interface (Parent_Type) - or else Is_Task_Interface (Parent_Type) + or else Is_Concurrent_Interface (Parent_Type) then Set_Is_Limited_Record (Derived_Type); end if; diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 3697aba..4b58d59 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -6999,10 +6999,7 @@ package body Sem_Ch6 is -- A limited interface that is not immutably limited is OK if Is_Limited_Interface (R_Type) - and then - not (Is_Task_Interface (R_Type) - or else Is_Protected_Interface (R_Type) - or else Is_Synchronized_Interface (R_Type)) + and then not Is_Concurrent_Interface (R_Type) then null; diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 25060cc..ef575d0 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -16209,11 +16209,9 @@ package body Sem_Util is function Is_Concurrent_Interface (T : Entity_Id) return Boolean is begin - return Is_Interface (T) - and then - (Is_Protected_Interface (T) - or else Is_Synchronized_Interface (T) - or else Is_Task_Interface (T)); + return Is_Protected_Interface (T) + or else Is_Synchronized_Interface (T) + or else Is_Task_Interface (T); end Is_Concurrent_Interface; ----------------------- -- cgit v1.1 From 77630ba95a5b0220fdbb460727cf12e45a0c1115 Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Thu, 29 Apr 2021 11:44:29 -0700 Subject: [Ada] Fix some "current instance" bugs gcc/ada/ * exp_ch3.adb (Build_Record_Init_Proc.Build_Assignment): When building the assignment statement corresponding to the default expression for a component, we make a copy of the expression. When making that copy (and if we have seen a component that requires late initialization), pass a Map parameter into the call to New_Copy_Tree to redirect references to the type to instead refer to the _Init formal parameter of the init proc. This includes hoisting the declaration of Has_Late_Init_Comp out one level so that it becomes available to Build_Assignment. (Find_Current_Instance): Return True for other kinds of current instance references, instead of just access-valued attribute references such as T'Access. * sem_util.adb (Is_Aliased_View): Return True for the _Init formal parameter of an init procedure. The changes in exp_ch3.adb can have the effect of replacing a "T'Access" attribute reference in an init procedure with an "_Init'Access" attribute reference. We want such an attribute reference to be legal. However, we do not simply mark the formal parameter as being aliased because that might impact callers. (Is_Object_Image): Return True if Is_Current_Instance returns True for the prefix of an Image (or related attribute) attribute reference. --- gcc/ada/exp_ch3.adb | 51 ++++++++++++++++++++------------------------------- gcc/ada/sem_util.adb | 13 ++++++++++++- 2 files changed, 32 insertions(+), 32 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 2f997a3..504410d 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -1926,6 +1926,7 @@ package body Exp_Ch3 is Proc_Id : Entity_Id; Rec_Type : Entity_Id; Set_Tag : Entity_Id := Empty; + Has_Late_Init_Comp : Boolean := False; -- set in Build_Init_Statements function Build_Assignment (Id : Entity_Id; @@ -2021,35 +2022,27 @@ package body Exp_Ch3 is Selector_Name => New_Occurrence_Of (Id, Default_Loc)); Set_Assignment_OK (Lhs); - -- Case of an access attribute applied to the current instance. - -- Replace the reference to the type by a reference to the actual - -- object. (Note that this handles the case of the top level of - -- the expression being given by such an attribute, but does not - -- cover uses nested within an initial value expression. Nested - -- uses are unlikely to occur in practice, but are theoretically - -- possible.) It is not clear how to handle them without fully - -- traversing the expression. ??? - - if Kind = N_Attribute_Reference - and then Attribute_Name (Default) in Name_Unchecked_Access - | Name_Unrestricted_Access - and then Is_Entity_Name (Prefix (Default)) - and then Is_Type (Entity (Prefix (Default))) - and then Entity (Prefix (Default)) = Rec_Type - then - Exp := - Make_Attribute_Reference (Default_Loc, - Prefix => - Make_Identifier (Default_Loc, Name_uInit), - Attribute_Name => Name_Unrestricted_Access); - end if; - -- Take a copy of Exp to ensure that later copies of this component -- declaration in derived types see the original tree, not a node -- rewritten during expansion of the init_proc. If the copy contains -- itypes, the scope of the new itypes is the init_proc being built. - Exp := New_Copy_Tree (Exp, New_Scope => Proc_Id); + declare + Map : Elist_Id := No_Elist; + begin + if Has_Late_Init_Comp then + -- Map the type to the _Init parameter in order to + -- handle "current instance" references. + + Map := New_Elmt_List + (Elmt1 => Rec_Type, + Elmt2 => Defining_Identifier (First + (Parameter_Specifications + (Parent (Proc_Id))))); + end if; + + Exp := New_Copy_Tree (Exp, New_Scope => Proc_Id, Map => Map); + end; Res := New_List ( Make_Assignment_Statement (Loc, @@ -2981,7 +2974,6 @@ package body Exp_Ch3 is Counter_Id : Entity_Id := Empty; Comp_Loc : Source_Ptr; Decl : Node_Id; - Has_Late_Init_Comp : Boolean; Id : Entity_Id; Parent_Stmts : List_Id; Stmts : List_Id; @@ -3097,10 +3089,9 @@ package body Exp_Ch3 is function Find_Current_Instance (N : Node_Id) return Traverse_Result is begin - if Nkind (N) = N_Attribute_Reference - and then Is_Access_Type (Etype (N)) - and then Is_Entity_Name (Prefix (N)) - and then Is_Type (Entity (Prefix (N))) + if Is_Entity_Name (N) + and then Present (Entity (N)) + and then Is_Current_Instance (N) then References_Current_Instance := True; return Abandon; @@ -3255,8 +3246,6 @@ package body Exp_Ch3 is -- step deals with regular components. The second step deals with -- components that require late initialization. - Has_Late_Init_Comp := False; - -- First pass : regular components Decl := First_Non_Pragma (Component_Items (Comp_List)); diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index ef575d0..7ea809b 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -15691,6 +15691,15 @@ package body Sem_Util is -- statement is aliased if its type is immutably limited. or else (Is_Return_Object (E) + and then Is_Limited_View (Etype (E))) + + -- The current instance of a limited type is aliased, so + -- we want to allow uses of T'Access in the init proc for + -- a limited type T. However, we don't want to mark the formal + -- parameter as being aliased since that could impact callers. + + or else (Is_Formal (E) + and then Chars (E) = Name_uInit and then Is_Limited_View (Etype (E))); elsif Nkind (Obj) = N_Selected_Component then @@ -18838,7 +18847,9 @@ package body Sem_Util is -- This is because the parser always checks that prefixes of attributes -- are named. - return not (Is_Entity_Name (Prefix) and then Is_Type (Entity (Prefix))); + return not (Is_Entity_Name (Prefix) + and then Is_Type (Entity (Prefix)) + and then not Is_Current_Instance (Prefix)); end Is_Object_Image; ------------------------- -- cgit v1.1 From 796b616383780e7707c21e4e31eb627e5937a93f Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Fri, 30 Apr 2021 11:52:35 -0400 Subject: [Ada] Use runtime from base compiler during stage1 #2 gcc/ada/ * Make-generated.in: Add -f switch to ensure cp will never fail. --- gcc/ada/Make-generated.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/Make-generated.in b/gcc/ada/Make-generated.in index 7d452b8..948fc50 100644 --- a/gcc/ada/Make-generated.in +++ b/gcc/ada/Make-generated.in @@ -83,4 +83,4 @@ ada/stamp-sdefault : $(srcdir)/ada/version.c Makefile touch ada/stamp-sdefault ada/%: $(srcdir)/ada/libgnat/% - $(CP) $< $@ + $(CP) -f $< $@ -- cgit v1.1 From 902d7076663aff56198b81f8efa356c3e1024e80 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Fri, 30 Apr 2021 12:41:22 +0200 Subject: [Ada] Adapt SPARK RM rule on non-effectively volatile abstract state gcc/ada/ * sem_prag.adb (Analyze_Global_Item): Adapt to update SPARK RM rule. --- gcc/ada/sem_prag.adb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index fa63fda..0efdcef 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -2433,10 +2433,13 @@ package body Sem_Prag is SPARK_Msg_N ("\use its constituents instead", Item); return; - -- An external state cannot appear as a global item of a - -- nonvolatile function (SPARK RM 7.1.3(8)). + -- An external state which has Async_Writers or + -- Effective_Reads enabled cannot appear as a global item + -- of a nonvolatile function (SPARK RM 7.1.3(8)). elsif Is_External_State (Item_Id) + and then (Async_Writers_Enabled (Item_Id) + or else Effective_Reads_Enabled (Item_Id)) and then Ekind (Spec_Id) in E_Function | E_Generic_Function and then not Is_Volatile_Function (Spec_Id) then -- cgit v1.1 From fdb5c200369c8ba56358a145e0c5c6c461ad5a45 Mon Sep 17 00:00:00 2001 From: Claire Dross Date: Fri, 30 Apr 2021 10:24:30 +0200 Subject: [Ada] Add Reference and Constant_Reference functions to formal containers gcc/ada/ * libgnat/a-cfdlli.ads, libgnat/a-cfdlli.adb libgnat/a-cfinve.ads, libgnat/a-cfinve.adb, libgnat/a-cofove.ads, libgnat/a-cofove.adb, libgnat/a-coboho.ads, libgnat/a-coboho.adb (Constant_Reference): Get a read-only access to an element of the container. (At_End): Ghost functions used to express pledges in the postcondition of Reference. (Reference): Get a read-write access to an element of the container. * libgnat/a-cfhama.ads, libgnat/a-cfhama.adb, libgnat/a-cforma.ads, libgnat/a-cforma.adb: The full view of the Map type is no longer a tagged type, but a wrapper over this tagged type. This is to avoid issues with dispatching result in At_End functions. (Constant_Reference): Get a read-only access to an element of the container. (At_End): Ghost functions used to express pledges in the postcondition of Reference. (Reference): Get a read-write access to an element of the container. * libgnat/a-cfhase.ads, libgnat/a-cfhase.adb, libgnat/a-cforse.ads, libgnat/a-cforse.adb: The full view of the Map type is no longer a tagged type, but a wrapper over this tagged type. (Constant_Reference): Get a read-only access to an element of the container. * libgnat/a-cofuse.ads, libgnat/a-cofuve.ads (Copy_Element): Expression function used to cause SPARK to make sure Element_Type is copiable. * libgnat/a-cofuma.ads (Copy_Key): Expression function used to cause SPARK to make sure Key_Type is copiable. (Copy_Element): Expression function used to cause SPARK to make sure Element_Type is copiable. --- gcc/ada/libgnat/a-cfdlli.adb | 32 +++++ gcc/ada/libgnat/a-cfdlli.ads | 49 +++++++- gcc/ada/libgnat/a-cfhama.adb | 181 ++++++++++++++++++++--------- gcc/ada/libgnat/a-cfhama.ads | 96 ++++++++++++++- gcc/ada/libgnat/a-cfhase.adb | 212 +++++++++++++++++++--------------- gcc/ada/libgnat/a-cfhase.ads | 17 ++- gcc/ada/libgnat/a-cfinve.adb | 48 ++++++++ gcc/ada/libgnat/a-cfinve.ads | 44 ++++++- gcc/ada/libgnat/a-cforma.adb | 236 ++++++++++++++++++++++++------------- gcc/ada/libgnat/a-cforma.ads | 96 ++++++++++++++- gcc/ada/libgnat/a-cforse.adb | 269 +++++++++++++++++++++++++------------------ gcc/ada/libgnat/a-cforse.ads | 25 ++-- gcc/ada/libgnat/a-coboho.adb | 34 +++++- gcc/ada/libgnat/a-coboho.ads | 6 + gcc/ada/libgnat/a-cofove.adb | 32 +++++ gcc/ada/libgnat/a-cofove.ads | 44 ++++++- gcc/ada/libgnat/a-cofuma.ads | 8 ++ gcc/ada/libgnat/a-cofuse.ads | 7 ++ gcc/ada/libgnat/a-cofuve.ads | 7 ++ 19 files changed, 1073 insertions(+), 370 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/a-cfdlli.adb b/gcc/ada/libgnat/a-cfdlli.adb index d96a8f6..b289def 100644 --- a/gcc/ada/libgnat/a-cfdlli.adb +++ b/gcc/ada/libgnat/a-cfdlli.adb @@ -188,6 +188,22 @@ is Free (Container, X); end Clear; + ------------------------ + -- Constant_Reference -- + ------------------------ + + function Constant_Reference + (Container : aliased List; + Position : Cursor) return not null access constant Element_Type + is + begin + if not Has_Element (Container => Container, Position => Position) then + raise Constraint_Error with "Position cursor has no element"; + end if; + + return Container.Nodes (Position.Node).Element'Access; + end Constant_Reference; + -------------- -- Contains -- -------------- @@ -1376,6 +1392,22 @@ is return (Node => Container.Nodes (Position.Node).Prev); end Previous; + --------------- + -- Reference -- + --------------- + + function Reference + (Container : not null access List; + Position : Cursor) return not null access Element_Type + is + begin + if not Has_Element (Container.all, Position) then + raise Constraint_Error with "Position cursor has no element"; + end if; + + return Container.Nodes (Position.Node).Element'Access; + end Reference; + --------------------- -- Replace_Element -- --------------------- diff --git a/gcc/ada/libgnat/a-cfdlli.ads b/gcc/ada/libgnat/a-cfdlli.ads index e3a2de6..8713d33 100644 --- a/gcc/ada/libgnat/a-cfdlli.ads +++ b/gcc/ada/libgnat/a-cfdlli.ads @@ -387,6 +387,53 @@ is Model (Container), P.Get (Positions (Container), Position)); + function At_End (E : access constant List) return access constant List + is (E) + with Ghost, + Annotate => (GNATprove, At_End_Borrow); + + function At_End + (E : access constant Element_Type) return access constant Element_Type + is (E) + with Ghost, + Annotate => (GNATprove, At_End_Borrow); + + function Constant_Reference + (Container : aliased List; + Position : Cursor) return not null access constant Element_Type + with + Global => null, + Pre => Has_Element (Container, Position), + Post => + Constant_Reference'Result.all = + Element (Model (Container), P.Get (Positions (Container), Position)); + + function Reference + (Container : not null access List; + Position : Cursor) return not null access Element_Type + with + Global => null, + Pre => Has_Element (Container.all, Position), + Post => + Length (Container.all) = Length (At_End (Container).all) + + -- Cursors are preserved + + and Positions (Container.all) = Positions (At_End (Container).all) + + -- Container will have Result.all at position Position + + and At_End (Reference'Result).all = + Element (Model (At_End (Container).all), + P.Get (Positions (At_End (Container).all), Position)) + + -- All other elements are preserved + + and M.Equal_Except + (Model (Container.all), + Model (At_End (Container).all), + P.Get (Positions (At_End (Container).all), Position)); + procedure Move (Target : in out List; Source : in out List) with Global => null, Pre => Target.Capacity >= Length (Source), @@ -1609,7 +1656,7 @@ private type Node_Type is record Prev : Count_Type'Base := -1; Next : Count_Type; - Element : Element_Type; + Element : aliased Element_Type; end record; function "=" (L, R : Node_Type) return Boolean is abstract; diff --git a/gcc/ada/libgnat/a-cfhama.adb b/gcc/ada/libgnat/a-cfhama.adb index 17971b2..179b400 100644 --- a/gcc/ada/libgnat/a-cfhama.adb +++ b/gcc/ada/libgnat/a-cfhama.adb @@ -109,20 +109,21 @@ is ENode : Count_Type; begin - Node := Left.First.Node; + Node := First (Left).Node; while Node /= 0 loop ENode := Find (Container => Right, - Key => Left.Nodes (Node).Key).Node; + Key => Left.Content.Nodes (Node).Key).Node; if ENode = 0 or else - Right.Nodes (ENode).Element /= Left.Nodes (Node).Element + Right.Content.Nodes (ENode).Element /= + Left.Content.Nodes (Node).Element then return False; end if; - Node := HT_Ops.Next (Left, Node); + Node := HT_Ops.Next (Left.Content, Node); end loop; return True; @@ -145,7 +146,7 @@ is -------------------- procedure Insert_Element (Source_Node : Count_Type) is - N : Node_Type renames Source.Nodes (Source_Node); + N : Node_Type renames Source.Content.Nodes (Source_Node); begin Insert (Target, N.Key, N.Element); end Insert_Element; @@ -164,7 +165,7 @@ is Clear (Target); - Insert_Elements (Source); + Insert_Elements (Source.Content); end Assign; -------------- @@ -173,7 +174,7 @@ is function Capacity (Container : Map) return Count_Type is begin - return Container.Nodes'Length; + return Container.Content.Nodes'Length; end Capacity; ----------- @@ -182,9 +183,44 @@ is procedure Clear (Container : in out Map) is begin - HT_Ops.Clear (Container); + HT_Ops.Clear (Container.Content); end Clear; + ------------------------ + -- Constant_Reference -- + ------------------------ + + function Constant_Reference + (Container : aliased Map; + Position : Cursor) return not null access constant Element_Type + is + begin + if not Has_Element (Container, Position) then + raise Constraint_Error with "Position cursor has no element"; + end if; + + pragma Assert + (Vet (Container, Position), + "bad cursor in function Constant_Reference"); + + return Container.Content.Nodes (Position.Node).Element'Access; + end Constant_Reference; + + function Constant_Reference + (Container : aliased Map; + Key : Key_Type) return not null access constant Element_Type + is + Node : constant Count_Type := Find (Container, Key).Node; + + begin + if Node = 0 then + raise Constraint_Error with + "no element available because key not in map"; + end if; + + return Container.Content.Nodes (Node).Element'Access; + end Constant_Reference; + -------------- -- Contains -- -------------- @@ -214,18 +250,18 @@ is raise Capacity_Error; end if; - Target.Length := Source.Length; - Target.Free := Source.Free; + Target.Content.Length := Source.Content.Length; + Target.Content.Free := Source.Content.Free; H := 1; while H <= Source.Modulus loop - Target.Buckets (H) := Source.Buckets (H); + Target.Content.Buckets (H) := Source.Content.Buckets (H); H := H + 1; end loop; N := 1; while N <= Source.Capacity loop - Target.Nodes (N) := Source.Nodes (N); + Target.Content.Nodes (N) := Source.Content.Nodes (N); N := N + 1; end loop; @@ -255,7 +291,7 @@ is X : Count_Type; begin - Key_Ops.Delete_Key_Sans_Free (Container, Key, X); + Key_Ops.Delete_Key_Sans_Free (Container.Content, Key, X); if X = 0 then raise Constraint_Error with "attempt to delete key not in map"; @@ -273,7 +309,7 @@ is pragma Assert (Vet (Container, Position), "bad cursor in Delete"); - HT_Ops.Delete_Node_Sans_Free (Container, Position.Node); + HT_Ops.Delete_Node_Sans_Free (Container.Content, Position.Node); Free (Container, Position.Node); Position := No_Element; @@ -292,7 +328,7 @@ is "no element available because key not in map"; end if; - return Container.Nodes (Node).Element; + return Container.Content.Nodes (Node).Element; end Element; function Element (Container : Map; Position : Cursor) return Element_Type is @@ -304,7 +340,7 @@ is pragma Assert (Vet (Container, Position), "bad cursor in function Element"); - return Container.Nodes (Position.Node).Element; + return Container.Content.Nodes (Position.Node).Element; end Element; --------------------- @@ -326,7 +362,7 @@ is procedure Exclude (Container : in out Map; Key : Key_Type) is X : Count_Type; begin - Key_Ops.Delete_Key_Sans_Free (Container, Key, X); + Key_Ops.Delete_Key_Sans_Free (Container.Content, Key, X); Free (Container, X); end Exclude; @@ -335,7 +371,7 @@ is ---------- function Find (Container : Map; Key : Key_Type) return Cursor is - Node : constant Count_Type := Key_Ops.Find (Container, Key); + Node : constant Count_Type := Key_Ops.Find (Container.Content, Key); begin if Node = 0 then @@ -350,7 +386,7 @@ is ----------- function First (Container : Map) return Cursor is - Node : constant Count_Type := HT_Ops.First (Container); + Node : constant Count_Type := HT_Ops.First (Container.Content); begin if Node = 0 then @@ -407,7 +443,7 @@ is ---------- function Keys (Container : Map) return K.Sequence is - Position : Count_Type := HT_Ops.First (Container); + Position : Count_Type := HT_Ops.First (Container.Content); R : K.Sequence; begin @@ -415,8 +451,8 @@ is -- for their postconditions. while Position /= 0 loop - R := K.Add (R, Container.Nodes (Position).Key); - Position := HT_Ops.Next (Container, Position); + R := K.Add (R, Container.Content.Nodes (Position).Key); + Position := HT_Ops.Next (Container.Content, Position); end loop; return R; @@ -458,7 +494,7 @@ is ----------- function Model (Container : Map) return M.Map is - Position : Count_Type := HT_Ops.First (Container); + Position : Count_Type := HT_Ops.First (Container.Content); R : M.Map; begin @@ -469,10 +505,10 @@ is R := M.Add (Container => R, - New_Key => Container.Nodes (Position).Key, - New_Item => Container.Nodes (Position).Element); + New_Key => Container.Content.Nodes (Position).Key, + New_Item => Container.Content.Nodes (Position).Element); - Position := HT_Ops.Next (Container, Position); + Position := HT_Ops.Next (Container.Content, Position); end loop; return R; @@ -484,7 +520,7 @@ is function Positions (Container : Map) return P.Map is I : Count_Type := 1; - Position : Count_Type := HT_Ops.First (Container); + Position : Count_Type := HT_Ops.First (Container.Content); R : P.Map; begin @@ -494,7 +530,7 @@ is while Position /= 0 loop R := P.Add (R, (Node => Position), I); pragma Assert (P.Length (R) = I); - Position := HT_Ops.Next (Container, Position); + Position := HT_Ops.Next (Container.Content, Position); I := I + 1; end loop; @@ -511,8 +547,8 @@ is begin if X /= 0 then pragma Assert (X <= HT.Capacity); - HT.Nodes (X).Has_Element := False; - HT_Ops.Free (HT, X); + HT.Content.Nodes (X).Has_Element := False; + HT_Ops.Free (HT.Content, X); end if; end Free; @@ -525,8 +561,8 @@ is new HT_Ops.Generic_Allocate (Set_Element); begin - Allocate (HT, Node); - HT.Nodes (Node).Has_Element := True; + Allocate (HT.Content, Node); + HT.Content.Nodes (Node).Has_Element := True; end Generic_Allocate; ----------------- @@ -536,7 +572,7 @@ is function Has_Element (Container : Map; Position : Cursor) return Boolean is begin if Position.Node = 0 - or else not Container.Nodes (Position.Node).Has_Element + or else not Container.Content.Nodes (Position.Node).Has_Element then return False; else @@ -570,7 +606,7 @@ is if not Inserted then declare - N : Node_Type renames Container.Nodes (Position.Node); + N : Node_Type renames Container.Content.Nodes (Position.Node); begin N.Key := Key; N.Element := New_Item; @@ -625,7 +661,7 @@ is -- Start of processing for Insert begin - Local_Insert (Container, Key, Position.Node, Inserted); + Local_Insert (Container.Content, Key, Position.Node, Inserted); end Insert; procedure Insert @@ -668,7 +704,7 @@ is pragma Assert (Vet (Container, Position), "bad cursor in function Key"); - return Container.Nodes (Position.Node).Key; + return Container.Content.Nodes (Position.Node).Key; end Key; ------------ @@ -677,7 +713,7 @@ is function Length (Container : Map) return Count_Type is begin - return Container.Length; + return Container.Content.Length; end Length; ---------- @@ -688,7 +724,7 @@ is (Target : in out Map; Source : in out Map) is - NN : HT_Types.Nodes_Type renames Source.Nodes; + NN : HT_Types.Nodes_Type renames Source.Content.Nodes; X : Count_Type; Y : Count_Type; @@ -704,17 +740,17 @@ is Clear (Target); - if Source.Length = 0 then + if Source.Content.Length = 0 then return; end if; - X := HT_Ops.First (Source); + X := HT_Ops.First (Source.Content); while X /= 0 loop Insert (Target, NN (X).Key, NN (X).Element); -- optimize??? - Y := HT_Ops.Next (Source, X); + Y := HT_Ops.Next (Source.Content, X); - HT_Ops.Delete_Node_Sans_Free (Source, X); + HT_Ops.Delete_Node_Sans_Free (Source.Content, X); Free (Source, X); X := Y; @@ -743,7 +779,8 @@ is pragma Assert (Vet (Container, Position), "bad cursor in function Next"); declare - Node : constant Count_Type := HT_Ops.Next (Container, Position.Node); + Node : constant Count_Type := + HT_Ops.Next (Container.Content, Position.Node); begin if Node = 0 then @@ -759,6 +796,40 @@ is Position := Next (Container, Position); end Next; + --------------- + -- Reference -- + --------------- + + function Reference + (Container : not null access Map; + Position : Cursor) return not null access Element_Type + is + begin + if not Has_Element (Container.all, Position) then + raise Constraint_Error with "Position cursor has no element"; + end if; + + pragma Assert + (Vet (Container.all, Position), "bad cursor in function Reference"); + + return Container.Content.Nodes (Position.Node).Element'Access; + end Reference; + + function Reference + (Container : not null access Map; + Key : Key_Type) return not null access Element_Type + is + Node : constant Count_Type := Find (Container.all, Key).Node; + + begin + if Node = 0 then + raise Constraint_Error with + "no element available because key not in map"; + end if; + + return Container.Content.Nodes (Node).Element'Access; + end Reference; + ------------- -- Replace -- ------------- @@ -768,7 +839,7 @@ is Key : Key_Type; New_Item : Element_Type) is - Node : constant Count_Type := Key_Ops.Find (Container, Key); + Node : constant Count_Type := Key_Ops.Find (Container.Content, Key); begin if Node = 0 then @@ -776,7 +847,7 @@ is end if; declare - N : Node_Type renames Container.Nodes (Node); + N : Node_Type renames Container.Content.Nodes (Node); begin N.Key := Key; N.Element := New_Item; @@ -801,7 +872,7 @@ is pragma Assert (Vet (Container, Position), "bad cursor in Replace_Element"); - Container.Nodes (Position.Node).Element := New_Item; + Container.Content.Nodes (Position.Node).Element := New_Item; end Replace_Element; ---------------------- @@ -841,7 +912,7 @@ is X : Count_Type; begin - if Container.Length = 0 then + if Container.Content.Length = 0 then return False; end if; @@ -849,7 +920,7 @@ is return False; end if; - if Container.Buckets'Length = 0 then + if Container.Content.Buckets'Length = 0 then return False; end if; @@ -857,15 +928,17 @@ is return False; end if; - if Container.Nodes (Position.Node).Next = Position.Node then + if Container.Content.Nodes (Position.Node).Next = Position.Node then return False; end if; X := - Container.Buckets - (Key_Ops.Index (Container, Container.Nodes (Position.Node).Key)); + Container.Content.Buckets + (Key_Ops.Index + (Container.Content, + Container.Content.Nodes (Position.Node).Key)); - for J in 1 .. Container.Length loop + for J in 1 .. Container.Content.Length loop if X = Position.Node then return True; end if; @@ -874,14 +947,14 @@ is return False; end if; - if X = Container.Nodes (X).Next then + if X = Container.Content.Nodes (X).Next then -- Prevent unnecessary looping return False; end if; - X := Container.Nodes (X).Next; + X := Container.Content.Nodes (X).Next; end loop; return False; diff --git a/gcc/ada/libgnat/a-cfhama.ads b/gcc/ada/libgnat/a-cfhama.ads index e9b0268..2b49c13 100644 --- a/gcc/ada/libgnat/a-cfhama.ads +++ b/gcc/ada/libgnat/a-cfhama.ads @@ -394,6 +394,95 @@ is Model (Container)'Old, Key (Container, Position)); + function At_End + (E : not null access constant Map) return not null access constant Map + is (E) + with Ghost, + Annotate => (GNATprove, At_End_Borrow); + + function At_End + (E : access constant Element_Type) return access constant Element_Type + is (E) + with Ghost, + Annotate => (GNATprove, At_End_Borrow); + + function Constant_Reference + (Container : aliased Map; + Position : Cursor) return not null access constant Element_Type + with + Global => null, + Pre => Has_Element (Container, Position), + Post => + Constant_Reference'Result.all = + Element (Model (Container), Key (Container, Position)); + + function Reference + (Container : not null access Map; + Position : Cursor) return not null access Element_Type + with + Global => null, + Pre => Has_Element (Container.all, Position), + Post => + + -- Order of keys and cursors is preserved + + Keys (At_End (Container).all) = Keys (Container.all) + and Positions (At_End (Container).all) = Positions (Container.all) + + -- The value designated by the result of Reference is now associated + -- with the key at position Position in Container. + + and Element (At_End (Container).all, Position) = + At_End (Reference'Result).all + + -- Elements associated with other keys are preserved + + and M.Same_Keys + (Model (At_End (Container).all), + Model (Container.all)) + and M.Elements_Equal_Except + (Model (At_End (Container).all), + Model (Container.all), + Key (At_End (Container).all, Position)); + + function Constant_Reference + (Container : aliased Map; + Key : Key_Type) return not null access constant Element_Type + with + Global => null, + Pre => Contains (Container, Key), + Post => + Constant_Reference'Result.all = Element (Model (Container), Key); + + function Reference + (Container : not null access Map; + Key : Key_Type) return not null access Element_Type + with + Global => null, + Pre => Contains (Container.all, Key), + Post => + + -- Order of keys and cursors is preserved + + Keys (At_End (Container).all) = Keys (Container.all) + and Positions (At_End (Container).all) = Positions (Container.all) + + -- The value designated by the result of Reference is now associated + -- with Key in Container. + + and Element (Model (At_End (Container).all), Key) = + At_End (Reference'Result).all + + -- Elements associated with other keys are preserved + + and M.Same_Keys + (Model (At_End (Container).all), + Model (Container.all)) + and M.Elements_Equal_Except + (Model (At_End (Container).all), + Model (Container.all), + Key); + procedure Move (Target : in out Map; Source : in out Map) with Global => null, Pre => Target.Capacity >= Length (Source), @@ -804,7 +893,7 @@ private type Node_Type is record Key : Key_Type; - Element : Element_Type; + Element : aliased Element_Type; Next : Count_Type; Has_Element : Boolean := False; end record; @@ -812,8 +901,9 @@ private package HT_Types is new Ada.Containers.Hash_Tables.Generic_Bounded_Hash_Table_Types (Node_Type); - type Map (Capacity : Count_Type; Modulus : Hash_Type) is - new HT_Types.Hash_Table_Type (Capacity, Modulus) with null record; + type Map (Capacity : Count_Type; Modulus : Hash_Type) is record + Content : HT_Types.Hash_Table_Type (Capacity, Modulus); + end record; Empty_Map : constant Map := (Capacity => 0, Modulus => 0, others => <>); diff --git a/gcc/ada/libgnat/a-cfhase.adb b/gcc/ada/libgnat/a-cfhase.adb index 3679ca4..cdb8a98 100644 --- a/gcc/ada/libgnat/a-cfhase.adb +++ b/gcc/ada/libgnat/a-cfhase.adb @@ -136,15 +136,16 @@ is ENode := Find (Container => Right, - Item => Left.Nodes (Node).Element).Node; + Item => Left.Content.Nodes (Node).Element).Node; if ENode = 0 - or else Right.Nodes (ENode).Element /= Left.Nodes (Node).Element + or else Right.Content.Nodes (ENode).Element /= + Left.Content.Nodes (Node).Element then return False; end if; - Node := HT_Ops.Next (Left, Node); + Node := HT_Ops.Next (Left.Content, Node); end loop; return True; @@ -166,7 +167,7 @@ is -------------------- procedure Insert_Element (Source_Node : Count_Type) is - N : Node_Type renames Source.Nodes (Source_Node); + N : Node_Type renames Source.Content.Nodes (Source_Node); X : Count_Type; B : Boolean; @@ -186,8 +187,8 @@ is raise Storage_Error with "not enough capacity"; -- SE or CE? ??? end if; - HT_Ops.Clear (Target); - Insert_Elements (Source); + HT_Ops.Clear (Target.Content); + Insert_Elements (Source.Content); end Assign; -------------- @@ -196,7 +197,7 @@ is function Capacity (Container : Set) return Count_Type is begin - return Container.Nodes'Length; + return Container.Content.Nodes'Length; end Capacity; ----------- @@ -205,9 +206,28 @@ is procedure Clear (Container : in out Set) is begin - HT_Ops.Clear (Container); + HT_Ops.Clear (Container.Content); end Clear; + ------------------------ + -- Constant_Reference -- + ------------------------ + + function Constant_Reference + (Container : aliased Set; + Position : Cursor) return not null access constant Element_Type + is + begin + if not Has_Element (Container, Position) then + raise Constraint_Error with "Position cursor equals No_Element"; + end if; + + pragma Assert + (Vet (Container, Position), "bad cursor in function Element"); + + return Container.Content.Nodes (Position.Node).Element'Access; + end Constant_Reference; + -------------- -- Contains -- -------------- @@ -237,18 +257,18 @@ is raise Capacity_Error; end if; - Target.Length := Source.Length; - Target.Free := Source.Free; + Target.Content.Length := Source.Content.Length; + Target.Content.Free := Source.Content.Free; H := 1; while H <= Source.Modulus loop - Target.Buckets (H) := Source.Buckets (H); + Target.Content.Buckets (H) := Source.Content.Buckets (H); H := H + 1; end loop; N := 1; while N <= Source.Capacity loop - Target.Nodes (N) := Source.Nodes (N); + Target.Content.Nodes (N) := Source.Content.Nodes (N); N := N + 1; end loop; @@ -278,7 +298,7 @@ is X : Count_Type; begin - Element_Keys.Delete_Key_Sans_Free (Container, Item, X); + Element_Keys.Delete_Key_Sans_Free (Container.Content, Item, X); if X = 0 then raise Constraint_Error with "attempt to delete element not in set"; @@ -295,7 +315,7 @@ is pragma Assert (Vet (Container, Position), "bad cursor in Delete"); - HT_Ops.Delete_Node_Sans_Free (Container, Position.Node); + HT_Ops.Delete_Node_Sans_Free (Container.Content, Position.Node); Free (Container, Position.Node); Position := No_Element; @@ -311,8 +331,8 @@ is Src_Node : Count_Type; Tgt_Node : Count_Type; - TN : Nodes_Type renames Target.Nodes; - SN : Nodes_Type renames Source.Nodes; + TN : Nodes_Type renames Target.Content.Nodes; + SN : Nodes_Type renames Source.Content.Nodes; begin if Target'Address = Source'Address then @@ -320,44 +340,45 @@ is return; end if; - Src_Length := Source.Length; + Src_Length := Source.Content.Length; if Src_Length = 0 then return; end if; - if Src_Length >= Target.Length then - Tgt_Node := HT_Ops.First (Target); + if Src_Length >= Target.Content.Length then + Tgt_Node := HT_Ops.First (Target.Content); while Tgt_Node /= 0 loop - if Element_Keys.Find (Source, TN (Tgt_Node).Element) /= 0 then + if Element_Keys.Find (Source.Content, TN (Tgt_Node).Element) /= 0 + then declare X : constant Count_Type := Tgt_Node; begin - Tgt_Node := HT_Ops.Next (Target, Tgt_Node); - HT_Ops.Delete_Node_Sans_Free (Target, X); + Tgt_Node := HT_Ops.Next (Target.Content, Tgt_Node); + HT_Ops.Delete_Node_Sans_Free (Target.Content, X); Free (Target, X); end; else - Tgt_Node := HT_Ops.Next (Target, Tgt_Node); + Tgt_Node := HT_Ops.Next (Target.Content, Tgt_Node); end if; end loop; return; else - Src_Node := HT_Ops.First (Source); + Src_Node := HT_Ops.First (Source.Content); Src_Last := 0; end if; while Src_Node /= Src_Last loop - Tgt_Node := Element_Keys.Find (Target, SN (Src_Node).Element); + Tgt_Node := Element_Keys.Find (Target.Content, SN (Src_Node).Element); if Tgt_Node /= 0 then - HT_Ops.Delete_Node_Sans_Free (Target, Tgt_Node); + HT_Ops.Delete_Node_Sans_Free (Target.Content, Tgt_Node); Free (Target, Tgt_Node); end if; - Src_Node := HT_Ops.Next (Source, Src_Node); + Src_Node := HT_Ops.Next (Source.Content, Src_Node); end loop; end Difference; @@ -373,7 +394,7 @@ is procedure Process (L_Node : Count_Type) is B : Boolean; - E : Element_Type renames Left.Nodes (L_Node).Element; + E : Element_Type renames Left.Content.Nodes (L_Node).Element; X : Count_Type; begin @@ -386,7 +407,7 @@ is -- Start of processing for Difference begin - Iterate (Left); + Iterate (Left.Content); end Difference; function Difference (Left : Set; Right : Set) return Set is @@ -403,7 +424,7 @@ is end if; if Length (Right) = 0 then - return Left.Copy; + return Copy (Left); end if; C := Length (Left); @@ -430,7 +451,7 @@ is pragma Assert (Vet (Container, Position), "bad cursor in function Element"); - return Container.Nodes (Position.Node).Element; + return Container.Content.Nodes (Position.Node).Element; end Element; --------------------- @@ -479,7 +500,7 @@ is -- Start of processing for Equivalent_Sets begin - return Is_Equivalent (Left, Right); + return Is_Equivalent (Left.Content, Right.Content); end Equivalent_Sets; --------------------- @@ -501,7 +522,7 @@ is procedure Exclude (Container : in out Set; Item : Element_Type) is X : Count_Type; begin - Element_Keys.Delete_Key_Sans_Free (Container, Item, X); + Element_Keys.Delete_Key_Sans_Free (Container.Content, Item, X); Free (Container, X); end Exclude; @@ -513,7 +534,8 @@ is (Container : Set; Item : Element_Type) return Cursor is - Node : constant Count_Type := Element_Keys.Find (Container, Item); + Node : constant Count_Type := + Element_Keys.Find (Container.Content, Item); begin if Node = 0 then @@ -528,7 +550,7 @@ is ----------- function First (Container : Set) return Cursor is - Node : constant Count_Type := HT_Ops.First (Container); + Node : constant Count_Type := HT_Ops.First (Container.Content); begin if Node = 0 then @@ -632,7 +654,7 @@ is -------------- function Elements (Container : Set) return E.Sequence is - Position : Count_Type := HT_Ops.First (Container); + Position : Count_Type := HT_Ops.First (Container.Content); R : E.Sequence; begin @@ -640,8 +662,8 @@ is -- for their postconditions. while Position /= 0 loop - R := E.Add (R, Container.Nodes (Position).Element); - Position := HT_Ops.Next (Container, Position); + R := E.Add (R, Container.Content.Nodes (Position).Element); + Position := HT_Ops.Next (Container.Content, Position); end loop; return R; @@ -710,7 +732,7 @@ is ----------- function Model (Container : Set) return M.Set is - Position : Count_Type := HT_Ops.First (Container); + Position : Count_Type := HT_Ops.First (Container.Content); R : M.Set; begin @@ -721,9 +743,9 @@ is R := M.Add (Container => R, - Item => Container.Nodes (Position).Element); + Item => Container.Content.Nodes (Position).Element); - Position := HT_Ops.Next (Container, Position); + Position := HT_Ops.Next (Container.Content, Position); end loop; return R; @@ -735,7 +757,7 @@ is function Positions (Container : Set) return P.Map is I : Count_Type := 1; - Position : Count_Type := HT_Ops.First (Container); + Position : Count_Type := HT_Ops.First (Container.Content); R : P.Map; begin @@ -745,7 +767,7 @@ is while Position /= 0 loop R := P.Add (R, (Node => Position), I); pragma Assert (P.Length (R) = I); - Position := HT_Ops.Next (Container, Position); + Position := HT_Ops.Next (Container.Content, Position); I := I + 1; end loop; @@ -762,8 +784,8 @@ is begin if X /= 0 then pragma Assert (X <= HT.Capacity); - HT.Nodes (X).Has_Element := False; - HT_Ops.Free (HT, X); + HT.Content.Nodes (X).Has_Element := False; + HT_Ops.Free (HT.Content, X); end if; end Free; @@ -774,8 +796,8 @@ is procedure Generic_Allocate (HT : in out Set; Node : out Count_Type) is procedure Allocate is new HT_Ops.Generic_Allocate (Set_Element); begin - Allocate (HT, Node); - HT.Nodes (Node).Has_Element := True; + Allocate (HT.Content, Node); + HT.Content.Nodes (Node).Has_Element := True; end Generic_Allocate; package body Generic_Keys with SPARK_Mode => Off is @@ -821,7 +843,7 @@ is X : Count_Type; begin - Key_Keys.Delete_Key_Sans_Free (Container, Key, X); + Key_Keys.Delete_Key_Sans_Free (Container.Content, Key, X); if X = 0 then raise Constraint_Error with "attempt to delete key not in set"; @@ -845,7 +867,7 @@ is raise Constraint_Error with "key not in map"; end if; - return Container.Nodes (Node).Element; + return Container.Content.Nodes (Node).Element; end Element; ------------------------- @@ -867,7 +889,7 @@ is procedure Exclude (Container : in out Set; Key : Key_Type) is X : Count_Type; begin - Key_Keys.Delete_Key_Sans_Free (Container, Key, X); + Key_Keys.Delete_Key_Sans_Free (Container.Content, Key, X); Free (Container, X); end Exclude; @@ -879,7 +901,7 @@ is (Container : Set; Key : Key_Type) return Cursor is - Node : constant Count_Type := Key_Keys.Find (Container, Key); + Node : constant Count_Type := Key_Keys.Find (Container.Content, Key); begin return (if Node = 0 then No_Element else (Node => Node)); end Find; @@ -927,7 +949,7 @@ is (Vet (Container, Position), "bad cursor in function Key"); declare - N : Node_Type renames Container.Nodes (Position.Node); + N : Node_Type renames Container.Content.Nodes (Position.Node); begin return Key (N.Element); end; @@ -942,14 +964,14 @@ is Key : Key_Type; New_Item : Element_Type) is - Node : constant Count_Type := Key_Keys.Find (Container, Key); + Node : constant Count_Type := Key_Keys.Find (Container.Content, Key); begin if Node = 0 then raise Constraint_Error with "attempt to replace key not in set"; end if; - Replace_Element (Container, Node, New_Item); + Replace_Element (Container.Content, Node, New_Item); end Replace; end Generic_Keys; @@ -961,7 +983,7 @@ is function Has_Element (Container : Set; Position : Cursor) return Boolean is begin if Position.Node = 0 - or else not Container.Nodes (Position.Node).Has_Element + or else not Container.Content.Nodes (Position.Node).Has_Element then return False; end if; @@ -990,7 +1012,7 @@ is Insert (Container, New_Item, Position, Inserted); if not Inserted then - Container.Nodes (Position.Node).Element := New_Item; + Container.Content.Nodes (Position.Node).Element := New_Item; end if; end Include; @@ -1062,7 +1084,7 @@ is -- Start of processing for Insert begin - Local_Insert (Container, New_Item, Node, Inserted); + Local_Insert (Container.Content, New_Item, Node, Inserted); end Insert; ------------------ @@ -1071,29 +1093,29 @@ is procedure Intersection (Target : in out Set; Source : Set) is Tgt_Node : Count_Type; - TN : Nodes_Type renames Target.Nodes; + TN : Nodes_Type renames Target.Content.Nodes; begin if Target'Address = Source'Address then return; end if; - if Source.Length = 0 then + if Source.Content.Length = 0 then Clear (Target); return; end if; - Tgt_Node := HT_Ops.First (Target); + Tgt_Node := HT_Ops.First (Target.Content); while Tgt_Node /= 0 loop if Find (Source, TN (Tgt_Node).Element).Node /= 0 then - Tgt_Node := HT_Ops.Next (Target, Tgt_Node); + Tgt_Node := HT_Ops.Next (Target.Content, Tgt_Node); else declare X : constant Count_Type := Tgt_Node; begin - Tgt_Node := HT_Ops.Next (Target, Tgt_Node); - HT_Ops.Delete_Node_Sans_Free (Target, X); + Tgt_Node := HT_Ops.Next (Target.Content, Tgt_Node); + HT_Ops.Delete_Node_Sans_Free (Target.Content, X); Free (Target, X); end; end if; @@ -1111,7 +1133,7 @@ is ------------- procedure Process (L_Node : Count_Type) is - E : Element_Type renames Left.Nodes (L_Node).Element; + E : Element_Type renames Left.Content.Nodes (L_Node).Element; X : Count_Type; B : Boolean; @@ -1125,7 +1147,7 @@ is -- Start of processing for Intersection begin - Iterate (Left); + Iterate (Left.Content); end Intersection; function Intersection (Left : Set; Right : Set) return Set is @@ -1134,7 +1156,7 @@ is begin if Left'Address = Right'Address then - return Left.Copy; + return Copy (Left); end if; C := Count_Type'Min (Length (Left), Length (Right)); -- ??? @@ -1162,7 +1184,7 @@ is function Is_In (HT : Set; Key : Node_Type) return Boolean is begin - return Element_Keys.Find (HT, Key.Element) /= 0; + return Element_Keys.Find (HT.Content, Key.Element) /= 0; end Is_In; --------------- @@ -1171,7 +1193,7 @@ is function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is Subset_Node : Count_Type; - Subset_Nodes : Nodes_Type renames Subset.Nodes; + Subset_Nodes : Nodes_Type renames Subset.Content.Nodes; begin if Subset'Address = Of_Set'Address then @@ -1194,7 +1216,7 @@ is end if; end; - Subset_Node := HT_Ops.Next (Subset, Subset_Node); + Subset_Node := HT_Ops.Next (Subset.Content, Subset_Node); end loop; return True; @@ -1206,7 +1228,7 @@ is function Length (Container : Set) return Count_Type is begin - return Container.Length; + return Container.Content.Length; end Length; ---------- @@ -1216,7 +1238,7 @@ is -- Comments??? procedure Move (Target : in out Set; Source : in out Set) is - NN : HT_Types.Nodes_Type renames Source.Nodes; + NN : HT_Types.Nodes_Type renames Source.Content.Nodes; X, Y : Count_Type; begin @@ -1231,17 +1253,17 @@ is Clear (Target); - if Source.Length = 0 then + if Source.Content.Length = 0 then return; end if; - X := HT_Ops.First (Source); + X := HT_Ops.First (Source.Content); while X /= 0 loop Insert (Target, NN (X).Element); -- optimize??? - Y := HT_Ops.Next (Source, X); + Y := HT_Ops.Next (Source.Content, X); - HT_Ops.Delete_Node_Sans_Free (Source, X); + HT_Ops.Delete_Node_Sans_Free (Source.Content, X); Free (Source, X); X := Y; @@ -1269,7 +1291,7 @@ is pragma Assert (Vet (Container, Position), "bad cursor in Next"); - return (Node => HT_Ops.Next (Container, Position.Node)); + return (Node => HT_Ops.Next (Container.Content, Position.Node)); end Next; procedure Next (Container : Set; Position : in out Cursor) is @@ -1283,7 +1305,7 @@ is function Overlap (Left, Right : Set) return Boolean is Left_Node : Count_Type; - Left_Nodes : Nodes_Type renames Left.Nodes; + Left_Nodes : Nodes_Type renames Left.Content.Nodes; begin if Length (Right) = 0 or Length (Left) = 0 then @@ -1305,7 +1327,7 @@ is end if; end; - Left_Node := HT_Ops.Next (Left, Left_Node); + Left_Node := HT_Ops.Next (Left.Content, Left_Node); end loop; return False; @@ -1316,14 +1338,15 @@ is ------------- procedure Replace (Container : in out Set; New_Item : Element_Type) is - Node : constant Count_Type := Element_Keys.Find (Container, New_Item); + Node : constant Count_Type := + Element_Keys.Find (Container.Content, New_Item); begin if Node = 0 then raise Constraint_Error with "attempt to replace element not in set"; end if; - Container.Nodes (Node).Element := New_Item; + Container.Content.Nodes (Node).Element := New_Item; end Replace; --------------------- @@ -1343,7 +1366,7 @@ is pragma Assert (Vet (Container, Position), "bad cursor in Replace_Element"); - Replace_Element (Container, Position.Node, New_Item); + Replace_Element (Container.Content, Position.Node, New_Item); end Replace_Element; ---------------------- @@ -1394,7 +1417,7 @@ is procedure Process (Source_Node : Count_Type) is B : Boolean; - N : Node_Type renames Source.Nodes (Source_Node); + N : Node_Type renames Source.Content.Nodes (Source_Node); X : Count_Type; begin @@ -1419,7 +1442,7 @@ is return; end if; - Iterate (Source); + Iterate (Source.Content); end Symmetric_Difference; function Symmetric_Difference (Left : Set; Right : Set) return Set is @@ -1432,11 +1455,11 @@ is end if; if Length (Right) = 0 then - return Left.Copy; + return Copy (Left); end if; if Length (Left) = 0 then - return Right.Copy; + return Copy (Right); end if; C := Length (Left) + Length (Right); @@ -1478,7 +1501,7 @@ is ------------- procedure Process (Src_Node : Count_Type) is - N : Node_Type renames Source.Nodes (Src_Node); + N : Node_Type renames Source.Content.Nodes (Src_Node); E : Element_Type renames N.Element; X : Count_Type; @@ -1495,7 +1518,7 @@ is return; end if; - Iterate (Source); + Iterate (Source.Content); end Union; function Union (Left : Set; Right : Set) return Set is @@ -1504,15 +1527,15 @@ is begin if Left'Address = Right'Address then - return Left.Copy; + return Copy (Left); end if; if Length (Right) = 0 then - return Left.Copy; + return Copy (Left); end if; if Length (Left) = 0 then - return Right.Copy; + return Copy (Right); end if; C := Length (Left) + Length (Right); @@ -1535,11 +1558,11 @@ is declare S : Set renames Container; - N : Nodes_Type renames S.Nodes; + N : Nodes_Type renames S.Content.Nodes; X : Count_Type; begin - if S.Length = 0 then + if S.Content.Length = 0 then return False; end if; @@ -1551,9 +1574,10 @@ is return False; end if; - X := S.Buckets (Element_Keys.Index (S, N (Position.Node).Element)); + X := S.Content.Buckets + (Element_Keys.Index (S.Content, N (Position.Node).Element)); - for J in 1 .. S.Length loop + for J in 1 .. S.Content.Length loop if X = Position.Node then return True; end if; diff --git a/gcc/ada/libgnat/a-cfhase.ads b/gcc/ada/libgnat/a-cfhase.ads index 5d57863..9bcd8ce 100644 --- a/gcc/ada/libgnat/a-cfhase.ads +++ b/gcc/ada/libgnat/a-cfhase.ads @@ -515,6 +515,16 @@ is Position => Position) and Positions (Container) = Positions (Container)'Old; + function Constant_Reference + (Container : aliased Set; + Position : Cursor) return not null access constant Element_Type + with + Global => null, + Pre => Has_Element (Container, Position), + Post => + Constant_Reference'Result.all = + E.Get (Elements (Container), P.Get (Positions (Container), Position)); + procedure Move (Target : in out Set; Source : in out Set) with Global => null, Pre => Target.Capacity >= Length (Source), @@ -1462,7 +1472,7 @@ private type Node_Type is record - Element : Element_Type; + Element : aliased Element_Type; Next : Count_Type; Has_Element : Boolean := False; end record; @@ -1470,8 +1480,9 @@ private package HT_Types is new Ada.Containers.Hash_Tables.Generic_Bounded_Hash_Table_Types (Node_Type); - type Set (Capacity : Count_Type; Modulus : Hash_Type) is - new HT_Types.Hash_Table_Type (Capacity, Modulus) with null record; + type Set (Capacity : Count_Type; Modulus : Hash_Type) is record + Content : HT_Types.Hash_Table_Type (Capacity, Modulus); + end record; use HT_Types; diff --git a/gcc/ada/libgnat/a-cfinve.adb b/gcc/ada/libgnat/a-cfinve.adb index 6ab4935..d0c7e82 100644 --- a/gcc/ada/libgnat/a-cfinve.adb +++ b/gcc/ada/libgnat/a-cfinve.adb @@ -184,6 +184,28 @@ is Free (Container.Elements_Ptr); end Clear; + ------------------------ + -- Constant_Reference -- + ------------------------ + + function Constant_Reference + (Container : aliased Vector; + Index : Index_Type) return not null access constant Element_Type + is + begin + if Index > Container.Last then + raise Constraint_Error with "Index is out of range"; + end if; + + declare + II : constant Int'Base := Int (Index) - Int (No_Index); + I : constant Capacity_Range := Capacity_Range (II); + + begin + return Constant_Reference (Elemsc (Container) (I)); + end; + end Constant_Reference; + -------------- -- Contains -- -------------- @@ -1180,6 +1202,32 @@ is Insert (Container, Index_Type'First, New_Item, Count); end Prepend; + --------------- + -- Reference -- + --------------- + + function Reference + (Container : not null access Vector; + Index : Index_Type) return not null access Element_Type + is + begin + if Index > Container.Last then + raise Constraint_Error with "Index is out of range"; + end if; + + declare + II : constant Int'Base := Int (Index) - Int (No_Index); + I : constant Capacity_Range := Capacity_Range (II); + + begin + if Container.Elements_Ptr = null then + return Reference (Container.Elements (I)'Access); + else + return Reference (Container.Elements_Ptr (I)'Access); + end if; + end; + end Reference; + --------------------- -- Replace_Element -- --------------------- diff --git a/gcc/ada/libgnat/a-cfinve.ads b/gcc/ada/libgnat/a-cfinve.ads index 37dde92..9b95437 100644 --- a/gcc/ada/libgnat/a-cfinve.ads +++ b/gcc/ada/libgnat/a-cfinve.ads @@ -311,6 +311,48 @@ is Right => Model (Container), Position => Index); + function At_End (E : access constant Vector) return access constant Vector + is (E) + with Ghost, + Annotate => (GNATprove, At_End_Borrow); + + function At_End + (E : access constant Element_Type) return access constant Element_Type + is (E) + with Ghost, + Annotate => (GNATprove, At_End_Borrow); + + function Constant_Reference + (Container : aliased Vector; + Index : Index_Type) return not null access constant Element_Type + with + Global => null, + Pre => Index in First_Index (Container) .. Last_Index (Container), + Post => + Constant_Reference'Result.all = Element (Model (Container), Index); + + function Reference + (Container : not null access Vector; + Index : Index_Type) return not null access Element_Type + with + Global => null, + Pre => + Index in First_Index (Container.all) .. Last_Index (Container.all), + Post => + Length (Container.all) = Length (At_End (Container).all) + + -- Container will have Result.all at index Index + + and At_End (Reference'Result).all = + Element (Model (At_End (Container).all), Index) + + -- All other elements are preserved + + and M.Equal_Except + (Left => Model (Container.all), + Right => Model (At_End (Container).all), + Position => Index); + procedure Insert (Container : in out Vector; Before : Extended_Index; @@ -909,7 +951,7 @@ private use Holders; subtype Array_Index is Capacity_Range range 1 .. Capacity_Range'Last; - type Elements_Array is array (Array_Index range <>) of Holder; + type Elements_Array is array (Array_Index range <>) of aliased Holder; function "=" (L, R : Elements_Array) return Boolean is abstract; type Elements_Array_Ptr is access all Elements_Array; diff --git a/gcc/ada/libgnat/a-cforma.adb b/gcc/ada/libgnat/a-cforma.adb index f384619..45f9be7 100644 --- a/gcc/ada/libgnat/a-cforma.adb +++ b/gcc/ada/libgnat/a-cforma.adb @@ -133,19 +133,20 @@ is return True; end if; - Lst := Next (Left, Last (Left).Node); + Lst := Next (Left.Content, Last (Left).Node); Node := First (Left).Node; while Node /= Lst loop - ENode := Find (Right, Left.Nodes (Node).Key).Node; + ENode := Find (Right, Left.Content.Nodes (Node).Key).Node; if ENode = 0 or else - Left.Nodes (Node).Element /= Right.Nodes (ENode).Element + Left.Content.Nodes (Node).Element /= + Right.Content.Nodes (ENode).Element then return False; end if; - Node := Next (Left, Node); + Node := Next (Left.Content, Node); end loop; return True; @@ -166,7 +167,7 @@ is -------------------- procedure Append_Element (Source_Node : Count_Type) is - SN : Node_Type renames Source.Nodes (Source_Node); + SN : Node_Type renames Source.Content.Nodes (Source_Node); procedure Set_Element (Node : in out Node_Type); pragma Inline (Set_Element); @@ -193,7 +194,7 @@ is function New_Node return Count_Type is Result : Count_Type; begin - Allocate (Target, Result); + Allocate (Target.Content, Result); return Result; end New_Node; @@ -213,7 +214,7 @@ is begin Unconditional_Insert_Avec_Hint - (Tree => Target, + (Tree => Target.Content, Hint => 0, Key => SN.Key, Node => Target_Node); @@ -230,8 +231,8 @@ is raise Storage_Error with "not enough capacity"; -- SE or CE? ??? end if; - Tree_Operations.Clear_Tree (Target); - Append_Elements (Source); + Tree_Operations.Clear_Tree (Target.Content); + Append_Elements (Source.Content); end Assign; ------------- @@ -239,7 +240,7 @@ is ------------- function Ceiling (Container : Map; Key : Key_Type) return Cursor is - Node : constant Count_Type := Key_Ops.Ceiling (Container, Key); + Node : constant Count_Type := Key_Ops.Ceiling (Container.Content, Key); begin if Node = 0 then @@ -255,7 +256,7 @@ is procedure Clear (Container : in out Map) is begin - Tree_Operations.Clear_Tree (Container); + Tree_Operations.Clear_Tree (Container.Content); end Clear; ----------- @@ -267,6 +268,40 @@ is return Node.Color; end Color; + ------------------------ + -- Constant_Reference -- + ------------------------ + + function Constant_Reference + (Container : aliased Map; + Position : Cursor) return not null access constant Element_Type + is + begin + if not Has_Element (Container, Position) then + raise Constraint_Error with "Position cursor has no element"; + end if; + + pragma Assert (Vet (Container.Content, Position.Node), + "bad cursor in function Constant_Reference"); + + return Container.Content.Nodes (Position.Node).Element'Access; + end Constant_Reference; + + function Constant_Reference + (Container : aliased Map; + Key : Key_Type) return not null access constant Element_Type + is + Node : constant Node_Access := Find (Container, Key).Node; + + begin + if Node = 0 then + raise Constraint_Error with + "no element available because key not in map"; + end if; + + return Container.Content.Nodes (Node).Element'Access; + end Constant_Reference; + -------------- -- Contains -- -------------- @@ -291,33 +326,33 @@ is return Target : Map (Count_Type'Max (Source.Capacity, Capacity)) do if Length (Source) > 0 then - Target.Length := Source.Length; - Target.Root := Source.Root; - Target.First := Source.First; - Target.Last := Source.Last; - Target.Free := Source.Free; + Target.Content.Length := Source.Content.Length; + Target.Content.Root := Source.Content.Root; + Target.Content.First := Source.Content.First; + Target.Content.Last := Source.Content.Last; + Target.Content.Free := Source.Content.Free; while Node <= Source.Capacity loop - Target.Nodes (Node).Element := - Source.Nodes (Node).Element; - Target.Nodes (Node).Key := - Source.Nodes (Node).Key; - Target.Nodes (Node).Parent := - Source.Nodes (Node).Parent; - Target.Nodes (Node).Left := - Source.Nodes (Node).Left; - Target.Nodes (Node).Right := - Source.Nodes (Node).Right; - Target.Nodes (Node).Color := - Source.Nodes (Node).Color; - Target.Nodes (Node).Has_Element := - Source.Nodes (Node).Has_Element; + Target.Content.Nodes (Node).Element := + Source.Content.Nodes (Node).Element; + Target.Content.Nodes (Node).Key := + Source.Content.Nodes (Node).Key; + Target.Content.Nodes (Node).Parent := + Source.Content.Nodes (Node).Parent; + Target.Content.Nodes (Node).Left := + Source.Content.Nodes (Node).Left; + Target.Content.Nodes (Node).Right := + Source.Content.Nodes (Node).Right; + Target.Content.Nodes (Node).Color := + Source.Content.Nodes (Node).Color; + Target.Content.Nodes (Node).Has_Element := + Source.Content.Nodes (Node).Has_Element; Node := Node + 1; end loop; while Node <= Target.Capacity loop N := Node; - Formal_Ordered_Maps.Free (Tree => Target, X => N); + Free (Tree => Target, X => N); Node := Node + 1; end loop; end if; @@ -335,25 +370,25 @@ is "Position cursor of Delete has no element"; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "Position cursor of Delete is bad"); - Tree_Operations.Delete_Node_Sans_Free (Container, + Tree_Operations.Delete_Node_Sans_Free (Container.Content, Position.Node); - Formal_Ordered_Maps.Free (Container, Position.Node); + Free (Container, Position.Node); Position := No_Element; end Delete; procedure Delete (Container : in out Map; Key : Key_Type) is - X : constant Node_Access := Key_Ops.Find (Container, Key); + X : constant Node_Access := Key_Ops.Find (Container.Content, Key); begin if X = 0 then raise Constraint_Error with "key not in map"; end if; - Tree_Operations.Delete_Node_Sans_Free (Container, X); - Formal_Ordered_Maps.Free (Container, X); + Tree_Operations.Delete_Node_Sans_Free (Container.Content, X); + Free (Container, X); end Delete; ------------------ @@ -364,8 +399,8 @@ is X : constant Node_Access := First (Container).Node; begin if X /= 0 then - Tree_Operations.Delete_Node_Sans_Free (Container, X); - Formal_Ordered_Maps.Free (Container, X); + Tree_Operations.Delete_Node_Sans_Free (Container.Content, X); + Free (Container, X); end if; end Delete_First; @@ -377,8 +412,8 @@ is X : constant Node_Access := Last (Container).Node; begin if X /= 0 then - Tree_Operations.Delete_Node_Sans_Free (Container, X); - Formal_Ordered_Maps.Free (Container, X); + Tree_Operations.Delete_Node_Sans_Free (Container.Content, X); + Free (Container, X); end if; end Delete_Last; @@ -393,10 +428,10 @@ is "Position cursor of function Element has no element"; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "Position cursor of function Element is bad"); - return Container.Nodes (Position.Node).Element; + return Container.Content.Nodes (Position.Node).Element; end Element; @@ -408,7 +443,7 @@ is raise Constraint_Error with "key not in map"; end if; - return Container.Nodes (Node).Element; + return Container.Content.Nodes (Node).Element; end Element; --------------------- @@ -431,11 +466,11 @@ is ------------- procedure Exclude (Container : in out Map; Key : Key_Type) is - X : constant Node_Access := Key_Ops.Find (Container, Key); + X : constant Node_Access := Key_Ops.Find (Container.Content, Key); begin if X /= 0 then - Tree_Operations.Delete_Node_Sans_Free (Container, X); - Formal_Ordered_Maps.Free (Container, X); + Tree_Operations.Delete_Node_Sans_Free (Container.Content, X); + Free (Container, X); end if; end Exclude; @@ -444,7 +479,7 @@ is ---------- function Find (Container : Map; Key : Key_Type) return Cursor is - Node : constant Count_Type := Key_Ops.Find (Container, Key); + Node : constant Count_Type := Key_Ops.Find (Container.Content, Key); begin if Node = 0 then @@ -464,7 +499,7 @@ is return No_Element; end if; - return (Node => Container.First); + return (Node => Container.Content.First); end First; ------------------- @@ -477,7 +512,7 @@ is raise Constraint_Error with "map is empty"; end if; - return Container.Nodes (First (Container).Node).Element; + return Container.Content.Nodes (First (Container).Node).Element; end First_Element; --------------- @@ -490,7 +525,7 @@ is raise Constraint_Error with "map is empty"; end if; - return Container.Nodes (First (Container).Node).Key; + return Container.Content.Nodes (First (Container).Node).Key; end First_Key; ----------- @@ -498,7 +533,7 @@ is ----------- function Floor (Container : Map; Key : Key_Type) return Cursor is - Node : constant Count_Type := Key_Ops.Floor (Container, Key); + Node : constant Count_Type := Key_Ops.Floor (Container.Content, Key); begin if Node = 0 then @@ -602,7 +637,7 @@ is ---------- function Keys (Container : Map) return K.Sequence is - Position : Count_Type := Container.First; + Position : Count_Type := Container.Content.First; R : K.Sequence; begin @@ -610,8 +645,8 @@ is -- for their postconditions. while Position /= 0 loop - R := K.Add (R, Container.Nodes (Position).Key); - Position := Tree_Operations.Next (Container, Position); + R := K.Add (R, Container.Content.Nodes (Position).Key); + Position := Tree_Operations.Next (Container.Content, Position); end loop; return R; @@ -628,7 +663,7 @@ is ----------- function Model (Container : Map) return M.Map is - Position : Count_Type := Container.First; + Position : Count_Type := Container.Content.First; R : M.Map; begin @@ -639,10 +674,10 @@ is R := M.Add (Container => R, - New_Key => Container.Nodes (Position).Key, - New_Item => Container.Nodes (Position).Element); + New_Key => Container.Content.Nodes (Position).Key, + New_Item => Container.Content.Nodes (Position).Element); - Position := Tree_Operations.Next (Container, Position); + Position := Tree_Operations.Next (Container.Content, Position); end loop; return R; @@ -701,7 +736,7 @@ is function Positions (Container : Map) return P.Map is I : Count_Type := 1; - Position : Count_Type := Container.First; + Position : Count_Type := Container.Content.First; R : P.Map; begin @@ -711,7 +746,7 @@ is while Position /= 0 loop R := P.Add (R, (Node => Position), I); pragma Assert (P.Length (R) = I); - Position := Tree_Operations.Next (Container, Position); + Position := Tree_Operations.Next (Container.Content, Position); I := I + 1; end loop; @@ -729,8 +764,8 @@ is X : Count_Type) is begin - Tree.Nodes (X).Has_Element := False; - Tree_Operations.Free (Tree, X); + Tree.Content.Nodes (X).Has_Element := False; + Tree_Operations.Free (Tree.Content, X); end Free; ---------------------- @@ -758,7 +793,7 @@ is return False; end if; - return Container.Nodes (Position.Node).Has_Element; + return Container.Content.Nodes (Position.Node).Has_Element; end Has_Element; ------------- @@ -778,7 +813,7 @@ is if not Inserted then declare - N : Node_Type renames Container.Nodes (Position.Node); + N : Node_Type renames Container.Content.Nodes (Position.Node); begin N.Key := Key; N.Element := New_Item; @@ -819,7 +854,7 @@ is X : Node_Access; begin - Allocate_Node (Container, X); + Allocate_Node (Container.Content, X); return X; end New_Node; @@ -827,7 +862,7 @@ is begin Insert_Sans_Hint - (Container, + (Container.Content, Key, Position.Node, Inserted); @@ -895,10 +930,10 @@ is "Position cursor of function Key has no element"; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "Position cursor of function Key is bad"); - return Container.Nodes (Position.Node).Key; + return Container.Content.Nodes (Position.Node).Key; end Key; ---------- @@ -911,7 +946,7 @@ is return No_Element; end if; - return (Node => Container.Last); + return (Node => Container.Content.Last); end Last; ------------------ @@ -924,7 +959,7 @@ is raise Constraint_Error with "map is empty"; end if; - return Container.Nodes (Last (Container).Node).Element; + return Container.Content.Nodes (Last (Container).Node).Element; end Last_Element; -------------- @@ -937,7 +972,7 @@ is raise Constraint_Error with "map is empty"; end if; - return Container.Nodes (Last (Container).Node).Key; + return Container.Content.Nodes (Last (Container).Node).Key; end Last_Key; -------------- @@ -955,7 +990,7 @@ is function Length (Container : Map) return Count_Type is begin - return Container.Length; + return Container.Content.Length; end Length; ---------- @@ -963,7 +998,7 @@ is ---------- procedure Move (Target : in out Map; Source : in out Map) is - NN : Tree_Types.Nodes_Type renames Source.Nodes; + NN : Tree_Types.Nodes_Type renames Source.Content.Nodes; X : Node_Access; begin @@ -989,7 +1024,7 @@ is Insert (Target, NN (X).Key, NN (X).Element); -- optimize??? - Tree_Operations.Delete_Node_Sans_Free (Source, X); + Tree_Operations.Delete_Node_Sans_Free (Source.Content, X); Formal_Ordered_Maps.Free (Source, X); end loop; end Move; @@ -1013,10 +1048,10 @@ is raise Constraint_Error; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "bad cursor in Next"); - return (Node => Tree_Operations.Next (Container, Position.Node)); + return (Node => Tree_Operations.Next (Container.Content, Position.Node)); end Next; ------------ @@ -1047,12 +1082,12 @@ is raise Constraint_Error; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "bad cursor in Previous"); declare Node : constant Count_Type := - Tree_Operations.Previous (Container, Position.Node); + Tree_Operations.Previous (Container.Content, Position.Node); begin if Node = 0 then @@ -1063,6 +1098,41 @@ is end; end Previous; + -------------- + -- Reference -- + -------------- + + function Reference + (Container : not null access Map; + Position : Cursor) return not null access Element_Type + is + begin + if not Has_Element (Container.all, Position) then + raise Constraint_Error with "Position cursor has no element"; + end if; + + pragma Assert + (Vet (Container.Content, Position.Node), + "bad cursor in function Reference"); + + return Container.Content.Nodes (Position.Node).Element'Access; + end Reference; + + function Reference + (Container : not null access Map; + Key : Key_Type) return not null access Element_Type + is + Node : constant Count_Type := Find (Container.all, Key).Node; + + begin + if Node = 0 then + raise Constraint_Error with + "no element available because key not in map"; + end if; + + return Container.Content.Nodes (Node).Element'Access; + end Reference; + ------------- -- Replace -- ------------- @@ -1074,7 +1144,7 @@ is is begin declare - Node : constant Node_Access := Key_Ops.Find (Container, Key); + Node : constant Node_Access := Key_Ops.Find (Container.Content, Key); begin if Node = 0 then @@ -1082,7 +1152,7 @@ is end if; declare - N : Node_Type renames Container.Nodes (Node); + N : Node_Type renames Container.Content.Nodes (Node); begin N.Key := Key; N.Element := New_Item; @@ -1105,10 +1175,10 @@ is "Position cursor of Replace_Element has no element"; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "Position cursor of Replace_Element is bad"); - Container.Nodes (Position.Node).Element := New_Item; + Container.Content.Nodes (Position.Node).Element := New_Item; end Replace_Element; --------------- diff --git a/gcc/ada/libgnat/a-cforma.ads b/gcc/ada/libgnat/a-cforma.ads index d32727e..a1cad03 100644 --- a/gcc/ada/libgnat/a-cforma.ads +++ b/gcc/ada/libgnat/a-cforma.ads @@ -400,6 +400,95 @@ is Model (Container)'Old, Key (Container, Position)); + function At_End + (E : not null access constant Map) return not null access constant Map + is (E) + with Ghost, + Annotate => (GNATprove, At_End_Borrow); + + function At_End + (E : access constant Element_Type) return access constant Element_Type + is (E) + with Ghost, + Annotate => (GNATprove, At_End_Borrow); + + function Constant_Reference + (Container : aliased Map; + Position : Cursor) return not null access constant Element_Type + with + Global => null, + Pre => Has_Element (Container, Position), + Post => + Constant_Reference'Result.all = + Element (Model (Container), Key (Container, Position)); + + function Reference + (Container : not null access Map; + Position : Cursor) return not null access Element_Type + with + Global => null, + Pre => Has_Element (Container.all, Position), + Post => + + -- Order of keys and cursors is preserved + + Keys (At_End (Container).all) = Keys (Container.all) + and Positions (At_End (Container).all) = Positions (Container.all) + + -- The value designated by the result of Reference is now associated + -- with the key at position Position in Container. + + and Element (At_End (Container).all, Position) = + At_End (Reference'Result).all + + -- Elements associated with other keys are preserved + + and M.Same_Keys + (Model (At_End (Container).all), + Model (Container.all)) + and M.Elements_Equal_Except + (Model (At_End (Container).all), + Model (Container.all), + Key (At_End (Container).all, Position)); + + function Constant_Reference + (Container : aliased Map; + Key : Key_Type) return not null access constant Element_Type + with + Global => null, + Pre => Contains (Container, Key), + Post => + Constant_Reference'Result.all = Element (Model (Container), Key); + + function Reference + (Container : not null access Map; + Key : Key_Type) return not null access Element_Type + with + Global => null, + Pre => Contains (Container.all, Key), + Post => + + -- Order of keys and cursors is preserved + + Keys (At_End (Container).all) = Keys (Container.all) + and Positions (At_End (Container).all) = Positions (Container.all) + + -- The value designated by the result of Reference is now associated + -- with Key in Container. + + and Element (Model (At_End (Container).all), Key) = + At_End (Reference'Result).all + + -- Elements associated with other keys are preserved + + and M.Same_Keys + (Model (At_End (Container).all), + Model (Container.all)) + and M.Elements_Equal_Except + (Model (At_End (Container).all), + Model (Container.all), + Key); + procedure Move (Target : in out Map; Source : in out Map) with Global => null, Pre => Target.Capacity >= Length (Source), @@ -1045,14 +1134,15 @@ private Right : Node_Access := 0; Color : Red_Black_Trees.Color_Type := Red; Key : Key_Type; - Element : Element_Type; + Element : aliased Element_Type; end record; package Tree_Types is new Ada.Containers.Red_Black_Trees.Generic_Bounded_Tree_Types (Node_Type); - type Map (Capacity : Count_Type) is - new Tree_Types.Tree_Type (Capacity) with null record; + type Map (Capacity : Count_Type) is record + Content : Tree_Types.Tree_Type (Capacity); + end record; Empty_Map : constant Map := (Capacity => 0, others => <>); diff --git a/gcc/ada/libgnat/a-cforse.adb b/gcc/ada/libgnat/a-cforse.adb index e5525b9..7c45e4f 100644 --- a/gcc/ada/libgnat/a-cforse.adb +++ b/gcc/ada/libgnat/a-cforse.adb @@ -81,6 +81,10 @@ is -- Comments needed??? + procedure Assign + (Target : in out Tree_Types.Tree_Type; + Source : Tree_Types.Tree_Type); + generic with procedure Set_Element (Node : in out Node_Type); procedure Generic_Allocate @@ -90,13 +94,13 @@ is procedure Free (Tree : in out Set; X : Count_Type); procedure Insert_Sans_Hint - (Container : in out Set; + (Container : in out Tree_Types.Tree_Type; New_Item : Element_Type; Node : out Count_Type; Inserted : out Boolean); procedure Insert_With_Hint - (Dst_Set : in out Set; + (Dst_Set : in out Tree_Types.Tree_Type; Dst_Hint : Count_Type; Src_Node : Node_Type; Dst_Node : out Count_Type); @@ -141,7 +145,7 @@ is package Set_Ops is new Red_Black_Trees.Generic_Bounded_Set_Operations (Tree_Operations => Tree_Operations, - Set_Type => Set, + Set_Type => Tree_Types.Tree_Type, Assign => Assign, Insert_With_Hint => Insert_With_Hint, Is_Less => Is_Less_Node_Node); @@ -164,18 +168,19 @@ is return True; end if; - Lst := Next (Left, Last (Left).Node); + Lst := Next (Left.Content, Last (Left).Node); Node := First (Left).Node; while Node /= Lst loop - ENode := Find (Right, Left.Nodes (Node).Element).Node; + ENode := Find (Right, Left.Content.Nodes (Node).Element).Node; if ENode = 0 - or else Left.Nodes (Node).Element /= Right.Nodes (ENode).Element + or else Left.Content.Nodes (Node).Element /= + Right.Content.Nodes (ENode).Element then return False; end if; - Node := Next (Left, Node); + Node := Next (Left.Content, Node); end loop; return True; @@ -185,7 +190,10 @@ is -- Assign -- ------------ - procedure Assign (Target : in out Set; Source : Set) is + procedure Assign + (Target : in out Tree_Types.Tree_Type; + Source : Tree_Types.Tree_Type) + is procedure Append_Element (Source_Node : Count_Type); procedure Append_Elements is @@ -267,12 +275,18 @@ is Append_Elements (Source); end Assign; + procedure Assign (Target : in out Set; Source : Set) is + begin + Assign (Target.Content, Source.Content); + end Assign; + ------------- -- Ceiling -- ------------- function Ceiling (Container : Set; Item : Element_Type) return Cursor is - Node : constant Count_Type := Element_Keys.Ceiling (Container, Item); + Node : constant Count_Type := + Element_Keys.Ceiling (Container.Content, Item); begin if Node = 0 then @@ -288,7 +302,7 @@ is procedure Clear (Container : in out Set) is begin - Tree_Operations.Clear_Tree (Container); + Tree_Operations.Clear_Tree (Container.Content); end Clear; ----------- @@ -300,6 +314,25 @@ is return Node.Color; end Color; + ------------------------ + -- Constant_Reference -- + ------------------------ + + function Constant_Reference + (Container : aliased Set; + Position : Cursor) return not null access constant Element_Type + is + begin + if not Has_Element (Container, Position) then + raise Constraint_Error with "Position cursor has no element"; + end if; + + pragma Assert (Vet (Container.Content, Position.Node), + "bad cursor in Element"); + + return Container.Content.Nodes (Position.Node).Element'Access; + end Constant_Reference; + -------------- -- Contains -- -------------- @@ -327,32 +360,32 @@ is end if; if Length (Source) > 0 then - Target.Length := Source.Length; - Target.Root := Source.Root; - Target.First := Source.First; - Target.Last := Source.Last; - Target.Free := Source.Free; + Target.Content.Length := Source.Content.Length; + Target.Content.Root := Source.Content.Root; + Target.Content.First := Source.Content.First; + Target.Content.Last := Source.Content.Last; + Target.Content.Free := Source.Content.Free; Node := 1; while Node <= Source.Capacity loop - Target.Nodes (Node).Element := - Source.Nodes (Node).Element; - Target.Nodes (Node).Parent := - Source.Nodes (Node).Parent; - Target.Nodes (Node).Left := - Source.Nodes (Node).Left; - Target.Nodes (Node).Right := - Source.Nodes (Node).Right; - Target.Nodes (Node).Color := - Source.Nodes (Node).Color; - Target.Nodes (Node).Has_Element := - Source.Nodes (Node).Has_Element; + Target.Content.Nodes (Node).Element := + Source.Content.Nodes (Node).Element; + Target.Content.Nodes (Node).Parent := + Source.Content.Nodes (Node).Parent; + Target.Content.Nodes (Node).Left := + Source.Content.Nodes (Node).Left; + Target.Content.Nodes (Node).Right := + Source.Content.Nodes (Node).Right; + Target.Content.Nodes (Node).Color := + Source.Content.Nodes (Node).Color; + Target.Content.Nodes (Node).Has_Element := + Source.Content.Nodes (Node).Has_Element; Node := Node + 1; end loop; while Node <= Target.Capacity loop N := Node; - Formal_Ordered_Sets.Free (Tree => Target, X => N); + Free (Tree => Target, X => N); Node := Node + 1; end loop; end if; @@ -370,25 +403,25 @@ is raise Constraint_Error with "Position cursor has no element"; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "bad cursor in Delete"); - Tree_Operations.Delete_Node_Sans_Free (Container, + Tree_Operations.Delete_Node_Sans_Free (Container.Content, Position.Node); - Formal_Ordered_Sets.Free (Container, Position.Node); + Free (Container, Position.Node); Position := No_Element; end Delete; procedure Delete (Container : in out Set; Item : Element_Type) is - X : constant Count_Type := Element_Keys.Find (Container, Item); + X : constant Count_Type := Element_Keys.Find (Container.Content, Item); begin if X = 0 then raise Constraint_Error with "attempt to delete element not in set"; end if; - Tree_Operations.Delete_Node_Sans_Free (Container, X); - Formal_Ordered_Sets.Free (Container, X); + Tree_Operations.Delete_Node_Sans_Free (Container.Content, X); + Free (Container, X); end Delete; ------------------ @@ -396,11 +429,11 @@ is ------------------ procedure Delete_First (Container : in out Set) is - X : constant Count_Type := Container.First; + X : constant Count_Type := Container.Content.First; begin if X /= 0 then - Tree_Operations.Delete_Node_Sans_Free (Container, X); - Formal_Ordered_Sets.Free (Container, X); + Tree_Operations.Delete_Node_Sans_Free (Container.Content, X); + Free (Container, X); end if; end Delete_First; @@ -409,11 +442,11 @@ is ----------------- procedure Delete_Last (Container : in out Set) is - X : constant Count_Type := Container.Last; + X : constant Count_Type := Container.Content.Last; begin if X /= 0 then - Tree_Operations.Delete_Node_Sans_Free (Container, X); - Formal_Ordered_Sets.Free (Container, X); + Tree_Operations.Delete_Node_Sans_Free (Container.Content, X); + Free (Container, X); end if; end Delete_Last; @@ -423,7 +456,7 @@ is procedure Difference (Target : in out Set; Source : Set) is begin - Set_Ops.Set_Difference (Target, Source); + Set_Ops.Set_Difference (Target.Content, Source.Content); end Difference; function Difference (Left, Right : Set) return Set is @@ -437,11 +470,12 @@ is end if; if Length (Right) = 0 then - return Left.Copy; + return Copy (Left); end if; return S : Set (Length (Left)) do - Assign (S, Set_Ops.Set_Difference (Left, Right)); + Assign + (S.Content, Set_Ops.Set_Difference (Left.Content, Right.Content)); end return; end Difference; @@ -455,10 +489,10 @@ is raise Constraint_Error with "Position cursor has no element"; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "bad cursor in Element"); - return Container.Nodes (Position.Node).Element; + return Container.Content.Nodes (Position.Node).Element; end Element; ------------------------- @@ -506,7 +540,7 @@ is -- Start of processing for Equivalent_Sets begin - return Is_Equivalent (Left, Right); + return Is_Equivalent (Left.Content, Right.Content); end Equivalent_Sets; ------------- @@ -514,11 +548,11 @@ is ------------- procedure Exclude (Container : in out Set; Item : Element_Type) is - X : constant Count_Type := Element_Keys.Find (Container, Item); + X : constant Count_Type := Element_Keys.Find (Container.Content, Item); begin if X /= 0 then - Tree_Operations.Delete_Node_Sans_Free (Container, X); - Formal_Ordered_Sets.Free (Container, X); + Tree_Operations.Delete_Node_Sans_Free (Container.Content, X); + Free (Container, X); end if; end Exclude; @@ -527,7 +561,8 @@ is ---------- function Find (Container : Set; Item : Element_Type) return Cursor is - Node : constant Count_Type := Element_Keys.Find (Container, Item); + Node : constant Count_Type := + Element_Keys.Find (Container.Content, Item); begin if Node = 0 then @@ -547,7 +582,7 @@ is return No_Element; end if; - return (Node => Container.First); + return (Node => Container.Content.First); end First; ------------------- @@ -562,7 +597,7 @@ is end if; declare - N : Tree_Types.Nodes_Type renames Container.Nodes; + N : Tree_Types.Nodes_Type renames Container.Content.Nodes; begin return N (Fst).Element; end; @@ -575,7 +610,8 @@ is function Floor (Container : Set; Item : Element_Type) return Cursor is begin declare - Node : constant Count_Type := Element_Keys.Floor (Container, Item); + Node : constant Count_Type := + Element_Keys.Floor (Container.Content, Item); begin if Node = 0 then @@ -748,7 +784,7 @@ is -------------- function Elements (Container : Set) return E.Sequence is - Position : Count_Type := Container.First; + Position : Count_Type := Container.Content.First; R : E.Sequence; begin @@ -756,8 +792,8 @@ is -- for their postconditions. while Position /= 0 loop - R := E.Add (R, Container.Nodes (Position).Element); - Position := Tree_Operations.Next (Container, Position); + R := E.Add (R, Container.Content.Nodes (Position).Element); + Position := Tree_Operations.Next (Container.Content, Position); end loop; return R; @@ -873,7 +909,7 @@ is ----------- function Model (Container : Set) return M.Set is - Position : Count_Type := Container.First; + Position : Count_Type := Container.Content.First; R : M.Set; begin @@ -884,9 +920,9 @@ is R := M.Add (Container => R, - Item => Container.Nodes (Position).Element); + Item => Container.Content.Nodes (Position).Element); - Position := Tree_Operations.Next (Container, Position); + Position := Tree_Operations.Next (Container.Content, Position); end loop; return R; @@ -898,7 +934,7 @@ is function Positions (Container : Set) return P.Map is I : Count_Type := 1; - Position : Count_Type := Container.First; + Position : Count_Type := Container.Content.First; R : P.Map; begin @@ -908,7 +944,7 @@ is while Position /= 0 loop R := P.Add (R, (Node => Position), I); pragma Assert (P.Length (R) = I); - Position := Tree_Operations.Next (Container, Position); + Position := Tree_Operations.Next (Container.Content, Position); I := I + 1; end loop; @@ -923,8 +959,8 @@ is procedure Free (Tree : in out Set; X : Count_Type) is begin - Tree.Nodes (X).Has_Element := False; - Tree_Operations.Free (Tree, X); + Tree.Content.Nodes (X).Has_Element := False; + Tree_Operations.Free (Tree.Content, X); end Free; ---------------------- @@ -978,7 +1014,8 @@ is ------------- function Ceiling (Container : Set; Key : Key_Type) return Cursor is - Node : constant Count_Type := Key_Keys.Ceiling (Container, Key); + Node : constant Count_Type := + Key_Keys.Ceiling (Container.Content, Key); begin if Node = 0 then @@ -1002,15 +1039,15 @@ is ------------ procedure Delete (Container : in out Set; Key : Key_Type) is - X : constant Count_Type := Key_Keys.Find (Container, Key); + X : constant Count_Type := Key_Keys.Find (Container.Content, Key); begin if X = 0 then raise Constraint_Error with "attempt to delete key not in set"; end if; - Delete_Node_Sans_Free (Container, X); - Formal_Ordered_Sets.Free (Container, X); + Delete_Node_Sans_Free (Container.Content, X); + Free (Container, X); end Delete; ------------- @@ -1018,7 +1055,7 @@ is ------------- function Element (Container : Set; Key : Key_Type) return Element_Type is - Node : constant Count_Type := Key_Keys.Find (Container, Key); + Node : constant Count_Type := Key_Keys.Find (Container.Content, Key); begin if Node = 0 then @@ -1026,7 +1063,7 @@ is end if; declare - N : Tree_Types.Nodes_Type renames Container.Nodes; + N : Tree_Types.Nodes_Type renames Container.Content.Nodes; begin return N (Node).Element; end; @@ -1052,11 +1089,11 @@ is ------------- procedure Exclude (Container : in out Set; Key : Key_Type) is - X : constant Count_Type := Key_Keys.Find (Container, Key); + X : constant Count_Type := Key_Keys.Find (Container.Content, Key); begin if X /= 0 then - Delete_Node_Sans_Free (Container, X); - Formal_Ordered_Sets.Free (Container, X); + Delete_Node_Sans_Free (Container.Content, X); + Free (Container, X); end if; end Exclude; @@ -1065,7 +1102,7 @@ is ---------- function Find (Container : Set; Key : Key_Type) return Cursor is - Node : constant Count_Type := Key_Keys.Find (Container, Key); + Node : constant Count_Type := Key_Keys.Find (Container.Content, Key); begin return (if Node = 0 then No_Element else (Node => Node)); end Find; @@ -1075,7 +1112,7 @@ is ----------- function Floor (Container : Set; Key : Key_Type) return Cursor is - Node : constant Count_Type := Key_Keys.Floor (Container, Key); + Node : constant Count_Type := Key_Keys.Floor (Container.Content, Key); begin return (if Node = 0 then No_Element else (Node => Node)); end Floor; @@ -1225,11 +1262,11 @@ is "Position cursor has no element"; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "bad cursor in Key"); declare - N : Tree_Types.Nodes_Type renames Container.Nodes; + N : Tree_Types.Nodes_Type renames Container.Content.Nodes; begin return Key (N (Position.Node).Element); end; @@ -1244,7 +1281,7 @@ is Key : Key_Type; New_Item : Element_Type) is - Node : constant Count_Type := Key_Keys.Find (Container, Key); + Node : constant Count_Type := Key_Keys.Find (Container.Content, Key); begin if not Has_Element (Container, (Node => Node)) then raise Constraint_Error with @@ -1265,7 +1302,7 @@ is if Position.Node = 0 then return False; else - return Container.Nodes (Position.Node).Has_Element; + return Container.Content.Nodes (Position.Node).Has_Element; end if; end Has_Element; @@ -1282,7 +1319,7 @@ is if not Inserted then declare - N : Tree_Types.Nodes_Type renames Container.Nodes; + N : Tree_Types.Nodes_Type renames Container.Content.Nodes; begin N (Position.Node).Element := New_Item; end; @@ -1300,7 +1337,7 @@ is Inserted : out Boolean) is begin - Insert_Sans_Hint (Container, New_Item, Position.Node, Inserted); + Insert_Sans_Hint (Container.Content, New_Item, Position.Node, Inserted); end Insert; procedure Insert @@ -1324,7 +1361,7 @@ is ---------------------- procedure Insert_Sans_Hint - (Container : in out Set; + (Container : in out Tree_Types.Tree_Type; New_Item : Element_Type; Node : out Count_Type; Inserted : out Boolean) @@ -1377,7 +1414,7 @@ is ---------------------- procedure Insert_With_Hint - (Dst_Set : in out Set; + (Dst_Set : in out Tree_Types.Tree_Type; Dst_Hint : Count_Type; Src_Node : Node_Type; Dst_Node : out Count_Type) @@ -1439,17 +1476,18 @@ is procedure Intersection (Target : in out Set; Source : Set) is begin - Set_Ops.Set_Intersection (Target, Source); + Set_Ops.Set_Intersection (Target.Content, Source.Content); end Intersection; function Intersection (Left, Right : Set) return Set is begin if Left'Address = Right'Address then - return Left.Copy; + return Copy (Left); end if; return S : Set (Count_Type'Min (Length (Left), Length (Right))) do - Assign (S, Set_Ops.Set_Intersection (Left, Right)); + Assign (S.Content, + Set_Ops.Set_Intersection (Left.Content, Right.Content)); end return; end Intersection; @@ -1503,7 +1541,7 @@ is function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is begin - return Set_Ops.Set_Subset (Subset, Of_Set => Of_Set); + return Set_Ops.Set_Subset (Subset.Content, Of_Set => Of_Set.Content); end Is_Subset; ---------- @@ -1514,7 +1552,7 @@ is begin return (if Length (Container) = 0 then No_Element - else (Node => Container.Last)); + else (Node => Container.Content.Last)); end Last; ------------------ @@ -1528,7 +1566,7 @@ is end if; declare - N : Tree_Types.Nodes_Type renames Container.Nodes; + N : Tree_Types.Nodes_Type renames Container.Content.Nodes; begin return N (Last (Container).Node).Element; end; @@ -1549,7 +1587,7 @@ is function Length (Container : Set) return Count_Type is begin - return Container.Length; + return Container.Content.Length; end Length; ---------- @@ -1557,7 +1595,7 @@ is ---------- procedure Move (Target : in out Set; Source : in out Set) is - N : Tree_Types.Nodes_Type renames Source.Nodes; + N : Tree_Types.Nodes_Type renames Source.Content.Nodes; X : Count_Type; begin @@ -1573,13 +1611,13 @@ is Clear (Target); loop - X := Source.First; + X := Source.Content.First; exit when X = 0; Insert (Target, N (X).Element); -- optimize??? - Tree_Operations.Delete_Node_Sans_Free (Source, X); - Formal_Ordered_Sets.Free (Source, X); + Tree_Operations.Delete_Node_Sans_Free (Source.Content, X); + Free (Source, X); end loop; end Move; @@ -1597,9 +1635,9 @@ is raise Constraint_Error; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "bad cursor in Next"); - return (Node => Tree_Operations.Next (Container, Position.Node)); + return (Node => Tree_Operations.Next (Container.Content, Position.Node)); end Next; procedure Next (Container : Set; Position : in out Cursor) is @@ -1613,7 +1651,7 @@ is function Overlap (Left, Right : Set) return Boolean is begin - return Set_Ops.Set_Overlap (Left, Right); + return Set_Ops.Set_Overlap (Left.Content, Right.Content); end Overlap; ------------ @@ -1639,12 +1677,12 @@ is raise Constraint_Error; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "bad cursor in Previous"); declare Node : constant Count_Type := - Tree_Operations.Previous (Container, Position.Node); + Tree_Operations.Previous (Container.Content, Position.Node); begin return (if Node = 0 then No_Element else (Node => Node)); end; @@ -1660,7 +1698,8 @@ is ------------- procedure Replace (Container : in out Set; New_Item : Element_Type) is - Node : constant Count_Type := Element_Keys.Find (Container, New_Item); + Node : constant Count_Type := + Element_Keys.Find (Container.Content, New_Item); begin if Node = 0 then @@ -1668,7 +1707,7 @@ is "attempt to replace element not in set"; end if; - Container.Nodes (Node).Element := New_Item; + Container.Content.Nodes (Node).Element := New_Item; end Replace; --------------------- @@ -1696,7 +1735,7 @@ is (Local_Insert_Post, Local_Insert_Sans_Hint); - NN : Tree_Types.Nodes_Type renames Tree.Nodes; + NN : Tree_Types.Nodes_Type renames Tree.Content.Nodes; -------------- -- New_Node -- @@ -1730,7 +1769,7 @@ is return; end if; - Hint := Element_Keys.Ceiling (Tree, Item); + Hint := Element_Keys.Ceiling (Tree.Content, Item); if Hint = 0 then null; @@ -1746,10 +1785,10 @@ is raise Program_Error with "attempt to replace existing element"; end if; - Tree_Operations.Delete_Node_Sans_Free (Tree, Node); + Tree_Operations.Delete_Node_Sans_Free (Tree.Content, Node); Local_Insert_With_Hint - (Tree => Tree, + (Tree => Tree.Content, Position => Hint, Key => Item, Node => Result, @@ -1770,7 +1809,7 @@ is "Position cursor has no element"; end if; - pragma Assert (Vet (Container, Position.Node), + pragma Assert (Vet (Container.Content, Position.Node), "bad cursor in Replace_Element"); Replace_Element (Container, Position.Node, New_Item); @@ -1830,7 +1869,7 @@ is procedure Symmetric_Difference (Target : in out Set; Source : Set) is begin - Set_Ops.Set_Symmetric_Difference (Target, Source); + Set_Ops.Set_Symmetric_Difference (Target.Content, Source.Content); end Symmetric_Difference; function Symmetric_Difference (Left, Right : Set) return Set is @@ -1840,15 +1879,17 @@ is end if; if Length (Right) = 0 then - return Left.Copy; + return Copy (Left); end if; if Length (Left) = 0 then - return Right.Copy; + return Copy (Right); end if; return S : Set (Length (Left) + Length (Right)) do - Assign (S, Set_Ops.Set_Symmetric_Difference (Left, Right)); + Assign + (S.Content, + Set_Ops.Set_Symmetric_Difference (Left.Content, Right.Content)); end return; end Symmetric_Difference; @@ -1861,7 +1902,7 @@ is Inserted : Boolean; begin return S : Set (Capacity => 1) do - Insert_Sans_Hint (S, New_Item, Node, Inserted); + Insert_Sans_Hint (S.Content, New_Item, Node, Inserted); pragma Assert (Inserted); end return; end To_Set; @@ -1872,21 +1913,21 @@ is procedure Union (Target : in out Set; Source : Set) is begin - Set_Ops.Set_Union (Target, Source); + Set_Ops.Set_Union (Target.Content, Source.Content); end Union; function Union (Left, Right : Set) return Set is begin if Left'Address = Right'Address then - return Left.Copy; + return Copy (Left); end if; if Length (Left) = 0 then - return Right.Copy; + return Copy (Right); end if; if Length (Right) = 0 then - return Left.Copy; + return Copy (Left); end if; return S : Set (Length (Left) + Length (Right)) do diff --git a/gcc/ada/libgnat/a-cforse.ads b/gcc/ada/libgnat/a-cforse.ads index 12d2d3c..e1d7c91 100644 --- a/gcc/ada/libgnat/a-cforse.ads +++ b/gcc/ada/libgnat/a-cforse.ads @@ -529,6 +529,16 @@ is Position => Position) and Positions (Container) = Positions (Container)'Old; + function Constant_Reference + (Container : aliased Set; + Position : Cursor) return not null access constant Element_Type + with + Global => null, + Pre => Has_Element (Container, Position), + Post => + Constant_Reference'Result.all = + E.Get (Elements (Container), P.Get (Positions (Container), Position)); + procedure Move (Target : in out Set; Source : in out Set) with Global => null, Pre => Target.Capacity >= Length (Source), @@ -1770,18 +1780,19 @@ private type Node_Type is record Has_Element : Boolean := False; - Parent : Count_Type := 0; - Left : Count_Type := 0; - Right : Count_Type := 0; - Color : Red_Black_Trees.Color_Type; - Element : Element_Type; + Parent : Count_Type := 0; + Left : Count_Type := 0; + Right : Count_Type := 0; + Color : Red_Black_Trees.Color_Type; + Element : aliased Element_Type; end record; package Tree_Types is new Red_Black_Trees.Generic_Bounded_Tree_Types (Node_Type); - type Set (Capacity : Count_Type) is - new Tree_Types.Tree_Type (Capacity) with null record; + type Set (Capacity : Count_Type) is record + Content : Tree_Types.Tree_Type (Capacity); + end record; use Red_Black_Trees; diff --git a/gcc/ada/libgnat/a-coboho.adb b/gcc/ada/libgnat/a-coboho.adb index 32346d0..21b9f54 100644 --- a/gcc/ada/libgnat/a-coboho.adb +++ b/gcc/ada/libgnat/a-coboho.adb @@ -65,6 +65,26 @@ package body Ada.Containers.Bounded_Holders is return Get (Left) = Get (Right); end "="; + ------------------------ + -- Constant_Reference -- + ------------------------ + + function Constant_Reference + (Container : aliased Holder) return not null access constant Element_Type + is + begin + return Cast (Container'Address); + end Constant_Reference; + + --------- + -- Get -- + --------- + + function Get (Container : Holder) return Element_Type is + begin + return Cast (Container'Address).all; + end Get; + --------------- -- Put_Image -- --------------- @@ -79,14 +99,16 @@ package body Ada.Containers.Bounded_Holders is Array_After (S); end Put_Image; - --------- - -- Get -- - --------- + --------------- + -- Reference -- + --------------- - function Get (Container : Holder) return Element_Type is + function Reference + (Container : not null access Holder) return not null access Element_Type + is begin - return Cast (Container'Address).all; - end Get; + return Cast (Container.all'Address); + end Reference; --------- -- Set -- diff --git a/gcc/ada/libgnat/a-coboho.ads b/gcc/ada/libgnat/a-coboho.ads index 9dd73ba..086f194 100644 --- a/gcc/ada/libgnat/a-coboho.ads +++ b/gcc/ada/libgnat/a-coboho.ads @@ -81,6 +81,12 @@ package Ada.Containers.Bounded_Holders is procedure Set (Container : in out Holder; New_Item : Element_Type); + function Constant_Reference + (Container : aliased Holder) return not null access constant Element_Type; + + function Reference + (Container : not null access Holder) return not null access Element_Type; + private -- The implementation uses low-level tricks (Address clauses and unchecked diff --git a/gcc/ada/libgnat/a-cofove.adb b/gcc/ada/libgnat/a-cofove.adb index a1f13ed..c7f4f06 100644 --- a/gcc/ada/libgnat/a-cofove.adb +++ b/gcc/ada/libgnat/a-cofove.adb @@ -142,6 +142,22 @@ is Container.Last := No_Index; end Clear; + ------------------------ + -- Constant_Reference -- + ------------------------ + + function Constant_Reference + (Container : aliased Vector; + Index : Index_Type) return not null access constant Element_Type + is + begin + if Index > Container.Last then + raise Constraint_Error with "Index is out of range"; + end if; + + return Container.Elements (To_Array_Index (Index))'Access; + end Constant_Reference; + -------------- -- Contains -- -------------- @@ -1096,6 +1112,22 @@ is end; end Replace_Element; + --------------- + -- Reference -- + --------------- + + function Reference + (Container : not null access Vector; + Index : Index_Type) return not null access Element_Type + is + begin + if Index > Container.Last then + raise Constraint_Error with "Index is out of range"; + end if; + + return Container.Elements (To_Array_Index (Index))'Access; + end Reference; + ---------------------- -- Reserve_Capacity -- ---------------------- diff --git a/gcc/ada/libgnat/a-cofove.ads b/gcc/ada/libgnat/a-cofove.ads index 61115dd..a4ed7e5 100644 --- a/gcc/ada/libgnat/a-cofove.ads +++ b/gcc/ada/libgnat/a-cofove.ads @@ -290,6 +290,48 @@ is Right => Model (Container), Position => Index); + function At_End (E : access constant Vector) return access constant Vector + is (E) + with Ghost, + Annotate => (GNATprove, At_End_Borrow); + + function At_End + (E : access constant Element_Type) return access constant Element_Type + is (E) + with Ghost, + Annotate => (GNATprove, At_End_Borrow); + + function Constant_Reference + (Container : aliased Vector; + Index : Index_Type) return not null access constant Element_Type + with + Global => null, + Pre => Index in First_Index (Container) .. Last_Index (Container), + Post => + Constant_Reference'Result.all = Element (Model (Container), Index); + + function Reference + (Container : not null access Vector; + Index : Index_Type) return not null access Element_Type + with + Global => null, + Pre => + Index in First_Index (Container.all) .. Last_Index (Container.all), + Post => + Length (Container.all) = Length (At_End (Container).all) + + -- Container will have Result.all at index Index + + and At_End (Reference'Result).all = + Element (Model (At_End (Container).all), Index) + + -- All other elements are preserved + + and M.Equal_Except + (Left => Model (Container.all), + Right => Model (At_End (Container).all), + Position => Index); + procedure Insert (Container : in out Vector; Before : Extended_Index; @@ -905,7 +947,7 @@ private pragma Inline (Contains); subtype Array_Index is Capacity_Range range 1 .. Capacity_Range'Last; - type Elements_Array is array (Array_Index range <>) of Element_Type; + type Elements_Array is array (Array_Index range <>) of aliased Element_Type; function "=" (L, R : Elements_Array) return Boolean is abstract; type Vector (Capacity : Capacity_Range) is record diff --git a/gcc/ada/libgnat/a-cofuma.ads b/gcc/ada/libgnat/a-cofuma.ads index ca872e2..a1dd764 100644 --- a/gcc/ada/libgnat/a-cofuma.ads +++ b/gcc/ada/libgnat/a-cofuma.ads @@ -302,6 +302,14 @@ package Ada.Containers.Functional_Maps with SPARK_Mode is Global => null, Pre => Has_Witness (Container, Witness); + function Copy_Key (Key : Key_Type) return Key_Type is (Key); + function Copy_Element (Item : Element_Type) return Element_Type is (Item); + -- Elements and Keys of maps are copied by numerous primitives in this + -- package. This function causes GNATprove to verify that such a copy is + -- valid (in particular, it does not break the ownership policy of SPARK, + -- i.e. it does not contain pointers that could be used to alias mutable + -- data). + --------------------------- -- Iteration Primitives -- --------------------------- diff --git a/gcc/ada/libgnat/a-cofuse.ads b/gcc/ada/libgnat/a-cofuse.ads index d852be9..d0acba7 100644 --- a/gcc/ada/libgnat/a-cofuse.ads +++ b/gcc/ada/libgnat/a-cofuse.ads @@ -249,6 +249,13 @@ package Ada.Containers.Functional_Sets with SPARK_Mode is and Right <= Union'Result and Included_In_Union (Union'Result, Left, Right); + function Copy_Element (Item : Element_Type) return Element_Type is (Item); + -- Elements of containers are copied by numerous primitives in this + -- package. This function causes GNATprove to verify that such a copy is + -- valid (in particular, it does not break the ownership policy of SPARK, + -- i.e. it does not contain pointers that could be used to alias mutable + -- data). + --------------------------- -- Iteration Primitives -- --------------------------- diff --git a/gcc/ada/libgnat/a-cofuve.ads b/gcc/ada/libgnat/a-cofuve.ads index bdd0e94..ee52730 100644 --- a/gcc/ada/libgnat/a-cofuve.ads +++ b/gcc/ada/libgnat/a-cofuve.ads @@ -336,6 +336,13 @@ package Ada.Containers.Functional_Vectors with SPARK_Mode is Lst => Last (Remove'Result), Offset => 1); + function Copy_Element (Item : Element_Type) return Element_Type is (Item); + -- Elements of containers are copied by numerous primitives in this + -- package. This function causes GNATprove to verify that such a copy is + -- valid (in particular, it does not break the ownership policy of SPARK, + -- i.e. it does not contain pointers that could be used to alias mutable + -- data). + --------------------------- -- Iteration Primitives -- --------------------------- -- cgit v1.1 From 59748b7180590360d3608d30e707a27b0b2cb476 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 30 Apr 2021 00:29:33 +0200 Subject: [Ada] Reject overlays in Global/Depends/Initializes contracts gcc/ada/ * sem_prag.adb (Analyze_Depends_In_Decl_Part): Reject overlays in Depends and Refined_Depends contracts. (Analyze_Global_In_Decl_Part): Likewise for Global and Refined_Global. (Analyze_Initializes_In_Decl_Part): Likewise for Initializes (when appearing both as a single item and as a initialization clause). * sem_util.ads (Ultimate_Overlaid_Entity): New routine. * sem_util.adb (Report_Unused_Body_States): Ignore overlays. (Ultimate_Overlaid_Entity): New routine. --- gcc/ada/sem_prag.adb | 44 ++++++++++++++++++++++++++++++++++++++++++++ gcc/ada/sem_util.adb | 40 ++++++++++++++++++++++++++++++++++++++++ gcc/ada/sem_util.ads | 9 +++++++++ 3 files changed, 93 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 0efdcef..41e887d 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -1139,6 +1139,17 @@ package body Sem_Prag is (State_Id => Item_Id, Ref => Item); end if; + + elsif Ekind (Item_Id) in E_Constant | E_Variable + and then Present (Ultimate_Overlaid_Entity (Item_Id)) + then + SPARK_Msg_NE + ("overlaying object & cannot appear in Depends", + Item, Item_Id); + SPARK_Msg_NE + ("\use the overlaid object & instead", + Item, Ultimate_Overlaid_Entity (Item_Id)); + return; end if; -- When the item renames an entire object, replace the @@ -2387,6 +2398,17 @@ package body Sem_Prag is elsif Is_Formal_Object (Item_Id) then null; + elsif Ekind (Item_Id) in E_Constant | E_Variable + and then Present (Ultimate_Overlaid_Entity (Item_Id)) + then + SPARK_Msg_NE + ("overlaying object & cannot appear in Global", + Item, Item_Id); + SPARK_Msg_NE + ("\use the overlaid object & instead", + Item, Ultimate_Overlaid_Entity (Item_Id)); + return; + -- The only legal references are those to abstract states, -- objects and various kinds of constants (SPARK RM 6.1.4(4)). @@ -2984,6 +3006,16 @@ package body Sem_Prag is if Item_Id = Any_Id then null; + elsif Ekind (Item_Id) in E_Constant | E_Variable + and then Present (Ultimate_Overlaid_Entity (Item_Id)) + then + SPARK_Msg_NE + ("overlaying object & cannot appear in Initializes", + Item, Item_Id); + SPARK_Msg_NE + ("\use the overlaid object & instead", + Item, Ultimate_Overlaid_Entity (Item_Id)); + -- The state or variable must be declared in the visible -- declarations of the package (SPARK RM 7.1.5(7)). @@ -3126,6 +3158,18 @@ package body Sem_Prag is end if; end if; + if Ekind (Input_Id) in E_Constant | E_Variable + and then Present (Ultimate_Overlaid_Entity (Input_Id)) + then + SPARK_Msg_NE + ("overlaying object & cannot appear in Initializes", + Input, Input_Id); + SPARK_Msg_NE + ("\use the overlaid object & instead", + Input, Ultimate_Overlaid_Entity (Input_Id)); + return; + end if; + -- Detect a duplicate use of the same input item -- (SPARK RM 7.1.5(5)). diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 7ea809b..038c1ee 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -5708,6 +5708,13 @@ package body Sem_Util is if Ekind (State_Id) = E_Constant then null; + -- Overlays do not contribute to package state + + elsif Ekind (State_Id) = E_Variable + and then Present (Ultimate_Overlaid_Entity (State_Id)) + then + null; + -- Generate an error message of the form: -- body of package ... has unused hidden states @@ -29312,6 +29319,39 @@ package body Sem_Util is end if; end Type_Without_Stream_Operation; + ------------------------------ + -- Ultimate_Overlaid_Entity -- + ------------------------------ + + function Ultimate_Overlaid_Entity (E : Entity_Id) return Entity_Id is + Address : Node_Id; + Alias : Entity_Id := E; + Offset : Boolean; + + begin + -- Currently this routine is only called for stand-alone objects that + -- have been analysed, since the analysis of the Address aspect is often + -- delayed. + + pragma Assert (Ekind (E) in E_Constant | E_Variable); + + loop + Address := Address_Clause (Alias); + if Present (Address) then + Find_Overlaid_Entity (Address, Alias, Offset); + if Present (Alias) then + null; + else + return Empty; + end if; + elsif Alias = E then + return Empty; + else + return Alias; + end if; + end loop; + end Ultimate_Overlaid_Entity; + --------------------- -- Ultimate_Prefix -- --------------------- diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index a49272e..7cacae2 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -3275,6 +3275,15 @@ package Sem_Util is -- prevents the construction of a composite stream operation. If Op is -- specified we check only for the given stream operation. + function Ultimate_Overlaid_Entity (E : Entity_Id) return Entity_Id; + -- If entity E is overlaying some other entity via an Address clause (which + -- possibly overlays yet another entity via its own Address clause), then + -- return the ultimate overlaid entity. If entity E is not overlaying any + -- other entity (or the overlaid entity cannot be determined statically), + -- then return Empty. + -- + -- Subsidiary to the analysis of object overlays in SPARK. + function Ultimate_Prefix (N : Node_Id) return Node_Id; -- Obtain the "outermost" prefix of arbitrary node N. Return N if no such -- prefix exists. -- cgit v1.1 From 8e0b3827bbab6bf92d88d00909ecf8fb43365f39 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jun 2021 14:31:23 +0000 Subject: [Ada] Regenerate *.texi files with Sphinx 4.0.2 gcc/ada/ * gnat-style.texi, gnat_rm.texi, gnat_ugn.texi: Regenerate. --- gcc/ada/gnat-style.texi | 1691 +++++++++++++++++++++++++-------------- gcc/ada/gnat_rm.texi | 2040 +++++++++++++++++++++++------------------------ gcc/ada/gnat_ugn.texi | 910 ++++++++++----------- 3 files changed, 2563 insertions(+), 2078 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/gnat-style.texi b/gcc/ada/gnat-style.texi index 50adaab..37ce690 100644 --- a/gcc/ada/gnat-style.texi +++ b/gcc/ada/gnat-style.texi @@ -1,94 +1,71 @@ \input texinfo @c -*-texinfo-*- @c %**start of header - -@c oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo -@c o -@c GNAT DOCUMENTATION o -@c o -@c G N A T C O D I N G S T Y L E o -@c o -@c Copyright (C) 1992-2012, AdaCore o -@c o -@c oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo - @setfilename gnat-style.info +@documentencoding UTF-8 +@ifinfo +@*Generated by Sphinx 4.0.2.@* +@end ifinfo +@settitle GNAT Coding Style A Guide for GNAT Developers +@defindex ge +@paragraphindent 0 +@exampleindent 4 +@finalout +@dircategory GNU Ada Tools +@direntry +* gnat-style: (gnat-style.info). gnat-style +@end direntry -@copying -Copyright @copyright{} 1992-2012, AdaCore +@definfoenclose strong,`,' +@definfoenclose emph,`,' +@c %**end of header -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 or -any later version published by the Free Software Foundation; with no -Invariant Sections, with no Front-Cover Texts and with no Back-Cover -Texts. A copy of the license is included in the section entitled -``GNU Free Documentation License''. -@end copying +@copying +@quotation +GNAT Coding Style: A Guide for GNAT Developers , Jun 23, 2021 -@settitle GNAT Coding Style -@setchapternewpage odd +AdaCore -@include gcc-common.texi +Copyright @copyright{} 2008-2021, Free Software Foundation +@end quotation -@dircategory Software development -@direntry -* gnat-style: (gnat-style). GNAT Coding Style -@end direntry - -@macro syntax{element} -@t{\element\} -@end macro -@c %**end of header +@end copying @titlepage -@titlefont{GNAT Coding Style:} -@sp 1 -@title A Guide for GNAT Developers -@subtitle GNAT, The GNU Ada Compiler -@versionsubtitle -@author Ada Core Technologies, Inc. -@page -@vskip 0pt plus 1filll - +@title GNAT Coding Style A Guide for GNAT Developers @insertcopying @end titlepage +@contents -@raisesections +@c %** start of user preamble -@node Top, General, , (dir) -@comment node-name, next, previous, up +@c %** end of user preamble @ifnottex -@noindent -GNAT Coding Style@* -A Guide for GNAT Developers -@sp 2 -@noindent -GNAT, The GNU Ada Compiler@* - -@noindent +@node Top +@top GNAT Coding Style A Guide for GNAT Developers @insertcopying @end ifnottex - +@c %**start of body +@anchor{gnat-style doc}@anchor{0} @menu -* General:: -* Lexical Elements:: -* Declarations and Types:: -* Expressions and Names:: -* Statements:: -* Subprograms:: -* Packages:: -* Program Structure:: -* GNU Free Documentation License:: -* Index:: +* General:: +* Lexical Elements:: +* Declarations and Types:: +* Expressions and Names:: +* Statements:: +* Subprograms:: +* Packages and Visibility Rules:: +* Program Structure and Compilation Issues:: +* Index:: + @end menu -@c ------------------------------------------------------------------------- -@node General, Lexical Elements, Top, Top -@section General -@c ------------------------------------------------------------------------- +@node General,Lexical Elements,Top,Top +@anchor{gnat-style general}@anchor{1}@anchor{gnat-style gnat-coding-style-a-guide-for-gnat-developers}@anchor{2} +@chapter General + -@noindent Most of GNAT is written in Ada using a consistent style to ensure readability of the code. This document has been written to help maintain this consistent style, while having a large group of developers @@ -97,148 +74,184 @@ work on the compiler. For the coding style in the C parts of the compiler and run time, see the GNU Coding Guidelines. -This document is structured after the @cite{Ada Reference Manual}. +This document is structured after the Ada Reference Manual. Those familiar with that document should be able to quickly lookup style rules for particular constructs. +@node Lexical Elements,Declarations and Types,General,Top +@anchor{gnat-style lexical-elements}@anchor{3} +@chapter Lexical Elements -@c ------------------------------------------------------------------------- -@node Lexical Elements, Declarations and Types, General, Top -@section Lexical Elements -@c ------------------------------------------------------------------------- -@cindex Lexical elements - -@subsection Character Set and Separators -@c ------------------------------------------------------------------------- -@cindex Character set -@cindex ASCII -@cindex Separators -@cindex End-of-line -@cindex Line length -@cindex Indentation - -@itemize @bullet -@item -The character set used should be plain 7-bit ASCII@. + +@menu +* Character Set and Separators:: +* Identifiers:: +* Numeric Literals:: +* Reserved Words:: +* Comments:: + +@end menu + +@node Character Set and Separators,Identifiers,,Lexical Elements +@anchor{gnat-style character-set-and-separators}@anchor{4} +@section Character Set and Separators + + +@geindex Character set + +@geindex ASCII + +@geindex Separators + +@geindex End-of-line + +@geindex Line length + +@geindex Indentation + + +@itemize * + +@item +The character set used should be plain 7-bit ASCII. The only separators allowed are space and the end-of-line sequence. No other control character or format effector (such as @code{HT}, -@code{VT}, @code{FF}) +@code{VT}, @code{FF} ) should be used. The normal end-of-line sequence is used, which may be @code{LF}, @code{CR/LF} or @code{CR}, depending on the host system. An optional @code{SUB} -(@code{16#1A#}) may be present as the +( @code{16#1A#} ) may be present as the last character in the file on hosts using that character as file terminator. -@item +@item Files that are checked in or distributed should be in host format. -@item +@item A line should never be longer than 79 characters, not counting the line separator. -@item +@item Lines must not have trailing blanks. -@item +@item Indentation is 3 characters per level for @code{if} statements, loops, and @code{case} statements. For exact information on required spacing between lexical -elements, see file @file{style.adb}. -@cindex @file{style.adb} file +elements, see file style.adb. + +@geindex style.adb file @end itemize +@node Identifiers,Numeric Literals,Character Set and Separators,Lexical Elements +@anchor{gnat-style identifiers}@anchor{5} +@section Identifiers + -@subsection Identifiers -@c ------------------------------------------------------------------------- -@itemize @bullet -@cindex Identifiers -@item +@itemize * + +@item Identifiers will start with an upper case letter, and each letter following an underscore will be upper case. -@cindex Casing (for identifiers) + +@geindex Casing (for identifiers) + Short acronyms may be all upper case. All other letters are lower case. An exception is for identifiers matching a foreign language. In particular, -we use all lower case where appropriate for C@. +we use all lower case where appropriate for C. -@item +@item Use underscores to separate words in an identifier. -@cindex Underscores -@item Try to limit your use of abbreviations in identifiers. +@geindex Underscores + +@item +Try to limit your use of abbreviations in identifiers. It is ok to make a few abbreviations, explain what they mean, and then -use them frequently, but don't use lots of obscure abbreviations. An +use them frequently, but don’t use lots of obscure abbreviations. An example is the @code{ALI} word which stands for Ada Library Information and is by convention always written in upper-case when used in entity names. -@smallexample @c adanocomment - procedure Find_ALI_Files; -@end smallexample +@example +procedure Find_ALI_Files; +@end example -@item -Don't use the variable name @code{I}, use @code{J} instead; @code{I} is too -easily confused with @code{1} in some fonts. Similarly don't use the +@item +Don’t use the variable name @code{I}, use @code{J} instead; @code{I} is too +easily confused with @code{1} in some fonts. Similarly don’t use the variable @code{O}, which is too easily mistaken for the number @code{0}. @end itemize -@subsection Numeric Literals -@c ------------------------------------------------------------------------- -@cindex Numeric literals +@node Numeric Literals,Reserved Words,Identifiers,Lexical Elements +@anchor{gnat-style numeric-literals}@anchor{6} +@section Numeric Literals + + + +@itemize * -@itemize @bullet -@item +@item Numeric literals should include underscores where helpful for readability. -@cindex Underscores -@smallexample - 1_000_000 - 16#8000_0000# - 3.14159_26535_89793_23846 -@end smallexample +@geindex Underscores + +@example +1_000_000 +16#8000_0000# +3.14159_26535_89793_23846 +@end example @end itemize -@subsection Reserved Words -@c ------------------------------------------------------------------------- -@cindex Reserved words +@node Reserved Words,Comments,Numeric Literals,Lexical Elements +@anchor{gnat-style reserved-words}@anchor{7} +@section Reserved Words + + -@itemize @bullet -@item +@itemize * + +@item Reserved words use all lower case. -@cindex Casing (for reserved words) -@smallexample @c adanocomment - return else -@end smallexample +@geindex Casing (for reserved words) + +@example +return else +@end example -@item +@item The words @code{Access}, @code{Delta} and @code{Digits} are -capitalized when used as @syntax{attribute_designator}. +capitalized when used as attribute_designator. @end itemize -@subsection Comments -@c ------------------------------------------------------------------------- -@cindex Comments +@node Comments,,Reserved Words,Lexical Elements +@anchor{gnat-style comments}@anchor{8} +@section Comments -@itemize @bullet -@item + + +@itemize * + +@item A comment starts with @code{--} followed by two spaces. -The only exception to this rule (i.e.@: one space is tolerated) is when the +The only exception to this rule (i.e. one space is tolerated) is when the comment ends with a single space followed by @code{--}. It is also acceptable to have only one space between @code{--} and the start of the comment when the comment is at the end of a line, after some Ada code. -@item +@item Every sentence in a comment should start with an upper-case letter (including the first letter of the comment). -@cindex Casing (in comments) -@item -When declarations are commented with ``hanging'' comments, i.e.@: +@geindex Casing (in comments) + +@item +When declarations are commented with ‘hanging’ comments, i.e. comments after the declaration, there is no blank line before the comment, and if it is absolutely necessary to have blank lines within the comments, e.g. to make paragraph separations within a single comment, @@ -246,217 +259,232 @@ these blank lines @emph{do} have a @code{--} (unlike the normal rule, which is to use entirely blank lines for separating comment paragraphs). The comment starts at same level of indentation as code it is commenting. -@cindex Blank lines (in comments) -@cindex Indentation -@smallexample @c adanocomment - z : Integer; - -- Integer value for storing value of z - -- - -- The previous line was a blank line. -@end smallexample +@geindex Blank lines (in comments) + +@geindex Indentation -@item +@example +z : Integer; +-- Integer value for storing value of z +-- +-- The previous line was a blank line. +@end example + +@item Comments that are dubious or incomplete, or that comment on possibly -wrong or incomplete code, should be preceded or followed by @code{???}@. +wrong or incomplete code, should be preceded or followed by @code{???}. -@item +@item Comments in a subprogram body must generally be surrounded by blank lines. An exception is a comment that follows a line containing a single keyword -(@code{begin}, @code{else}, @code{loop}): +( @code{begin}, @code{else}, @code{loop} ): -@smallexample @c adanocomment -@group - begin - -- Comment for the next statement +@example +begin + -- Comment for the next statement - A := 5; + A := 5; - -- Comment for the B statement + -- Comment for the B statement - B := 6; - end; -@end group -@end smallexample + B := 6; +end; +@end example -@item +@item In sequences of statements, comments at the end of the lines should be aligned. -@cindex Alignment (in comments) -@smallexample @c adanocomment - My_Identifier := 5; -- First comment - Other_Id := 6; -- Second comment -@end smallexample +@geindex Alignment (in comments) + +@example +My_Identifier := 5; -- First comment +Other_Id := 6; -- Second comment +@end example -@item +@item Short comments that fit on a single line are @emph{not} ended with a period. Comments taking more than a line are punctuated in the normal manner. -@item +@item Comments should focus on @emph{why} instead of @emph{what}. Descriptions of what subprograms do go with the specification. -@item +@item Comments describing a subprogram spec should specifically mention the formal argument names. General rule: write a comment that does not depend on the names of things. The names are supplementary, not sufficient, as comments. -@item +@item @emph{Do not} put two spaces after periods in comments. @end itemize -@c ------------------------------------------------------------------------- -@node Declarations and Types, Expressions and Names, Lexical Elements,Top -@section Declarations and Types -@c ------------------------------------------------------------------------- -@cindex Declarations and Types +@node Declarations and Types,Expressions and Names,Lexical Elements,Top +@anchor{gnat-style declarations-and-types}@anchor{9} +@chapter Declarations and Types + + -@itemize @bullet -@item +@itemize * + +@item In entity declarations, colons must be surrounded by spaces. Colons should be aligned. -@cindex Alignment (in declarations) -@smallexample @c adanocomment - Entity1 : Integer; - My_Entity : Integer; -@end smallexample +@geindex Alignment (in declarations) + +@example +Entity1 : Integer; +My_Entity : Integer; +@end example -@item +@item Declarations should be grouped in a logical order. Related groups of declarations may be preceded by a header comment. -@item +@item All local subprograms in a subprogram or package body should be declared before the first local subprogram body. -@item +@item Do not declare local entities that hide global entities. -@cindex Hiding of outer entities -@item +@geindex Hiding of outer entities + +@item Do not declare multiple variables in one declaration that spans lines. Start a new declaration on each line, instead. -@item -The @syntax{defining_identifier}s of global declarations serve as -comments of a sort. So don't choose terse names, but look for names +@item +The defining_identifiers of global declarations serve as +comments of a sort. So don’t choose terse names, but look for names that give useful information instead. -@item +@item Local names can be shorter, because they are used only within one context, where comments explain their purpose. -@item +@item When starting an initialization or default expression on the line that follows the declaration line, use 2 characters for indentation. -@smallexample @c adanocomment - Entity1 : Integer := - Function_Name (Parameters, For_Call); -@end smallexample +@example +Entity1 : Integer := + Function_Name (Parameters, For_Call); +@end example -@item +@item If an initialization or default expression needs to be continued on subsequent lines, the continuations should be indented from the start of the expression. -@smallexample @c adanocomment - Entity1 : Integer := Long_Function_Name - (parameters for call); -@end smallexample - +@example +Entity1 : Integer := Long_Function_Name + (parameters for call); +@end example @end itemize +@node Expressions and Names,Statements,Declarations and Types,Top +@anchor{gnat-style expressions-and-names}@anchor{a} +@chapter Expressions and Names + -@c ------------------------------------------------------------------------- -@node Expressions and Names, Statements, Declarations and Types, Top -@section Expressions and Names -@c ------------------------------------------------------------------------- -@cindex Expressions and names -@itemize @bullet +@itemize * -@item +@item Every operator must be surrounded by spaces. An exception is that this rule does not apply to the exponentiation operator, for which there are no specific layout rules. The reason for this exception is that sometimes it makes clearer reading to leave out the spaces around exponentiation. -@cindex Operators -@smallexample @c adanocomment - E := A * B**2 + 3 * (C - D); -@end smallexample +@geindex Operators -@item +@example +E := A * B**2 + 3 * (C - D); +@end example + +@item Use parentheses where they clarify the intended association of operands with operators: -@cindex Parenthesization of expressions -@smallexample @c adanocomment - (A / B) * C -@end smallexample + +@geindex Parenthesization of expressions + +@example +(A / B) * C +@end example @end itemize -@c ------------------------------------------------------------------------- -@node Statements, Subprograms, Expressions and Names, Top -@section Statements -@c ------------------------------------------------------------------------- -@cindex Statements +@node Statements,Subprograms,Expressions and Names,Top +@anchor{gnat-style statements}@anchor{b} +@chapter Statements + + +@menu +* Simple and Compound Statements:: +* If Statements:: +* Case Statements:: +* Loop Statements:: +* Block Statements:: + +@end menu + +@node Simple and Compound Statements,If Statements,,Statements +@anchor{gnat-style simple-and-compound-statements}@anchor{c} +@section Simple and Compound Statements -@subsection Simple and Compound Statements -@c ------------------------------------------------------------------------- -@cindex Simple and compound statements -@itemize @bullet -@item + +@itemize * + +@item Use only one statement or label per line. -@item -A longer @syntax{sequence_of_statements} may be divided in logical + +@item +A longer sequence_of_statements may be divided in logical groups or separated from surrounding code using a blank line. @end itemize -@subsection If Statements -@c ------------------------------------------------------------------------- -@cindex @code{if} statement +@node If Statements,Case Statements,Simple and Compound Statements,Statements +@anchor{gnat-style if-statements}@anchor{d} +@section If Statements + -@itemize @bullet -@item + +@itemize * + +@item When the @code{if}, @code{elsif} or @code{else} keywords fit on the same line with the condition and the @code{then} keyword, then the statement is formatted as follows: -@cindex Alignment (in an @code{if} statement) - -@smallexample @c adanocomment -@group - if @var{condition} then - ... - elsif @var{condition} then - ... - else - ... - end if; -@end group -@end smallexample - -@noindent + +@geindex Alignment (in an if statement) + +@example +if condition then + ... +elsif condition then + ... +else + ... +end if; +@end example + When the above layout is not possible, @code{then} should be aligned with @code{if}, and conditions should preferably be split before an @code{and} or @code{or} keyword a follows: -@smallexample @c adanocomment -@group - if @var{long_condition_that_has_to_be_split} - and then @var{continued_on_the_next_line} - then - ... - end if; -@end group -@end smallexample - -@noindent +@example +if long_condition_that_has_to_be_split + and then continued_on_the_next_line +then + ... +end if; +@end example + The @code{elsif}, @code{else} and @code{end if} always line up with the @code{if} keyword. The preferred location for splitting the line is before @code{and} or @code{or}. The continuation of a condition is @@ -464,287 +492,280 @@ indented with two spaces or as many as needed to make nesting clear. As an exception, if conditions are closely related either of the following is allowed: -@smallexample -@group - if x = lakdsjfhlkashfdlkflkdsalkhfsalkdhflkjdsahf - or else - x = asldkjhalkdsjfhhfd - or else - x = asdfadsfadsf - then - ... - end if; -@end group - -@group - if x = lakdsjfhlkashfdlkflkdsalkhfsalkdhflkjdsahf or else - x = asldkjhalkdsjfhhfd or else - x = asdfadsfadsf - then - ... - end if; -@end group -@end smallexample - -@item -Conditions should use short-circuit forms (@code{and then}, -@code{or else}), except when the operands are boolean variables +@example +if x = lakdsjfhlkashfdlkflkdsalkhfsalkdhflkjdsahf + or else + x = asldkjhalkdsjfhhfd + or else + x = asdfadsfadsf +then + ... +end if; + +if x = lakdsjfhlkashfdlkflkdsalkhfsalkdhflkjdsahf or else + x = asldkjhalkdsjfhhfd or else + x = asdfadsfadsf +then + ... +end if; +@end example + +@item +Conditions should use short-circuit forms ( @code{and then}, +@code{or else} ), except when the operands are boolean variables or boolean constants. -@cindex Short-circuit forms -@item +@geindex Short-circuit forms + +@item Complex conditions in @code{if} statements are indented two characters: -@cindex Indentation (in @code{if} statements) - -@smallexample @c adanocomment -@group - if @var{this_complex_condition} - and then @var{that_other_one} - and then @var{one_last_one} - then - ... - end if; -@end group -@end smallexample - -@noindent + +@geindex Indentation (in if statements) + +@example +if this_complex_condition + and then that_other_one + and then one_last_one +then + ... +end if; +@end example + There are some cases where complex conditionals can be laid out in manners that do not follow these rules to preserve better parallelism between branches, e.g. -@smallexample @c adanocomment -@group - if xyz.abc (gef) = 'c' - or else - xyz.abc (gef) = 'x' - then - ... - end if; -@end group -@end smallexample +@example +if xyz.abc (gef) = 'c' + or else + xyz.abc (gef) = 'x' +then + ... +end if; +@end example - -@item +@item Every @code{if} block is preceded and followed by a blank line, except -where it begins or ends a @syntax{sequence_of_statements}. -@cindex Blank lines (in an @code{if} statement) +where it begins or ends a sequence_of_statements. + +@geindex Blank lines (in an if statement) -@smallexample @c adanocomment -@group - A := 5; +@example +A := 5; - if A = 5 then - null; - end if; +if A = 5 then + null; +end if; - A := 6; -@end group -@end smallexample +A := 6; +@end example @end itemize -@subsection Case Statements -@cindex @code{case} statements +@node Case Statements,Loop Statements,If Statements,Statements +@anchor{gnat-style case-statements}@anchor{e} +@section Case Statements + + + +@itemize * -@itemize @bullet -@item +@item Layout is as below. For long @code{case} statements, the extra indentation can be saved by aligning the @code{when} clauses with the opening @code{case}. -@smallexample @c adanocomment -@group - case @var{expression} is - when @var{condition} => - ... - when @var{condition} => - ... - end case; -@end group -@end smallexample +@example +case expression is + when condition => + ... + when condition => + ... +end case; +@end example @end itemize -@subsection Loop Statements -@cindex Loop statements +@node Loop Statements,Block Statements,Case Statements,Statements +@anchor{gnat-style loop-statements}@anchor{f} +@section Loop Statements + + -@itemize @bullet -@item +@itemize * + +@item When possible, have @code{for} or @code{while} on one line with the condition and the @code{loop} keyword. -@smallexample @c adanocomment -@group - for J in S'Range loop - ... - end loop; -@end group -@end smallexample - -@noindent -If the condition is too long, split the condition (see ``If -statements'' above) and align @code{loop} with the @code{for} or +@example +for J in S'Range loop + ... +end loop; +@end example + +If the condition is too long, split the condition (see ‘If +statements’ above) and align @code{loop} with the @code{for} or @code{while} keyword. -@cindex Alignment (in a loop statement) - -@smallexample @c adanocomment -@group - while @var{long_condition_that_has_to_be_split} - and then @var{continued_on_the_next_line} - loop - ... - end loop; -@end group -@end smallexample - -@noindent -If the @syntax{loop_statement} has an identifier, it is laid out as follows: - -@smallexample @c adanocomment -@group - Outer : while not @var{condition} loop - ... - end Outer; -@end group -@end smallexample + +@geindex Alignment (in a loop statement) + +@example +while long_condition_that_has_to_be_split + and then continued_on_the_next_line +loop + ... +end loop; +@end example + +If the loop_statement has an identifier, it is laid out as follows: + +@example +Outer : while not condition loop + ... +end Outer; +@end example @end itemize -@subsection Block Statements -@cindex Block statement +@node Block Statements,,Loop Statements,Statements +@anchor{gnat-style block-statements}@anchor{10} +@section Block Statements + + + +@itemize * -@itemize @bullet -@item +@item The @code{declare} (optional), @code{begin} and @code{end} words -are aligned, except when the @syntax{block_statement} is named. There +are aligned, except when the block_statement is named. There is a blank line before the @code{begin} keyword: -@cindex Alignment (in a block statement) -@smallexample @c adanocomment -@group - Some_Block : declare - ... +@geindex Alignment (in a block statement) - begin - ... - end Some_Block; -@end group -@end smallexample +@example +Some_Block : declare + ... +begin + ... +end Some_Block; +@end example @end itemize -@c ------------------------------------------------------------------------- -@node Subprograms, Packages, Statements, Top -@section Subprograms -@c ------------------------------------------------------------------------- -@cindex Subprograms +@node Subprograms,Packages and Visibility Rules,Statements,Top +@anchor{gnat-style subprograms}@anchor{11} +@chapter Subprograms -@subsection Subprogram Declarations -@c ------------------------------------------------------------------------- -@itemize @bullet -@item +@menu +* Subprogram Declarations:: +* Subprogram Bodies:: + +@end menu + +@node Subprogram Declarations,Subprogram Bodies,,Subprograms +@anchor{gnat-style subprogram-declarations}@anchor{12} +@section Subprogram Declarations + + + +@itemize * + +@item Do not write the @code{in} for parameters. -@smallexample @c adanocomment - function Length (S : String) return Integer; -@end smallexample +@example +function Length (S : String) return Integer; +@end example -@item +@item When the declaration line for a procedure or a function is too long to fit the entire declaration (including the keyword procedure or function) on a single line, then fold it, putting a single parameter on a line, aligning the colons, as in: -@smallexample @c adanocomment -@group - procedure Set_Heading - (Source : String; - Count : Natural; - Pad : Character := Space; - Fill : Boolean := True); -@end group -@end smallexample - -@noindent +@example +procedure Set_Heading + (Source : String; + Count : Natural; + Pad : Character := Space; + Fill : Boolean := True); +@end example + In the case of a function, if the entire spec does not fit on one line, then the return may appear after the last parameter, as in: -@smallexample @c adanocomment -@group - function Head - (Source : String; - Count : Natural; - Pad : Character := Space) return String; -@end group -@end smallexample +@example +function Head + (Source : String; + Count : Natural; + Pad : Character := Space) return String; +@end example -@noindent Or it may appear on its own as a separate line. This form is preferred when putting the return on the same line as the last parameter would result in an overlong line. The return type may optionally be aligned with the types of the parameters (usually we do this aligning if it results only in a small -number of extra spaces, and otherwise we don't attempt to align). So two +number of extra spaces, and otherwise we don’t attempt to align). So two alternative forms for the above spec are: -@smallexample @c adanocomment -@group - function Head - (Source : String; - Count : Natural; - Pad : Character := Space) - return String; - - function Head - (Source : String; - Count : Natural; - Pad : Character := Space) - return String; -@end group -@end smallexample - +@example +function Head + (Source : String; + Count : Natural; + Pad : Character := Space) + return String; + +function Head + (Source : String; + Count : Natural; + Pad : Character := Space) + return String; +@end example @end itemize -@subsection Subprogram Bodies -@c ------------------------------------------------------------------------- -@cindex Subprogram bodies +@node Subprogram Bodies,,Subprogram Declarations,Subprograms +@anchor{gnat-style subprogram-bodies}@anchor{13} +@section Subprogram Bodies + + -@itemize @bullet -@item +@itemize * + +@item Function and procedure bodies should usually be sorted alphabetically. Do not attempt to sort them in some logical order by functionality. For a sequence of subprogram specs, a general alphabetical sorting is also usually appropriate, but occasionally it makes sense to group by major function, with appropriate headers. -@item +@item All subprograms have a header giving the function name, with the following format: -@smallexample @c adanocomment -@group - ----------------- - -- My_Function -- - ----------------- +@example +----------------- +-- My_Function -- +----------------- - procedure My_Function is - begin - ... - end My_Function; -@end group -@end smallexample +procedure My_Function is +begin + ... +end My_Function; +@end example -@noindent Note that the name in the header is preceded by a single space, not two spaces as for other comments. These headers are used on nested subprograms as well as outer level subprograms. They may also be used as headers for sections of comments, or collections of declarations that are related. -@item -Every subprogram body must have a preceding @syntax{subprogram_declaration}, +@item +Every subprogram body must have a preceding subprogram_declaration, which includes proper client documentation so that you do not need to read the subprogram body in order to understand what the subprogram does and how to call it. All subprograms should be documented, without exceptions. -@item -@cindex Blank lines (in subprogram bodies) +@geindex Blank lines (in subprogram bodies) + +@item A sequence of declarations may optionally be separated from the following begin by a blank line. Just as we optionally allow blank lines in general between declarations, this blank line should be present only if it improves @@ -752,22 +773,20 @@ readability. Generally we avoid this blank line if the declarative part is small (one or two lines) and the body has no blank lines, and we include it if the declarative part is long or if the body has blank lines. -@item +@item If the declarations in a subprogram contain at least one nested subprogram body, then just before the @code{begin} of the enclosing subprogram, there is a comment line and a blank line: -@smallexample @c adanocomment -@group - -- Start of processing for @var{Enclosing_Subprogram} +@example +-- Start of processing for Enclosing_Subprogram - begin - ... - end @var{Enclosing_Subprogram}; -@end group -@end smallexample +begin + ... +end Enclosing_Subprogram; +@end example -@item +@item When nested subprograms are present, variables that are referenced by any nested subprogram should precede the nested subprogram specs. For variables that are not referenced by nested procedures, the declarations can either also @@ -775,180 +794,646 @@ be before any of the nested subprogram specs (this is the old style, more generally used). Or then can come just before the begin, with a header. The following example shows the two possible styles: -@smallexample @c adanocomment -@group - procedure Style1 is - Var_Referenced_In_Nested : Integer; - Var_Referenced_Only_In_Style1 : Integer; - - proc Nested; - -- Comments ... - +@example +procedure Style1 is + Var_Referenced_In_Nested : Integer; + Var_Referenced_Only_In_Style1 : Integer; - ------------ - -- Nested -- - ------------ + proc Nested; + -- Comments ... - procedure Nested is - begin - ... - end Nested; + ------------ + -- Nested -- + ------------ - -- Start of processing for Style1 - - begin - ... - end Style1; + procedure Nested is + begin + ... + end Nested; -@end group +-- Start of processing for Style1 -@group - procedure Style2 is - Var_Referenced_In_Nested : Integer; +begin + ... +end Style1; - proc Nested; - -- Comments ... +procedure Style2 is + Var_Referenced_In_Nested : Integer; - ------------ - -- Nested -- - ------------ + proc Nested; + -- Comments ... - procedure Nested is - begin - ... - end Nested; + ------------ + -- Nested -- + ------------ - -- Local variables + procedure Nested is + begin + ... + end Nested; - Var_Referenced_Only_In_Style2 : Integer; + -- Local variables - -- Start of processing for Style2 + Var_Referenced_Only_In_Style2 : Integer; - begin - ... - end Style2; +-- Start of processing for Style2 -@end group -@end smallexample +begin + ... +end Style2; +@end example -@noindent For new code, we generally prefer Style2, but we do not insist on modifying all legacy occurrences of Style1, which is still much more common in the sources. - @end itemize +@node Packages and Visibility Rules,Program Structure and Compilation Issues,Subprograms,Top +@anchor{gnat-style packages-and-visibility-rules}@anchor{14} +@chapter Packages and Visibility Rules + -@c ------------------------------------------------------------------------- -@node Packages, Program Structure, Subprograms, Top -@section Packages and Visibility Rules -@c ------------------------------------------------------------------------- -@cindex Packages -@itemize @bullet -@item +@itemize * + +@item All program units and subprograms have their name at the end: -@smallexample @c adanocomment -@group - package P is - ... - end P; -@end group -@end smallexample +@example +package P is + ... +end P; +@end example -@item -We will use the style of @code{use}-ing @code{with}-ed packages, with +@item +We will use the style of @code{use} -ing @code{with} -ed packages, with the context clauses looking like: -@cindex @code{use} clauses -@smallexample @c adanocomment -@group - with A; use A; - with B; use B; -@end group -@end smallexample +@geindex use clauses + +@example +with A; use A; +with B; use B; +@end example -@item +@item Names declared in the visible part of packages should be -unique, to prevent name clashes when the packages are @code{use}d. -@cindex Name clash avoidance - -@smallexample @c adanocomment -@group - package Entity is - type Entity_Kind is ...; - ... - end Entity; -@end group -@end smallexample - -@item +unique, to prevent name clashes when the packages are @code{use} d. + +@geindex Name clash avoidance + +@example +package Entity is + type Entity_Kind is ...; + ... +end Entity; +@end example + +@item After the file header comment, the context clause and unit specification -should be the first thing in a @syntax{program_unit}. +should be the first thing in a program_unit. -@item +@item Preelaborate, Pure and Elaborate_Body pragmas should be added right after the package name, indented an extra level and using the parameterless form: -@smallexample @c adanocomment -@group - package Preelaborate_Package is - pragma Preelaborate; - ... - end Preelaborate_Package; -@end group -@end smallexample - +@example +package Preelaborate_Package is + pragma Preelaborate; + ... +end Preelaborate_Package; +@end example @end itemize -@c ------------------------------------------------------------------------- -@node Program Structure, GNU Free Documentation License, Packages, Top -@section Program Structure and Compilation Issues -@c ------------------------------------------------------------------------- -@cindex Program structure +@node Program Structure and Compilation Issues,Index,Packages and Visibility Rules,Top +@anchor{gnat-style program-structure-and-compilation-issues}@anchor{15} +@chapter Program Structure and Compilation Issues -@itemize @bullet -@item -Every GNAT source file must be compiled with the @option{-gnatg} + + +@itemize * + +@item +Every GNAT source file must be compiled with the @code{-gnatg} switch to check the coding style. (Note that you should look at -@file{style.adb} to see the lexical rules enforced by -@option{-gnatg}). -@cindex @option{-gnatg} option (to gcc) -@cindex @file{style.adb} file +style.adb to see the lexical rules enforced by @code{-gnatg} ). + +@geindex -gnatg option (to gcc) + +@geindex style.adb file -@item +@item Each source file should contain only one compilation unit. -@item +@item Filenames should be 8 or fewer characters, followed by the @code{.adb} extension for a body or @code{.ads} for a spec. -@cindex File name length -@item -Unit names should be distinct when ``krunch''ed to 8 characters -(see @file{krunch.ads}) and the filenames should match the unit name, +@geindex File name length + +@item +Unit names should be distinct when ‘krunch’ed to 8 characters +(see krunch.ads) and the filenames should match the unit name, except that they are all lower case. -@cindex @file{krunch.ads} file + +@geindex krunch.ads file @end itemize +@menu +* GNU Free Documentation License:: + +@end menu -@c ********************************** -@c * GNU Free Documentation License * -@c ********************************** -@node GNU Free Documentation License,Index, Program Structure, Top -@unnumberedsec GNU Free Documentation License -@set nodefaultgnufreedocumentationlicensenode -@include fdl.texi -@c GNU Free Documentation License -@cindex GNU Free Documentation License +@node GNU Free Documentation License,,,Program Structure and Compilation Issues +@anchor{share/gnu_free_documentation_license doc}@anchor{16}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{17}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{18} +@section GNU Free Documentation License + + +Version 1.3, 3 November 2008 + +Copyright 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc +@indicateurl{http://fsf.org/} + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +@strong{Preamble} + +The purpose of this License is to make a manual, textbook, or other +functional and useful document “free” in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of “copyleft”, which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +@strong{1. APPLICABILITY AND DEFINITIONS} + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The @strong{Document}, below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as “@strong{you}”. You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A “@strong{Modified Version}” of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A “@strong{Secondary Section}” is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document’s overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (Thus, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The “@strong{Invariant Sections}” are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The “@strong{Cover Texts}” are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A “@strong{Transparent}” copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not “Transparent” is called @strong{Opaque}. + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The “@strong{Title Page}” means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, “Title Page” means +the text near the most prominent appearance of the work’s title, +preceding the beginning of the body of the text. + +The “@strong{publisher}” means any person or entity that distributes +copies of the Document to the public. + +A section “@strong{Entitled XYZ}” means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as “@strong{Acknowledgements}”, +“@strong{Dedications}”, “@strong{Endorsements}”, or “@strong{History}”.) +To “@strong{Preserve the Title}” +of such a section when you modify the Document means that it remains a +section “Entitled XYZ” according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +@strong{2. VERBATIM COPYING} + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + +@strong{3. COPYING IN QUANTITY} + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document’s license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + +@strong{4. MODIFICATIONS} + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + + +@enumerate A + +@item +Use in the Title Page (and on the covers, if any) a title distinct +from that of the Document, and from those of previous versions +(which should, if there were any, be listed in the History section +of the Document). You may use the same title as a previous version +if the original publisher of that version gives permission. + +@item +List on the Title Page, as authors, one or more persons or entities +responsible for authorship of the modifications in the Modified +Version, together with at least five of the principal authors of the +Document (all of its principal authors, if it has fewer than five), +unless they release you from this requirement. + +@item +State on the Title page the name of the publisher of the +Modified Version, as the publisher. + +@item +Preserve all the copyright notices of the Document. + +@item +Add an appropriate copyright notice for your modifications +adjacent to the other copyright notices. + +@item +Include, immediately after the copyright notices, a license notice +giving the public permission to use the Modified Version under the +terms of this License, in the form shown in the Addendum below. + +@item +Preserve in that license notice the full lists of Invariant Sections +and required Cover Texts given in the Document’s license notice. + +@item +Include an unaltered copy of this License. + +@item +Preserve the section Entitled “History”, Preserve its Title, and add +to it an item stating at least the title, year, new authors, and +publisher of the Modified Version as given on the Title Page. If +there is no section Entitled “History” in the Document, create one +stating the title, year, authors, and publisher of the Document as +given on its Title Page, then add an item describing the Modified +Version as stated in the previous sentence. + +@item +Preserve the network location, if any, given in the Document for +public access to a Transparent copy of the Document, and likewise +the network locations given in the Document for previous versions +it was based on. These may be placed in the “History” section. +You may omit a network location for a work that was published at +least four years before the Document itself, or if the original +publisher of the version it refers to gives permission. + +@item +For any section Entitled “Acknowledgements” or “Dedications”, +Preserve the Title of the section, and preserve in the section all +the substance and tone of each of the contributor acknowledgements +and/or dedications given therein. + +@item +Preserve all the Invariant Sections of the Document, +unaltered in their text and in their titles. Section numbers +or the equivalent are not considered part of the section titles. + +@item +Delete any section Entitled “Endorsements”. Such a section +may not be included in the Modified Version. + +@item +Do not retitle any existing section to be Entitled “Endorsements” +or to conflict in title with any Invariant Section. + +@item +Preserve any Warranty Disclaimers. +@end enumerate + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version’s license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled “Endorsements”, provided it contains +nothing but endorsements of your Modified Version by various +parties—for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + +@strong{5. COMBINING DOCUMENTS} + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled “History” +in the various original documents, forming one section Entitled +“History”; likewise combine any sections Entitled “Acknowledgements”, +and any sections Entitled “Dedications”. You must delete all sections +Entitled “Endorsements”. + +@strong{6. COLLECTIONS OF DOCUMENTS} + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + +@strong{7. AGGREGATION WITH INDEPENDENT WORKS} + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an “aggregate” if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation’s users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document’s Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + +@strong{8. TRANSLATION} + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled “Acknowledgements”, +“Dedications”, or “History”, the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + +@strong{9. TERMINATION} + +You may not copy, modify, sublicense, or distribute the Document +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, or distribute it is void, and +will automatically terminate your rights under this License. + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, receipt of a copy of some or all of the same material does +not give you any rights to use it. + +@strong{10. FUTURE REVISIONS OF THIS LICENSE} + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +@indicateurl{http://www.gnu.org/copyleft/}. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License “or any later version” applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. If the Document +specifies that a proxy can decide which future versions of this +License can be used, that proxy’s public statement of acceptance of a +version permanently authorizes you to choose that version for the +Document. + +@strong{11. RELICENSING} + +“Massive Multiauthor Collaboration Site” (or “MMC Site”) means any +World Wide Web server that publishes copyrightable works and also +provides prominent facilities for anybody to edit those works. A +public wiki that anybody can edit is an example of such a server. A +“Massive Multiauthor Collaboration” (or “MMC”) contained in the +site means any set of copyrightable works thus published on the MMC +site. + +“CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 +license published by Creative Commons Corporation, a not-for-profit +corporation with a principal place of business in San Francisco, +California, as well as future copyleft versions of that license +published by that same organization. + +“Incorporate” means to publish or republish a Document, in whole or +in part, as part of another Document. + +An MMC is “eligible for relicensing” if it is licensed under this +License, and if all works that were first published under this License +somewhere other than this MMC, and subsequently incorporated in whole +or in part into the MMC, (1) had no cover texts or invariant sections, +and (2) were thus incorporated prior to November 1, 2008. + +The operator of an MMC Site may republish an MMC contained in the site +under CC-BY-SA on the same site at any time before August 1, 2009, +provided the MMC is eligible for relicensing. + +@strong{ADDENDUM: How to use this License for your documents} + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + +@quotation + +Copyright © YEAR YOUR NAME. +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 +or any later version published by the Free Software Foundation; +with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +A copy of the license is included in the section entitled “GNU +Free Documentation License”. +@end quotation -@node Index,,GNU Free Documentation License, Top -@unnumberedsec Index +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the “with … Texts.” line with this: -@printindex cp +@quotation + +with the Invariant Sections being LIST THEIR TITLES, with the +Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. +@end quotation + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. + +@node Index,,Program Structure and Compilation Issues,Top +@unnumbered Index + + +@printindex ge -@contents +@c %**end of body @bye diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 79f8bb3..14b03c4 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -3,7 +3,7 @@ @setfilename gnat_rm.info @documentencoding UTF-8 @ifinfo -@*Generated by Sphinx 1.4.6.@* +@*Generated by Sphinx 4.0.2.@* @end ifinfo @settitle GNAT Reference Manual @defindex ge @@ -21,7 +21,7 @@ @copying @quotation -GNAT Reference Manual , Apr 12, 2021 +GNAT Reference Manual , Jun 23, 2021 AdaCore @@ -58,8 +58,8 @@ AdaCore Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no -Invariant Sections, with the Front-Cover Texts being "GNAT Reference -Manual", and with no Back-Cover Texts. A copy of the license is +Invariant Sections, with the Front-Cover Texts being “GNAT Reference +Manual”, and with no Back-Cover Texts. A copy of the license is included in the section entitled @ref{1,,GNU Free Documentation License}. @menu @@ -320,7 +320,7 @@ Implementation Defined Aspects * Aspect Initializes:: * Aspect Inline_Always:: * Aspect Invariant:: -* Aspect Invariant'Class:: +* Aspect Invariant’Class:: * Aspect Iterable:: * Aspect Linker_Section:: * Aspect Lock_Free:: @@ -557,7 +557,7 @@ Implementation Advice * RM 3.5.5(8); Enumeration Values: RM 3 5 5 8 Enumeration Values. * RM 3.5.7(17); Float Types: RM 3 5 7 17 Float Types. * RM 3.6.2(11); Multidimensional Arrays: RM 3 6 2 11 Multidimensional Arrays. -* RM 9.6(30-31); Duration'Small: RM 9 6 30-31 Duration'Small. +* RM 9.6(30-31); Duration’Small: RM 9 6 30-31 Duration’Small. * RM 10.2.1(12); Consistent Representation: RM 10 2 1 12 Consistent Representation. * RM 11.4.1(19); Exception Information: RM 11 4 1 19 Exception Information. * RM 11.5(28); Suppression of Checks: RM 11 5 28 Suppression of Checks. @@ -913,7 +913,7 @@ Implementation-dependent characteristics @end menu @node About This Guide,Implementation Defined Pragmas,Top,Top -@anchor{gnat_rm/about_this_guide about-this-guide}@anchor{2}@anchor{gnat_rm/about_this_guide doc}@anchor{3}@anchor{gnat_rm/about_this_guide gnat-reference-manual}@anchor{4}@anchor{gnat_rm/about_this_guide id1}@anchor{5} +@anchor{gnat_rm/about_this_guide doc}@anchor{2}@anchor{gnat_rm/about_this_guide about-this-guide}@anchor{3}@anchor{gnat_rm/about_this_guide gnat-reference-manual}@anchor{4}@anchor{gnat_rm/about_this_guide id1}@anchor{5} @chapter About This Guide @@ -928,8 +928,8 @@ invoked in Ada 83 compatibility mode. By default, GNAT assumes Ada 2012, but you can override with a compiler switch to explicitly specify the language version. -(Please refer to the @emph{GNAT User's Guide} for details on these switches.) -Throughout this manual, references to 'Ada' without a year suffix +(Please refer to the @emph{GNAT User’s Guide} for details on these switches.) +Throughout this manual, references to ‘Ada’ without a year suffix apply to all the Ada versions of the language. Ada is designed to be highly portable. @@ -1002,7 +1002,7 @@ of representation clauses and pragmas that is accepted. @item @ref{e,,Standard Library Routines}, provides a listing of packages and a -brief description of the functionality that is provided by Ada's +brief description of the functionality that is provided by Ada’s extensive set of standard library routines as implemented by GNAT. @item @@ -1024,7 +1024,7 @@ of the specialized needs annexes. @item @ref{13,,Implementation of Specific Ada Features}, discusses issues related -to GNAT's implementation of machine code insertions, tasking, and several +to GNAT’s implementation of machine code insertions, tasking, and several other features. @item @@ -1118,7 +1118,7 @@ See the following documents for further information on GNAT: @itemize * @item -@cite{GNAT User's Guide for Native Platforms}, +@cite{GNAT User’s Guide for Native Platforms}, which provides information on how to use the GNAT development environment. @@ -1154,7 +1154,7 @@ compiler system. @end itemize @node Implementation Defined Pragmas,Implementation Defined Aspects,About This Guide,Top -@anchor{gnat_rm/implementation_defined_pragmas implementation-defined-pragmas}@anchor{7}@anchor{gnat_rm/implementation_defined_pragmas doc}@anchor{19}@anchor{gnat_rm/implementation_defined_pragmas id1}@anchor{1a} +@anchor{gnat_rm/implementation_defined_pragmas doc}@anchor{19}@anchor{gnat_rm/implementation_defined_pragmas id1}@anchor{1a}@anchor{gnat_rm/implementation_defined_pragmas implementation-defined-pragmas}@anchor{7} @chapter Implementation Defined Pragmas @@ -1412,7 +1412,7 @@ end; @end example @node Pragma Abstract_State,Pragma Ada_83,Pragma Abort_Defer,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-abstract-state}@anchor{1c}@anchor{gnat_rm/implementation_defined_pragmas id2}@anchor{1d} +@anchor{gnat_rm/implementation_defined_pragmas id2}@anchor{1c}@anchor{gnat_rm/implementation_defined_pragmas pragma-abstract-state}@anchor{1d} @section Pragma Abstract_State @@ -1664,7 +1664,7 @@ rather than rejected to allow common sets of sources to be used in the two situations. @node Pragma Annotate,Pragma Assert,Pragma Allow_Integer_Address,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-annotate}@anchor{26}@anchor{gnat_rm/implementation_defined_pragmas id3}@anchor{27} +@anchor{gnat_rm/implementation_defined_pragmas id3}@anchor{26}@anchor{gnat_rm/implementation_defined_pragmas pragma-annotate}@anchor{27} @section Pragma Annotate @@ -1849,7 +1849,7 @@ The pragma applies in both cases to pragmas and aspects with matching names, e.g. @code{Pre} applies to the Pre aspect, and @code{Precondition} applies to both the @code{Precondition} pragma and the aspect @code{Precondition}. Note that the identifiers for -pragmas Pre_Class and Post_Class are Pre'Class and Post'Class (not +pragmas Pre_Class and Post_Class are Pre’Class and Post’Class (not Pre_Class and Post_Class), since these pragmas are intended to be identical to the corresponding aspects). @@ -1866,7 +1866,7 @@ The implementation defined policy @code{DISABLE} is like @code{IGNORE} except that it completely disables semantic checking of the corresponding pragma or aspect. This is useful when the pragma or aspect argument references subprograms -in a with'ed package which is replaced by a dummy package +in a with’ed package which is replaced by a dummy package for the final build. The implementation defined assertion kind @code{Assertions} applies to all @@ -1966,7 +1966,7 @@ is erroneous so there are no guarantees that this will always be the case, and it is recommended that these two options not be used together. @node Pragma Async_Readers,Pragma Async_Writers,Pragma Assume_No_Invalid_Values,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-async-readers}@anchor{2d}@anchor{gnat_rm/implementation_defined_pragmas id4}@anchor{2e} +@anchor{gnat_rm/implementation_defined_pragmas id4}@anchor{2d}@anchor{gnat_rm/implementation_defined_pragmas pragma-async-readers}@anchor{2e} @section Pragma Async_Readers @@ -2124,13 +2124,13 @@ This implementation permission accommodates the notion of infinities in IEEE floating-point, and corresponds to the efficient execution mode on most machines. GNAT will not raise overflow exceptions on these machines; instead it will generate -infinities and NaN's as defined in the IEEE standard. +infinities and NaN’s as defined in the IEEE standard. Generating infinities, although efficient, is not always desirable. Often the preferable approach is to check for overflow, even at the (perhaps considerable) expense of run-time performance. -This can be accomplished by defining your own constrained floating-point subtypes -- i.e., by supplying explicit -range constraints -- and indeed such a subtype +This can be accomplished by defining your own constrained floating-point subtypes – i.e., by supplying explicit +range constraints – and indeed such a subtype can have the same base range as its base type. For example: @example @@ -2326,7 +2326,7 @@ indicating that the necessary attribute for implementation of this pragma is not available. @node Pragma Compile_Time_Error,Pragma Compile_Time_Warning,Pragma Common_Object,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-compile-time-error}@anchor{39}@anchor{gnat_rm/implementation_defined_pragmas compile-time-error}@anchor{3a} +@anchor{gnat_rm/implementation_defined_pragmas compile-time-error}@anchor{39}@anchor{gnat_rm/implementation_defined_pragmas pragma-compile-time-error}@anchor{3a} @section Pragma Compile_Time_Error @@ -2369,8 +2369,8 @@ of an error message. If switch @emph{-gnatw_C} is used, a warning is only issued if the value of the expression is known to be True at compile time, not when the value of the expression is not known at compile time. Note that if this pragma is used in a package that -is with'ed by a client, the client will get the warning even though it -is issued by a with'ed package (normally warnings in with'ed units are +is with’ed by a client, the client will get the warning even though it +is issued by a with’ed package (normally warnings in with’ed units are suppressed, but this is a special exception to that rule). One typical use is within a generic where compile time known characteristics @@ -2380,7 +2380,7 @@ for example that it is not fully implemented. In previous versions of the compiler, combining @emph{-gnatwe} with Compile_Time_Warning resulted in a fatal error. Now the compiler always emits -a warning. You can use @ref{3a,,Pragma Compile_Time_Error} to force the generation of +a warning. You can use @ref{39,,Pragma Compile_Time_Error} to force the generation of an error. @node Pragma Compiler_Unit,Pragma Compiler_Unit_Warning,Pragma Compile_Time_Warning,Implementation Defined Pragmas @@ -2744,13 +2744,13 @@ must be of one of the following forms: @strong{function} @code{Fname} @strong{return} T` @item -@strong{function} @code{Fname} @strong{return} T'Class +@strong{function} @code{Fname} @strong{return} T’Class @item -@strong{function} @code{Fname} (...) @strong{return} T` +@strong{function} @code{Fname} (…) @strong{return} T` @item -@strong{function} @code{Fname} (...) @strong{return} T'Class +@strong{function} @code{Fname} (…) @strong{return} T’Class @end itemize where @code{T} is a limited record type imported from C++ with pragma @@ -2759,7 +2759,7 @@ where @code{T} is a limited record type imported from C++ with pragma The first two forms import the default constructor, used when an object of type @code{T} is created on the Ada side with no explicit constructor. The latter two forms cover all the non-default constructors of the type. -See the GNAT User's Guide for details. +See the GNAT User’s Guide for details. If no constructors are imported, it is impossible to create any objects on the Ada side and the type is implicitly declared abstract. @@ -2984,7 +2984,7 @@ versions of Ada as an implementation-defined pragma. See Ada 2012 Reference Manual for details. @node Pragma Depends,Pragma Detect_Blocking,Pragma Default_Storage_Pool,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-depends}@anchor{53}@anchor{gnat_rm/implementation_defined_pragmas id9}@anchor{54} +@anchor{gnat_rm/implementation_defined_pragmas id9}@anchor{53}@anchor{gnat_rm/implementation_defined_pragmas pragma-depends}@anchor{54} @section Pragma Depends @@ -3118,7 +3118,7 @@ pragma Elaboration_Checks (Dynamic | Static); This is a configuration pragma which specifies the elaboration model to be used during compilation. For more information on the elaboration models of -GNAT, consult the chapter on elaboration order handling in the @emph{GNAT User's +GNAT, consult the chapter on elaboration order handling in the @emph{GNAT User’s Guide}. The pragma may appear in the following contexts: @@ -3130,7 +3130,7 @@ The pragma may appear in the following contexts: Configuration pragmas file @item -Prior to the context clauses of a compilation unit's initial declaration +Prior to the context clauses of a compilation unit’s initial declaration @end itemize Any other placement of the pragma will result in a warning and the effects of @@ -3585,7 +3585,7 @@ definition. Note that such a package is a child of @code{System} and thus is considered part of the implementation. To compile it you will have to use the @emph{-gnatg} switch for compiling System units, as explained in the -GNAT User's Guide. +GNAT User’s Guide. @node Pragma Extensions_Allowed,Pragma Extensions_Visible,Pragma Extend_System,Implementation Defined Pragmas @anchor{gnat_rm/implementation_defined_pragmas pragma-extensions-allowed}@anchor{64} @@ -3662,7 +3662,7 @@ Casing on composite values (aka pattern matching) The selector for a case statement may be of a composite type, subject to some restrictions (described below). Aggregate syntax is used for choices -of such a case statement; however, in cases where a "normal" aggregate would +of such a case statement; however, in cases where a “normal” aggregate would require a discrete value, a discrete subtype may be used instead; box notation can also be used to match all values (but currently only for discrete subcomponents). @@ -3694,7 +3694,7 @@ then Do_That will be called; otherwise, Do_The_Other_Thing will be called. If the set of values that match the choice(s) of an earlier alternative overlaps the corresponding set of a later alternative, then the first set shall be a proper subset of the second (and the later alternative -will not be executed if the earlier alternative "matches"). All possible +will not be executed if the earlier alternative “matches”). All possible values of the composite type shall be covered. The composite type of the selector shall be a nonlimited untagged undiscriminated record type, all of whose subcomponent subtypes are either static discrete subtypes or @@ -3705,7 +3705,7 @@ In addition, pattern bindings are supported. This is a mechanism for binding a name to a component of a matching value for use within an alternative of a case statement. For a component association that occurs within a case choice, the expression may be followed by -"is ". In the special case of a "box" component association, +“is ”. In the special case of a “box” component association, the identifier may instead be provided within the box. Either of these indicates that the given identifer denotes (a constant view of) the matching subcomponent of the case selector. @@ -3750,7 +3750,7 @@ Fixed lower bounds for array types and subtypes Unconstrained array types and subtypes can be specified with a lower bound that is fixed to a certain value, by writing an index range that uses the -syntax " .. <>". This guarantees that all objects +syntax “ .. <>”. This guarantees that all objects of the type or subtype will have the specified lower bound. For example, a matrix type with fixed lower bounds of zero for each @@ -3780,7 +3780,7 @@ subtype String_1 is String (1 .. <>); @end quotation If a string slice is passed to a formal of subtype String_1 in a call to -a subprogram S, the slice's bounds will "slide" so that the lower bound +a subprogram S, the slice’s bounds will “slide” so that the lower bound is 1. Within S, the lower bound of the formal is known to be 1, so, unlike a normal unconstrained String formal, there is no need to worry about accounting for other possible lower-bound values. Sliding of bounds also @@ -3790,7 +3790,7 @@ conversions. Use of this feature increases safety by simplifying code, and can also improve the efficiency of indexing operations, since the compiler statically -knows the lower bound of unconstrained array formals when the formal's +knows the lower bound of unconstrained array formals when the formal’s subtype has index ranges with static fixed lower bounds. @end itemize @@ -4022,7 +4022,7 @@ No other value of digits is permitted. @end itemize @node Pragma Ghost,Pragma Global,Pragma Float_Representation,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-ghost}@anchor{6e}@anchor{gnat_rm/implementation_defined_pragmas id14}@anchor{6f} +@anchor{gnat_rm/implementation_defined_pragmas id14}@anchor{6e}@anchor{gnat_rm/implementation_defined_pragmas pragma-ghost}@anchor{6f} @section Pragma Ghost @@ -4036,7 +4036,7 @@ For the semantics of this pragma, see the entry for aspect @code{Ghost} in the S 2014 Reference Manual, section 6.9. @node Pragma Global,Pragma Ident,Pragma Ghost,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-global}@anchor{70}@anchor{gnat_rm/implementation_defined_pragmas id15}@anchor{71} +@anchor{gnat_rm/implementation_defined_pragmas id15}@anchor{70}@anchor{gnat_rm/implementation_defined_pragmas pragma-global}@anchor{71} @section Pragma Global @@ -4165,7 +4165,7 @@ By_Entry guarantees that the action of requeueing will proceed from an entry to another entry. Implementation kind By_Protected_Procedure transforms the requeue into a dispatching call, thus eliminating the chance of blocking. Kind By_Any shares the behavior of By_Entry and By_Protected_Procedure depending on -the target's overriding subprogram kind. +the target’s overriding subprogram kind. @node Pragma Implicit_Packing,Pragma Import_Function,Pragma Implemented,Implementation Defined Pragmas @anchor{gnat_rm/implementation_defined_pragmas pragma-implicit-packing}@anchor{76} @@ -4544,14 +4544,14 @@ Initialization with low values. Initialization with a specific bit pattern. @end itemize -See the GNAT User's Guide for binder options for specifying these cases. +See the GNAT User’s Guide for binder options for specifying these cases. The bind-time approach is intended to provide fast turnaround for testing with different values, without having to recompile the program. @item At execution time, the programmer can specify the invalid values using an -environment variable. See the GNAT User's Guide for details. +environment variable. See the GNAT User’s Guide for details. The execution-time approach is intended to provide fast turnaround for testing with different values, without having to recompile and rebind the @@ -4561,7 +4561,7 @@ program. Note that pragma @code{Initialize_Scalars} is particularly useful in conjunction with the enhanced validity checking that is now provided in GNAT, which checks for invalid values under more conditions. Using this feature (see description -of the @emph{-gnatV} flag in the GNAT User's Guide) in conjunction with pragma +of the @emph{-gnatV} flag in the GNAT User’s Guide) in conjunction with pragma @code{Initialize_Scalars} provides a powerful new tool to assist in the detection of problems caused by uninitialized variables. @@ -4569,10 +4569,10 @@ Note: the use of @code{Initialize_Scalars} has a fairly extensive effect on the generated code. This may cause your code to be substantially larger. It may also cause an increase in the amount of stack required, so it is probably a good idea to turn on stack checking (see description of stack checking in the -GNAT User's Guide) when using this pragma. +GNAT User’s Guide) when using this pragma. @node Pragma Initializes,Pragma Inline_Always,Pragma Initialize_Scalars,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-initializes}@anchor{80}@anchor{gnat_rm/implementation_defined_pragmas id17}@anchor{81} +@anchor{gnat_rm/implementation_defined_pragmas id17}@anchor{80}@anchor{gnat_rm/implementation_defined_pragmas pragma-initializes}@anchor{81} @section Pragma Initializes @@ -4778,7 +4778,7 @@ operating system documentation, or the value of the array @code{Reserved} declared in the spec of package @code{System.OS_Interface}. Overriding the default state of signals used by the Ada runtime may interfere -with an application's runtime behavior in the cases of the synchronous signals, +with an application’s runtime behavior in the cases of the synchronous signals, and in the case of the signal used to implement the @code{abort} statement. @node Pragma Invariant,Pragma Keep_Names,Pragma Interrupt_State,Implementation Defined Pragmas @@ -4813,7 +4813,7 @@ is violated. If no Message parameter is provided, a default message that identifies the line on which the pragma appears is used. It is permissible to have multiple Invariants for the same type entity, in -which case they are and'ed together. It is permissible to use this pragma +which case they are and’ed together. It is permissible to use this pragma in Ada 2012 mode, but you cannot have both an invariant aspect and an invariant pragma for the same entity. @@ -4897,13 +4897,13 @@ are recognized, and license information is derived from them as follows. A GNAT license header starts with a line containing 78 hyphens. The following comment text is searched for the appearance of any of the following strings. -If the string 'GNU General Public License' is found, then the unit is assumed -to have GPL license, unless the string 'As a special exception' follows, in +If the string ‘GNU General Public License’ is found, then the unit is assumed +to have GPL license, unless the string ‘As a special exception’ follows, in which case the license is assumed to be modified GPL. If one of the strings -'This specification is adapted from the Ada Semantic Interface' or -'This specification is derived from the Ada Reference Manual' is found +‘This specification is adapted from the Ada Semantic Interface’ or +‘This specification is derived from the Ada Reference Manual’ is found then the unit is assumed to be unrestricted. These default actions means that a program with a restricted license pragma @@ -5071,7 +5071,7 @@ declared at the library level. This pragma specifies the name of the linker section for the given entity. It is equivalent to @code{__attribute__((section))} in GNU C and causes @code{LOCAL_NAME} to be placed in the @code{static_string_EXPRESSION} section of the -executable (assuming the linker doesn't rename the section). +executable (assuming the linker doesn’t rename the section). GNAT also provides an implementation defined aspect of the same name. In the case of specifying this aspect for a type, the effect is to @@ -5199,7 +5199,7 @@ except that in an @code{Assertion_Policy} pragma, the identifier of statements of a loop body, or nested inside block statements that appear in the sequence of statements of a loop body. The intention is that it be used to -represent a "loop invariant" assertion, i.e. something that is true each +represent a “loop invariant” assertion, i.e. something that is true each time through the loop, and which can be used to show that the loop is achieving its purpose. @@ -5339,7 +5339,7 @@ Machine-dependent attributes can be specified for types and/or declarations. This pragma is semantically equivalent to @code{__attribute__((@emph{attribute_name}))} (if @code{info} is not specified) or @code{__attribute__((@emph{attribute_name(info})))} -or @code{__attribute__((@emph{attribute_name(info,...})))} in GNU C, +or @code{__attribute__((@emph{attribute_name(info,…})))} in GNU C, where @emph{attribute_name} is recognized by the compiler middle-end or the @code{TARGET_ATTRIBUTE_TABLE} machine specific macro. Note that a string literal for the optional parameter @code{info} or the @@ -5428,7 +5428,7 @@ dummy body with a No_Body pragma ensures that there is no interference from earlier versions of the package body. @node Pragma No_Caching,Pragma No_Component_Reordering,Pragma No_Body,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-no-caching}@anchor{9e}@anchor{gnat_rm/implementation_defined_pragmas id23}@anchor{9f} +@anchor{gnat_rm/implementation_defined_pragmas id23}@anchor{9e}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-caching}@anchor{9f} @section Pragma No_Caching @@ -5475,7 +5475,7 @@ This is a program unit pragma (there is also an equivalent aspect of the same name) that establishes the restriction @code{No_Elaboration_Code} for the current unit and any extended main source units (body and subunits). It also has the effect of enforcing a transitive application of this -aspect, so that if any unit is implicitly or explicitly with'ed by the +aspect, so that if any unit is implicitly or explicitly with’ed by the current unit, it must also have the No_Elaboration_Code_All aspect set. It may be applied to package or subprogram specs or their generic versions. @@ -5574,12 +5574,12 @@ arguments is a configuration pragma which applies to all access types declared in units to which the pragma applies. For a detailed description of the strict aliasing optimization, and the situations in which it must be suppressed, see the section on Optimization and Strict Aliasing -in the @cite{GNAT User's Guide}. +in the @cite{GNAT User’s Guide}. This pragma currently has no effects on access to unconstrained array types. @node Pragma No_Tagged_Streams,Pragma Normalize_Scalars,Pragma No_Strict_Aliasing,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-no-tagged-streams}@anchor{a8}@anchor{gnat_rm/implementation_defined_pragmas id26}@anchor{a9} +@anchor{gnat_rm/implementation_defined_pragmas id26}@anchor{a8}@anchor{gnat_rm/implementation_defined_pragmas pragma-no-tagged-streams}@anchor{a9} @section Pragma No_Tagged_Streams @@ -5639,14 +5639,14 @@ are as follows: @item @emph{Standard.Character} Objects whose root type is Standard.Character are initialized to -Character'Last unless the subtype range excludes NUL (in which case +Character’Last unless the subtype range excludes NUL (in which case NUL is used). This choice will always generate an invalid value if one exists. @item @emph{Standard.Wide_Character} Objects whose root type is Standard.Wide_Character are initialized to -Wide_Character'Last unless the subtype range excludes NUL (in which case +Wide_Character’Last unless the subtype range excludes NUL (in which case NUL is used). This choice will always generate an invalid value if one exists. @@ -5700,7 +5700,7 @@ will always generate an invalid value if one exists. @end table @node Pragma Obsolescent,Pragma Optimize_Alignment,Pragma Normalize_Scalars,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-obsolescent}@anchor{ab}@anchor{gnat_rm/implementation_defined_pragmas id27}@anchor{ac} +@anchor{gnat_rm/implementation_defined_pragmas id27}@anchor{ab}@anchor{gnat_rm/implementation_defined_pragmas pragma-obsolescent}@anchor{ac} @section Pragma Obsolescent @@ -5971,7 +5971,7 @@ template can be instantiated for both cases), so we never generate warnings for the case of generic enumerated types. For additional information please refer to the description of the -@emph{-gnatw.u} switch in the GNAT User's Guide. +@emph{-gnatw.u} switch in the GNAT User’s Guide. @node Pragma Overflow_Mode,Pragma Overriding_Renamings,Pragma Ordered,Implementation Defined Pragmas @anchor{gnat_rm/implementation_defined_pragmas pragma-overflow-mode}@anchor{af} @@ -5990,8 +5990,8 @@ MODE ::= STRICT | MINIMIZED | ELIMINATED This pragma sets the current overflow mode to the given setting. For details of the meaning of these modes, please refer to the -'Overflow Check Handling in GNAT' appendix in the -GNAT User's Guide. If only the @code{General} parameter is present, +‘Overflow Check Handling in GNAT’ appendix in the +GNAT User’s Guide. If only the @code{General} parameter is present, the given mode applies to all expressions. If both parameters are present, the @code{General} mode applies to expressions outside assertions, and the @code{Eliminated} mode applies to expressions within assertions. @@ -6102,7 +6102,7 @@ optimized. GNAT does not attempt to optimize any tasks in this manner (since protected objects are available in place of passive tasks). For more information on the subject of passive tasks, see the section -'Passive Task Optimization' in the GNAT Users Guide. +‘Passive Task Optimization’ in the GNAT Users Guide. @node Pragma Persistent_BSS,Pragma Post,Pragma Passive,Implementation Defined Pragmas @anchor{gnat_rm/implementation_defined_pragmas id29}@anchor{b5}@anchor{gnat_rm/implementation_defined_pragmas pragma-persistent-bss}@anchor{b6} @@ -6186,7 +6186,7 @@ implicit returns at the end of procedure bodies and associated exception handlers). In addition, the boolean expression which is the condition which -must be true may contain references to function'Result in the case +must be true may contain references to function’Result in the case of a function to refer to the returned value. @code{Postcondition} pragmas may appear either immediately following the @@ -6253,7 +6253,7 @@ If a postcondition fails, then the exception a message argument was supplied, then the given string will be used as the exception message. If no message argument was supplied, then the default message has -the form "Postcondition failed at file_name:line". The +the form “Postcondition failed at file_name:line”. The exception is raised in the context of the subprogram body, so it is possible to catch postcondition failures within the subprogram body itself. @@ -6393,11 +6393,11 @@ pragma Rename_Pragma ( Renamed => Inline_Always); @end example -Then GNAT will treat "pragma Inline_Only ..." as if you had written -"pragma Inline_Always ...". +Then GNAT will treat “pragma Inline_Only …” as if you had written +“pragma Inline_Always …”. Pragma Inline_Only will not necessarily mean the same thing as the other Ada -compiler; it's up to you to make sure the semantics are close enough. +compiler; it’s up to you to make sure the semantics are close enough. @node Pragma Pre,Pragma Precondition,Pragma Rename_Pragma,Implementation Defined Pragmas @anchor{gnat_rm/implementation_defined_pragmas pragma-pre}@anchor{bb} @@ -6445,7 +6445,7 @@ pragma Precondition ( The @code{Precondition} pragma is similar to @code{Postcondition} except that the corresponding checks take place immediately upon entry to the subprogram, and if a precondition fails, the exception -is raised in the context of the caller, and the attribute 'Result +is raised in the context of the caller, and the attribute ‘Result cannot be used within the precondition expression. Otherwise, the placement and visibility rules are identical to those @@ -6484,7 +6484,7 @@ Ada 2012, and has been retained in its original form for compatibility purposes. @node Pragma Predicate,Pragma Predicate_Failure,Pragma Precondition,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-predicate}@anchor{bd}@anchor{gnat_rm/implementation_defined_pragmas id30}@anchor{be} +@anchor{gnat_rm/implementation_defined_pragmas id30}@anchor{bd}@anchor{gnat_rm/implementation_defined_pragmas pragma-predicate}@anchor{be} @section Pragma Predicate @@ -6529,7 +6529,7 @@ the program and thus do not have a neutral effect if ignored. The motivation behind providing pragmas equivalent to corresponding aspects is to allow a program to be written using the pragmas, and then compiled with a compiler that -will ignore the pragmas. That doesn't work in the case of +will ignore the pragmas. That doesn’t work in the case of static and dynamic predicates, since if the corresponding pragmas are ignored, then the behavior of the program is fundamentally changed (for example a membership test @@ -6806,7 +6806,7 @@ packages: @end itemize This set of configuration pragmas and restrictions correspond to the -definition of the 'Ravenscar Profile' for limited tasking, devised and +definition of the ‘Ravenscar Profile’ for limited tasking, devised and published by the @cite{International Real-Time Ada Workshop@comma{} 1997}. A description is also available at @indicateurl{http://www-users.cs.york.ac.uk/~burns/ravenscar.ps}. @@ -6849,7 +6849,7 @@ The @code{Max_Protected_Entries}, @code{Max_Entry_Queue_Length}, and Details on the rationale for @code{Jorvik} and implications for use may be found in @cite{A New Ravenscar-Based Profile} by P. Rogers, J. Ruiz, -T. Gingold and P. Bernardi, in @cite{Reliable Software Technologies -- Ada Europe 2017}, Springer-Verlag Lecture Notes in Computer Science, +T. Gingold and P. Bernardi, in @cite{Reliable Software Technologies – Ada Europe 2017}, Springer-Verlag Lecture Notes in Computer Science, Number 10300. @item @@ -6993,7 +6993,7 @@ either an unsigned or signed type. It has the effect of providing the five shift operators (Shift_Left, Shift_Right, Shift_Right_Arithmetic, Rotate_Left and Rotate_Right) for the given type. It is similar to including the function declarations for these five operators, together -with the pragma Import (Intrinsic, ...) statements. +with the pragma Import (Intrinsic, …) statements. @node Pragma Psect_Object,Pragma Pure_Function,Pragma Provide_Shift_Operators,Implementation Defined Pragmas @anchor{gnat_rm/implementation_defined_pragmas pragma-psect-object}@anchor{c8} @@ -7016,7 +7016,7 @@ EXTERNAL_SYMBOL ::= This pragma is identical in effect to pragma @code{Common_Object}. @node Pragma Pure_Function,Pragma Rational,Pragma Psect_Object,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-pure-function}@anchor{c9}@anchor{gnat_rm/implementation_defined_pragmas id31}@anchor{ca} +@anchor{gnat_rm/implementation_defined_pragmas id31}@anchor{c9}@anchor{gnat_rm/implementation_defined_pragmas pragma-pure-function}@anchor{ca} @section Pragma Pure_Function @@ -7116,7 +7116,7 @@ pragma Profile (Ravenscar); which is the preferred method of setting the @code{Ravenscar} profile. @node Pragma Refined_Depends,Pragma Refined_Global,Pragma Ravenscar,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-refined-depends}@anchor{cd}@anchor{gnat_rm/implementation_defined_pragmas id32}@anchor{ce} +@anchor{gnat_rm/implementation_defined_pragmas id32}@anchor{cd}@anchor{gnat_rm/implementation_defined_pragmas pragma-refined-depends}@anchor{ce} @section Pragma Refined_Depends @@ -7149,7 +7149,7 @@ For the semantics of this pragma, see the entry for aspect @code{Refined_Depends the SPARK 2014 Reference Manual, section 6.1.5. @node Pragma Refined_Global,Pragma Refined_Post,Pragma Refined_Depends,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-refined-global}@anchor{cf}@anchor{gnat_rm/implementation_defined_pragmas id33}@anchor{d0} +@anchor{gnat_rm/implementation_defined_pragmas id33}@anchor{cf}@anchor{gnat_rm/implementation_defined_pragmas pragma-refined-global}@anchor{d0} @section Pragma Refined_Global @@ -7174,7 +7174,7 @@ For the semantics of this pragma, see the entry for aspect @code{Refined_Global} the SPARK 2014 Reference Manual, section 6.1.4. @node Pragma Refined_Post,Pragma Refined_State,Pragma Refined_Global,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-refined-post}@anchor{d1}@anchor{gnat_rm/implementation_defined_pragmas id34}@anchor{d2} +@anchor{gnat_rm/implementation_defined_pragmas id34}@anchor{d1}@anchor{gnat_rm/implementation_defined_pragmas pragma-refined-post}@anchor{d2} @section Pragma Refined_Post @@ -7188,7 +7188,7 @@ For the semantics of this pragma, see the entry for aspect @code{Refined_Post} i the SPARK 2014 Reference Manual, section 7.2.7. @node Pragma Refined_State,Pragma Relative_Deadline,Pragma Refined_Post,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-refined-state}@anchor{d3}@anchor{gnat_rm/implementation_defined_pragmas id35}@anchor{d4} +@anchor{gnat_rm/implementation_defined_pragmas id35}@anchor{d3}@anchor{gnat_rm/implementation_defined_pragmas pragma-refined-state}@anchor{d4} @section Pragma Refined_State @@ -7445,7 +7445,7 @@ an @code{integer_EXPRESSION} of bytes is assigned from the primary stack instead For most targets, the pragma does not apply as the secondary stack grows on demand: allocated as a chain of blocks in the heap. The default size of these blocks can be modified via the @code{-D} binder option as described in -@cite{GNAT User's Guide}. +@cite{GNAT User’s Guide}. Note that no check is made to see if the secondary stack can fit inside the primary stack. @@ -7513,7 +7513,7 @@ This pragma is provided for compatibility with other Ada implementations. It is recognized but ignored by all current versions of GNAT. @node Pragma Simple_Storage_Pool_Type,Pragma Source_File_Name,Pragma Short_Descriptors,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-simple-storage-pool-type}@anchor{e2}@anchor{gnat_rm/implementation_defined_pragmas id39}@anchor{e3} +@anchor{gnat_rm/implementation_defined_pragmas id39}@anchor{e2}@anchor{gnat_rm/implementation_defined_pragmas pragma-simple-storage-pool-type}@anchor{e3} @section Pragma Simple_Storage_Pool_Type @@ -7528,7 +7528,7 @@ Syntax: pragma Simple_Storage_Pool_Type (type_LOCAL_NAME); @end example -A type can be established as a 'simple storage pool type' by applying +A type can be established as a ‘simple storage pool type’ by applying the representation pragma @code{Simple_Storage_Pool_Type} to the type. A type named in the pragma must be a library-level immutably limited record type or limited tagged type declared immediately within a package declaration. @@ -7581,7 +7581,7 @@ See attribute @ref{e4,,Simple_Storage_Pool} for further details. @node Pragma Source_File_Name,Pragma Source_File_Name_Project,Pragma Simple_Storage_Pool_Type,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name}@anchor{e5}@anchor{gnat_rm/implementation_defined_pragmas id40}@anchor{e6} +@anchor{gnat_rm/implementation_defined_pragmas id40}@anchor{e5}@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name}@anchor{e6} @section Pragma Source_File_Name @@ -7677,16 +7677,16 @@ Source_File_Name cannot appear after a @ref{e7,,Pragma Source_File_Name_Project} For more details on the use of the @code{Source_File_Name} pragma, see the sections on @cite{Using Other File Names} and @cite{Alternative File Naming Schemes} -in the @cite{GNAT User's Guide}. +in the @cite{GNAT User’s Guide}. @node Pragma Source_File_Name_Project,Pragma Source_Reference,Pragma Source_File_Name,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name-project}@anchor{e7}@anchor{gnat_rm/implementation_defined_pragmas id41}@anchor{e8} +@anchor{gnat_rm/implementation_defined_pragmas id41}@anchor{e8}@anchor{gnat_rm/implementation_defined_pragmas pragma-source-file-name-project}@anchor{e7} @section Pragma Source_File_Name_Project This pragma has the same syntax and semantics as pragma Source_File_Name. It is only allowed as a stand-alone configuration pragma. -It cannot appear after a @ref{e5,,Pragma Source_File_Name}, and +It cannot appear after a @ref{e6,,Pragma Source_File_Name}, and most importantly, once pragma Source_File_Name_Project appears, no further Source_File_Name pragmas are allowed. @@ -7722,7 +7722,7 @@ string expression other than a string literal. This is because its value is needed for error messages issued by all phases of the compiler. @node Pragma SPARK_Mode,Pragma Static_Elaboration_Desired,Pragma Source_Reference,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-spark-mode}@anchor{ea}@anchor{gnat_rm/implementation_defined_pragmas id42}@anchor{eb} +@anchor{gnat_rm/implementation_defined_pragmas id42}@anchor{ea}@anchor{gnat_rm/implementation_defined_pragmas pragma-spark-mode}@anchor{eb} @section Pragma SPARK_Mode @@ -7769,7 +7769,7 @@ Normally a subprogram or package spec/body inherits the current mode that is active at the point it is declared. But this can be overridden by pragma within the spec or body as above. -The basic consistency rule is that you can't turn SPARK_Mode back +The basic consistency rule is that you can’t turn SPARK_Mode back @code{On}, once you have explicitly (with a pragma) turned if @code{Off}. So the following rules apply: @@ -7896,7 +7896,7 @@ The effect is that if the value of an unbounded string is written to a stream, then the representation of the item in the stream is in the same format that would be used for @code{Standard.String'Output}, and this same representation is expected when a value of this type is read from the stream. Note that the -value written always includes the bounds, even for Unbounded_String'Write, +value written always includes the bounds, even for Unbounded_String’Write, since Unbounded_String is not an array type. Note that the @code{Stream_Convert} pragma is not effective in the case of @@ -7947,7 +7947,7 @@ gcc -c -gnatyl ... The form @code{ALL_CHECKS} activates all standard checks (its use is equivalent to the use of the @code{gnaty} switch with no options. -See the @cite{GNAT User's Guide} for details.) +See the @cite{GNAT User’s Guide} for details.) Note: the behavior is slightly different in GNAT mode (@code{-gnatg} used). In this case, @code{ALL_CHECKS} implies the standard set of GNAT mode style check @@ -8058,7 +8058,7 @@ checks, but does not require the compiler to omit checks. The compiler will generate checks if they are essentially free, even when they are suppressed. In particular, if the compiler can prove that a certain check will necessarily fail, it will generate code to do an -unconditional 'raise', even if checks are suppressed. The compiler +unconditional ‘raise’, even if checks are suppressed. The compiler warns in this case. Of course, run-time checks are omitted whenever the compiler can prove @@ -8084,7 +8084,7 @@ The use of the standard Ada pragma @code{Suppress (All_Checks)} as a normal configuration pragma is the preferred usage in GNAT. @node Pragma Suppress_Debug_Info,Pragma Suppress_Exception_Locations,Pragma Suppress_All,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-debug-info}@anchor{f2}@anchor{gnat_rm/implementation_defined_pragmas id43}@anchor{f3} +@anchor{gnat_rm/implementation_defined_pragmas id43}@anchor{f2}@anchor{gnat_rm/implementation_defined_pragmas pragma-suppress-debug-info}@anchor{f3} @section Pragma Suppress_Debug_Info @@ -8243,7 +8243,7 @@ created, depending on the target. This pragma can appear anywhere a type. @node Pragma Test_Case,Pragma Thread_Local_Storage,Pragma Task_Storage,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-test-case}@anchor{f9}@anchor{gnat_rm/implementation_defined_pragmas id45}@anchor{fa} +@anchor{gnat_rm/implementation_defined_pragmas id45}@anchor{f9}@anchor{gnat_rm/implementation_defined_pragmas pragma-test-case}@anchor{fa} @section Pragma Test_Case @@ -8299,7 +8299,7 @@ postcondition. Mode @code{Robustness} indicates that the precondition and postcondition of the subprogram should be ignored for this test case. @node Pragma Thread_Local_Storage,Pragma Time_Slice,Pragma Test_Case,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-thread-local-storage}@anchor{fb}@anchor{gnat_rm/implementation_defined_pragmas id46}@anchor{fc} +@anchor{gnat_rm/implementation_defined_pragmas id46}@anchor{fb}@anchor{gnat_rm/implementation_defined_pragmas pragma-thread-local-storage}@anchor{fc} @section Pragma Thread_Local_Storage @@ -8317,7 +8317,7 @@ pragma Thread_Local_Storage ([Entity =>] LOCAL_NAME); This pragma specifies that the specified entity, which must be a variable declared in a library-level package, is to be marked as -"Thread Local Storage" (@code{TLS}). On systems supporting this (which +“Thread Local Storage” (@code{TLS}). On systems supporting this (which include Windows, Solaris, GNU/Linux, and VxWorks 6), this causes each thread (and hence each Ada task) to see a distinct copy of the variable. @@ -8521,7 +8521,7 @@ The abort only happens if code is being generated. Thus you can use specs of unimplemented packages in syntax or semantic checking mode. @node Pragma Universal_Aliasing,Pragma Unmodified,Pragma Unimplemented_Unit,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-universal-aliasing}@anchor{105}@anchor{gnat_rm/implementation_defined_pragmas id48}@anchor{106} +@anchor{gnat_rm/implementation_defined_pragmas id48}@anchor{105}@anchor{gnat_rm/implementation_defined_pragmas pragma-universal-aliasing}@anchor{106} @section Pragma Universal_Aliasing @@ -8537,10 +8537,10 @@ optimization for the given type. In other words, the effect is as though access types designating this type were subject to pragma No_Strict_Aliasing. For a detailed description of the strict aliasing optimization, and the situations in which it must be suppressed, see the section on -@code{Optimization and Strict Aliasing} in the @cite{GNAT User's Guide}. +@code{Optimization and Strict Aliasing} in the @cite{GNAT User’s Guide}. @node Pragma Unmodified,Pragma Unreferenced,Pragma Universal_Aliasing,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-unmodified}@anchor{107}@anchor{gnat_rm/implementation_defined_pragmas id49}@anchor{108} +@anchor{gnat_rm/implementation_defined_pragmas id49}@anchor{107}@anchor{gnat_rm/implementation_defined_pragmas pragma-unmodified}@anchor{108} @section Pragma Unmodified @@ -8574,7 +8574,7 @@ Thus it is never necessary to use @code{pragma Unmodified} for such variables, though it is harmless to do so. @node Pragma Unreferenced,Pragma Unreferenced_Objects,Pragma Unmodified,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced}@anchor{109}@anchor{gnat_rm/implementation_defined_pragmas id50}@anchor{10a} +@anchor{gnat_rm/implementation_defined_pragmas id50}@anchor{109}@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced}@anchor{10a} @section Pragma Unreferenced @@ -8618,7 +8618,7 @@ Note that if a warning is desired for all calls to a given subprogram, regardless of whether they occur in the same unit as the subprogram declaration, then this pragma should not be used (calls from another unit would not be flagged); pragma Obsolescent can be used instead -for this purpose, see @ref{ab,,Pragma Obsolescent}. +for this purpose, see @ref{ac,,Pragma Obsolescent}. The second form of pragma @code{Unreferenced} is used within a context clause. In this case the arguments must be unit names of units previously @@ -8634,7 +8634,7 @@ Thus it is never necessary to use @code{pragma Unreferenced} for such variables, though it is harmless to do so. @node Pragma Unreferenced_Objects,Pragma Unreserve_All_Interrupts,Pragma Unreferenced,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced-objects}@anchor{10b}@anchor{gnat_rm/implementation_defined_pragmas id51}@anchor{10c} +@anchor{gnat_rm/implementation_defined_pragmas id51}@anchor{10b}@anchor{gnat_rm/implementation_defined_pragmas pragma-unreferenced-objects}@anchor{10c} @section Pragma Unreferenced_Objects @@ -8747,15 +8747,15 @@ pragma Use_VADS_Size; @end example This is a configuration pragma. In a unit to which it applies, any use -of the 'Size attribute is automatically interpreted as a use of the -'VADS_Size attribute. Note that this may result in incorrect semantic +of the ‘Size attribute is automatically interpreted as a use of the +‘VADS_Size attribute. Note that this may result in incorrect semantic processing of valid Ada 95 or Ada 2005 programs. This is intended to aid in the handling of existing code which depends on the interpretation of Size as implemented in the VADS compiler. See description of the VADS_Size attribute for further details. @node Pragma Unused,Pragma Validity_Checks,Pragma Use_VADS_Size,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-unused}@anchor{110}@anchor{gnat_rm/implementation_defined_pragmas id52}@anchor{111} +@anchor{gnat_rm/implementation_defined_pragmas id52}@anchor{110}@anchor{gnat_rm/implementation_defined_pragmas pragma-unused}@anchor{111} @section Pragma Unused @@ -8812,7 +8812,7 @@ activated. The validity checks are first set to include only the default reference manual settings, and then a string of letters in the string specifies the exact set of options required. The form of this string is exactly as described for the @emph{-gnatVx} compiler switch (see the -GNAT User's Guide for details). For example the following two +GNAT User’s Guide for details). For example the following two methods can be used to enable validity checking for mode @code{in} and @code{in out} subprogram parameters: @@ -8845,7 +8845,7 @@ A := C; -- C will be validity checked @end example @node Pragma Volatile,Pragma Volatile_Full_Access,Pragma Validity_Checks,Implementation Defined Pragmas -@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile}@anchor{113}@anchor{gnat_rm/implementation_defined_pragmas id53}@anchor{114} +@anchor{gnat_rm/implementation_defined_pragmas id53}@anchor{113}@anchor{gnat_rm/implementation_defined_pragmas pragma-volatile}@anchor{114} @section Pragma Volatile @@ -8920,7 +8920,7 @@ as an error. This gives more precise control than -gnatwe, which treats warnings as errors. This pragma can apply to regular warnings (messages enabled by -gnatw) -and to style warnings (messages that start with "(style)", +and to style warnings (messages that start with “(style)”, enabled by -gnaty). The pattern may contain asterisks, which match zero or more characters @@ -8989,8 +8989,8 @@ Note that this pragma does not affect the set of warnings issued in any way, it merely changes the effect of a matching warning if one is produced as a result of other warnings options. As shown in this example, if the pragma results in a warning being treated as an error, -the tag is changed from "warning:" to "error:" and the string -"[warning-as-error]" is appended to the end of the message. +the tag is changed from “warning:” to “error:” and the string +“[warning-as-error]” is appended to the end of the message. @node Pragma Warnings,Pragma Weak_External,Pragma Warning_As_Error,Implementation Defined Pragmas @anchor{gnat_rm/implementation_defined_pragmas id56}@anchor{11b}@anchor{gnat_rm/implementation_defined_pragmas pragma-warnings}@anchor{11a} @@ -9059,7 +9059,7 @@ line switch controlling warnings. For a brief summary, use the gnatmake command with no arguments, which will generate usage information containing the list of warnings switches supported. For full details see the section on @code{Warning Message Control} in the -@cite{GNAT User's Guide}. +@cite{GNAT User’s Guide}. This form can also be used as a configuration pragma. The warnings controlled by the @code{-gnatw} switch are generated by the @@ -9081,7 +9081,7 @@ also be used as a configuration pragma. The fourth form, with an @code{On|Off} parameter and a string, is used to control individual messages, based on their text. The string argument is a pattern that is used to match against the text of individual -warning messages (not including the initial "warning: " tag). +warning messages (not including the initial “warning: ” tag). The pattern may contain asterisks, which match zero or more characters in the message. For example, you can use @@ -9218,7 +9218,7 @@ to appear within the same file. However, note that the pragma cannot immediately precede the relevant wide character, because then the previous encoding will still be in -effect, causing "illegal character" errors. +effect, causing “illegal character” errors. The argument can be an identifier or a character literal. In the identifier case, it is one of @code{HEX}, @code{UPPER}, @code{SHIFT_JIS}, @@ -9231,7 +9231,7 @@ encoding within that file, and does not affect withed units, specs, or subunits. @node Implementation Defined Aspects,Implementation Defined Attributes,Implementation Defined Pragmas,Top -@anchor{gnat_rm/implementation_defined_aspects implementation-defined-aspects}@anchor{11e}@anchor{gnat_rm/implementation_defined_aspects doc}@anchor{11f}@anchor{gnat_rm/implementation_defined_aspects id1}@anchor{120} +@anchor{gnat_rm/implementation_defined_aspects doc}@anchor{11e}@anchor{gnat_rm/implementation_defined_aspects id1}@anchor{11f}@anchor{gnat_rm/implementation_defined_aspects implementation-defined-aspects}@anchor{120} @chapter Implementation Defined Aspects @@ -9307,7 +9307,7 @@ or attribute definition clause. * Aspect Initializes:: * Aspect Inline_Always:: * Aspect Invariant:: -* Aspect Invariant'Class:: +* Aspect Invariant’Class:: * Aspect Iterable:: * Aspect Linker_Section:: * Aspect Lock_Free:: @@ -9357,7 +9357,7 @@ or attribute definition clause. @geindex Abstract_State -This aspect is equivalent to @ref{1c,,pragma Abstract_State}. +This aspect is equivalent to @ref{1d,,pragma Abstract_State}. @node Aspect Annotate,Aspect Async_Readers,Aspect Abstract_State,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-annotate}@anchor{122} @@ -9368,7 +9368,7 @@ This aspect is equivalent to @ref{1c,,pragma Abstract_State}. There are three forms of this aspect (where ID is an identifier, and ARG is a general expression), -corresponding to @ref{26,,pragma Annotate}. +corresponding to @ref{27,,pragma Annotate}. @table @asis @@ -9393,7 +9393,7 @@ Equivalent to @code{pragma Annotate (ID, ID @{, ARG@}, Entity => Name);} @geindex Async_Readers -This boolean aspect is equivalent to @ref{2d,,pragma Async_Readers}. +This boolean aspect is equivalent to @ref{2e,,pragma Async_Readers}. @node Aspect Async_Writers,Aspect Constant_After_Elaboration,Aspect Async_Readers,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-async-writers}@anchor{124} @@ -9431,7 +9431,7 @@ aggregate. @geindex Depends -This aspect is equivalent to @ref{53,,pragma Depends}. +This aspect is equivalent to @ref{54,,pragma Depends}. @node Aspect Default_Initial_Condition,Aspect Dimension,Aspect Depends,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-default-initial-condition}@anchor{128} @@ -9535,7 +9535,7 @@ Note that in the above type definition, we use the @code{at} symbol (@code{@@}) represent a theta character (avoiding the use of extended Latin-1 characters in this context). -See section 'Performing Dimensionality Analysis in GNAT' in the GNAT Users +See section ‘Performing Dimensionality Analysis in GNAT’ in the GNAT Users Guide for detailed examples of use of the dimension system. @node Aspect Disable_Controlled,Aspect Effective_Reads,Aspect Dimension_System,Implementation Defined Aspects @@ -9594,7 +9594,7 @@ This boolean aspect is equivalent to @ref{6b,,pragma Favor_Top_Level}. @geindex Ghost -This aspect is equivalent to @ref{6e,,pragma Ghost}. +This aspect is equivalent to @ref{6f,,pragma Ghost}. @node Aspect Global,Aspect Initial_Condition,Aspect Ghost,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-global}@anchor{131} @@ -9603,7 +9603,7 @@ This aspect is equivalent to @ref{6e,,pragma Ghost}. @geindex Global -This aspect is equivalent to @ref{70,,pragma Global}. +This aspect is equivalent to @ref{71,,pragma Global}. @node Aspect Initial_Condition,Aspect Initializes,Aspect Global,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-initial-condition}@anchor{132} @@ -9621,7 +9621,7 @@ This aspect is equivalent to @ref{7e,,pragma Initial_Condition}. @geindex Initializes -This aspect is equivalent to @ref{80,,pragma Initializes}. +This aspect is equivalent to @ref{81,,pragma Initializes}. @node Aspect Inline_Always,Aspect Invariant,Aspect Initializes,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-inline-always}@anchor{134} @@ -9632,7 +9632,7 @@ This aspect is equivalent to @ref{80,,pragma Initializes}. This boolean aspect is equivalent to @ref{83,,pragma Inline_Always}. -@node Aspect Invariant,Aspect Invariant'Class,Aspect Inline_Always,Implementation Defined Aspects +@node Aspect Invariant,Aspect Invariant’Class,Aspect Inline_Always,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-invariant}@anchor{135} @section Aspect Invariant @@ -9643,9 +9643,9 @@ This aspect is equivalent to @ref{8a,,pragma Invariant}. It is a synonym for the language defined aspect @code{Type_Invariant} except that it is separately controllable using pragma @code{Assertion_Policy}. -@node Aspect Invariant'Class,Aspect Iterable,Aspect Invariant,Implementation Defined Aspects +@node Aspect Invariant’Class,Aspect Iterable,Aspect Invariant,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-invariant-class}@anchor{136} -@section Aspect Invariant'Class +@section Aspect Invariant’Class @geindex Invariant'Class @@ -9654,7 +9654,7 @@ This aspect is equivalent to @ref{101,,pragma Type_Invariant_Class}. It is a synonym for the language defined aspect @code{Type_Invariant'Class} except that it is separately controllable using pragma @code{Assertion_Policy}. -@node Aspect Iterable,Aspect Linker_Section,Aspect Invariant'Class,Implementation Defined Aspects +@node Aspect Iterable,Aspect Linker_Section,Aspect Invariant’Class,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-iterable}@anchor{137} @section Aspect Iterable @@ -9768,7 +9768,7 @@ This aspect is equivalent to @ref{9c,,pragma Max_Queue_Length}. @geindex No_Caching -This boolean aspect is equivalent to @ref{9e,,pragma No_Caching}. +This boolean aspect is equivalent to @ref{9f,,pragma No_Caching}. @node Aspect No_Elaboration_Code_All,Aspect No_Inline,Aspect No_Caching,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-no-elaboration-code-all}@anchor{13c} @@ -9796,7 +9796,7 @@ This boolean aspect is equivalent to @ref{a5,,pragma No_Inline}. @geindex No_Tagged_Streams -This aspect is equivalent to @ref{a8,,pragma No_Tagged_Streams} with an +This aspect is equivalent to @ref{a9,,pragma No_Tagged_Streams} with an argument specifying a root tagged type (thus this aspect can only be applied to such a type). @@ -9810,11 +9810,11 @@ applied to such a type). Applies to a type. If True, requires that the type and any descendants do not have any task parts. The rules for this aspect are the same as for the language-defined No_Controlled_Parts aspect (see RM-H.4.1), -replacing "controlled" with "task". +replacing “controlled” with “task”. If No_Task_Parts is True for a type T, then the compiler can optimize away certain tasking-related code that would otherwise be needed -for T'Class, because descendants of T might contain tasks. +for T’Class, because descendants of T might contain tasks. @node Aspect Object_Size,Aspect Obsolescent,Aspect No_Task_Parts,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-object-size}@anchor{140} @@ -9832,7 +9832,7 @@ This aspect is equivalent to @ref{141,,attribute Object_Size}. @geindex Obsolsecent -This aspect is equivalent to @ref{ab,,pragma Obsolescent}. Note that the +This aspect is equivalent to @ref{ac,,pragma Obsolescent}. Note that the evaluation of this aspect happens at the point of occurrence, it is not delayed until the freeze point. @@ -9861,7 +9861,7 @@ This boolean aspect is equivalent to @ref{b6,,pragma Persistent_BSS}. @geindex Predicate -This aspect is equivalent to @ref{bd,,pragma Predicate}. It is thus +This aspect is equivalent to @ref{be,,pragma Predicate}. It is thus similar to the language defined aspects @code{Dynamic_Predicate} and @code{Static_Predicate} except that whether the resulting predicate is static or dynamic is controlled by the form of the @@ -9875,7 +9875,7 @@ expression. It is also separately controllable using pragma @geindex Pure_Function -This boolean aspect is equivalent to @ref{c9,,pragma Pure_Function}. +This boolean aspect is equivalent to @ref{ca,,pragma Pure_Function}. @node Aspect Refined_Depends,Aspect Refined_Global,Aspect Pure_Function,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-refined-depends}@anchor{147} @@ -9884,7 +9884,7 @@ This boolean aspect is equivalent to @ref{c9,,pragma Pure_Function}. @geindex Refined_Depends -This aspect is equivalent to @ref{cd,,pragma Refined_Depends}. +This aspect is equivalent to @ref{ce,,pragma Refined_Depends}. @node Aspect Refined_Global,Aspect Refined_Post,Aspect Refined_Depends,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-refined-global}@anchor{148} @@ -9893,7 +9893,7 @@ This aspect is equivalent to @ref{cd,,pragma Refined_Depends}. @geindex Refined_Global -This aspect is equivalent to @ref{cf,,pragma Refined_Global}. +This aspect is equivalent to @ref{d0,,pragma Refined_Global}. @node Aspect Refined_Post,Aspect Refined_State,Aspect Refined_Global,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-refined-post}@anchor{149} @@ -9902,7 +9902,7 @@ This aspect is equivalent to @ref{cf,,pragma Refined_Global}. @geindex Refined_Post -This aspect is equivalent to @ref{d1,,pragma Refined_Post}. +This aspect is equivalent to @ref{d2,,pragma Refined_Post}. @node Aspect Refined_State,Aspect Relaxed_Initialization,Aspect Refined_Post,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-refined-state}@anchor{14a} @@ -9911,7 +9911,7 @@ This aspect is equivalent to @ref{d1,,pragma Refined_Post}. @geindex Refined_State -This aspect is equivalent to @ref{d3,,pragma Refined_State}. +This aspect is equivalent to @ref{d4,,pragma Refined_State}. @node Aspect Relaxed_Initialization,Aspect Remote_Access_Type,Aspect Refined_State,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-relaxed-initialization}@anchor{14b} @@ -9976,7 +9976,7 @@ This aspect is equivalent to @ref{e4,,attribute Simple_Storage_Pool}. @geindex Simple_Storage_Pool_Type -This boolean aspect is equivalent to @ref{e2,,pragma Simple_Storage_Pool_Type}. +This boolean aspect is equivalent to @ref{e3,,pragma Simple_Storage_Pool_Type}. @node Aspect SPARK_Mode,Aspect Suppress_Debug_Info,Aspect Simple_Storage_Pool_Type,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-spark-mode}@anchor{153} @@ -9985,7 +9985,7 @@ This boolean aspect is equivalent to @ref{e2,,pragma Simple_Storage_Pool_Type}. @geindex SPARK_Mode -This aspect is equivalent to @ref{ea,,pragma SPARK_Mode} and +This aspect is equivalent to @ref{eb,,pragma SPARK_Mode} and may be specified for either or both of the specification and body of a subprogram or package. @@ -9996,7 +9996,7 @@ of a subprogram or package. @geindex Suppress_Debug_Info -This boolean aspect is equivalent to @ref{f2,,pragma Suppress_Debug_Info}. +This boolean aspect is equivalent to @ref{f3,,pragma Suppress_Debug_Info}. @node Aspect Suppress_Initialization,Aspect Test_Case,Aspect Suppress_Debug_Info,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-suppress-initialization}@anchor{155} @@ -10014,7 +10014,7 @@ This boolean aspect is equivalent to @ref{f6,,pragma Suppress_Initialization}. @geindex Test_Case -This aspect is equivalent to @ref{f9,,pragma Test_Case}. +This aspect is equivalent to @ref{fa,,pragma Test_Case}. @node Aspect Thread_Local_Storage,Aspect Universal_Aliasing,Aspect Test_Case,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-thread-local-storage}@anchor{157} @@ -10023,7 +10023,7 @@ This aspect is equivalent to @ref{f9,,pragma Test_Case}. @geindex Thread_Local_Storage -This boolean aspect is equivalent to @ref{fb,,pragma Thread_Local_Storage}. +This boolean aspect is equivalent to @ref{fc,,pragma Thread_Local_Storage}. @node Aspect Universal_Aliasing,Aspect Unmodified,Aspect Thread_Local_Storage,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-universal-aliasing}@anchor{158} @@ -10032,7 +10032,7 @@ This boolean aspect is equivalent to @ref{fb,,pragma Thread_Local_Storage}. @geindex Universal_Aliasing -This boolean aspect is equivalent to @ref{105,,pragma Universal_Aliasing}. +This boolean aspect is equivalent to @ref{106,,pragma Universal_Aliasing}. @node Aspect Unmodified,Aspect Unreferenced,Aspect Universal_Aliasing,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-unmodified}@anchor{159} @@ -10041,7 +10041,7 @@ This boolean aspect is equivalent to @ref{105,,pragma Universal_Aliasing}. @geindex Unmodified -This boolean aspect is equivalent to @ref{107,,pragma Unmodified}. +This boolean aspect is equivalent to @ref{108,,pragma Unmodified}. @node Aspect Unreferenced,Aspect Unreferenced_Objects,Aspect Unmodified,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-unreferenced}@anchor{15a} @@ -10050,7 +10050,7 @@ This boolean aspect is equivalent to @ref{107,,pragma Unmodified}. @geindex Unreferenced -This boolean aspect is equivalent to @ref{109,,pragma Unreferenced}. +This boolean aspect is equivalent to @ref{10a,,pragma Unreferenced}. When using the @code{-gnat2022} switch, this aspect is also supported on formal parameters, which is in particular the only form possible for expression @@ -10063,7 +10063,7 @@ functions. @geindex Unreferenced_Objects -This boolean aspect is equivalent to @ref{10b,,pragma Unreferenced_Objects}. +This boolean aspect is equivalent to @ref{10c,,pragma Unreferenced_Objects}. @node Aspect Value_Size,Aspect Volatile_Full_Access,Aspect Unreferenced_Objects,Implementation Defined Aspects @anchor{gnat_rm/implementation_defined_aspects aspect-value-size}@anchor{15c} @@ -10104,7 +10104,7 @@ where the first argument is @code{ON} or @code{OFF} and the second argument is the entity. @node Implementation Defined Attributes,Standard and Implementation Defined Restrictions,Implementation Defined Aspects,Top -@anchor{gnat_rm/implementation_defined_attributes doc}@anchor{161}@anchor{gnat_rm/implementation_defined_attributes implementation-defined-attributes}@anchor{8}@anchor{gnat_rm/implementation_defined_attributes id1}@anchor{162} +@anchor{gnat_rm/implementation_defined_attributes doc}@anchor{161}@anchor{gnat_rm/implementation_defined_attributes id1}@anchor{162}@anchor{gnat_rm/implementation_defined_attributes implementation-defined-attributes}@anchor{8} @chapter Implementation Defined Attributes @@ -10235,9 +10235,9 @@ intercept the abort exception). @code{Standard'Address_Size} (@code{Standard} is the only allowed prefix) is a static constant giving the number of bits in an -@code{Address}. It is the same value as System.Address'Size, +@code{Address}. It is the same value as System.Address’Size, but has the advantage of being static, while a direct -reference to System.Address'Size is nonstatic because Address +reference to System.Address’Size is nonstatic because Address is a private type. @node Attribute Asm_Input,Attribute Asm_Output,Attribute Address_Size,Implementation Defined Attributes @@ -10848,7 +10848,7 @@ standard input-output functions for fixed-point values. @geindex Invalid_Value -For every scalar type S, S'Invalid_Value returns an undefined value of the +For every scalar type S, S’Invalid_Value returns an undefined value of the type. If possible this value is an invalid representation for the type. The value returned is identical to the value used to initialize an otherwise uninitialized value of the type if pragma Initialize_Scalars is used, @@ -11165,7 +11165,7 @@ bounds are allocated just before the first component, whereas @code{X'Address} returns the address of the first component. -Here, we are interpreting 'storage pool' broadly to mean +Here, we are interpreting ‘storage pool’ broadly to mean @code{wherever the object is allocated}, which could be a user-defined storage pool, the global heap, on the stack, or in a static memory area. @@ -11197,7 +11197,7 @@ same result as @code{Length} applied to the array itself. This attribute allows compile time testing of restrictions that are currently in effect. It is primarily intended for specializing code in the run-time based on restrictions that are active (e.g. -don't need to save fpt registers if restriction No_Floating_Point +don’t need to save fpt registers if restriction No_Floating_Point is known to be in effect), but can be used anywhere. There are two forms: @@ -11308,7 +11308,7 @@ the Ada 83 reference manual for an exact description of the semantics of this attribute. @node Attribute Scalar_Storage_Order,Attribute Simple_Storage_Pool,Attribute Safe_Small,Implementation Defined Attributes -@anchor{gnat_rm/implementation_defined_attributes id4}@anchor{19c}@anchor{gnat_rm/implementation_defined_attributes attribute-scalar-storage-order}@anchor{14f} +@anchor{gnat_rm/implementation_defined_attributes attribute-scalar-storage-order}@anchor{14f}@anchor{gnat_rm/implementation_defined_attributes id4}@anchor{19c} @section Attribute Scalar_Storage_Order @@ -11362,7 +11362,7 @@ defined by Ada RM 13.5.3(4). The default is @code{System.Default_Bit_Order}. For a record type @code{T}, if @code{T'Scalar_Storage_Order} is specified explicitly, it shall be equal to @code{T'Bit_Order}. Note: this means that if a @code{Scalar_Storage_Order} attribute definition -clause is not confirming, then the type's @code{Bit_Order} shall be +clause is not confirming, then the type’s @code{Bit_Order} shall be specified explicitly and set to the same value. Derived types inherit an explicitly set scalar storage order from their parent @@ -11456,7 +11456,7 @@ for Acc'Simple_Storage_Pool use My_Pool; The name given in an attribute_definition_clause for the @code{Simple_Storage_Pool} attribute shall denote a variable of -a 'simple storage pool type' (see pragma @cite{Simple_Storage_Pool_Type}). +a ‘simple storage pool type’ (see pragma @cite{Simple_Storage_Pool_Type}). The use of this attribute is only allowed for a prefix denoting a type for which it has been specified. The type of the attribute is the type @@ -11555,7 +11555,7 @@ prefix) provides the same value as @code{System.Storage_Unit}. The GNAT implementation of remote access-to-classwide types is organized as described in AARM section E.4 (20.t): a value of an RACW type (designating a remote object) is represented as a normal access -value, pointing to a "stub" object which in turn contains the +value, pointing to a “stub” object which in turn contains the necessary information to contact the designated remote object. A call on any dispatching operation of such a stub object does the remote call, if necessary, using the information in the stub object @@ -11597,7 +11597,7 @@ alignment request is larger than this value. prefix) provides a static string value that identifies the target for the current compilation. For GCC implementations, this is the standard gcc target name without the terminating slash (for -example, GNAT 5.0 on windows yields "i586-pc-mingw32msv"). +example, GNAT 5.0 on windows yields “i586-pc-mingw32msv”). @node Attribute To_Address,Attribute To_Any,Attribute Target_Name,Implementation Defined Attributes @anchor{gnat_rm/implementation_defined_attributes attribute-to-address}@anchor{1a5} @@ -11791,9 +11791,9 @@ For instance, if a function uses @code{Unrestricted_Access} to create an access-to-unconstrained-array and returns that value to the caller, the result will involve dangling pointers. In addition, it is only valid to create pointers to unconstrained arrays using this attribute -if the pointer has the normal default 'fat' representation where a +if the pointer has the normal default ‘fat’ representation where a pointer has two components, one points to the array and one points to -the bounds. If a size clause is used to force 'thin' representation +the bounds. If a size clause is used to force ‘thin’ representation for a pointer to unconstrained where there is only space for a single pointer, then the resulting pointer is not usable. @@ -11909,7 +11909,7 @@ begin end; @end example -In general this is a risky approach. It may appear to "work" but such uses of +In general this is a risky approach. It may appear to “work” but such uses of @code{Unrestricted_Access} are potentially non-portable, even from one version of GNAT to another, so are best avoided if possible. @@ -12061,7 +12061,7 @@ gives the result that would be obtained by applying the attribute to the corresponding type. @node Attribute Value_Size,Attribute Wchar_T_Size,Attribute VADS_Size,Implementation Defined Attributes -@anchor{gnat_rm/implementation_defined_attributes id6}@anchor{1b1}@anchor{gnat_rm/implementation_defined_attributes attribute-value-size}@anchor{15d} +@anchor{gnat_rm/implementation_defined_attributes attribute-value-size}@anchor{15d}@anchor{gnat_rm/implementation_defined_attributes id6}@anchor{1b1} @section Attribute Value_Size @@ -12098,7 +12098,7 @@ prefix) provides the value @code{System.Word_Size}. The result is a static constant. @node Standard and Implementation Defined Restrictions,Implementation Advice,Implementation Defined Attributes,Top -@anchor{gnat_rm/standard_and_implementation_defined_restrictions standard-and-implementation-defined-restrictions}@anchor{9}@anchor{gnat_rm/standard_and_implementation_defined_restrictions doc}@anchor{1b4}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id1}@anchor{1b5} +@anchor{gnat_rm/standard_and_implementation_defined_restrictions doc}@anchor{1b4}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id1}@anchor{1b5}@anchor{gnat_rm/standard_and_implementation_defined_restrictions standard-and-implementation-defined-restrictions}@anchor{9} @chapter Standard and Implementation Defined Restrictions @@ -12127,7 +12127,7 @@ language defined or GNAT-specific, are listed in the following. @end menu @node Partition-Wide Restrictions,Program Unit Level Restrictions,,Standard and Implementation Defined Restrictions -@anchor{gnat_rm/standard_and_implementation_defined_restrictions partition-wide-restrictions}@anchor{1b6}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id2}@anchor{1b7} +@anchor{gnat_rm/standard_and_implementation_defined_restrictions id2}@anchor{1b6}@anchor{gnat_rm/standard_and_implementation_defined_restrictions partition-wide-restrictions}@anchor{1b7} @section Partition-Wide Restrictions @@ -12287,7 +12287,7 @@ defined by a discriminant of a subtype whose corresponding bound is static. @geindex Max_Storage_At_Blocking -[RM D.7] Specifies the maximum portion (in storage elements) of a task's +[RM D.7] Specifies the maximum portion (in storage elements) of a task’s Storage_Size that can be retained by a blocked task. A violation of this restriction causes Storage_Error to be raised. @@ -12407,7 +12407,7 @@ coextensions. See 3.10.2. [GNAT] This restriction prohibits any instance of default initialization of variables. The binder implements a consistency rule which prevents -any unit compiled without the restriction from with'ing a unit with the +any unit compiled without the restriction from with’ing a unit with the restriction (this allows the generation of initialization procedures to be skipped, since you can be sure that no call is ever generated to an initialization procedure in a unit with the restriction active). If used @@ -12723,7 +12723,7 @@ of composite objects and the Max/Min attributes. @geindex trampoline -[GNAT] This restriction prevents the compiler from building 'trampolines'. +[GNAT] This restriction prevents the compiler from building ‘trampolines’. This is a structure that is built on the stack and contains dynamic code to be executed at run time. On some targets, a trampoline is built for the following features: @code{Access}, @@ -12735,7 +12735,7 @@ protection) will cause trampolines to raise an exception. Trampolines are also quite slow at run time. On many targets, trampolines have been largely eliminated. Look at the -version of system.ads for your target --- if it has +version of system.ads for your target — if it has Always_Compatible_Rep equal to False, then trampolines are largely eliminated. In particular, a trampoline is built for the following features: @code{Address} of a nested subprogram; @@ -12836,7 +12836,7 @@ declared at the library level. [GNAT] This partition-wide restriction forbids any explicit reference to type Standard.Long_Long_Integer, and also forbids declaring range types whose implicit base type is Long_Long_Integer, and modular types whose size exceeds -Long_Integer'Size. +Long_Integer’Size. @node No_Multiple_Elaboration,No_Nested_Finalization,No_Long_Long_Integers,Partition-Wide Restrictions @anchor{gnat_rm/standard_and_implementation_defined_restrictions no-multiple-elaboration}@anchor{1e4} @@ -13202,7 +13202,7 @@ character literals, implicitly defined comparison operators, @item -uses of the Standard."not" operator, +uses of the Standard.”not” operator, @item short-circuit operator, @@ -13256,7 +13256,7 @@ are static, and that there are no dependences on the package in a Storage_Size pragma or attribute definition clause is static. @node Program Unit Level Restrictions,,Partition-Wide Restrictions,Standard and Implementation Defined Restrictions -@anchor{gnat_rm/standard_and_implementation_defined_restrictions program-unit-level-restrictions}@anchor{203}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id3}@anchor{204} +@anchor{gnat_rm/standard_and_implementation_defined_restrictions id3}@anchor{203}@anchor{gnat_rm/standard_and_implementation_defined_restrictions program-unit-level-restrictions}@anchor{204} @section Program Unit Level Restrictions @@ -13332,7 +13332,7 @@ is not possible to document the precise conditions under which the optimizer can figure this out. Note that this the implementation of this restriction requires full -code generation. If it is used in conjunction with "semantics only" +code generation. If it is used in conjunction with “semantics only” checking, then some cases of violations may be missed. When this restriction is active, we are not requesting control-flow @@ -13448,9 +13448,9 @@ of packages Ada, Interfaces, or System. @geindex No_Implicit_Aliasing [GNAT] This restriction, which is not required to be partition-wide consistent, -requires an explicit aliased keyword for an object to which 'Access, -'Unchecked_Access, or 'Address is applied, and forbids entirely the use of -the 'Unrestricted_Access attribute for objects. Note: the reason that +requires an explicit aliased keyword for an object to which ‘Access, +‘Unchecked_Access, or ‘Address is applied, and forbids entirely the use of +the ‘Unrestricted_Access attribute for objects. Note: the reason that Unrestricted_Access is forbidden is that it would require the prefix to be aliased, and in such cases, it can always be replaced by the standard attribute Unchecked_Access which is preferable. @@ -13530,7 +13530,7 @@ gnatprove -P project.gpr --mode=check_all @end example @node Implementation Advice,Implementation Defined Characteristics,Standard and Implementation Defined Restrictions,Top -@anchor{gnat_rm/implementation_advice doc}@anchor{214}@anchor{gnat_rm/implementation_advice implementation-advice}@anchor{a}@anchor{gnat_rm/implementation_advice id1}@anchor{215} +@anchor{gnat_rm/implementation_advice doc}@anchor{214}@anchor{gnat_rm/implementation_advice id1}@anchor{215}@anchor{gnat_rm/implementation_advice implementation-advice}@anchor{a} @chapter Implementation Advice @@ -13539,7 +13539,7 @@ behavior of all Ada compilers, and the GNAT compiler conforms to these requirements. In addition, there are sections throughout the Ada Reference Manual headed -by the phrase 'Implementation advice'. These sections are not normative, +by the phrase ‘Implementation advice’. These sections are not normative, i.e., they do not specify requirements that all compilers must follow. Rather they provide advice on generally desirable behavior. They are not requirements, because they describe behavior that cannot @@ -13552,7 +13552,7 @@ RM section number and paragraph number and the subject of the advice. The contents of each section consists of the RM text within quotation marks, followed by the GNAT interpretation of the advice. Most often, this simply says -'followed', which means that GNAT follows the advice. However, in a +‘followed’, which means that GNAT follows the advice. However, in a number of cases, GNAT deliberately deviates from this advice, in which case the text describes what GNAT does and why. @@ -13570,7 +13570,7 @@ case the text describes what GNAT does and why. * RM 3.5.5(8); Enumeration Values: RM 3 5 5 8 Enumeration Values. * RM 3.5.7(17); Float Types: RM 3 5 7 17 Float Types. * RM 3.6.2(11); Multidimensional Arrays: RM 3 6 2 11 Multidimensional Arrays. -* RM 9.6(30-31); Duration'Small: RM 9 6 30-31 Duration'Small. +* RM 9.6(30-31); Duration’Small: RM 9 6 30-31 Duration’Small. * RM 10.2.1(12); Consistent Representation: RM 10 2 1 12 Consistent Representation. * RM 11.4.1(19); Exception Information: RM 11 4 1 19 Exception Information. * RM 11.5(28); Suppression of Checks: RM 11 5 28 Suppression of Checks. @@ -13634,9 +13634,9 @@ case the text describes what GNAT does and why. @quotation -"If an implementation detects the use of an unsupported Specialized Needs +“If an implementation detects the use of an unsupported Specialized Needs Annex feature at run time, it should raise @code{Program_Error} if -feasible." +feasible.” @end quotation Not relevant. All specialized needs annex features are either supported, @@ -13651,9 +13651,9 @@ or diagnosed at compile time. @quotation -"If an implementation wishes to provide implementation-defined +“If an implementation wishes to provide implementation-defined extensions to the functionality of a language-defined library unit, it -should normally do so by adding children to the library unit." +should normally do so by adding children to the library unit.” @end quotation Followed. @@ -13667,8 +13667,8 @@ Followed. @quotation -"If an implementation detects a bounded error or erroneous -execution, it should raise @code{Program_Error}." +“If an implementation detects a bounded error or erroneous +execution, it should raise @code{Program_Error}.” @end quotation Followed in all cases in which the implementation detects a bounded @@ -13684,10 +13684,10 @@ runtime. @quotation -"Normally, implementation-defined pragmas should have no semantic effect +“Normally, implementation-defined pragmas should have no semantic effect for error-free programs; that is, if the implementation-defined pragmas are removed from a working program, the program should still be legal, -and should still have the same semantics." +and should still have the same semantics.” @end quotation The following implementation defined pragmas are exceptions to this @@ -13797,7 +13797,7 @@ that this advice not be followed. For details see @quotation -"Normally, an implementation should not define pragmas that can +“Normally, an implementation should not define pragmas that can make an illegal program legal, except as follows: @@ -13808,7 +13808,7 @@ A pragma used to complete a declaration, such as a pragma @code{Import}; @item A pragma used to configure the environment by adding, removing, or -replacing @code{library_items}." +replacing @code{library_items}.” @end itemize @end quotation @@ -13825,16 +13825,16 @@ See @ref{21a,,RM 2.8(16); Pragmas}. @quotation -"If an implementation supports a mode with alternative interpretations +“If an implementation supports a mode with alternative interpretations for @code{Character} and @code{Wide_Character}, the set of graphic characters of @code{Character} should nevertheless remain a proper subset of the set of graphic characters of @code{Wide_Character}. Any -character set 'localizations' should be reflected in the results of +character set ‘localizations’ should be reflected in the results of the subprograms defined in the language-defined package @code{Characters.Handling} (see A.3) available in such a mode. In a mode with an alternative interpretation of @code{Character}, the implementation should also support a corresponding change in what is a legal -@code{identifier_letter}." +@code{identifier_letter}.” @end quotation Not all wide character modes follow this advice, in particular the JIS @@ -13853,11 +13853,11 @@ there is no such restriction. @quotation -"An implementation should support @code{Long_Integer} in addition to +“An implementation should support @code{Long_Integer} in addition to @code{Integer} if the target machine supports 32-bit (or longer) arithmetic. No other named integer subtypes are recommended for package @code{Standard}. Instead, appropriate named integer subtypes should be -provided in the library package @code{Interfaces} (see B.2)." +provided in the library package @code{Interfaces} (see B.2).” @end quotation @code{Long_Integer} is supported. Other standard integer types are supported @@ -13872,9 +13872,9 @@ types of the machine are easily available. @quotation -"An implementation for a two's complement machine should support +“An implementation for a two’s complement machine should support modular types with a binary modulus up to @code{System.Max_Int*2+2}. An -implementation should support a non-binary modules up to @code{Integer'Last}." +implementation should support a non-binary modules up to @code{Integer'Last}.” @end quotation Followed. @@ -13888,13 +13888,13 @@ Followed. @quotation -"For the evaluation of a call on @code{S'Pos} for an enumeration +“For the evaluation of a call on @code{S'Pos} for an enumeration subtype, if the value of the operand does not correspond to the internal code for any enumeration literal of its type (perhaps due to an un-initialized variable), then the implementation should raise @code{Program_Error}. This is particularly important for enumeration types with noncontiguous internal codes specified by an -enumeration_representation_clause." +enumeration_representation_clause.” @end quotation Followed. @@ -13908,11 +13908,11 @@ Followed. @quotation -"An implementation should support @code{Long_Float} in addition to +“An implementation should support @code{Long_Float} in addition to @code{Float} if the target machine supports 11 or more digits of precision. No other named floating point subtypes are recommended for package @code{Standard}. Instead, appropriate named floating point subtypes -should be provided in the library package @code{Interfaces} (see B.2)." +should be provided in the library package @code{Interfaces} (see B.2).” @end quotation @code{Short_Float} and @code{Long_Long_Float} are also provided. The @@ -13931,57 +13931,57 @@ is a software rather than a hardware format. @geindex Arrays @geindex multidimensional -@node RM 3 6 2 11 Multidimensional Arrays,RM 9 6 30-31 Duration'Small,RM 3 5 7 17 Float Types,Implementation Advice +@node RM 3 6 2 11 Multidimensional Arrays,RM 9 6 30-31 Duration’Small,RM 3 5 7 17 Float Types,Implementation Advice @anchor{gnat_rm/implementation_advice rm-3-6-2-11-multidimensional-arrays}@anchor{221} @section RM 3.6.2(11): Multidimensional Arrays @quotation -"An implementation should normally represent multidimensional arrays in +“An implementation should normally represent multidimensional arrays in row-major order, consistent with the notation used for multidimensional array aggregates (see 4.3.3). However, if a pragma @code{Convention} -(@code{Fortran}, ...) applies to a multidimensional array type, then -column-major order should be used instead (see B.5, @emph{Interfacing with Fortran})." +(@code{Fortran}, …) applies to a multidimensional array type, then +column-major order should be used instead (see B.5, @emph{Interfacing with Fortran}).” @end quotation Followed. @geindex Duration'Small -@node RM 9 6 30-31 Duration'Small,RM 10 2 1 12 Consistent Representation,RM 3 6 2 11 Multidimensional Arrays,Implementation Advice +@node RM 9 6 30-31 Duration’Small,RM 10 2 1 12 Consistent Representation,RM 3 6 2 11 Multidimensional Arrays,Implementation Advice @anchor{gnat_rm/implementation_advice rm-9-6-30-31-duration-small}@anchor{222} -@section RM 9.6(30-31): Duration'Small +@section RM 9.6(30-31): Duration’Small @quotation -"Whenever possible in an implementation, the value of @code{Duration'Small} -should be no greater than 100 microseconds." +“Whenever possible in an implementation, the value of @code{Duration'Small} +should be no greater than 100 microseconds.” @end quotation Followed. (@code{Duration'Small} = 10**(-9)). @quotation -"The time base for @code{delay_relative_statements} should be monotonic; -it need not be the same time base as used for @code{Calendar.Clock}." +“The time base for @code{delay_relative_statements} should be monotonic; +it need not be the same time base as used for @code{Calendar.Clock}.” @end quotation Followed. -@node RM 10 2 1 12 Consistent Representation,RM 11 4 1 19 Exception Information,RM 9 6 30-31 Duration'Small,Implementation Advice +@node RM 10 2 1 12 Consistent Representation,RM 11 4 1 19 Exception Information,RM 9 6 30-31 Duration’Small,Implementation Advice @anchor{gnat_rm/implementation_advice rm-10-2-1-12-consistent-representation}@anchor{223} @section RM 10.2.1(12): Consistent Representation @quotation -"In an implementation, a type declared in a pre-elaborated package should +“In an implementation, a type declared in a pre-elaborated package should have the same representation in every elaboration of a given version of the package, whether the elaborations occur in distinct executions of the same program, or in executions of distinct programs or partitions -that include the given version." +that include the given version.” @end quotation Followed, except in the case of tagged types. Tagged types involve @@ -13999,18 +13999,18 @@ advice without severely impacting efficiency of execution. @quotation -"@code{Exception_Message} by default and @code{Exception_Information} +“@code{Exception_Message} by default and @code{Exception_Information} should produce information useful for debugging. @code{Exception_Message} should be short, about one line. @code{Exception_Information} can be long. @code{Exception_Message} should not include the @code{Exception_Name}. @code{Exception_Information} should include both -the @code{Exception_Name} and the @code{Exception_Message}." +the @code{Exception_Name} and the @code{Exception_Message}.” @end quotation -Followed. For each exception that doesn't have a specified +Followed. For each exception that doesn’t have a specified @code{Exception_Message}, the compiler generates one containing the location -of the raise statement. This location has the form 'file_name:line', where +of the raise statement. This location has the form ‘file_name:line’, where file_name is the short file name (without path information) and line is the line number in the file. Note that in the case of the Zero Cost Exception mechanism, these messages become redundant with the Exception_Information that @@ -14030,8 +14030,8 @@ Pragma @code{Discard_Names}. @quotation -"The implementation should minimize the code executed for checks that -have been suppressed." +“The implementation should minimize the code executed for checks that +have been suppressed.” @end quotation Followed. @@ -14045,14 +14045,14 @@ Followed. @quotation -"The recommended level of support for all representation items is +“The recommended level of support for all representation items is qualified as follows: An implementation need not support representation items containing nonstatic expressions, except that an implementation should support a representation item for a given entity if each nonstatic expression in the representation item is a name that statically denotes a constant -declared before the entity." +declared before the entity.” @end quotation Followed. In fact, GNAT goes beyond the recommended level of support @@ -14079,8 +14079,8 @@ described above. @quotation -"An aliased component, or a component whose type is by-reference, should -always be allocated at an addressable location." +“An aliased component, or a component whose type is by-reference, should +always be allocated at an addressable location.” @end quotation Followed. @@ -14094,7 +14094,7 @@ Followed. @quotation -"If a type is packed, then the implementation should try to minimize +“If a type is packed, then the implementation should try to minimize storage allocated to objects of the type, possibly at the expense of speed of accessing components, subject to reasonable complexity in addressing calculations. @@ -14106,7 +14106,7 @@ possible subject to the Sizes of the component subtypes, and subject to any @emph{record_representation_clause} that applies to the type; the implementation may, but need not, reorder components or cross aligned word boundaries to improve the packing. A component whose @code{Size} is -greater than the word size may be allocated an integral number of words." +greater than the word size may be allocated an integral number of words.” @end quotation Followed. Tight packing of arrays is supported for all component sizes @@ -14118,8 +14118,8 @@ subcomponent of the packed type. @quotation -"An implementation should support Address clauses for imported -subprograms." +“An implementation should support Address clauses for imported +subprograms.” @end quotation Followed. @@ -14133,19 +14133,19 @@ Followed. @quotation -"For an array @code{X}, @code{X'Address} should point at the first -component of the array, and not at the array bounds." +“For an array @code{X}, @code{X'Address} should point at the first +component of the array, and not at the array bounds.” @end quotation Followed. @quotation -"The recommended level of support for the @code{Address} attribute is: +“The recommended level of support for the @code{Address} attribute is: @code{X'Address} should produce a useful result if @code{X} is an object that is aliased or of a by-reference type, or is an entity whose -@code{Address} has been specified." +@code{Address} has been specified.” @end quotation Followed. A valid address will be produced even if none of those @@ -14154,25 +14154,25 @@ memory to ensure the address is valid. @quotation -"An implementation should support @code{Address} clauses for imported -subprograms." +“An implementation should support @code{Address} clauses for imported +subprograms.” @end quotation Followed. @quotation -"Objects (including subcomponents) that are aliased or of a by-reference -type should be allocated on storage element boundaries." +“Objects (including subcomponents) that are aliased or of a by-reference +type should be allocated on storage element boundaries.” @end quotation Followed. @quotation -"If the @code{Address} of an object is specified, or it is imported or exported, +“If the @code{Address} of an object is specified, or it is imported or exported, then the implementation should not perform optimizations based on -assumptions of no aliases." +assumptions of no aliases.” @end quotation Followed. @@ -14186,50 +14186,50 @@ Followed. @quotation -"The recommended level of support for the @code{Alignment} attribute for +“The recommended level of support for the @code{Alignment} attribute for subtypes is: An implementation should support specified Alignments that are factors and multiples of the number of storage elements per word, subject to the -following:" +following:” @end quotation Followed. @quotation -"An implementation need not support specified Alignments for +“An implementation need not support specified Alignments for combinations of Sizes and Alignments that cannot be easily -loaded and stored by available machine instructions." +loaded and stored by available machine instructions.” @end quotation Followed. @quotation -"An implementation need not support specified Alignments that are +“An implementation need not support specified Alignments that are greater than the maximum @code{Alignment} the implementation ever returns by -default." +default.” @end quotation Followed. @quotation -"The recommended level of support for the @code{Alignment} attribute for +“The recommended level of support for the @code{Alignment} attribute for objects is: -Same as above, for subtypes, but in addition:" +Same as above, for subtypes, but in addition:” @end quotation Followed. @quotation -"For stand-alone library-level objects of statically constrained +“For stand-alone library-level objects of statically constrained subtypes, the implementation should support all alignments supported by the target linker. For example, page alignment is likely to -be supported for such objects, but not for subtypes." +be supported for such objects, but not for subtypes.” @end quotation Followed. @@ -14243,13 +14243,13 @@ Followed. @quotation -"The recommended level of support for the @code{Size} attribute of +“The recommended level of support for the @code{Size} attribute of objects is: A @code{Size} clause should be supported for an object if the specified -@code{Size} is at least as large as its subtype's @code{Size}, and +@code{Size} is at least as large as its subtype’s @code{Size}, and corresponds to a size in storage elements that is a multiple of the -object's @code{Alignment} (if the @code{Alignment} is nonzero)." +object’s @code{Alignment} (if the @code{Alignment} is nonzero).” @end quotation Followed. @@ -14261,20 +14261,20 @@ Followed. @quotation -"If the @code{Size} of a subtype is specified, and allows for efficient +“If the @code{Size} of a subtype is specified, and allows for efficient independent addressability (see 9.10) on the target architecture, then the @code{Size} of the following objects of the subtype should equal the @code{Size} of the subtype: -Aliased objects (including components)." +Aliased objects (including components).” @end quotation Followed. @quotation -"@cite{Size} clause on a composite subtype should not affect the -internal layout of components." +“@cite{Size} clause on a composite subtype should not affect the +internal layout of components.” @end quotation Followed. But note that this can be overridden by use of the implementation @@ -14282,23 +14282,23 @@ pragma Implicit_Packing in the case of packed arrays. @quotation -"The recommended level of support for the @code{Size} attribute of subtypes is: +“The recommended level of support for the @code{Size} attribute of subtypes is: The @code{Size} (if not specified) of a static discrete or fixed point subtype should be the number of bits needed to represent each value belonging to the subtype using an unbiased representation, leaving space for a sign bit only if the subtype contains negative values. If such a subtype is a first subtype, then an implementation should support a -specified @code{Size} for it that reflects this representation." +specified @code{Size} for it that reflects this representation.” @end quotation Followed. @quotation -"For a subtype implemented with levels of indirection, the @code{Size} +“For a subtype implemented with levels of indirection, the @code{Size} should include the size of the pointers, but not the size of what they -point at." +point at.” @end quotation Followed. @@ -14312,24 +14312,24 @@ Followed. @quotation -"The recommended level of support for the @code{Component_Size} +“The recommended level of support for the @code{Component_Size} attribute is: An implementation need not support specified @code{Component_Sizes} that are -less than the @code{Size} of the component subtype." +less than the @code{Size} of the component subtype.” @end quotation Followed. @quotation -"An implementation should support specified Component_Sizes that +“An implementation should support specified Component_Sizes that are factors and multiples of the word size. For such Component_Sizes, the array should contain no gaps between components. For other Component_Sizes (if supported), the array should contain no gaps between components when packing is also specified; the implementation should forbid this combination in cases -where it cannot support a no-gaps representation." +where it cannot support a no-gaps representation.” @end quotation Followed. @@ -14346,12 +14346,12 @@ Followed. @quotation -"The recommended level of support for enumeration representation clauses +“The recommended level of support for enumeration representation clauses is: An implementation need not support enumeration representation clauses for boolean types, but should at minimum support the internal codes in -the range @code{System.Min_Int .. System.Max_Int}." +the range @code{System.Min_Int .. System.Max_Int}.” @end quotation Followed. @@ -14368,52 +14368,52 @@ Followed. @quotation -"The recommended level of support for +“The recommended level of support for @emph{record_representation_clause}s is: An implementation should support storage places that can be extracted with a load, mask, shift sequence of machine code, and set with a load, shift, mask, store sequence, given the available machine instructions -and run-time model." +and run-time model.” @end quotation Followed. @quotation -"A storage place should be supported if its size is equal to the +“A storage place should be supported if its size is equal to the @code{Size} of the component subtype, and it starts and ends on a -boundary that obeys the @code{Alignment} of the component subtype." +boundary that obeys the @code{Alignment} of the component subtype.” @end quotation Followed. @quotation -"If the default bit ordering applies to the declaration of a given type, -then for a component whose subtype's @code{Size} is less than the word +“If the default bit ordering applies to the declaration of a given type, +then for a component whose subtype’s @code{Size} is less than the word size, any storage place that does not cross an aligned word boundary -should be supported." +should be supported.” @end quotation Followed. @quotation -"An implementation may reserve a storage place for the tag field of a -tagged type, and disallow other components from overlapping that place." +“An implementation may reserve a storage place for the tag field of a +tagged type, and disallow other components from overlapping that place.” @end quotation Followed. The storage place for the tag field is the beginning of the tagged -record, and its size is Address'Size. GNAT will reject an explicit component +record, and its size is Address’Size. GNAT will reject an explicit component clause for the tag field. @quotation -"An implementation need not support a @emph{component_clause} for a +“An implementation need not support a @emph{component_clause} for a component of an extension part if the storage place is not after the storage places of all components of the parent type, whether or not -those storage places had been specified." +those storage places had been specified.” @end quotation Followed. The above advice on record representation clauses is followed, @@ -14428,13 +14428,13 @@ and all mentioned features are implemented. @quotation -"If a component is represented using some form of pointer (such as an +“If a component is represented using some form of pointer (such as an offset) to the actual data of the component, and this data is contiguous with the rest of the object, then the storage place attributes should reflect the place of the actual data, not the pointer. If a component is allocated discontinuously from the rest of the object, then a warning should be generated upon reference to one of its storage place -attributes." +attributes.” @end quotation Followed. There are no such components in GNAT. @@ -14448,11 +14448,11 @@ Followed. There are no such components in GNAT. @quotation -"The recommended level of support for the non-default bit ordering is: +“The recommended level of support for the non-default bit ordering is: If @code{Word_Size} = @code{Storage_Unit}, then the implementation should support the non-default bit ordering in addition to the default -bit ordering." +bit ordering.” @end quotation Followed. Word size does not equal storage size in this implementation. @@ -14468,7 +14468,7 @@ Thus non-default bit ordering is not supported. @quotation -"@cite{Address} should be of a private type." +“@cite{Address} should be of a private type.” @end quotation Followed. @@ -14486,10 +14486,10 @@ Followed. @quotation -"Operations in @code{System} and its children should reflect the target +“Operations in @code{System} and its children should reflect the target environment semantics as closely as is reasonable. For example, on most -machines, it makes sense for address arithmetic to 'wrap around'. -Operations that do not make sense should raise @code{Program_Error}." +machines, it makes sense for address arithmetic to ‘wrap around’. +Operations that do not make sense should raise @code{Program_Error}.” @end quotation Followed. Address arithmetic is modular arithmetic that wraps around. No @@ -14504,19 +14504,19 @@ operation raises @code{Program_Error}, since all operations make sense. @quotation -"The @code{Size} of an array object should not include its bounds; hence, -the bounds should not be part of the converted data." +“The @code{Size} of an array object should not include its bounds; hence, +the bounds should not be part of the converted data.” @end quotation Followed. @quotation -"The implementation should not generate unnecessary run-time checks to +“The implementation should not generate unnecessary run-time checks to ensure that the representation of @code{S} is a representation of the target type. It should take advantage of the permission to return by reference when possible. Restrictions on unchecked conversions should be -avoided unless required by the target environment." +avoided unless required by the target environment.” @end quotation Followed. There are no restrictions on unchecked conversion. A warning is @@ -14525,7 +14525,7 @@ the semantics in this case may be target dependent. @quotation -"The recommended level of support for unchecked conversions is: +“The recommended level of support for unchecked conversions is: Unchecked conversions should be supported and should be reversible in the cases where this clause defines the result. To enable meaningful use @@ -14533,7 +14533,7 @@ of unchecked conversion, a contiguous representation should be used for elementary subtypes, for statically constrained array subtypes whose component subtype is one of the subtypes described in this paragraph, and for record subtypes without discriminants whose component subtypes -are described in this paragraph." +are described in this paragraph.” @end quotation Followed. @@ -14548,9 +14548,9 @@ Followed. @quotation -"An implementation should document any cases in which it dynamically +“An implementation should document any cases in which it dynamically allocates heap storage for a purpose other than the evaluation of an -allocator." +allocator.” @end quotation Followed, the only other points at which heap storage is dynamically @@ -14574,18 +14574,18 @@ stack is used for returning variable length results. @quotation -"A default (implementation-provided) storage pool for an +“A default (implementation-provided) storage pool for an access-to-constant type should not have overhead to support deallocation of -individual objects." +individual objects.” @end quotation Followed. @quotation -"A storage pool for an anonymous access type should be created at the +“A storage pool for an anonymous access type should be created at the point of an allocator for the type, and be reclaimed when the designated -object becomes inaccessible." +object becomes inaccessible.” @end quotation Followed. @@ -14599,8 +14599,8 @@ Followed. @quotation -"For a standard storage pool, @code{Free} should actually reclaim the -storage." +“For a standard storage pool, @code{Free} should actually reclaim the +storage.” @end quotation Followed. @@ -14614,11 +14614,11 @@ Followed. @quotation -"If not specified, the value of Stream_Size for an elementary type +“If not specified, the value of Stream_Size for an elementary type should be the number of bits that corresponds to the minimum number of stream elements required by the first subtype of the type, rounded up to the nearest factor or multiple of the word size that is also a -multiple of the stream element size." +multiple of the stream element size.” @end quotation Followed, except that the number of stream elements is 1, 2, 3, 4 or 8. @@ -14645,11 +14645,11 @@ scalar types. This XDR alternative can be enabled via the binder switch -xdr. @quotation -"If an implementation provides additional named predefined integer types, +“If an implementation provides additional named predefined integer types, then the names should end with @code{Integer} as in @code{Long_Integer}. If an implementation provides additional named predefined floating point types, then the names should end with -@code{Float} as in @code{Long_Float}." +@code{Float} as in @code{Long_Float}.” @end quotation Followed. @@ -14663,10 +14663,10 @@ Followed. @quotation -"If an implementation provides a localized definition of @code{Character} +“If an implementation provides a localized definition of @code{Character} or @code{Wide_Character}, then the effects of the subprograms in @code{Characters.Handling} should reflect the localizations. -See also 3.5.2." +See also 3.5.2.” @end quotation Followed. GNAT provides no such localized definitions. @@ -14680,8 +14680,8 @@ Followed. GNAT provides no such localized definitions. @quotation -"Bounded string objects should not be implemented by implicit pointers -and dynamic allocation." +“Bounded string objects should not be implemented by implicit pointers +and dynamic allocation.” @end quotation Followed. No implicit pointers or dynamic allocation are used. @@ -14695,21 +14695,21 @@ Followed. No implicit pointers or dynamic allocation are used. @quotation -"Any storage associated with an object of type @code{Generator} should be -reclaimed on exit from the scope of the object." +“Any storage associated with an object of type @code{Generator} should be +reclaimed on exit from the scope of the object.” @end quotation Followed. @quotation -"If the generator period is sufficiently long in relation to the number +“If the generator period is sufficiently long in relation to the number of distinct initiator values, then each possible value of @code{Initiator} passed to @code{Reset} should initiate a sequence of random numbers that does not, in a practical sense, overlap the sequence initiated by any other value. If this is not possible, then the mapping between initiator values and generator states should be a rapidly -varying function of the initiator value." +varying function of the initiator value.” @end quotation Followed. The generator period is sufficiently long for the first @@ -14724,13 +14724,13 @@ condition here to hold true. @quotation -"The @code{Get_Immediate} procedures should be implemented with +“The @code{Get_Immediate} procedures should be implemented with unbuffered input. For a device such as a keyboard, input should be available if a key has already been typed, whereas for a disk file, input should always be available except at end of file. For a file associated with a keyboard-like device, any line-editing features of the underlying operating system should be disabled during the execution of -@code{Get_Immediate}." +@code{Get_Immediate}.” @end quotation Followed on all targets except VxWorks. For VxWorks, there is no way to @@ -14752,7 +14752,7 @@ section A.18 and its subsections) is followed except for A.18.24(17): @quotation -"Bounded ordered set objects should be implemented without implicit pointers or dynamic allocation. " +“Bounded ordered set objects should be implemented without implicit pointers or dynamic allocation. “ @end quotation The implementations of the two Reference_Preserving_Key functions of @@ -14769,7 +14769,7 @@ follow the implementation advice. @quotation -"If an implementation supports pragma @code{Export} to a given language, +“If an implementation supports pragma @code{Export} to a given language, then it should also allow the main subprogram to be written in that language. It should support some mechanism for invoking the elaboration of the Ada library units included in the system, and for invoking the @@ -14778,15 +14778,15 @@ recommended mechanism is to provide two subprograms whose link names are @code{adainit} and @code{adafinal}. @code{adainit} should contain the elaboration code for library units. @code{adafinal} should contain the finalization code. These subprograms should have no effect the second -and subsequent time they are called." +and subsequent time they are called.” @end quotation Followed. @quotation -"Automatic elaboration of pre-elaborated packages should be -provided when pragma @code{Export} is supported." +“Automatic elaboration of pre-elaborated packages should be +provided when pragma @code{Export} is supported.” @end quotation Followed when the main program is in Ada. If the main program is in a @@ -14796,12 +14796,12 @@ packages. @quotation -"For each supported convention @emph{L} other than @code{Intrinsic}, an +“For each supported convention @emph{L} other than @code{Intrinsic}, an implementation should support @code{Import} and @code{Export} pragmas for objects of @emph{L}-compatible types and for subprograms, and pragma @cite{Convention} for @emph{L}-eligible types and for subprograms, presuming the other language has corresponding features. Pragma -@code{Convention} need not be supported for scalar types." +@code{Convention} need not be supported for scalar types.” @end quotation Followed. @@ -14817,22 +14817,22 @@ Followed. @quotation -"For each implementation-defined convention identifier, there should be a +“For each implementation-defined convention identifier, there should be a child package of package Interfaces with the corresponding name. This package should contain any declarations that would be useful for interfacing to the language (implementation) represented by the convention. Any declarations useful for interfacing to any language on the given hardware architecture should be provided directly in -@code{Interfaces}." +@code{Interfaces}.” @end quotation Followed. @quotation -"An implementation supporting an interface to C, COBOL, or Fortran should +“An implementation supporting an interface to C, COBOL, or Fortran should provide the corresponding package or packages described in the following -clauses." +clauses.” @end quotation Followed. GNAT provides all the packages described in this section. @@ -14847,60 +14847,60 @@ Followed. GNAT provides all the packages described in this section. @quotation -"An implementation should support the following interface correspondences -between Ada and C." +“An implementation should support the following interface correspondences +between Ada and C.” @end quotation Followed. @quotation -"An Ada procedure corresponds to a void-returning C function." +“An Ada procedure corresponds to a void-returning C function.” @end quotation Followed. @quotation -"An Ada function corresponds to a non-void C function." +“An Ada function corresponds to a non-void C function.” @end quotation Followed. @quotation -"An Ada @code{in} scalar parameter is passed as a scalar argument to a C -function." +“An Ada @code{in} scalar parameter is passed as a scalar argument to a C +function.” @end quotation Followed. @quotation -"An Ada @code{in} parameter of an access-to-object type with designated +“An Ada @code{in} parameter of an access-to-object type with designated type @code{T} is passed as a @code{t*} argument to a C function, -where @code{t} is the C type corresponding to the Ada type @code{T}." +where @code{t} is the C type corresponding to the Ada type @code{T}.” @end quotation Followed. @quotation -"An Ada access @code{T} parameter, or an Ada @code{out} or @code{in out} +“An Ada access @code{T} parameter, or an Ada @code{out} or @code{in out} parameter of an elementary type @code{T}, is passed as a @code{t*} argument to a C function, where @code{t} is the C type corresponding to the Ada type @code{T}. In the case of an elementary @code{out} or @code{in out} parameter, a pointer to a temporary copy is used to -preserve by-copy semantics." +preserve by-copy semantics.” @end quotation Followed. @quotation -"An Ada parameter of a record type @code{T}, of any mode, is passed as a +“An Ada parameter of a record type @code{T}, of any mode, is passed as a @code{t*} argument to a C function, where @code{t} is the C -structure corresponding to the Ada type @code{T}." +structure corresponding to the Ada type @code{T}.” @end quotation Followed. This convention may be overridden by the use of the C_Pass_By_Copy @@ -14909,18 +14909,18 @@ call using an extended import or export pragma. @quotation -"An Ada parameter of an array type with component type @code{T}, of any +“An Ada parameter of an array type with component type @code{T}, of any mode, is passed as a @code{t*} argument to a C function, where -@code{t} is the C type corresponding to the Ada type @code{T}." +@code{t} is the C type corresponding to the Ada type @code{T}.” @end quotation Followed. @quotation -"An Ada parameter of an access-to-subprogram type is passed as a pointer +“An Ada parameter of an access-to-subprogram type is passed as a pointer to a C function whose prototype corresponds to the designated -subprogram's specification." +subprogram’s specification.” @end quotation Followed. @@ -14935,33 +14935,33 @@ Followed. @quotation -"An Ada implementation should support the following interface -correspondences between Ada and COBOL." +“An Ada implementation should support the following interface +correspondences between Ada and COBOL.” @end quotation Followed. @quotation -"An Ada access @code{T} parameter is passed as a @code{BY REFERENCE} data item of -the COBOL type corresponding to @code{T}." +“An Ada access @code{T} parameter is passed as a @code{BY REFERENCE} data item of +the COBOL type corresponding to @code{T}.” @end quotation Followed. @quotation -"An Ada in scalar parameter is passed as a @code{BY CONTENT} data item of -the corresponding COBOL type." +“An Ada in scalar parameter is passed as a @code{BY CONTENT} data item of +the corresponding COBOL type.” @end quotation Followed. @quotation -"Any other Ada parameter is passed as a @code{BY REFERENCE} data item of the +“Any other Ada parameter is passed as a @code{BY REFERENCE} data item of the COBOL type corresponding to the Ada parameter type; for scalars, a local -copy is used if necessary to ensure by-copy semantics." +copy is used if necessary to ensure by-copy semantics.” @end quotation Followed. @@ -14976,44 +14976,44 @@ Followed. @quotation -"An Ada implementation should support the following interface -correspondences between Ada and Fortran:" +“An Ada implementation should support the following interface +correspondences between Ada and Fortran:” @end quotation Followed. @quotation -"An Ada procedure corresponds to a Fortran subroutine." +“An Ada procedure corresponds to a Fortran subroutine.” @end quotation Followed. @quotation -"An Ada function corresponds to a Fortran function." +“An Ada function corresponds to a Fortran function.” @end quotation Followed. @quotation -"An Ada parameter of an elementary, array, or record type @code{T} is +“An Ada parameter of an elementary, array, or record type @code{T} is passed as a @code{T} argument to a Fortran procedure, where @code{T} is the Fortran type corresponding to the Ada type @code{T}, and where the INTENT attribute of the corresponding dummy argument matches the Ada -formal parameter mode; the Fortran implementation's parameter passing +formal parameter mode; the Fortran implementation’s parameter passing conventions are used. For elementary types, a local copy is used if -necessary to ensure by-copy semantics." +necessary to ensure by-copy semantics.” @end quotation Followed. @quotation -"An Ada parameter of an access-to-subprogram type is passed as a +“An Ada parameter of an access-to-subprogram type is passed as a reference to a Fortran procedure whose interface corresponds to the -designated subprogram's specification." +designated subprogram’s specification.” @end quotation Followed. @@ -15027,30 +15027,30 @@ Followed. @quotation -"The machine code or intrinsic support should allow access to all +“The machine code or intrinsic support should allow access to all operations normally available to assembly language programmers for the -target environment, including privileged instructions, if any." +target environment, including privileged instructions, if any.” @end quotation Followed. @quotation -"The interfacing pragmas (see Annex B) should support interface to +“The interfacing pragmas (see Annex B) should support interface to assembler; the default assembler should be associated with the -convention identifier @code{Assembler}." +convention identifier @code{Assembler}.” @end quotation Followed. @quotation -"If an entity is exported to assembly language, then the implementation +“If an entity is exported to assembly language, then the implementation should allocate it at an addressable location, and should ensure that it is retained by the linking process, even if not otherwise referenced from the Ada code. The implementation should assume that any call to a machine code or assembler subprogram is allowed to read or update every -object that is specified as exported." +object that is specified as exported.” @end quotation Followed. @@ -15062,54 +15062,54 @@ Followed. @quotation -"The implementation should ensure that little or no overhead is -associated with calling intrinsic and machine-code subprograms." +“The implementation should ensure that little or no overhead is +associated with calling intrinsic and machine-code subprograms.” @end quotation Followed for both intrinsics and machine-code subprograms. @quotation -"It is recommended that intrinsic subprograms be provided for convenient +“It is recommended that intrinsic subprograms be provided for convenient access to any machine operations that provide special capabilities or efficiency and that are not otherwise available through the language -constructs." +constructs.” @end quotation Followed. A full set of machine operation intrinsic subprograms is provided. @quotation -"Atomic read-modify-write operations---e.g., test and set, compare and -swap, decrement and test, enqueue/dequeue." +“Atomic read-modify-write operations—e.g., test and set, compare and +swap, decrement and test, enqueue/dequeue.” @end quotation Followed on any target supporting such operations. @quotation -"Standard numeric functions---e.g.:, sin, log." +“Standard numeric functions—e.g.:, sin, log.” @end quotation Followed on any target supporting such operations. @quotation -"String manipulation operations---e.g.:, translate and test." +“String manipulation operations—e.g.:, translate and test.” @end quotation Followed on any target supporting such operations. @quotation -"Vector operations---e.g.:, compare vector against thresholds." +“Vector operations—e.g.:, compare vector against thresholds.” @end quotation Followed on any target supporting such operations. @quotation -"Direct operations on I/O ports." +“Direct operations on I/O ports.” @end quotation Followed on any target supporting such operations. @@ -15123,10 +15123,10 @@ Followed on any target supporting such operations. @quotation -"If the @code{Ceiling_Locking} policy is not in effect, the +“If the @code{Ceiling_Locking} policy is not in effect, the implementation should provide means for the application to specify which interrupts are to be blocked during protected actions, if the underlying -system allows for a finer-grain control of interrupt blocking." +system allows for a finer-grain control of interrupt blocking.” @end quotation Followed. The underlying system does not allow for finer-grain control @@ -15141,8 +15141,8 @@ of interrupt blocking. @quotation -"Whenever possible, the implementation should allow interrupt handlers to -be called directly by the hardware." +“Whenever possible, the implementation should allow interrupt handlers to +be called directly by the hardware.” @end quotation Followed on any target where the underlying operating system permits @@ -15150,8 +15150,8 @@ such direct calls. @quotation -"Whenever practical, violations of any -implementation-defined restrictions should be detected before run time." +“Whenever practical, violations of any +implementation-defined restrictions should be detected before run time.” @end quotation Followed. Compile time warnings are given when possible. @@ -15167,11 +15167,11 @@ Followed. Compile time warnings are given when possible. @quotation -"If implementation-defined forms of interrupt handler procedures are +“If implementation-defined forms of interrupt handler procedures are supported, such as protected procedures with parameters, then for each such form of a handler, a type analogous to @code{Parameterless_Handler} should be specified in a child package of @code{Interrupts}, with the -same operations as in the predefined package Interrupts." +same operations as in the predefined package Interrupts.” @end quotation Followed. @@ -15185,10 +15185,10 @@ Followed. @quotation -"It is recommended that pre-elaborated packages be implemented in such a +“It is recommended that pre-elaborated packages be implemented in such a way that there should be little or no code executed at run time for the elaboration of entities not already covered by the Implementation -Requirements." +Requirements.” @end quotation Followed. Executable code is generated in some cases, e.g., loops @@ -15201,9 +15201,9 @@ to initialize large arrays. @quotation -"If the pragma applies to an entity, then the implementation should +“If the pragma applies to an entity, then the implementation should reduce the amount of storage used for storing names associated with that -entity." +entity.” @end quotation Followed. @@ -15219,14 +15219,14 @@ Followed. @quotation -"Some implementations are targeted to domains in which memory use at run +“Some implementations are targeted to domains in which memory use at run time must be completely deterministic. For such implementations, it is recommended that the storage for task attributes will be pre-allocated statically and not from the heap. This can be accomplished by either -placing restrictions on the number and the size of the task's +placing restrictions on the number and the size of the task’s attributes, or by using the pre-allocated storage for the first @code{N} attribute objects, and the heap for the others. In the latter case, -@code{N} should be documented." +@code{N} should be documented.” @end quotation Not followed. This implementation is not targeted to such a domain. @@ -15240,8 +15240,8 @@ Not followed. This implementation is not targeted to such a domain. @quotation -"The implementation should use names that end with @code{_Locking} for -locking policies defined by the implementation." +“The implementation should use names that end with @code{_Locking} for +locking policies defined by the implementation.” @end quotation Followed. Two implementation-defined locking policies are defined, @@ -15257,8 +15257,8 @@ whose names (@code{Inheritance_Locking} and @quotation -"Names that end with @code{_Queuing} should be used -for all implementation-defined queuing policies." +“Names that end with @code{_Queuing} should be used +for all implementation-defined queuing policies.” @end quotation Followed. No such implementation-defined queuing policies exist. @@ -15272,19 +15272,19 @@ Followed. No such implementation-defined queuing policies exist. @quotation -"Even though the @emph{abort_statement} is included in the list of +“Even though the @emph{abort_statement} is included in the list of potentially blocking operations (see 9.5.1), it is recommended that this statement be implemented in a way that never requires the task executing -the @emph{abort_statement} to block." +the @emph{abort_statement} to block.” @end quotation Followed. @quotation -"On a multi-processor, the delay associated with aborting a task on +“On a multi-processor, the delay associated with aborting a task on another processor should be bounded; the implementation should use -periodic polling, if necessary, to achieve this." +periodic polling, if necessary, to achieve this.” @end quotation Followed. @@ -15298,8 +15298,8 @@ Followed. @quotation -"When feasible, the implementation should take advantage of the specified -restrictions to produce a more efficient implementation." +“When feasible, the implementation should take advantage of the specified +restrictions to produce a more efficient implementation.” @end quotation GNAT currently takes advantage of these restrictions by providing an optimized @@ -15317,8 +15317,8 @@ pragma @code{Profile (Restricted)} for more details. @quotation -"When appropriate, implementations should provide configuration -mechanisms to change the value of @code{Tick}." +“When appropriate, implementations should provide configuration +mechanisms to change the value of @code{Tick}.” @end quotation Such configuration mechanisms are not appropriate to this implementation @@ -15326,17 +15326,17 @@ and are thus not supported. @quotation -"It is recommended that @code{Calendar.Clock} and @code{Real_Time.Clock} -be implemented as transformations of the same time base." +“It is recommended that @code{Calendar.Clock} and @code{Real_Time.Clock} +be implemented as transformations of the same time base.” @end quotation Followed. @quotation -"It is recommended that the best time base which exists in +“It is recommended that the best time base which exists in the underlying system be available to the application through -@code{Clock}. @cite{Best} may mean highest accuracy or largest range." +@code{Clock}. @cite{Best} may mean highest accuracy or largest range.” @end quotation Followed. @@ -15352,10 +15352,10 @@ Followed. @quotation -"Whenever possible, the PCS on the called partition should allow for +“Whenever possible, the PCS on the called partition should allow for multiple tasks to call the RPC-receiver with different messages and should allow them to block until the corresponding subprogram body -returns." +returns.” @end quotation Followed by GLADE, a separately supplied PCS that can be used with @@ -15363,9 +15363,9 @@ GNAT. @quotation -"The @code{Write} operation on a stream of type @code{Params_Stream_Type} +“The @code{Write} operation on a stream of type @code{Params_Stream_Type} should raise @code{Storage_Error} if it runs out of space trying to -write the @code{Item} into the stream." +write the @code{Item} into the stream.” @end quotation Followed by GLADE, a separately supplied PCS that can be used with @@ -15380,13 +15380,13 @@ GNAT. @quotation -"If COBOL (respectively, C) is widely supported in the target +“If COBOL (respectively, C) is widely supported in the target environment, implementations supporting the Information Systems Annex should provide the child package @code{Interfaces.COBOL} (respectively, @code{Interfaces.C}) specified in Annex B and should support a @code{convention_identifier} of COBOL (respectively, C) in the interfacing pragmas (see Annex B), thus allowing Ada programs to interface with -programs written in that language." +programs written in that language.” @end quotation Followed. @@ -15400,11 +15400,11 @@ Followed. @quotation -"Packed decimal should be used as the internal representation for objects -of subtype @code{S} when @code{S}'Machine_Radix = 10." +“Packed decimal should be used as the internal representation for objects +of subtype @code{S} when @code{S}’Machine_Radix = 10.” @end quotation -Not followed. GNAT ignores @code{S}'Machine_Radix and always uses binary +Not followed. GNAT ignores @code{S}’Machine_Radix and always uses binary representations. @geindex Numerics @@ -15416,13 +15416,13 @@ representations. @quotation -"If Fortran (respectively, C) is widely supported in the target +“If Fortran (respectively, C) is widely supported in the target environment, implementations supporting the Numerics Annex should provide the child package @code{Interfaces.Fortran} (respectively, @code{Interfaces.C}) specified in Annex B and should support a @code{convention_identifier} of Fortran (respectively, C) in the interfacing pragmas (see Annex B), thus allowing Ada programs to interface with -programs written in that language." +programs written in that language.” @end quotation Followed. @@ -15436,7 +15436,7 @@ Followed. @quotation -"Because the usual mathematical meaning of multiplication of a complex +“Because the usual mathematical meaning of multiplication of a complex operand and a real operand is that of the scaling of both components of the former by the latter, an implementation should not perform this operation by first promoting the real operand to complex type and then @@ -15448,14 +15448,14 @@ component by the zero component obtained during promotion yields a NaN that propagates into the final result.) Analogous advice applies in the case of multiplication of a complex operand and a pure-imaginary operand, and in the case of division of a complex operand by a real or -pure-imaginary operand." +pure-imaginary operand.” @end quotation Not followed. @quotation -"Similarly, because the usual mathematical meaning of addition of a +“Similarly, because the usual mathematical meaning of addition of a complex operand and a real operand is that the imaginary operand remains unchanged, an implementation should not perform this operation by first promoting the real operand to complex type and then performing a full @@ -15468,14 +15468,14 @@ operand is a negatively signed zero. (Explicit addition of the negative zero to the zero obtained during promotion yields a positive zero.) Analogous advice applies in the case of addition of a complex operand and a pure-imaginary operand, and in the case of subtraction of a -complex operand and a real or pure-imaginary operand." +complex operand and a real or pure-imaginary operand.” @end quotation Not followed. @quotation -"Implementations in which @code{Real'Signed_Zeros} is @code{True} should +“Implementations in which @code{Real'Signed_Zeros} is @code{True} should attempt to provide a rational treatment of the signs of zero results and result components. As one example, the result of the @code{Argument} function should have the sign of the imaginary component of the @@ -15484,7 +15484,7 @@ the positive real axis; as another, the sign of the imaginary component of the @code{Compose_From_Polar} function should be the same as (respectively, the opposite of) that of the @code{Argument} parameter when that parameter has a value of zero and the @code{Modulus} parameter has a -nonnegative (respectively, negative) value." +nonnegative (respectively, negative) value.” @end quotation Followed. @@ -15498,7 +15498,7 @@ Followed. @quotation -"Implementations in which @code{Complex_Types.Real'Signed_Zeros} is +“Implementations in which @code{Complex_Types.Real'Signed_Zeros} is @code{True} should attempt to provide a rational treatment of the signs of zero results and result components. For example, many of the complex elementary functions have components that are odd functions of one of @@ -15506,7 +15506,7 @@ the parameter components; in these cases, the result component should have the sign of the parameter component at the origin. Other complex elementary functions have zero components whose sign is opposite that of a parameter component at the origin, or is always positive or always -negative." +negative.” @end quotation Followed. @@ -15520,14 +15520,14 @@ Followed. @quotation -"The versions of the forward trigonometric functions without a +“The versions of the forward trigonometric functions without a @code{Cycle} parameter should not be implemented by calling the corresponding version with a @code{Cycle} parameter of @code{2.0*Numerics.Pi}, since this will not provide the required accuracy in some portions of the domain. For the same reason, the version of @code{Log} without a @code{Base} parameter should not be implemented by calling the corresponding version with a @code{Base} -parameter of @code{Numerics.e}." +parameter of @code{Numerics.e}.” @end quotation Followed. @@ -15544,11 +15544,11 @@ Followed. @quotation -"The version of the @code{Compose_From_Polar} function without a +“The version of the @code{Compose_From_Polar} function without a @code{Cycle} parameter should not be implemented by calling the corresponding version with a @code{Cycle} parameter of @code{2.0*Numerics.Pi}, since this will not provide the required -accuracy in some portions of the domain." +accuracy in some portions of the domain.” @end quotation Followed. @@ -15562,16 +15562,16 @@ Followed. @quotation -"If the partition elaboration policy is @code{Sequential} and the +“If the partition elaboration policy is @code{Sequential} and the Environment task becomes permanently blocked during elaboration then the partition is deadlocked and it is recommended that the partition be -immediately terminated." +immediately terminated.” @end quotation Not followed. @node Implementation Defined Characteristics,Intrinsic Subprograms,Implementation Advice,Top -@anchor{gnat_rm/implementation_defined_characteristics implementation-defined-characteristics}@anchor{b}@anchor{gnat_rm/implementation_defined_characteristics doc}@anchor{258}@anchor{gnat_rm/implementation_defined_characteristics id1}@anchor{259} +@anchor{gnat_rm/implementation_defined_characteristics doc}@anchor{258}@anchor{gnat_rm/implementation_defined_characteristics id1}@anchor{259}@anchor{gnat_rm/implementation_defined_characteristics implementation-defined-characteristics}@anchor{b} @chapter Implementation Defined Characteristics @@ -15596,8 +15596,8 @@ Reference Manual. @itemize * @item -"Whether or not each recommendation given in Implementation -Advice is followed. See 1.1.2(37)." +“Whether or not each recommendation given in Implementation +Advice is followed. See 1.1.2(37).” @end itemize See @ref{a,,Implementation Advice}. @@ -15606,7 +15606,7 @@ See @ref{a,,Implementation Advice}. @itemize * @item -"Capacity limitations of the implementation. See 1.1.3(3)." +“Capacity limitations of the implementation. See 1.1.3(3).” @end itemize The complexity of programs that can be processed is limited only by the @@ -15617,8 +15617,8 @@ generated object files. @itemize * @item -"Variations from the standard that are impractical to avoid -given the implementation's execution environment. See 1.1.3(6)." +“Variations from the standard that are impractical to avoid +given the implementation’s execution environment. See 1.1.3(6).” @end itemize There are no variations from the standard. @@ -15627,8 +15627,8 @@ There are no variations from the standard. @itemize * @item -"Which code_statements cause external -interactions. See 1.1.3(10)." +“Which code_statements cause external +interactions. See 1.1.3(10).” @end itemize Any @emph{code_statement} can potentially cause external interactions. @@ -15637,8 +15637,8 @@ Any @emph{code_statement} can potentially cause external interactions. @itemize * @item -"The coded representation for the text of an Ada -program. See 2.1(4)." +“The coded representation for the text of an Ada +program. See 2.1(4).” @end itemize See separate section on source representation. @@ -15647,7 +15647,7 @@ See separate section on source representation. @itemize * @item -"The control functions allowed in comments. See 2.1(14)." +“The control functions allowed in comments. See 2.1(14).” @end itemize See separate section on source representation. @@ -15656,7 +15656,7 @@ See separate section on source representation. @itemize * @item -"The representation for an end of line. See 2.2(2)." +“The representation for an end of line. See 2.2(2).” @end itemize See separate section on source representation. @@ -15665,8 +15665,8 @@ See separate section on source representation. @itemize * @item -"Maximum supported line length and lexical element -length. See 2.2(15)." +“Maximum supported line length and lexical element +length. See 2.2(15).” @end itemize The maximum line length is 255 characters and the maximum length of @@ -15680,7 +15680,7 @@ length of a lexical element is the same as the maximum line length. @itemize * @item -"Implementation defined pragmas. See 2.8(14)." +“Implementation defined pragmas. See 2.8(14).” @end itemize See @ref{7,,Implementation Defined Pragmas}. @@ -15689,7 +15689,7 @@ See @ref{7,,Implementation Defined Pragmas}. @itemize * @item -"Effect of pragma @code{Optimize}. See 2.8(27)." +“Effect of pragma @code{Optimize}. See 2.8(27).” @end itemize Pragma @code{Optimize}, if given with a @code{Time} or @code{Space} @@ -15700,10 +15700,10 @@ not. @itemize * @item -"The sequence of characters of the value returned by +“The sequence of characters of the value returned by @code{S'Image} when some of the graphic characters of @code{S'Wide_Image} are not defined in @code{Character}. See -3.5(37)." +3.5(37).” @end itemize The sequence of characters is as defined by the wide character encoding @@ -15714,8 +15714,8 @@ further details. @itemize * @item -"The predefined integer types declared in -@code{Standard}. See 3.5.4(25)." +“The predefined integer types declared in +@code{Standard}. See 3.5.4(25).” @end itemize @@ -15786,8 +15786,8 @@ depending on the C definition of long) @itemize * @item -"Any nonstandard integer types and the operators defined -for them. See 3.5.4(26)." +“Any nonstandard integer types and the operators defined +for them. See 3.5.4(26).” @end itemize There are no nonstandard integer types. @@ -15796,8 +15796,8 @@ There are no nonstandard integer types. @itemize * @item -"Any nonstandard real types and the operators defined for -them. See 3.5.6(8)." +“Any nonstandard real types and the operators defined for +them. See 3.5.6(8).” @end itemize There are no nonstandard real types. @@ -15806,8 +15806,8 @@ There are no nonstandard real types. @itemize * @item -"What combinations of requested decimal precision and range -are supported for floating point types. See 3.5.7(7)." +“What combinations of requested decimal precision and range +are supported for floating point types. See 3.5.7(7).” @end itemize The precision and range are defined by the IEEE Standard for Floating-Point @@ -15817,8 +15817,8 @@ Arithmetic (IEEE 754-2019). @itemize * @item -"The predefined floating point types declared in -@code{Standard}. See 3.5.7(16)." +“The predefined floating point types declared in +@code{Standard}. See 3.5.7(16).” @end itemize @@ -15878,7 +15878,7 @@ digits are requested, zeros are printed. @itemize * @item -"The small of an ordinary fixed point type. See 3.5.9(8)." +“The small of an ordinary fixed point type. See 3.5.9(8).” @end itemize The small is the largest power of two that does not exceed the delta. @@ -15887,8 +15887,8 @@ The small is the largest power of two that does not exceed the delta. @itemize * @item -"What combinations of small, range, and digits are -supported for fixed point types. See 3.5.9(10)." +“What combinations of small, range, and digits are +supported for fixed point types. See 3.5.9(10).” @end itemize For an ordinary fixed point type, on 32-bit platforms, the small must lie in @@ -15917,8 +15917,8 @@ small must lie in 1.0E-38 .. 1.0E+38 and the digits in 1 .. 38. @itemize * @item -"The result of @code{Tags.Expanded_Name} for types declared -within an unnamed @emph{block_statement}. See 3.9(10)." +“The result of @code{Tags.Expanded_Name} for types declared +within an unnamed @emph{block_statement}. See 3.9(10).” @end itemize Block numbers of the form @code{B@emph{nnn}}, where @emph{nnn} is a @@ -15928,7 +15928,7 @@ decimal integer are allocated. @itemize * @item -"Implementation-defined attributes. See 4.1.4(12)." +“Implementation-defined attributes. See 4.1.4(12).” @end itemize See @ref{8,,Implementation Defined Attributes}. @@ -15937,7 +15937,7 @@ See @ref{8,,Implementation Defined Attributes}. @itemize * @item -"Any implementation-defined time types. See 9.6(6)." +“Any implementation-defined time types. See 9.6(6).” @end itemize There are no implementation-defined time types. @@ -15946,7 +15946,7 @@ There are no implementation-defined time types. @itemize * @item -"The time base associated with relative delays." +“The time base associated with relative delays.” @end itemize See 9.6(20). The time base used is that provided by the C library @@ -15956,8 +15956,8 @@ function @code{gettimeofday}. @itemize * @item -"The time base of the type @code{Calendar.Time}. See -9.6(23)." +“The time base of the type @code{Calendar.Time}. See +9.6(23).” @end itemize The time base used is that provided by the C library function @@ -15967,8 +15967,8 @@ The time base used is that provided by the C library function @itemize * @item -"The time zone used for package @code{Calendar} -operations. See 9.6(24)." +“The time zone used for package @code{Calendar} +operations. See 9.6(24).” @end itemize The time zone used by package @code{Calendar} is the current system time zone @@ -15979,8 +15979,8 @@ setting for local time, as accessed by the C library function @itemize * @item -"Any limit on @emph{delay_until_statements} of -@emph{select_statements}. See 9.6(29)." +“Any limit on @emph{delay_until_statements} of +@emph{select_statements}. See 9.6(29).” @end itemize There are no such limits. @@ -15989,10 +15989,10 @@ There are no such limits. @itemize * @item -"Whether or not two non-overlapping parts of a composite +“Whether or not two non-overlapping parts of a composite object are independently addressable, in the case where packing, record layout, or @code{Component_Size} is specified for the object. See -9.10(1)." +9.10(1).” @end itemize Separate components are independently addressable if they do not share @@ -16002,7 +16002,7 @@ overlapping storage units. @itemize * @item -"The representation for a compilation. See 10.1(2)." +“The representation for a compilation. See 10.1(2).” @end itemize A compilation is represented by a sequence of files presented to the @@ -16012,8 +16012,8 @@ compiler in a single invocation of the @emph{gcc} command. @itemize * @item -"Any restrictions on compilations that contain multiple -compilation_units. See 10.1(4)." +“Any restrictions on compilations that contain multiple +compilation_units. See 10.1(4).” @end itemize No single file can contain more than one compilation unit, but any @@ -16024,8 +16024,8 @@ compilation. @itemize * @item -"The mechanisms for creating an environment and for adding -and replacing compilation units. See 10.1.4(3)." +“The mechanisms for creating an environment and for adding +and replacing compilation units. See 10.1.4(3).” @end itemize See separate section on compilation model. @@ -16034,8 +16034,8 @@ See separate section on compilation model. @itemize * @item -"The manner of explicitly assigning library units to a -partition. See 10.2(2)." +“The manner of explicitly assigning library units to a +partition. See 10.2(2).” @end itemize If a unit contains an Ada main program, then the Ada units for the partition @@ -16055,15 +16055,15 @@ this case a list of units can be explicitly supplied to the binder for inclusion in the partition (all units needed by these units will also be included automatically). For full details on the use of these options, refer to @emph{GNAT Make Program gnatmake} in the -@cite{GNAT User's Guide}. +@cite{GNAT User’s Guide}. @itemize * @item -"The implementation-defined means, if any, of specifying +“The implementation-defined means, if any, of specifying which compilation units are needed by a given compilation unit. See -10.2(2)." +10.2(2).” @end itemize The units needed by a given compilation unit are as defined in @@ -16075,8 +16075,8 @@ means for specifying needed units. @itemize * @item -"The manner of designating the main subprogram of a -partition. See 10.2(7)." +“The manner of designating the main subprogram of a +partition. See 10.2(7).” @end itemize The main program is designated by providing the name of the @@ -16086,8 +16086,8 @@ corresponding @code{ALI} file as the input parameter to the binder. @itemize * @item -"The order of elaboration of @emph{library_items}. See -10.2(18)." +“The order of elaboration of @emph{library_items}. See +10.2(18).” @end itemize The first constraint on ordering is that it meets the requirements of @@ -16103,8 +16103,8 @@ where a choice still remains. @itemize * @item -"Parameter passing and function return for the main -subprogram. See 10.2(21)." +“Parameter passing and function return for the main +subprogram. See 10.2(21).” @end itemize The main program has no parameters. It may be a procedure, or a function @@ -16116,8 +16116,8 @@ may have been set by a call to @code{Ada.Command_Line.Set_Exit_Status}). @itemize * @item -"The mechanisms for building and running partitions. See -10.2(24)." +“The mechanisms for building and running partitions. See +10.2(24).” @end itemize GNAT itself supports programs with only a single partition. The GNATDIST @@ -16130,8 +16130,8 @@ for details. @itemize * @item -"The details of program execution, including program -termination. See 10.2(25)." +“The details of program execution, including program +termination. See 10.2(25).” @end itemize See separate section on compilation model. @@ -16140,8 +16140,8 @@ See separate section on compilation model. @itemize * @item -"The semantics of any non-active partitions supported by the -implementation. See 10.2(28)." +“The semantics of any non-active partitions supported by the +implementation. See 10.2(28).” @end itemize Passive partitions are supported on targets where shared memory is @@ -16152,8 +16152,8 @@ further details. @itemize * @item -"The information returned by @code{Exception_Message}. See -11.4.1(10)." +“The information returned by @code{Exception_Message}. See +11.4.1(10).” @end itemize Exception message returns the null string unless a specific message has @@ -16163,8 +16163,8 @@ been passed by the program. @itemize * @item -"The result of @code{Exceptions.Exception_Name} for types -declared within an unnamed @emph{block_statement}. See 11.4.1(12)." +“The result of @code{Exceptions.Exception_Name} for types +declared within an unnamed @emph{block_statement}. See 11.4.1(12).” @end itemize Blocks have implementation defined names of the form @code{B@emph{nnn}} @@ -16174,8 +16174,8 @@ where @emph{nnn} is an integer. @itemize * @item -"The information returned by -@code{Exception_Information}. See 11.4.1(13)." +“The information returned by +@code{Exception_Information}. See 11.4.1(13).” @end itemize @code{Exception_Information} returns a string in the following format: @@ -16212,7 +16212,7 @@ not making use of this field. The Load address line, the Call stack traceback locations line and the following values are present only if at least one traceback location was recorded. The Load address indicates the address at which the main executable -was loaded; this line may not be present if operating system hasn't relocated +was loaded; this line may not be present if operating system hasn’t relocated the main executable. The values are given in C style format, with lower case letters for a-f, and only as many digits present as are necessary. The line terminator sequence at the end of each line, including @@ -16224,7 +16224,7 @@ the last line is a single @code{LF} character (@code{16#0A#}). @itemize * @item -"Implementation-defined check names. See 11.5(27)." +“Implementation-defined check names. See 11.5(27).” @end itemize The implementation defined check names include Alignment_Check, @@ -16237,8 +16237,8 @@ Check_Name. See the description of pragma @code{Suppress} for full details. @itemize * @item -"The interpretation of each aspect of representation. See -13.1(20)." +“The interpretation of each aspect of representation. See +13.1(20).” @end itemize See separate section on data representations. @@ -16247,8 +16247,8 @@ See separate section on data representations. @itemize * @item -"Any restrictions placed upon representation items. See -13.1(20)." +“Any restrictions placed upon representation items. See +13.1(20).” @end itemize See separate section on data representations. @@ -16257,8 +16257,8 @@ See separate section on data representations. @itemize * @item -"The meaning of @code{Size} for indefinite subtypes. See -13.3(48)." +“The meaning of @code{Size} for indefinite subtypes. See +13.3(48).” @end itemize Size for an indefinite subtype is the maximum possible size, except that @@ -16269,8 +16269,8 @@ is the actual size. @itemize * @item -"The default external representation for a type tag. See -13.3(75)." +“The default external representation for a type tag. See +13.3(75).” @end itemize The default external representation for a type tag is the fully expanded @@ -16280,8 +16280,8 @@ name of the type in upper case letters. @itemize * @item -"What determines whether a compilation unit is the same in -two different partitions. See 13.3(76)." +“What determines whether a compilation unit is the same in +two different partitions. See 13.3(76).” @end itemize A compilation unit is the same in two different partitions if and only @@ -16291,7 +16291,7 @@ if it derives from the same source file. @itemize * @item -"Implementation-defined components. See 13.5.1(15)." +“Implementation-defined components. See 13.5.1(15).” @end itemize The only implementation defined component is the tag for a tagged type, @@ -16301,8 +16301,8 @@ which contains a pointer to the dispatching table. @itemize * @item -"If @code{Word_Size} = @code{Storage_Unit}, the default bit -ordering. See 13.5.3(5)." +“If @code{Word_Size} = @code{Storage_Unit}, the default bit +ordering. See 13.5.3(5).” @end itemize @code{Word_Size} (32) is not the same as @code{Storage_Unit} (8) for this @@ -16313,8 +16313,8 @@ bit ordering corresponds to the natural endianness of the target architecture. @itemize * @item -"The contents of the visible part of package @code{System} -and its language-defined children. See 13.7(2)." +“The contents of the visible part of package @code{System} +and its language-defined children. See 13.7(2).” @end itemize See the definition of these packages in files @code{system.ads} and @@ -16330,9 +16330,9 @@ Max_Interrupt_Priority : constant Positive := Interrupt_Priority'Last; @itemize * @item -"The contents of the visible part of package +“The contents of the visible part of package @code{System.Machine_Code}, and the meaning of -@emph{code_statements}. See 13.8(7)." +@emph{code_statements}. See 13.8(7).” @end itemize See the definition and documentation in file @code{s-maccod.ads}. @@ -16341,7 +16341,7 @@ See the definition and documentation in file @code{s-maccod.ads}. @itemize * @item -"The effect of unchecked conversion. See 13.9(11)." +“The effect of unchecked conversion. See 13.9(11).” @end itemize Unchecked conversion between types of the same size @@ -16362,8 +16362,8 @@ made with appropriate alignment @itemize * @item -"The semantics of operations on invalid representations. -See 13.9.2(10-11)." +“The semantics of operations on invalid representations. +See 13.9.2(10-11).” @end itemize For assignments and other operations where the use of invalid values cannot @@ -16391,8 +16391,8 @@ on the simple assignment of the invalid negative value from Y to Z. @itemize * @item -"The manner of choosing a storage pool for an access type -when @code{Storage_Pool} is not specified for the type. See 13.11(17)." +“The manner of choosing a storage pool for an access type +when @code{Storage_Pool} is not specified for the type. See 13.11(17).” @end itemize There are 3 different standard pools used by the compiler when @@ -16408,8 +16408,8 @@ default pools used. @itemize * @item -"Whether or not the implementation provides user-accessible -names for the standard pool type(s). See 13.11(17)." +“Whether or not the implementation provides user-accessible +names for the standard pool type(s). See 13.11(17).” @end itemize See documentation in the sources of the run time mentioned in the previous @@ -16420,7 +16420,7 @@ these units. @itemize * @item -"The meaning of @code{Storage_Size}. See 13.11(18)." +“The meaning of @code{Storage_Size}. See 13.11(18).” @end itemize @code{Storage_Size} is measured in storage units, and refers to the @@ -16431,8 +16431,8 @@ stack space for a task. @itemize * @item -"Implementation-defined aspects of storage pools. See -13.11(22)." +“Implementation-defined aspects of storage pools. See +13.11(22).” @end itemize See documentation in the sources of the run time mentioned in the @@ -16443,8 +16443,8 @@ for details on GNAT-defined aspects of storage pools. @itemize * @item -"The set of restrictions allowed in a pragma -@code{Restrictions}. See 13.12(7)." +“The set of restrictions allowed in a pragma +@code{Restrictions}. See 13.12(7).” @end itemize See @ref{9,,Standard and Implementation Defined Restrictions}. @@ -16453,8 +16453,8 @@ See @ref{9,,Standard and Implementation Defined Restrictions}. @itemize * @item -"The consequences of violating limitations on -@code{Restrictions} pragmas. See 13.12(9)." +“The consequences of violating limitations on +@code{Restrictions} pragmas. See 13.12(9).” @end itemize Restrictions that can be checked at compile time result in illegalities @@ -16465,9 +16465,9 @@ restrictions. @itemize * @item -"The representation used by the @code{Read} and +“The representation used by the @code{Read} and @code{Write} attributes of elementary types in terms of stream -elements. See 13.13.2(9)." +elements. See 13.13.2(9).” @end itemize The representation is the in-memory representation of the base type of @@ -16478,8 +16478,8 @@ the type, using the number of bits corresponding to the @itemize * @item -"The names and characteristics of the numeric subtypes -declared in the visible part of package @code{Standard}. See A.1(3)." +“The names and characteristics of the numeric subtypes +declared in the visible part of package @code{Standard}. See A.1(3).” @end itemize See items describing the integer and floating-point types supported. @@ -16488,20 +16488,20 @@ See items describing the integer and floating-point types supported. @itemize * @item -"The string returned by @code{Character_Set_Version}. -See A.3.5(3)." +“The string returned by @code{Character_Set_Version}. +See A.3.5(3).” @end itemize @code{Ada.Wide_Characters.Handling.Character_Set_Version} returns -the string "Unicode 4.0", referring to version 4.0 of the +the string “Unicode 4.0”, referring to version 4.0 of the Unicode specification. @itemize * @item -"The accuracy actually achieved by the elementary -functions. See A.5.1(1)." +“The accuracy actually achieved by the elementary +functions. See A.5.1(1).” @end itemize The elementary functions correspond to the functions available in the C @@ -16511,9 +16511,9 @@ library. Only fast math mode is implemented. @itemize * @item -"The sign of a zero result from some of the operators or +“The sign of a zero result from some of the operators or functions in @code{Numerics.Generic_Elementary_Functions}, when -@code{Float_Type'Signed_Zeros} is @code{True}. See A.5.1(46)." +@code{Float_Type'Signed_Zeros} is @code{True}. See A.5.1(46).” @end itemize The sign of zeroes follows the requirements of the IEEE 754 standard on @@ -16523,8 +16523,8 @@ floating-point. @itemize * @item -"The value of -@code{Numerics.Float_Random.Max_Image_Width}. See A.5.2(27)." +“The value of +@code{Numerics.Float_Random.Max_Image_Width}. See A.5.2(27).” @end itemize Maximum image width is 6864, see library file @code{s-rannum.ads}. @@ -16533,8 +16533,8 @@ Maximum image width is 6864, see library file @code{s-rannum.ads}. @itemize * @item -"The value of -@code{Numerics.Discrete_Random.Max_Image_Width}. See A.5.2(27)." +“The value of +@code{Numerics.Discrete_Random.Max_Image_Width}. See A.5.2(27).” @end itemize Maximum image width is 6864, see library file @code{s-rannum.ads}. @@ -16543,8 +16543,8 @@ Maximum image width is 6864, see library file @code{s-rannum.ads}. @itemize * @item -"The algorithms for random number generation. See -A.5.2(32)." +“The algorithms for random number generation. See +A.5.2(32).” @end itemize The algorithm is the Mersenne Twister, as documented in the source file @@ -16555,8 +16555,8 @@ The algorithm is the Mersenne Twister, as documented in the source file @itemize * @item -"The string representation of a random number generator's -state. See A.5.2(38)." +“The string representation of a random number generator’s +state. See A.5.2(38).” @end itemize The value returned by the Image function is the concatenation of @@ -16567,9 +16567,9 @@ of the state vector. @itemize * @item -"The minimum time interval between calls to the +“The minimum time interval between calls to the time-dependent Reset procedure that are guaranteed to initiate different -random number sequences. See A.5.2(45)." +random number sequences. See A.5.2(45).” @end itemize The minimum period between reset calls to guarantee distinct series of @@ -16579,10 +16579,10 @@ random numbers is one microsecond. @itemize * @item -"The values of the @code{Model_Mantissa}, +“The values of the @code{Model_Mantissa}, @code{Model_Emin}, @code{Model_Epsilon}, @code{Model}, @code{Safe_First}, and @code{Safe_Last} attributes, if the Numerics -Annex is not supported. See A.5.3(72)." +Annex is not supported. See A.5.3(72).” @end itemize Run the compiler with @emph{-gnatS} to produce a listing of package @@ -16592,8 +16592,8 @@ Run the compiler with @emph{-gnatS} to produce a listing of package @itemize * @item -"Any implementation-defined characteristics of the -input-output packages. See A.7(14)." +“Any implementation-defined characteristics of the +input-output packages. See A.7(14).” @end itemize There are no special implementation defined characteristics for these @@ -16603,8 +16603,8 @@ packages. @itemize * @item -"The value of @code{Buffer_Size} in @code{Storage_IO}. See -A.9(10)." +“The value of @code{Buffer_Size} in @code{Storage_IO}. See +A.9(10).” @end itemize All type representations are contiguous, and the @code{Buffer_Size} is @@ -16615,8 +16615,8 @@ boundary. @itemize * @item -"External files for standard input, standard output, and -standard error See A.10(5)." +“External files for standard input, standard output, and +standard error See A.10(5).” @end itemize These files are mapped onto the files provided by the C streams @@ -16626,8 +16626,8 @@ libraries. See source file @code{i-cstrea.ads} for further details. @itemize * @item -"The accuracy of the value produced by @code{Put}. See -A.10.9(36)." +“The accuracy of the value produced by @code{Put}. See +A.10.9(36).” @end itemize If more digits are requested in the output than are represented by the @@ -16638,8 +16638,8 @@ significant digit positions. @itemize * @item -"The meaning of @code{Argument_Count}, @code{Argument}, and -@code{Command_Name}. See A.15(1)." +“The meaning of @code{Argument_Count}, @code{Argument}, and +@code{Command_Name}. See A.15(1).” @end itemize These are mapped onto the @code{argv} and @code{argc} parameters of the @@ -16649,8 +16649,8 @@ main program in the natural manner. @itemize * @item -"The interpretation of the @code{Form} parameter in procedure -@code{Create_Directory}. See A.16(56)." +“The interpretation of the @code{Form} parameter in procedure +@code{Create_Directory}. See A.16(56).” @end itemize The @code{Form} parameter is not used. @@ -16659,8 +16659,8 @@ The @code{Form} parameter is not used. @itemize * @item -"The interpretation of the @code{Form} parameter in procedure -@code{Create_Path}. See A.16(60)." +“The interpretation of the @code{Form} parameter in procedure +@code{Create_Path}. See A.16(60).” @end itemize The @code{Form} parameter is not used. @@ -16669,8 +16669,8 @@ The @code{Form} parameter is not used. @itemize * @item -"The interpretation of the @code{Form} parameter in procedure -@code{Copy_File}. See A.16(68)." +“The interpretation of the @code{Form} parameter in procedure +@code{Copy_File}. See A.16(68).” @end itemize The @code{Form} parameter is case-insensitive. @@ -16681,8 +16681,8 @@ Two fields are recognized in the @code{Form} parameter: *mode=* @end example - starts immediately after the character '=' and ends with the -character immediately preceding the next comma (',') or with the last + starts immediately after the character ‘=’ and ends with the +character immediately preceding the next comma (‘,’) or with the last character of the parameter. The only possible values for preserve= are: @@ -16790,9 +16790,9 @@ Form => "mode=internal, preserve=timestamps" @itemize * @item -"The interpretation of the @code{Pattern} parameter, when not the null string, +“The interpretation of the @code{Pattern} parameter, when not the null string, in the @code{Start_Search} and @code{Search} procedures. -See A.16(104) and A.16(112)." +See A.16(104) and A.16(112).” @end itemize When the @code{Pattern} parameter is not the null string, it is interpreted @@ -16805,7 +16805,7 @@ See @ref{25a,,GNAT.Regexp (g-regexp.ads)}. @itemize * @item -"Implementation-defined convention names. See B.1(11)." +“Implementation-defined convention names. See B.1(11).” @end itemize The following convention names are supported @@ -16988,7 +16988,7 @@ use of such other names results in a warning. @itemize * @item -"The meaning of link names. See B.1(36)." +“The meaning of link names. See B.1(36).” @end itemize Link names are the actual names used by the linker. @@ -16997,9 +16997,9 @@ Link names are the actual names used by the linker. @itemize * @item -"The manner of choosing link names when neither the link +“The manner of choosing link names when neither the link name nor the address of an imported or exported entity is specified. See -B.1(36)." +B.1(36).” @end itemize The default linker name is that which would be assigned by the relevant @@ -17010,7 +17010,7 @@ letters. @itemize * @item -"The effect of pragma @code{Linker_Options}. See B.1(37)." +“The effect of pragma @code{Linker_Options}. See B.1(37).” @end itemize The string passed to @code{Linker_Options} is presented uninterpreted as @@ -17031,8 +17031,8 @@ from the corresponding package spec. @itemize * @item -"The contents of the visible part of package -@code{Interfaces} and its language-defined descendants. See B.2(1)." +“The contents of the visible part of package +@code{Interfaces} and its language-defined descendants. See B.2(1).” @end itemize See files with prefix @code{i-} in the distributed library. @@ -17041,9 +17041,9 @@ See files with prefix @code{i-} in the distributed library. @itemize * @item -"Implementation-defined children of package +“Implementation-defined children of package @code{Interfaces}. The contents of the visible part of package -@code{Interfaces}. See B.2(11)." +@code{Interfaces}. See B.2(11).” @end itemize See files with prefix @code{i-} in the distributed library. @@ -17052,11 +17052,11 @@ See files with prefix @code{i-} in the distributed library. @itemize * @item -"The types @code{Floating}, @code{Long_Floating}, +“The types @code{Floating}, @code{Long_Floating}, @code{Binary}, @code{Long_Binary}, @code{Decimal_ Element}, and @code{COBOL_Character}; and the initialization of the variables @code{Ada_To_COBOL} and @code{COBOL_To_Ada}, in -@code{Interfaces.COBOL}. See B.4(50)." +@code{Interfaces.COBOL}. See B.4(50).” @end itemize @@ -17126,7 +17126,7 @@ For initialization, see the file @code{i-cobol.ads} in the distributed library. @itemize * @item -"Support for access to machine instructions. See C.1(1)." +“Support for access to machine instructions. See C.1(1).” @end itemize See documentation in file @code{s-maccod.ads} in the distributed library. @@ -17135,8 +17135,8 @@ See documentation in file @code{s-maccod.ads} in the distributed library. @itemize * @item -"Implementation-defined aspects of access to machine -operations. See C.1(9)." +“Implementation-defined aspects of access to machine +operations. See C.1(9).” @end itemize See documentation in file @code{s-maccod.ads} in the distributed library. @@ -17145,7 +17145,7 @@ See documentation in file @code{s-maccod.ads} in the distributed library. @itemize * @item -"Implementation-defined aspects of interrupts. See C.3(2)." +“Implementation-defined aspects of interrupts. See C.3(2).” @end itemize Interrupts are mapped to signals or conditions as appropriate. See @@ -17157,8 +17157,8 @@ on the interrupts supported on a particular target. @itemize * @item -"Implementation-defined aspects of pre-elaboration. See -C.4(13)." +“Implementation-defined aspects of pre-elaboration. See +C.4(13).” @end itemize GNAT does not permit a partition to be restarted without reloading, @@ -17168,7 +17168,7 @@ except under control of the debugger. @itemize * @item -"The semantics of pragma @code{Discard_Names}. See C.5(7)." +“The semantics of pragma @code{Discard_Names}. See C.5(7).” @end itemize Pragma @code{Discard_Names} causes names of enumeration literals to @@ -17185,8 +17185,8 @@ level. @itemize * @item -"The result of the @code{Task_Identification.Image} -attribute. See C.7.1(7)." +“The result of the @code{Task_Identification.Image} +attribute. See C.7.1(7).” @end itemize The result of this attribute is a string that identifies @@ -17217,8 +17217,8 @@ virtual address of the control block of the task. @itemize * @item -"The value of @code{Current_Task} when in a protected entry -or interrupt handler. See C.7.1(17)." +“The value of @code{Current_Task} when in a protected entry +or interrupt handler. See C.7.1(17).” @end itemize Protected entries or interrupt handlers can be executed by any @@ -17228,8 +17228,8 @@ convenient thread, so the value of @code{Current_Task} is undefined. @itemize * @item -"The effect of calling @code{Current_Task} from an entry -body or interrupt handler. See C.7.1(19)." +“The effect of calling @code{Current_Task} from an entry +body or interrupt handler. See C.7.1(19).” @end itemize When GNAT can determine statically that @code{Current_Task} is called directly in @@ -17242,8 +17242,8 @@ currently executing the code. @itemize * @item -"Implementation-defined aspects of -@code{Task_Attributes}. See C.7.2(19)." +“Implementation-defined aspects of +@code{Task_Attributes}. See C.7.2(19).” @end itemize There are no implementation-defined aspects of @code{Task_Attributes}. @@ -17252,7 +17252,7 @@ There are no implementation-defined aspects of @code{Task_Attributes}. @itemize * @item -"Values of all @code{Metrics}. See D(2)." +“Values of all @code{Metrics}. See D(2).” @end itemize The metrics information for GNAT depends on the performance of the @@ -17268,8 +17268,8 @@ the required metrics. @itemize * @item -"The declarations of @code{Any_Priority} and -@code{Priority}. See D.1(11)." +“The declarations of @code{Any_Priority} and +@code{Priority}. See D.1(11).” @end itemize See declarations in file @code{system.ads}. @@ -17278,7 +17278,7 @@ See declarations in file @code{system.ads}. @itemize * @item -"Implementation-defined execution resources. See D.1(15)." +“Implementation-defined execution resources. See D.1(15).” @end itemize There are no implementation-defined execution resources. @@ -17287,8 +17287,8 @@ There are no implementation-defined execution resources. @itemize * @item -"Whether, on a multiprocessor, a task that is waiting for -access to a protected object keeps its processor busy. See D.2.1(3)." +“Whether, on a multiprocessor, a task that is waiting for +access to a protected object keeps its processor busy. See D.2.1(3).” @end itemize On a multi-processor, a task that is waiting for access to a protected @@ -17298,8 +17298,8 @@ object does not keep its processor busy. @itemize * @item -"The affect of implementation defined execution resources -on task dispatching. See D.2.1(9)." +“The affect of implementation defined execution resources +on task dispatching. See D.2.1(9).” @end itemize Tasks map to threads in the threads package used by GNAT. Where possible @@ -17310,8 +17310,8 @@ underlying operating system. @itemize * @item -"Implementation-defined @emph{policy_identifiers} allowed -in a pragma @code{Task_Dispatching_Policy}. See D.2.2(3)." +“Implementation-defined @emph{policy_identifiers} allowed +in a pragma @code{Task_Dispatching_Policy}. See D.2.2(3).” @end itemize There are no implementation-defined policy-identifiers allowed in this @@ -17321,8 +17321,8 @@ pragma. @itemize * @item -"Implementation-defined aspects of priority inversion. See -D.2.2(16)." +“Implementation-defined aspects of priority inversion. See +D.2.2(16).” @end itemize Execution of a task cannot be preempted by the implementation processing @@ -17332,7 +17332,7 @@ of delay expirations for lower priority tasks. @itemize * @item -"Implementation-defined task dispatching. See D.2.2(18)." +“Implementation-defined task dispatching. See D.2.2(18).” @end itemize The policy is the same as that of the underlying threads implementation. @@ -17341,8 +17341,8 @@ The policy is the same as that of the underlying threads implementation. @itemize * @item -"Implementation-defined @emph{policy_identifiers} allowed -in a pragma @code{Locking_Policy}. See D.3(4)." +“Implementation-defined @emph{policy_identifiers} allowed +in a pragma @code{Locking_Policy}. See D.3(4).” @end itemize The two implementation defined policies permitted in GNAT are @@ -17359,7 +17359,7 @@ concurrently. @itemize * @item -"Default ceiling priorities. See D.3(10)." +“Default ceiling priorities. See D.3(10).” @end itemize The ceiling priority of protected objects of the type @@ -17370,8 +17370,8 @@ Reference Manual D.3(10), @itemize * @item -"The ceiling of any protected object used internally by -the implementation. See D.3(16)." +“The ceiling of any protected object used internally by +the implementation. See D.3(16).” @end itemize The ceiling priority of internal protected objects is @@ -17381,7 +17381,7 @@ The ceiling priority of internal protected objects is @itemize * @item -"Implementation-defined queuing policies. See D.4(1)." +“Implementation-defined queuing policies. See D.4(1).” @end itemize There are no implementation-defined queuing policies. @@ -17390,9 +17390,9 @@ There are no implementation-defined queuing policies. @itemize * @item -"On a multiprocessor, any conditions that cause the +“On a multiprocessor, any conditions that cause the completion of an aborted construct to be delayed later than what is -specified for a single processor. See D.6(3)." +specified for a single processor. See D.6(3).” @end itemize The semantics for abort on a multi-processor is the same as on a single @@ -17402,8 +17402,8 @@ processor, there are no further delays. @itemize * @item -"Any operations that implicitly require heap storage -allocation. See D.7(8)." +“Any operations that implicitly require heap storage +allocation. See D.7(8).” @end itemize The only operation that implicitly requires heap storage allocation is @@ -17413,8 +17413,8 @@ task creation. @itemize * @item -"What happens when a task terminates in the presence of -pragma @code{No_Task_Termination}. See D.7(15)." +“What happens when a task terminates in the presence of +pragma @code{No_Task_Termination}. See D.7(15).” @end itemize Execution is erroneous in that case. @@ -17423,8 +17423,8 @@ Execution is erroneous in that case. @itemize * @item -"Implementation-defined aspects of pragma -@code{Restrictions}. See D.7(20)." +“Implementation-defined aspects of pragma +@code{Restrictions}. See D.7(20).” @end itemize There are no such implementation-defined aspects. @@ -17433,8 +17433,8 @@ There are no such implementation-defined aspects. @itemize * @item -"Implementation-defined aspects of package -@code{Real_Time}. See D.8(17)." +“Implementation-defined aspects of package +@code{Real_Time}. See D.8(17).” @end itemize There are no implementation defined aspects of package @code{Real_Time}. @@ -17443,8 +17443,8 @@ There are no implementation defined aspects of package @code{Real_Time}. @itemize * @item -"Implementation-defined aspects of -@emph{delay_statements}. See D.9(8)." +“Implementation-defined aspects of +@emph{delay_statements}. See D.9(8).” @end itemize Any difference greater than one microsecond will cause the task to be @@ -17454,8 +17454,8 @@ delayed (see D.9(7)). @itemize * @item -"The upper bound on the duration of interrupt blocking -caused by the implementation. See D.12(5)." +“The upper bound on the duration of interrupt blocking +caused by the implementation. See D.12(5).” @end itemize The upper bound is determined by the underlying operating system. In @@ -17465,8 +17465,8 @@ no cases is it more than 10 milliseconds. @itemize * @item -"The means for creating and executing distributed -programs. See E(5)." +“The means for creating and executing distributed +programs. See E(5).” @end itemize The GLADE package provides a utility GNATDIST for creating and executing @@ -17476,8 +17476,8 @@ distributed programs. See the GLADE reference manual for further details. @itemize * @item -"Any events that can result in a partition becoming -inaccessible. See E.1(7)." +“Any events that can result in a partition becoming +inaccessible. See E.1(7).” @end itemize See the GLADE reference manual for full details on such events. @@ -17486,9 +17486,9 @@ See the GLADE reference manual for full details on such events. @itemize * @item -"The scheduling policies, treatment of priorities, and +“The scheduling policies, treatment of priorities, and management of shared resources between partitions in certain cases. See -E.1(11)." +E.1(11).” @end itemize See the GLADE reference manual for full details on these aspects of @@ -17498,8 +17498,8 @@ multi-partition execution. @itemize * @item -"Events that cause the version of a compilation unit to -change. See E.3(5)." +“Events that cause the version of a compilation unit to +change. See E.3(5).” @end itemize Editing the source file of a compilation unit, or the source files of @@ -17512,8 +17512,8 @@ comments. @itemize * @item -"Whether the execution of the remote subprogram is -immediately aborted as a result of cancellation. See E.4(13)." +“Whether the execution of the remote subprogram is +immediately aborted as a result of cancellation. See E.4(13).” @end itemize See the GLADE reference manual for details on the effect of abort in @@ -17523,7 +17523,7 @@ a distributed application. @itemize * @item -"Implementation-defined aspects of the PCS. See E.5(25)." +“Implementation-defined aspects of the PCS. See E.5(25).” @end itemize See the GLADE reference manual for a full description of all implementation @@ -17533,8 +17533,8 @@ defined aspects of the PCS. @itemize * @item -"Implementation-defined interfaces in the PCS. See -E.5(26)." +“Implementation-defined interfaces in the PCS. See +E.5(26).” @end itemize See the GLADE reference manual for a full description of all @@ -17544,8 +17544,8 @@ implementation defined interfaces. @itemize * @item -"The values of named numbers in the package -@code{Decimal}. See F.2(7)." +“The values of named numbers in the package +@code{Decimal}. See F.2(7).” @end itemize @@ -17605,8 +17605,8 @@ Value @itemize * @item -"The value of @code{Max_Picture_Length} in the package -@code{Text_IO.Editing}. See F.3.3(16)." +“The value of @code{Max_Picture_Length} in the package +@code{Text_IO.Editing}. See F.3.3(16).” @end itemize 64 @@ -17615,8 +17615,8 @@ Value @itemize * @item -"The value of @code{Max_Picture_Length} in the package -@code{Wide_Text_IO.Editing}. See F.3.4(5)." +“The value of @code{Max_Picture_Length} in the package +@code{Wide_Text_IO.Editing}. See F.3.4(5).” @end itemize 64 @@ -17625,8 +17625,8 @@ Value @itemize * @item -"The accuracy actually achieved by the complex elementary -functions and by other complex arithmetic operations. See G.1(1)." +“The accuracy actually achieved by the complex elementary +functions and by other complex arithmetic operations. See G.1(1).” @end itemize Standard library functions are used for the complex arithmetic @@ -17636,9 +17636,9 @@ operations. Only fast math mode is currently supported. @itemize * @item -"The sign of a zero result (or a component thereof) from +“The sign of a zero result (or a component thereof) from any operator or function in @code{Numerics.Generic_Complex_Types}, when -@code{Real'Signed_Zeros} is True. See G.1.1(53)." +@code{Real'Signed_Zeros} is True. See G.1.1(53).” @end itemize The signs of zero values are as recommended by the relevant @@ -17648,10 +17648,10 @@ implementation advice. @itemize * @item -"The sign of a zero result (or a component thereof) from +“The sign of a zero result (or a component thereof) from any operator or function in @code{Numerics.Generic_Complex_Elementary_Functions}, when -@code{Real'Signed_Zeros} is @code{True}. See G.1.2(45)." +@code{Real'Signed_Zeros} is @code{True}. See G.1.2(45).” @end itemize The signs of zero values are as recommended by the relevant @@ -17661,8 +17661,8 @@ implementation advice. @itemize * @item -"Whether the strict mode or the relaxed mode is the -default. See G.2(2)." +“Whether the strict mode or the relaxed mode is the +default. See G.2(2).” @end itemize The strict mode is the default. There is no separate relaxed mode. GNAT @@ -17672,8 +17672,8 @@ provides a highly efficient implementation of strict mode. @itemize * @item -"The result interval in certain cases of fixed-to-float -conversion. See G.2.1(10)." +“The result interval in certain cases of fixed-to-float +conversion. See G.2.1(10).” @end itemize For cases where the result interval is implementation dependent, the @@ -17684,9 +17684,9 @@ floating-point format. @itemize * @item -"The result of a floating point arithmetic operation in +“The result of a floating point arithmetic operation in overflow situations, when the @code{Machine_Overflows} attribute of the -result type is @code{False}. See G.2.1(13)." +result type is @code{False}. See G.2.1(13).” @end itemize Infinite and NaN values are produced as dictated by the IEEE @@ -17701,9 +17701,9 @@ properly generated. @itemize * @item -"The result interval for division (or exponentiation by a +“The result interval for division (or exponentiation by a negative exponent), when the floating point hardware implements division -as multiplication by a reciprocal. See G.2.1(16)." +as multiplication by a reciprocal. See G.2.1(16).” @end itemize Not relevant, division is IEEE exact. @@ -17712,9 +17712,9 @@ Not relevant, division is IEEE exact. @itemize * @item -"The definition of close result set, which determines the +“The definition of close result set, which determines the accuracy of certain fixed point multiplications and divisions. See -G.2.3(5)." +G.2.3(5).” @end itemize Operations in the close result set are performed using IEEE long format @@ -17726,9 +17726,9 @@ is converted to the target type. @itemize * @item -"Conditions on a @emph{universal_real} operand of a fixed +“Conditions on a @emph{universal_real} operand of a fixed point multiplication or division for which the result shall be in the -perfect result set. See G.2.3(22)." +perfect result set. See G.2.3(22).” @end itemize The result is only defined to be in the perfect result set if the result @@ -17739,9 +17739,9 @@ representable in 64 bits. @itemize * @item -"The result of a fixed point arithmetic operation in +“The result of a fixed point arithmetic operation in overflow situations, when the @code{Machine_Overflows} attribute of the -result type is @code{False}. See G.2.3(27)." +result type is @code{False}. See G.2.3(27).” @end itemize Not relevant, @code{Machine_Overflows} is @code{True} for fixed-point @@ -17751,9 +17751,9 @@ types. @itemize * @item -"The result of an elementary function reference in +“The result of an elementary function reference in overflow situations, when the @code{Machine_Overflows} attribute of the -result type is @code{False}. See G.2.4(4)." +result type is @code{False}. See G.2.4(4).” @end itemize IEEE infinite and Nan values are produced as appropriate. @@ -17762,10 +17762,10 @@ IEEE infinite and Nan values are produced as appropriate. @itemize * @item -"The value of the angle threshold, within which certain +“The value of the angle threshold, within which certain elementary functions, complex arithmetic operations, and complex elementary functions yield results conforming to a maximum relative -error bound. See G.2.4(10)." +error bound. See G.2.4(10).” @end itemize Information on this subject is not yet available. @@ -17774,8 +17774,8 @@ Information on this subject is not yet available. @itemize * @item -"The accuracy of certain elementary functions for -parameters beyond the angle threshold. See G.2.4(10)." +“The accuracy of certain elementary functions for +parameters beyond the angle threshold. See G.2.4(10).” @end itemize Information on this subject is not yet available. @@ -17784,10 +17784,10 @@ Information on this subject is not yet available. @itemize * @item -"The result of a complex arithmetic operation or complex +“The result of a complex arithmetic operation or complex elementary function reference in overflow situations, when the @code{Machine_Overflows} attribute of the corresponding real type is -@code{False}. See G.2.6(5)." +@code{False}. See G.2.6(5).” @end itemize IEEE infinite and Nan values are produced as appropriate. @@ -17796,9 +17796,9 @@ IEEE infinite and Nan values are produced as appropriate. @itemize * @item -"The accuracy of certain complex arithmetic operations and +“The accuracy of certain complex arithmetic operations and certain complex elementary functions for parameters (or components -thereof) beyond the angle threshold. See G.2.6(8)." +thereof) beyond the angle threshold. See G.2.6(8).” @end itemize Information on those subjects is not yet available. @@ -17807,8 +17807,8 @@ Information on those subjects is not yet available. @itemize * @item -"Information regarding bounded errors and erroneous -execution. See H.2(1)." +“Information regarding bounded errors and erroneous +execution. See H.2(1).” @end itemize Information on this subject is not yet available. @@ -17817,8 +17817,8 @@ Information on this subject is not yet available. @itemize * @item -"Implementation-defined aspects of pragma -@code{Inspection_Point}. See H.3.2(8)." +“Implementation-defined aspects of pragma +@code{Inspection_Point}. See H.3.2(8).” @end itemize Pragma @code{Inspection_Point} ensures that the variable is live and can @@ -17828,8 +17828,8 @@ be examined by the debugger at the inspection point. @itemize * @item -"Implementation-defined aspects of pragma -@code{Restrictions}. See H.4(25)." +“Implementation-defined aspects of pragma +@code{Restrictions}. See H.4(25).” @end itemize There are no implementation-defined aspects of pragma @code{Restrictions}. The @@ -17840,14 +17840,14 @@ generated code. Checks must suppressed by use of pragma @code{Suppress}. @itemize * @item -"Any restrictions on pragma @code{Restrictions}. See -H.4(27)." +“Any restrictions on pragma @code{Restrictions}. See +H.4(27).” @end itemize There are no restrictions on pragma @code{Restrictions}. @node Intrinsic Subprograms,Representation Clauses and Pragmas,Implementation Defined Characteristics,Top -@anchor{gnat_rm/intrinsic_subprograms doc}@anchor{25b}@anchor{gnat_rm/intrinsic_subprograms intrinsic-subprograms}@anchor{c}@anchor{gnat_rm/intrinsic_subprograms id1}@anchor{25c} +@anchor{gnat_rm/intrinsic_subprograms doc}@anchor{25b}@anchor{gnat_rm/intrinsic_subprograms id1}@anchor{25c}@anchor{gnat_rm/intrinsic_subprograms intrinsic-subprograms}@anchor{c} @chapter Intrinsic Subprograms @@ -17910,13 +17910,13 @@ function "+" (X1 : Int1; X2 : Int2) return Int2; pragma Import (Intrinsic, "+"); @end example -This declaration would permit 'mixed mode' arithmetic on items +This declaration would permit ‘mixed mode’ arithmetic on items of the differing types @code{Int1} and @code{Int2}. It is also possible to specify such operators for private types, if the full views are appropriate arithmetic types. @node Compilation_ISO_Date,Compilation_Date,Intrinsic Operators,Intrinsic Subprograms -@anchor{gnat_rm/intrinsic_subprograms id3}@anchor{25f}@anchor{gnat_rm/intrinsic_subprograms compilation-iso-date}@anchor{260} +@anchor{gnat_rm/intrinsic_subprograms compilation-iso-date}@anchor{25f}@anchor{gnat_rm/intrinsic_subprograms id3}@anchor{260} @section Compilation_ISO_Date @@ -17954,7 +17954,7 @@ application program should simply call the function the current compilation (in local time format HH:MM:SS). @node Enclosing_Entity,Exception_Information,Compilation_Time,Intrinsic Subprograms -@anchor{gnat_rm/intrinsic_subprograms id6}@anchor{265}@anchor{gnat_rm/intrinsic_subprograms enclosing-entity}@anchor{266} +@anchor{gnat_rm/intrinsic_subprograms enclosing-entity}@anchor{265}@anchor{gnat_rm/intrinsic_subprograms id6}@anchor{266} @section Enclosing_Entity @@ -17968,7 +17968,7 @@ application program should simply call the function the current subprogram, package, task, entry, or protected subprogram. @node Exception_Information,Exception_Message,Enclosing_Entity,Intrinsic Subprograms -@anchor{gnat_rm/intrinsic_subprograms id7}@anchor{267}@anchor{gnat_rm/intrinsic_subprograms exception-information}@anchor{268} +@anchor{gnat_rm/intrinsic_subprograms exception-information}@anchor{267}@anchor{gnat_rm/intrinsic_subprograms id7}@anchor{268} @section Exception_Information @@ -18010,7 +18010,7 @@ so an application program should simply call the function the name of the current exception. @node File,Line,Exception_Name,Intrinsic Subprograms -@anchor{gnat_rm/intrinsic_subprograms id10}@anchor{26d}@anchor{gnat_rm/intrinsic_subprograms file}@anchor{26e} +@anchor{gnat_rm/intrinsic_subprograms file}@anchor{26d}@anchor{gnat_rm/intrinsic_subprograms id10}@anchor{26e} @section File @@ -18038,7 +18038,7 @@ application program should simply call the function source line. @node Shifts and Rotates,Source_Location,Line,Intrinsic Subprograms -@anchor{gnat_rm/intrinsic_subprograms shifts-and-rotates}@anchor{271}@anchor{gnat_rm/intrinsic_subprograms id12}@anchor{272} +@anchor{gnat_rm/intrinsic_subprograms id12}@anchor{271}@anchor{gnat_rm/intrinsic_subprograms shifts-and-rotates}@anchor{272} @section Shifts and Rotates @@ -18066,7 +18066,7 @@ with Import, Convention => Intrinsic; The function name must be one of Shift_Left, Shift_Right, Shift_Right_Arithmetic, Rotate_Left, or -Rotate_Right. T must be an integer type. T'Size must be +Rotate_Right. T must be an integer type. T’Size must be 8, 16, 32 or 64 bits; if T is modular, the modulus must be 2**8, 2**16, 2**32 or 2**64. The result type must be the same as the type of @code{Value}. @@ -18075,13 +18075,13 @@ The formal parameter names can be anything. A more convenient way of providing these shift operators is to use the Provide_Shift_Operators pragma, which provides the function declarations and -corresponding pragma Import's for all five shift functions. For signed types +corresponding pragma Import’s for all five shift functions. For signed types the semantics of these operators is to interpret the bitwise result of the corresponding operator for modular type. In particular, shifting a negative number may change its sign bit to positive. @node Source_Location,,Shifts and Rotates,Intrinsic Subprograms -@anchor{gnat_rm/intrinsic_subprograms source-location}@anchor{273}@anchor{gnat_rm/intrinsic_subprograms id13}@anchor{274} +@anchor{gnat_rm/intrinsic_subprograms id13}@anchor{273}@anchor{gnat_rm/intrinsic_subprograms source-location}@anchor{274} @section Source_Location @@ -18095,7 +18095,7 @@ application program should simply call the function source file location. @node Representation Clauses and Pragmas,Standard Library Routines,Intrinsic Subprograms,Top -@anchor{gnat_rm/representation_clauses_and_pragmas representation-clauses-and-pragmas}@anchor{d}@anchor{gnat_rm/representation_clauses_and_pragmas doc}@anchor{275}@anchor{gnat_rm/representation_clauses_and_pragmas id1}@anchor{276} +@anchor{gnat_rm/representation_clauses_and_pragmas doc}@anchor{275}@anchor{gnat_rm/representation_clauses_and_pragmas id1}@anchor{276}@anchor{gnat_rm/representation_clauses_and_pragmas representation-clauses-and-pragmas}@anchor{d} @chapter Representation Clauses and Pragmas @@ -18141,7 +18141,7 @@ and this section describes the additional capabilities provided. @end menu @node Alignment Clauses,Size Clauses,,Representation Clauses and Pragmas -@anchor{gnat_rm/representation_clauses_and_pragmas id2}@anchor{277}@anchor{gnat_rm/representation_clauses_and_pragmas alignment-clauses}@anchor{278} +@anchor{gnat_rm/representation_clauses_and_pragmas alignment-clauses}@anchor{277}@anchor{gnat_rm/representation_clauses_and_pragmas id2}@anchor{278} @section Alignment Clauses @@ -18316,10 +18316,10 @@ in accordance with the specific Implementation Advice in RM 13.3(43): @quotation -"A @code{Size} clause should be supported for an object if the specified -@code{Size} is at least as large as its subtype's @code{Size}, and corresponds -to a size in storage elements that is a multiple of the object's -@code{Alignment} (if the @code{Alignment} is nonzero)." +“A @code{Size} clause should be supported for an object if the specified +@code{Size} is at least as large as its subtype’s @code{Size}, and corresponds +to a size in storage elements that is a multiple of the object’s +@code{Alignment} (if the @code{Alignment} is nonzero).” @end quotation An explicit size clause may be used to override the default size by @@ -18349,7 +18349,7 @@ if it is known that a Size value can be accommodated in an object of type Integer. @node Storage_Size Clauses,Size of Variant Record Objects,Size Clauses,Representation Clauses and Pragmas -@anchor{gnat_rm/representation_clauses_and_pragmas storage-size-clauses}@anchor{27b}@anchor{gnat_rm/representation_clauses_and_pragmas id4}@anchor{27c} +@anchor{gnat_rm/representation_clauses_and_pragmas id4}@anchor{27b}@anchor{gnat_rm/representation_clauses_and_pragmas storage-size-clauses}@anchor{27c} @section Storage_Size Clauses @@ -18532,7 +18532,7 @@ the maximum size, regardless of the current variant value, the variant value. @node Biased Representation,Value_Size and Object_Size Clauses,Size of Variant Record Objects,Representation Clauses and Pragmas -@anchor{gnat_rm/representation_clauses_and_pragmas id6}@anchor{27f}@anchor{gnat_rm/representation_clauses_and_pragmas biased-representation}@anchor{280} +@anchor{gnat_rm/representation_clauses_and_pragmas biased-representation}@anchor{27f}@anchor{gnat_rm/representation_clauses_and_pragmas id6}@anchor{280} @section Biased Representation @@ -18617,7 +18617,7 @@ objects of the type respectively. The @code{Object_Size} is used for determining the default size of objects and components. This size value can be referred to using the -@code{Object_Size} attribute. The phrase 'is used' here means that it is +@code{Object_Size} attribute. The phrase ‘is used’ here means that it is the basis of the determination of the size. The backend is free to pad this up if necessary for efficiency, e.g., an 8-bit stand-alone character might be stored in 32 bits on a machine with no efficient @@ -18669,8 +18669,8 @@ only if negative values are possible). @item If a subtype statically matches the first subtype of a given type, then it has by default the same @code{Value_Size} as the first subtype. This is a -consequence of RM 13.1(14): "if two subtypes statically match, -then their subtype-specific aspects are the same".) +consequence of RM 13.1(14): “if two subtypes statically match, +then their subtype-specific aspects are the same”.) @item All other subtypes have a @code{Value_Size} corresponding to the minimum @@ -18803,7 +18803,7 @@ Value_Size @end multitable -Note: the entries marked '*' are not actually specified by the Ada +Note: the entries marked ‘*’ are not actually specified by the Ada Reference Manual, which has nothing to say about size in the dynamic case. What GNAT does is to allocate sufficient bits to accommodate any possible dynamic values for the bounds at run-time. @@ -18849,7 +18849,7 @@ the alignment requirement for objects of the record type. The X component will require four-byte alignment because that is what type Integer requires, whereas the Y component, a Character, will only require 1-byte alignment. Since the alignment required for X is the -greatest of all the components' alignments, that is the alignment +greatest of all the components’ alignments, that is the alignment required for the enclosing record type, i.e., 4 bytes or 32 bits. As indicated above, the actual object size must be rounded up so that it is a multiple of the alignment value. Therefore, 40 bits rounded up to the @@ -18886,7 +18886,7 @@ definition clause forces biased representation. This warning can be turned off using @code{-gnatw.B}. @node Component_Size Clauses,Bit_Order Clauses,Value_Size and Object_Size Clauses,Representation Clauses and Pragmas -@anchor{gnat_rm/representation_clauses_and_pragmas id8}@anchor{283}@anchor{gnat_rm/representation_clauses_and_pragmas component-size-clauses}@anchor{284} +@anchor{gnat_rm/representation_clauses_and_pragmas component-size-clauses}@anchor{283}@anchor{gnat_rm/representation_clauses_and_pragmas id8}@anchor{284} @section Component_Size Clauses @@ -19040,7 +19040,7 @@ if desired. The following section contains additional details regarding the issue of byte ordering. @node Effect of Bit_Order on Byte Ordering,Pragma Pack for Arrays,Bit_Order Clauses,Representation Clauses and Pragmas -@anchor{gnat_rm/representation_clauses_and_pragmas id10}@anchor{287}@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-bit-order-on-byte-ordering}@anchor{288} +@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-bit-order-on-byte-ordering}@anchor{287}@anchor{gnat_rm/representation_clauses_and_pragmas id10}@anchor{288} @section Effect of Bit_Order on Byte Ordering @@ -19059,8 +19059,8 @@ Reference Manual: @quotation -"2 A bit ordering is a method of interpreting the meaning of -the storage place attributes." +“2 A bit ordering is a method of interpreting the meaning of +the storage place attributes.” @end quotation To understand the precise definition of storage place attributes in @@ -19068,11 +19068,11 @@ this context, we visit section 13.5.1 of the manual: @quotation -"13 A record_representation_clause (without the mod_clause) +“13 A record_representation_clause (without the mod_clause) specifies the layout. The storage place attributes (see 13.5.2) are taken from the values of the position, first_bit, and last_bit expressions after normalizing those values so that first_bit is -less than Storage_Unit." +less than Storage_Unit.” @end quotation The critical point here is that storage places are taken from @@ -19082,14 +19082,14 @@ is described in the later part of the 13.5.3 paragraph: @quotation -"2 A bit ordering is a method of interpreting the meaning of +“2 A bit ordering is a method of interpreting the meaning of the storage place attributes. High_Order_First (known in the -vernacular as 'big endian') means that the first bit of a +vernacular as ‘big endian’) means that the first bit of a storage element (bit 0) is the most significant bit (interpreting the sequence of bits that represent a component as an unsigned integer value). Low_Order_First (known in the vernacular as -'little endian') means the opposite: the first bit is the -least significant." +‘little endian’) means the opposite: the first bit is the +least significant.” @end quotation Note that the numbering is with respect to the bits of a storage @@ -19103,7 +19103,7 @@ byte presented, which is the first (low addressed byte) of the two byte record is called Master, and the second byte is called Slave. The left most (most significant bit is called Control for each byte, and -the remaining 7 bits are called V1, V2, ... V7, where V7 is the rightmost +the remaining 7 bits are called V1, V2, … V7, where V7 is the rightmost (least significant) bit. On a big-endian machine, we can write the following representation clause @@ -19297,7 +19297,7 @@ to set the boolean constant @code{Master_Byte_First} in an appropriate manner. @node Pragma Pack for Arrays,Pragma Pack for Records,Effect of Bit_Order on Byte Ordering,Representation Clauses and Pragmas -@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-arrays}@anchor{289}@anchor{gnat_rm/representation_clauses_and_pragmas id11}@anchor{28a} +@anchor{gnat_rm/representation_clauses_and_pragmas id11}@anchor{289}@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-arrays}@anchor{28a} @section Pragma Pack for Arrays @@ -19417,7 +19417,7 @@ Here 31-bit packing is achieved as required, and no warning is generated, since in this case the programmer intention is clear. @node Pragma Pack for Records,Record Representation Clauses,Pragma Pack for Arrays,Representation Clauses and Pragmas -@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-records}@anchor{28b}@anchor{gnat_rm/representation_clauses_and_pragmas id12}@anchor{28c} +@anchor{gnat_rm/representation_clauses_and_pragmas id12}@anchor{28b}@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-records}@anchor{28c} @section Pragma Pack for Records @@ -19586,7 +19586,7 @@ end record; @geindex Handling of Records with Holes -As a result of alignment considerations, records may contain "holes" +As a result of alignment considerations, records may contain “holes” or gaps which do not correspond to the data bits of any of the components. Record representation clauses can also result in holes in records. @@ -19699,7 +19699,7 @@ the overhead of converting representation values to the corresponding positional values, (i.e., the value delivered by the @code{Pos} attribute). @node Address Clauses,Use of Address Clauses for Memory-Mapped I/O,Enumeration Clauses,Representation Clauses and Pragmas -@anchor{gnat_rm/representation_clauses_and_pragmas id16}@anchor{293}@anchor{gnat_rm/representation_clauses_and_pragmas address-clauses}@anchor{294} +@anchor{gnat_rm/representation_clauses_and_pragmas address-clauses}@anchor{293}@anchor{gnat_rm/representation_clauses_and_pragmas id16}@anchor{294} @section Address Clauses @@ -19710,12 +19710,12 @@ as found in RM 13.1(22): @quotation -"An implementation need not support representation +“An implementation need not support representation items containing nonstatic expressions, except that an implementation should support a representation item for a given entity if each nonstatic expression in the representation item is a name that statically denotes -a constant declared before the entity." +a constant declared before the entity.” @end quotation In practice this is applicable only to address clauses, since this is the @@ -19726,9 +19726,9 @@ the AARM notes in sections 13.1 (22.a-22.h): 22.a Reason: This is to avoid the following sort of thing: -22.b X : Integer := F(...); -Y : Address := G(...); -for X'Address use Y; +22.b X : Integer := F(…); +Y : Address := G(…); +for X’Address use Y; 22.c In the above, we have to evaluate the initialization expression for X before we @@ -19738,11 +19738,11 @@ like an unreasonable implementation burden. 22.d The above code should instead be written like this: -22.e Y : constant Address := G(...); -X : Integer := F(...); -for X'Address use Y; +22.e Y : constant Address := G(…); +X : Integer := F(…); +for X’Address use Y; -22.f This allows the expression 'Y' to be safely +22.f This allows the expression ‘Y’ to be safely evaluated before X is created. 22.g The constant could be a formal parameter of mode in. @@ -19789,7 +19789,7 @@ a component of a discriminated record. As noted above in section 22.h, address values are typically nonstatic. In particular the To_Address function, even if applied to a literal value, is a nonstatic function call. To avoid this minor annoyance, GNAT provides -the implementation defined attribute 'To_Address. The following two +the implementation defined attribute ‘To_Address. The following two expressions have identical values: @geindex Attribute @@ -19919,14 +19919,14 @@ implementation advice (RM 13.3(19)): @quotation -"19 If the Address of an object is specified, or it is imported +“19 If the Address of an object is specified, or it is imported or exported, then the implementation should not perform -optimizations based on assumptions of no aliases." +optimizations based on assumptions of no aliases.” @end quotation GNAT follows this recommendation, and goes further by also applying this recommendation to the overlaid variable (@code{A} in the above example) -in this case. This means that the overlay works "as expected", in that +in this case. This means that the overlay works “as expected”, in that a modification to one of the variables will affect the value of the other. More generally, GNAT interprets this recommendation conservatively for @@ -20086,7 +20086,7 @@ provides the pragma @code{Volatile_Full_Access} which can be used in lieu of pragma @code{Atomic} and will give the additional guarantee. @node Effect of Convention on Representation,Conventions and Anonymous Access Types,Use of Address Clauses for Memory-Mapped I/O,Representation Clauses and Pragmas -@anchor{gnat_rm/representation_clauses_and_pragmas id18}@anchor{297}@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-convention-on-representation}@anchor{298} +@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-convention-on-representation}@anchor{297}@anchor{gnat_rm/representation_clauses_and_pragmas id18}@anchor{298} @section Effect of Convention on Representation @@ -20183,7 +20183,7 @@ then the convention will apply to this anonymous type as well. This seems to make sense since it is anomolous in any case to have a different convention for an object and its type, and there is clearly no way to explicitly specify a convention for an anonymous type, since -it doesn't have a name to specify! +it doesn’t have a name to specify! Furthermore, we decide that if a convention is applied to a record type, then this convention is inherited by any of its components that are of an @@ -20240,7 +20240,7 @@ package ConvComp is @end example @node Determining the Representations chosen by GNAT,,Conventions and Anonymous Access Types,Representation Clauses and Pragmas -@anchor{gnat_rm/representation_clauses_and_pragmas id20}@anchor{29b}@anchor{gnat_rm/representation_clauses_and_pragmas determining-the-representations-chosen-by-gnat}@anchor{29c} +@anchor{gnat_rm/representation_clauses_and_pragmas determining-the-representations-chosen-by-gnat}@anchor{29b}@anchor{gnat_rm/representation_clauses_and_pragmas id20}@anchor{29c} @section Determining the Representations chosen by GNAT @@ -20392,7 +20392,7 @@ generated by the compiler into the original source to fix and guarantee the actual representation to be used. @node Standard Library Routines,The Implementation of Standard I/O,Representation Clauses and Pragmas,Top -@anchor{gnat_rm/standard_library_routines standard-library-routines}@anchor{e}@anchor{gnat_rm/standard_library_routines doc}@anchor{29d}@anchor{gnat_rm/standard_library_routines id1}@anchor{29e} +@anchor{gnat_rm/standard_library_routines doc}@anchor{29d}@anchor{gnat_rm/standard_library_routines id1}@anchor{29e}@anchor{gnat_rm/standard_library_routines standard-library-routines}@anchor{e} @chapter Standard Library Routines @@ -20567,7 +20567,7 @@ operations, which is not implemented in GNAT. This package provides constants describing the range of decimal numbers implemented, and also a decimal divide routine (analogous to the COBOL -verb DIVIDE ... GIVING ... REMAINDER ...) +verb DIVIDE … GIVING … REMAINDER …) @item @code{Ada.Direct_IO} @emph{(A.8.4)} @@ -20615,7 +20615,7 @@ all targets (see package spec for details). Not implemented in GNAT. -@item @code{Ada.Execution_Time.Timers} @emph{(D.14.1)'} +@item @code{Ada.Execution_Time.Timers} @emph{(D.14.1)’} Not implemented in GNAT. @@ -21216,7 +21216,7 @@ For packages in Interfaces and System, all the RM defined packages are available in GNAT, see the Ada 2012 RM for full details. @node The Implementation of Standard I/O,The GNAT Library,Standard Library Routines,Top -@anchor{gnat_rm/the_implementation_of_standard_i_o the-implementation-of-standard-i-o}@anchor{f}@anchor{gnat_rm/the_implementation_of_standard_i_o doc}@anchor{29f}@anchor{gnat_rm/the_implementation_of_standard_i_o id1}@anchor{2a0} +@anchor{gnat_rm/the_implementation_of_standard_i_o doc}@anchor{29f}@anchor{gnat_rm/the_implementation_of_standard_i_o id1}@anchor{2a0}@anchor{gnat_rm/the_implementation_of_standard_i_o the-implementation-of-standard-i-o}@anchor{f} @chapter The Implementation of Standard I/O @@ -21268,7 +21268,7 @@ these additional facilities are also described in this chapter. @end menu @node Standard I/O Packages,FORM Strings,,The Implementation of Standard I/O -@anchor{gnat_rm/the_implementation_of_standard_i_o standard-i-o-packages}@anchor{2a1}@anchor{gnat_rm/the_implementation_of_standard_i_o id2}@anchor{2a2} +@anchor{gnat_rm/the_implementation_of_standard_i_o id2}@anchor{2a1}@anchor{gnat_rm/the_implementation_of_standard_i_o standard-i-o-packages}@anchor{2a2} @section Standard I/O Packages @@ -21385,7 +21385,7 @@ There is no limit on the size of Direct_IO files, they are expanded as necessary to accommodate whatever records are written to the file. @node Sequential_IO,Text_IO,Direct_IO,The Implementation of Standard I/O -@anchor{gnat_rm/the_implementation_of_standard_i_o sequential-io}@anchor{2a7}@anchor{gnat_rm/the_implementation_of_standard_i_o id5}@anchor{2a8} +@anchor{gnat_rm/the_implementation_of_standard_i_o id5}@anchor{2a7}@anchor{gnat_rm/the_implementation_of_standard_i_o sequential-io}@anchor{2a8} @section Sequential_IO @@ -21551,7 +21551,7 @@ between two Ada files, then the difference may be observable in some situations. @node Reading and Writing Non-Regular Files,Get_Immediate,Stream Pointer Positioning,Text_IO -@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files}@anchor{2ad}@anchor{gnat_rm/the_implementation_of_standard_i_o id8}@anchor{2ae} +@anchor{gnat_rm/the_implementation_of_standard_i_o id8}@anchor{2ad}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files}@anchor{2ae} @subsection Reading and Writing Non-Regular Files @@ -21592,7 +21592,7 @@ above they will not be treated as page marks on input if the output is piped to another Ada program. Another important discrepancy when reading non-regular files is that the end -of file indication is not 'sticky'. If an end of file is entered, e.g., by +of file indication is not ‘sticky’. If an end of file is entered, e.g., by pressing the @code{EOT} key, then end of file is signaled once (i.e., the test @code{End_Of_File} @@ -21664,7 +21664,7 @@ the string is to be read. @end itemize @node Text_IO Facilities for Unbounded Strings,,Text_IO Extensions,Text_IO -@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-facilities-for-unbounded-strings}@anchor{2b5}@anchor{gnat_rm/the_implementation_of_standard_i_o id12}@anchor{2b6} +@anchor{gnat_rm/the_implementation_of_standard_i_o id12}@anchor{2b5}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-facilities-for-unbounded-strings}@anchor{2b6} @subsection Text_IO Facilities for Unbounded Strings @@ -21712,7 +21712,7 @@ files @code{a-szuzti.ads} and @code{a-szuzti.adb} provides similar extended @code{Wide_Wide_Text_IO} functionality for unbounded wide wide strings. @node Wide_Text_IO,Wide_Wide_Text_IO,Text_IO,The Implementation of Standard I/O -@anchor{gnat_rm/the_implementation_of_standard_i_o wide-text-io}@anchor{2b7}@anchor{gnat_rm/the_implementation_of_standard_i_o id13}@anchor{2b8} +@anchor{gnat_rm/the_implementation_of_standard_i_o id13}@anchor{2b7}@anchor{gnat_rm/the_implementation_of_standard_i_o wide-text-io}@anchor{2b8} @section Wide_Text_IO @@ -21915,11 +21915,11 @@ as UTF-8 will be used for text input output. If brackets notation is used, then any occurrence of a left bracket in the input file which is not the start of a valid wide character sequence will cause Constraint_Error to be raised. It is possible to -encode a left bracket as ["5B"] and Wide_Text_IO and Wide_Wide_Text_IO +encode a left bracket as [“5B”] and Wide_Text_IO and Wide_Wide_Text_IO input will interpret this as a left bracket. However, when a left bracket is output, it will be output as a left bracket -and not as ["5B"]. We make this decision because for normal use of +and not as [“5B”]. We make this decision because for normal use of Wide_Text_IO for outputting messages, it is unpleasant to clobber left brackets. For example, if we write: @@ -21939,7 +21939,7 @@ Start of output ["5B"]first run] @quotation In practice brackets encoding is reasonably useful for normal Put_Line use -since we won't get confused between left brackets and wide character +since we won’t get confused between left brackets and wide character sequences in the output. But for input, or when files are written out and read back in, it really makes better sense to use one of the standard encoding methods such as UTF-8. @@ -21959,7 +21959,7 @@ input also causes Constraint_Error to be raised. @end menu @node Stream Pointer Positioning<2>,Reading and Writing Non-Regular Files<2>,,Wide_Text_IO -@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-1}@anchor{2b9}@anchor{gnat_rm/the_implementation_of_standard_i_o id14}@anchor{2ba} +@anchor{gnat_rm/the_implementation_of_standard_i_o id14}@anchor{2b9}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-1}@anchor{2ba} @subsection Stream Pointer Positioning @@ -21983,7 +21983,7 @@ to a normal program using @code{Wide_Text_IO}. However, this discrepancy can be observed if the wide text file shares a stream with another file. @node Reading and Writing Non-Regular Files<2>,,Stream Pointer Positioning<2>,Wide_Text_IO -@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-1}@anchor{2bb}@anchor{gnat_rm/the_implementation_of_standard_i_o id15}@anchor{2bc} +@anchor{gnat_rm/the_implementation_of_standard_i_o id15}@anchor{2bb}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-1}@anchor{2bc} @subsection Reading and Writing Non-Regular Files @@ -22163,7 +22163,7 @@ input also causes Constraint_Error to be raised. @end menu @node Stream Pointer Positioning<3>,Reading and Writing Non-Regular Files<3>,,Wide_Wide_Text_IO -@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-2}@anchor{2bf}@anchor{gnat_rm/the_implementation_of_standard_i_o id17}@anchor{2c0} +@anchor{gnat_rm/the_implementation_of_standard_i_o id17}@anchor{2bf}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-2}@anchor{2c0} @subsection Stream Pointer Positioning @@ -22390,7 +22390,7 @@ Unicode 8-bit encoding This encoding is only supported on the Windows platform. @node Open Modes,Operations on C Streams,File content encoding,The Implementation of Standard I/O -@anchor{gnat_rm/the_implementation_of_standard_i_o open-modes}@anchor{2cd}@anchor{gnat_rm/the_implementation_of_standard_i_o id24}@anchor{2ce} +@anchor{gnat_rm/the_implementation_of_standard_i_o id24}@anchor{2cd}@anchor{gnat_rm/the_implementation_of_standard_i_o open-modes}@anchor{2ce} @section Open Modes @@ -22423,11 +22423,11 @@ Append_File @tab -"r+" +“r+” @tab -"w+" +“w+” @item @@ -22435,11 +22435,11 @@ In_File @tab -"r" +“r” @tab -"w+" +“w+” @item @@ -22447,11 +22447,11 @@ Out_File (Direct_IO) @tab -"r+" +“r+” @tab -"w" +“w” @item @@ -22459,11 +22459,11 @@ Out_File (all other cases) @tab -"w" +“w” @tab -"w" +“w” @item @@ -22471,11 +22471,11 @@ Inout_File @tab -"r+" +“r+” @tab -"w+" +“w+” @end multitable @@ -22493,7 +22493,7 @@ subsequently requires switching from reading to writing or vice-versa, then the file is reopened in @code{r+} mode to permit the required operation. @node Operations on C Streams,Interfacing to C Streams,Open Modes,The Implementation of Standard I/O -@anchor{gnat_rm/the_implementation_of_standard_i_o operations-on-c-streams}@anchor{2cf}@anchor{gnat_rm/the_implementation_of_standard_i_o id25}@anchor{2d0} +@anchor{gnat_rm/the_implementation_of_standard_i_o id25}@anchor{2cf}@anchor{gnat_rm/the_implementation_of_standard_i_o operations-on-c-streams}@anchor{2d0} @section Operations on C Streams @@ -22653,7 +22653,7 @@ end Interfaces.C_Streams; @end example @node Interfacing to C Streams,,Operations on C Streams,The Implementation of Standard I/O -@anchor{gnat_rm/the_implementation_of_standard_i_o interfacing-to-c-streams}@anchor{2d1}@anchor{gnat_rm/the_implementation_of_standard_i_o id26}@anchor{2d2} +@anchor{gnat_rm/the_implementation_of_standard_i_o id26}@anchor{2d1}@anchor{gnat_rm/the_implementation_of_standard_i_o interfacing-to-c-streams}@anchor{2d2} @section Interfacing to C Streams @@ -22746,7 +22746,7 @@ imported from a C program, allowing an Ada file to operate on an existing C file. @node The GNAT Library,Interfacing to Other Languages,The Implementation of Standard I/O,Top -@anchor{gnat_rm/the_gnat_library the-gnat-library}@anchor{10}@anchor{gnat_rm/the_gnat_library doc}@anchor{2d3}@anchor{gnat_rm/the_gnat_library id1}@anchor{2d4} +@anchor{gnat_rm/the_gnat_library doc}@anchor{2d3}@anchor{gnat_rm/the_gnat_library id1}@anchor{2d4}@anchor{gnat_rm/the_gnat_library the-gnat-library}@anchor{10} @chapter The GNAT Library @@ -22940,7 +22940,7 @@ of GNAT, and will generate a warning message. @end menu @node Ada Characters Latin_9 a-chlat9 ads,Ada Characters Wide_Latin_1 a-cwila1 ads,,The GNAT Library -@anchor{gnat_rm/the_gnat_library id2}@anchor{2d5}@anchor{gnat_rm/the_gnat_library ada-characters-latin-9-a-chlat9-ads}@anchor{2d6} +@anchor{gnat_rm/the_gnat_library ada-characters-latin-9-a-chlat9-ads}@anchor{2d5}@anchor{gnat_rm/the_gnat_library id2}@anchor{2d6} @section @code{Ada.Characters.Latin_9} (@code{a-chlat9.ads}) @@ -22974,7 +22974,7 @@ is specifically authorized by the Ada Reference Manual (RM A.3.3(27)). @node Ada Characters Wide_Latin_9 a-cwila1 ads,Ada Characters Wide_Wide_Latin_1 a-chzla1 ads,Ada Characters Wide_Latin_1 a-cwila1 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id4}@anchor{2d9}@anchor{gnat_rm/the_gnat_library ada-characters-wide-latin-9-a-cwila1-ads}@anchor{2da} +@anchor{gnat_rm/the_gnat_library ada-characters-wide-latin-9-a-cwila1-ads}@anchor{2d9}@anchor{gnat_rm/the_gnat_library id4}@anchor{2da} @section @code{Ada.Characters.Wide_Latin_9} (@code{a-cwila1.ads}) @@ -23025,7 +23025,7 @@ is specifically authorized by the Ada Reference Manual (RM A.3.3(27)). @node Ada Containers Formal_Doubly_Linked_Lists a-cfdlli ads,Ada Containers Formal_Hashed_Maps a-cfhama ads,Ada Characters Wide_Wide_Latin_9 a-chzla9 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id7}@anchor{2df}@anchor{gnat_rm/the_gnat_library ada-containers-formal-doubly-linked-lists-a-cfdlli-ads}@anchor{2e0} +@anchor{gnat_rm/the_gnat_library ada-containers-formal-doubly-linked-lists-a-cfdlli-ads}@anchor{2df}@anchor{gnat_rm/the_gnat_library id7}@anchor{2e0} @section @code{Ada.Containers.Formal_Doubly_Linked_Lists} (@code{a-cfdlli.ads}) @@ -23044,7 +23044,7 @@ efficient version than the one defined in the standard. In particular it does not have the complex overhead required to detect cursor tampering. @node Ada Containers Formal_Hashed_Maps a-cfhama ads,Ada Containers Formal_Hashed_Sets a-cfhase ads,Ada Containers Formal_Doubly_Linked_Lists a-cfdlli ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id8}@anchor{2e1}@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-maps-a-cfhama-ads}@anchor{2e2} +@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-maps-a-cfhama-ads}@anchor{2e1}@anchor{gnat_rm/the_gnat_library id8}@anchor{2e2} @section @code{Ada.Containers.Formal_Hashed_Maps} (@code{a-cfhama.ads}) @@ -23063,7 +23063,7 @@ efficient version than the one defined in the standard. In particular it does not have the complex overhead required to detect cursor tampering. @node Ada Containers Formal_Hashed_Sets a-cfhase ads,Ada Containers Formal_Ordered_Maps a-cforma ads,Ada Containers Formal_Hashed_Maps a-cfhama ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id9}@anchor{2e3}@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-sets-a-cfhase-ads}@anchor{2e4} +@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-sets-a-cfhase-ads}@anchor{2e3}@anchor{gnat_rm/the_gnat_library id9}@anchor{2e4} @section @code{Ada.Containers.Formal_Hashed_Sets} (@code{a-cfhase.ads}) @@ -23082,7 +23082,7 @@ efficient version than the one defined in the standard. In particular it does not have the complex overhead required to detect cursor tampering. @node Ada Containers Formal_Ordered_Maps a-cforma ads,Ada Containers Formal_Ordered_Sets a-cforse ads,Ada Containers Formal_Hashed_Sets a-cfhase ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id10}@anchor{2e5}@anchor{gnat_rm/the_gnat_library ada-containers-formal-ordered-maps-a-cforma-ads}@anchor{2e6} +@anchor{gnat_rm/the_gnat_library ada-containers-formal-ordered-maps-a-cforma-ads}@anchor{2e5}@anchor{gnat_rm/the_gnat_library id10}@anchor{2e6} @section @code{Ada.Containers.Formal_Ordered_Maps} (@code{a-cforma.ads}) @@ -23120,7 +23120,7 @@ efficient version than the one defined in the standard. In particular it does not have the complex overhead required to detect cursor tampering. @node Ada Containers Formal_Vectors a-cofove ads,Ada Containers Formal_Indefinite_Vectors a-cfinve ads,Ada Containers Formal_Ordered_Sets a-cforse ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id12}@anchor{2e9}@anchor{gnat_rm/the_gnat_library ada-containers-formal-vectors-a-cofove-ads}@anchor{2ea} +@anchor{gnat_rm/the_gnat_library ada-containers-formal-vectors-a-cofove-ads}@anchor{2e9}@anchor{gnat_rm/the_gnat_library id12}@anchor{2ea} @section @code{Ada.Containers.Formal_Vectors} (@code{a-cofove.ads}) @@ -23139,7 +23139,7 @@ efficient version than the one defined in the standard. In particular it does not have the complex overhead required to detect cursor tampering. @node Ada Containers Formal_Indefinite_Vectors a-cfinve ads,Ada Containers Functional_Vectors a-cofuve ads,Ada Containers Formal_Vectors a-cofove ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id13}@anchor{2eb}@anchor{gnat_rm/the_gnat_library ada-containers-formal-indefinite-vectors-a-cfinve-ads}@anchor{2ec} +@anchor{gnat_rm/the_gnat_library ada-containers-formal-indefinite-vectors-a-cfinve-ads}@anchor{2eb}@anchor{gnat_rm/the_gnat_library id13}@anchor{2ec} @section @code{Ada.Containers.Formal_Indefinite_Vectors} (@code{a-cfinve.ads}) @@ -23158,7 +23158,7 @@ efficient version than the one defined in the standard. In particular it does not have the complex overhead required to detect cursor tampering. @node Ada Containers Functional_Vectors a-cofuve ads,Ada Containers Functional_Sets a-cofuse ads,Ada Containers Formal_Indefinite_Vectors a-cfinve ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id14}@anchor{2ed}@anchor{gnat_rm/the_gnat_library ada-containers-functional-vectors-a-cofuve-ads}@anchor{2ee} +@anchor{gnat_rm/the_gnat_library ada-containers-functional-vectors-a-cofuve-ads}@anchor{2ed}@anchor{gnat_rm/the_gnat_library id14}@anchor{2ee} @section @code{Ada.Containers.Functional_Vectors} (@code{a-cofuve.ads}) @@ -23202,7 +23202,7 @@ and annotations, so that they can be removed from the final executable. The specification of this unit is compatible with SPARK 2014. @node Ada Containers Functional_Maps a-cofuma ads,Ada Containers Bounded_Holders a-coboho ads,Ada Containers Functional_Sets a-cofuse ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id16}@anchor{2f1}@anchor{gnat_rm/the_gnat_library ada-containers-functional-maps-a-cofuma-ads}@anchor{2f2} +@anchor{gnat_rm/the_gnat_library ada-containers-functional-maps-a-cofuma-ads}@anchor{2f1}@anchor{gnat_rm/the_gnat_library id16}@anchor{2f2} @section @code{Ada.Containers.Functional_Maps} (@code{a-cofuma.ads}) @@ -23249,7 +23249,7 @@ provides a mechanism for obtaining environment values on systems where this concept makes sense. @node Ada Command_Line Remove a-colire ads,Ada Command_Line Response_File a-clrefi ads,Ada Command_Line Environment a-colien ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id19}@anchor{2f7}@anchor{gnat_rm/the_gnat_library ada-command-line-remove-a-colire-ads}@anchor{2f8} +@anchor{gnat_rm/the_gnat_library ada-command-line-remove-a-colire-ads}@anchor{2f7}@anchor{gnat_rm/the_gnat_library id19}@anchor{2f8} @section @code{Ada.Command_Line.Remove} (@code{a-colire.ads}) @@ -23267,7 +23267,7 @@ to further calls on the subprograms in @code{Ada.Command_Line} will not see the removed argument. @node Ada Command_Line Response_File a-clrefi ads,Ada Direct_IO C_Streams a-diocst ads,Ada Command_Line Remove a-colire ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id20}@anchor{2f9}@anchor{gnat_rm/the_gnat_library ada-command-line-response-file-a-clrefi-ads}@anchor{2fa} +@anchor{gnat_rm/the_gnat_library ada-command-line-response-file-a-clrefi-ads}@anchor{2f9}@anchor{gnat_rm/the_gnat_library id20}@anchor{2fa} @section @code{Ada.Command_Line.Response_File} (@code{a-clrefi.ads}) @@ -23282,12 +23282,12 @@ see the removed argument. @geindex handling long command lines This child of @code{Ada.Command_Line} provides a mechanism facilities for -getting command line arguments from a text file, called a "response file". +getting command line arguments from a text file, called a “response file”. Using a response file allow passing a set of arguments to an executable longer than the maximum allowed by the system on the command line. @node Ada Direct_IO C_Streams a-diocst ads,Ada Exceptions Is_Null_Occurrence a-einuoc ads,Ada Command_Line Response_File a-clrefi ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id21}@anchor{2fb}@anchor{gnat_rm/the_gnat_library ada-direct-io-c-streams-a-diocst-ads}@anchor{2fc} +@anchor{gnat_rm/the_gnat_library ada-direct-io-c-streams-a-diocst-ads}@anchor{2fb}@anchor{gnat_rm/the_gnat_library id21}@anchor{2fc} @section @code{Ada.Direct_IO.C_Streams} (@code{a-diocst.ads}) @@ -23302,7 +23302,7 @@ extracted from a file opened on the Ada side, and an Ada file can be constructed from a stream opened on the C side. @node Ada Exceptions Is_Null_Occurrence a-einuoc ads,Ada Exceptions Last_Chance_Handler a-elchha ads,Ada Direct_IO C_Streams a-diocst ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id22}@anchor{2fd}@anchor{gnat_rm/the_gnat_library ada-exceptions-is-null-occurrence-a-einuoc-ads}@anchor{2fe} +@anchor{gnat_rm/the_gnat_library ada-exceptions-is-null-occurrence-a-einuoc-ads}@anchor{2fd}@anchor{gnat_rm/the_gnat_library id22}@anchor{2fe} @section @code{Ada.Exceptions.Is_Null_Occurrence} (@code{a-einuoc.ads}) @@ -23316,7 +23316,7 @@ exception occurrence (@code{Null_Occurrence}) without raising an exception. @node Ada Exceptions Last_Chance_Handler a-elchha ads,Ada Exceptions Traceback a-exctra ads,Ada Exceptions Is_Null_Occurrence a-einuoc ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id23}@anchor{2ff}@anchor{gnat_rm/the_gnat_library ada-exceptions-last-chance-handler-a-elchha-ads}@anchor{300} +@anchor{gnat_rm/the_gnat_library ada-exceptions-last-chance-handler-a-elchha-ads}@anchor{2ff}@anchor{gnat_rm/the_gnat_library id23}@anchor{300} @section @code{Ada.Exceptions.Last_Chance_Handler} (@code{a-elchha.ads}) @@ -23358,7 +23358,7 @@ extracted from a file opened on the Ada side, and an Ada file can be constructed from a stream opened on the C side. @node Ada Streams Stream_IO C_Streams a-ssicst ads,Ada Strings Unbounded Text_IO a-suteio ads,Ada Sequential_IO C_Streams a-siocst ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id26}@anchor{305}@anchor{gnat_rm/the_gnat_library ada-streams-stream-io-c-streams-a-ssicst-ads}@anchor{306} +@anchor{gnat_rm/the_gnat_library ada-streams-stream-io-c-streams-a-ssicst-ads}@anchor{305}@anchor{gnat_rm/the_gnat_library id26}@anchor{306} @section @code{Ada.Streams.Stream_IO.C_Streams} (@code{a-ssicst.ads}) @@ -23390,7 +23390,7 @@ strings, avoiding the necessity for an intermediate operation with ordinary strings. @node Ada Strings Wide_Unbounded Wide_Text_IO a-swuwti ads,Ada Strings Wide_Wide_Unbounded Wide_Wide_Text_IO a-szuzti ads,Ada Strings Unbounded Text_IO a-suteio ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id28}@anchor{309}@anchor{gnat_rm/the_gnat_library ada-strings-wide-unbounded-wide-text-io-a-swuwti-ads}@anchor{30a} +@anchor{gnat_rm/the_gnat_library ada-strings-wide-unbounded-wide-text-io-a-swuwti-ads}@anchor{309}@anchor{gnat_rm/the_gnat_library id28}@anchor{30a} @section @code{Ada.Strings.Wide_Unbounded.Wide_Text_IO} (@code{a-swuwti.ads}) @@ -23407,7 +23407,7 @@ wide strings, avoiding the necessity for an intermediate operation with ordinary wide strings. @node Ada Strings Wide_Wide_Unbounded Wide_Wide_Text_IO a-szuzti ads,Ada Task_Initialization a-tasini ads,Ada Strings Wide_Unbounded Wide_Text_IO a-swuwti ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id29}@anchor{30b}@anchor{gnat_rm/the_gnat_library ada-strings-wide-wide-unbounded-wide-wide-text-io-a-szuzti-ads}@anchor{30c} +@anchor{gnat_rm/the_gnat_library ada-strings-wide-wide-unbounded-wide-wide-text-io-a-szuzti-ads}@anchor{30b}@anchor{gnat_rm/the_gnat_library id29}@anchor{30c} @section @code{Ada.Strings.Wide_Wide_Unbounded.Wide_Wide_Text_IO} (@code{a-szuzti.ads}) @@ -23466,7 +23466,7 @@ execution (for example a standard input file may be redefined to be interactive). @node Ada Wide_Characters Unicode a-wichun ads,Ada Wide_Text_IO C_Streams a-wtcstr ads,Ada Text_IO Reset_Standard_Files a-tirsfi ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id33}@anchor{313}@anchor{gnat_rm/the_gnat_library ada-wide-characters-unicode-a-wichun-ads}@anchor{314} +@anchor{gnat_rm/the_gnat_library ada-wide-characters-unicode-a-wichun-ads}@anchor{313}@anchor{gnat_rm/the_gnat_library id33}@anchor{314} @section @code{Ada.Wide_Characters.Unicode} (@code{a-wichun.ads}) @@ -23479,7 +23479,7 @@ This package provides subprograms that allow categorization of Wide_Character values according to Unicode categories. @node Ada Wide_Text_IO C_Streams a-wtcstr ads,Ada Wide_Text_IO Reset_Standard_Files a-wrstfi ads,Ada Wide_Characters Unicode a-wichun ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id34}@anchor{315}@anchor{gnat_rm/the_gnat_library ada-wide-text-io-c-streams-a-wtcstr-ads}@anchor{316} +@anchor{gnat_rm/the_gnat_library ada-wide-text-io-c-streams-a-wtcstr-ads}@anchor{315}@anchor{gnat_rm/the_gnat_library id34}@anchor{316} @section @code{Ada.Wide_Text_IO.C_Streams} (@code{a-wtcstr.ads}) @@ -23509,7 +23509,7 @@ execution (for example a standard input file may be redefined to be interactive). @node Ada Wide_Wide_Characters Unicode a-zchuni ads,Ada Wide_Wide_Text_IO C_Streams a-ztcstr ads,Ada Wide_Text_IO Reset_Standard_Files a-wrstfi ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id36}@anchor{319}@anchor{gnat_rm/the_gnat_library ada-wide-wide-characters-unicode-a-zchuni-ads}@anchor{31a} +@anchor{gnat_rm/the_gnat_library ada-wide-wide-characters-unicode-a-zchuni-ads}@anchor{319}@anchor{gnat_rm/the_gnat_library id36}@anchor{31a} @section @code{Ada.Wide_Wide_Characters.Unicode} (@code{a-zchuni.ads}) @@ -23522,7 +23522,7 @@ This package provides subprograms that allow categorization of Wide_Wide_Character values according to Unicode categories. @node Ada Wide_Wide_Text_IO C_Streams a-ztcstr ads,Ada Wide_Wide_Text_IO Reset_Standard_Files a-zrstfi ads,Ada Wide_Wide_Characters Unicode a-zchuni ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id37}@anchor{31b}@anchor{gnat_rm/the_gnat_library ada-wide-wide-text-io-c-streams-a-ztcstr-ads}@anchor{31c} +@anchor{gnat_rm/the_gnat_library ada-wide-wide-text-io-c-streams-a-ztcstr-ads}@anchor{31b}@anchor{gnat_rm/the_gnat_library id37}@anchor{31c} @section @code{Ada.Wide_Wide_Text_IO.C_Streams} (@code{a-ztcstr.ads}) @@ -23576,7 +23576,7 @@ binding. This package provides the Vector/View conversion routines. @node GNAT Altivec Vector_Operations g-alveop ads,GNAT Altivec Vector_Types g-alvety ads,GNAT Altivec Conversions g-altcon ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id41}@anchor{323}@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-operations-g-alveop-ads}@anchor{324} +@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-operations-g-alveop-ads}@anchor{323}@anchor{gnat_rm/the_gnat_library id41}@anchor{324} @section @code{GNAT.Altivec.Vector_Operations} (@code{g-alveop.ads}) @@ -23610,7 +23610,7 @@ to AltiVec facilities. @geindex AltiVec -This package provides public 'View' data types from/to which private +This package provides public ‘View’ data types from/to which private vector representations can be converted via GNAT.Altivec.Conversions. This allows convenient access to individual vector elements and provides a simple way to initialize vector @@ -23630,7 +23630,7 @@ an array wherever the separators appear, and provide direct access to the resulting slices. @node GNAT AWK g-awk ads,GNAT Bind_Environment g-binenv ads,GNAT Array_Split g-arrspl ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id45}@anchor{32b}@anchor{gnat_rm/the_gnat_library gnat-awk-g-awk-ads}@anchor{32c} +@anchor{gnat_rm/the_gnat_library gnat-awk-g-awk-ads}@anchor{32b}@anchor{gnat_rm/the_gnat_library id45}@anchor{32c} @section @code{GNAT.AWK} (@code{g-awk.ads}) @@ -23645,7 +23645,7 @@ or more files containing formatted data. The file is viewed as a database where each record is a line and a field is a data element in this line. @node GNAT Bind_Environment g-binenv ads,GNAT Branch_Prediction g-brapre ads,GNAT AWK g-awk ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id46}@anchor{32d}@anchor{gnat_rm/the_gnat_library gnat-bind-environment-g-binenv-ads}@anchor{32e} +@anchor{gnat_rm/the_gnat_library gnat-bind-environment-g-binenv-ads}@anchor{32d}@anchor{gnat_rm/the_gnat_library id46}@anchor{32e} @section @code{GNAT.Bind_Environment} (@code{g-binenv.ads}) @@ -23658,7 +23658,7 @@ These associations can be specified using the @code{-V} binder command line switch. @node GNAT Branch_Prediction g-brapre ads,GNAT Bounded_Buffers g-boubuf ads,GNAT Bind_Environment g-binenv ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id47}@anchor{32f}@anchor{gnat_rm/the_gnat_library gnat-branch-prediction-g-brapre-ads}@anchor{330} +@anchor{gnat_rm/the_gnat_library gnat-branch-prediction-g-brapre-ads}@anchor{32f}@anchor{gnat_rm/the_gnat_library id47}@anchor{330} @section @code{GNAT.Branch_Prediction} (@code{g-brapre.ads}) @@ -23712,7 +23712,7 @@ data items. Exchange and comparison procedures are provided by passing access-to-procedure values. @node GNAT Bubble_Sort_A g-busora ads,GNAT Bubble_Sort_G g-busorg ads,GNAT Bubble_Sort g-bubsor ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id51}@anchor{337}@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-a-g-busora-ads}@anchor{338} +@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-a-g-busora-ads}@anchor{337}@anchor{gnat_rm/the_gnat_library id51}@anchor{338} @section @code{GNAT.Bubble_Sort_A} (@code{g-busora.ads}) @@ -23755,7 +23755,7 @@ multiple instantiations. @geindex Wide characte representations Provides a routine which given a string, reads the start of the string to -see whether it is one of the standard byte order marks (BOM's) which signal +see whether it is one of the standard byte order marks (BOM’s) which signal the encoding of the string. The routine includes detection of special XML sequences for various UCS input formats. @@ -23774,7 +23774,7 @@ General routines for swapping the bytes in 2-, 4-, and 8-byte quantities. Machine-specific implementations are available in some cases. @node GNAT Calendar g-calend ads,GNAT Calendar Time_IO g-catiio ads,GNAT Byte_Swapping g-bytswa ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id55}@anchor{33f}@anchor{gnat_rm/the_gnat_library gnat-calendar-g-calend-ads}@anchor{340} +@anchor{gnat_rm/the_gnat_library gnat-calendar-g-calend-ads}@anchor{33f}@anchor{gnat_rm/the_gnat_library id55}@anchor{340} @section @code{GNAT.Calendar} (@code{g-calend.ads}) @@ -23788,7 +23788,7 @@ Also provides conversion of @code{Ada.Calendar.Time} values to and from the C @code{timeval} format. @node GNAT Calendar Time_IO g-catiio ads,GNAT CRC32 g-crc32 ads,GNAT Calendar g-calend ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id56}@anchor{341}@anchor{gnat_rm/the_gnat_library gnat-calendar-time-io-g-catiio-ads}@anchor{342} +@anchor{gnat_rm/the_gnat_library gnat-calendar-time-io-g-catiio-ads}@anchor{341}@anchor{gnat_rm/the_gnat_library id56}@anchor{342} @section @code{GNAT.Calendar.Time_IO} (@code{g-catiio.ads}) @@ -23799,7 +23799,7 @@ C @code{timeval} format. @geindex GNAT.Calendar.Time_IO (g-catiio.ads) @node GNAT CRC32 g-crc32 ads,GNAT Case_Util g-casuti ads,GNAT Calendar Time_IO g-catiio ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id57}@anchor{343}@anchor{gnat_rm/the_gnat_library gnat-crc32-g-crc32-ads}@anchor{344} +@anchor{gnat_rm/the_gnat_library gnat-crc32-g-crc32-ads}@anchor{343}@anchor{gnat_rm/the_gnat_library id57}@anchor{344} @section @code{GNAT.CRC32} (@code{g-crc32.ads}) @@ -23816,7 +23816,7 @@ of this algorithm see Aug. 1988. Sarwate, D.V. @node GNAT Case_Util g-casuti ads,GNAT CGI g-cgi ads,GNAT CRC32 g-crc32 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id58}@anchor{345}@anchor{gnat_rm/the_gnat_library gnat-case-util-g-casuti-ads}@anchor{346} +@anchor{gnat_rm/the_gnat_library gnat-case-util-g-casuti-ads}@anchor{345}@anchor{gnat_rm/the_gnat_library id58}@anchor{346} @section @code{GNAT.Case_Util} (@code{g-casuti.ads}) @@ -23831,7 +23831,7 @@ without the overhead of the full casing tables in @code{Ada.Characters.Handling}. @node GNAT CGI g-cgi ads,GNAT CGI Cookie g-cgicoo ads,GNAT Case_Util g-casuti ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id59}@anchor{347}@anchor{gnat_rm/the_gnat_library gnat-cgi-g-cgi-ads}@anchor{348} +@anchor{gnat_rm/the_gnat_library gnat-cgi-g-cgi-ads}@anchor{347}@anchor{gnat_rm/the_gnat_library id59}@anchor{348} @section @code{GNAT.CGI} (@code{g-cgi.ads}) @@ -23873,7 +23873,7 @@ This is a package to help debugging CGI (Common Gateway Interface) programs written in Ada. @node GNAT Command_Line g-comlin ads,GNAT Compiler_Version g-comver ads,GNAT CGI Debug g-cgideb ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id62}@anchor{34d}@anchor{gnat_rm/the_gnat_library gnat-command-line-g-comlin-ads}@anchor{34e} +@anchor{gnat_rm/the_gnat_library gnat-command-line-g-comlin-ads}@anchor{34d}@anchor{gnat_rm/the_gnat_library id62}@anchor{34e} @section @code{GNAT.Command_Line} (@code{g-comlin.ads}) @@ -23904,7 +23904,7 @@ of the compiler if a consistent tool set is used to compile all units of a partition). @node GNAT Ctrl_C g-ctrl_c ads,GNAT Current_Exception g-curexc ads,GNAT Compiler_Version g-comver ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id64}@anchor{351}@anchor{gnat_rm/the_gnat_library gnat-ctrl-c-g-ctrl-c-ads}@anchor{352} +@anchor{gnat_rm/the_gnat_library gnat-ctrl-c-g-ctrl-c-ads}@anchor{351}@anchor{gnat_rm/the_gnat_library id64}@anchor{352} @section @code{GNAT.Ctrl_C} (@code{g-ctrl_c.ads}) @@ -23915,7 +23915,7 @@ of a partition). Provides a simple interface to handle Ctrl-C keyboard events. @node GNAT Current_Exception g-curexc ads,GNAT Debug_Pools g-debpoo ads,GNAT Ctrl_C g-ctrl_c ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id65}@anchor{353}@anchor{gnat_rm/the_gnat_library gnat-current-exception-g-curexc-ads}@anchor{354} +@anchor{gnat_rm/the_gnat_library gnat-current-exception-g-curexc-ads}@anchor{353}@anchor{gnat_rm/the_gnat_library id65}@anchor{354} @section @code{GNAT.Current_Exception} (@code{g-curexc.ads}) @@ -23946,7 +23946,7 @@ obtaining information about exceptions provided by Ada 83 compilers. Provide a debugging storage pools that helps tracking memory corruption problems. -See @code{The GNAT Debug_Pool Facility} section in the @cite{GNAT User's Guide}. +See @code{The GNAT Debug_Pool Facility} section in the @cite{GNAT User’s Guide}. @node GNAT Debug_Utilities g-debuti ads,GNAT Decode_String g-decstr ads,GNAT Debug_Pools g-debpoo ads,The GNAT Library @anchor{gnat_rm/the_gnat_library gnat-debug-utilities-g-debuti-ads}@anchor{357}@anchor{gnat_rm/the_gnat_library id67}@anchor{358} @@ -24007,7 +24007,7 @@ preinstantiation for UTF-8. See next entry. A preinstantiation of GNAT.Decode_Strings for UTF-8 encoding. @node GNAT Directory_Operations g-dirope ads,GNAT Directory_Operations Iteration g-diopit ads,GNAT Decode_UTF8_String g-deutst ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id70}@anchor{35d}@anchor{gnat_rm/the_gnat_library gnat-directory-operations-g-dirope-ads}@anchor{35e} +@anchor{gnat_rm/the_gnat_library gnat-directory-operations-g-dirope-ads}@anchor{35d}@anchor{gnat_rm/the_gnat_library id70}@anchor{35e} @section @code{GNAT.Directory_Operations} (@code{g-dirope.ads}) @@ -24020,7 +24020,7 @@ the current directory, making new directories, and scanning the files in a directory. @node GNAT Directory_Operations Iteration g-diopit ads,GNAT Dynamic_HTables g-dynhta ads,GNAT Directory_Operations g-dirope ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id71}@anchor{35f}@anchor{gnat_rm/the_gnat_library gnat-directory-operations-iteration-g-diopit-ads}@anchor{360} +@anchor{gnat_rm/the_gnat_library gnat-directory-operations-iteration-g-diopit-ads}@anchor{35f}@anchor{gnat_rm/the_gnat_library id71}@anchor{360} @section @code{GNAT.Directory_Operations.Iteration} (@code{g-diopit.ads}) @@ -24032,7 +24032,7 @@ A child unit of GNAT.Directory_Operations providing additional operations for iterating through directories. @node GNAT Dynamic_HTables g-dynhta ads,GNAT Dynamic_Tables g-dyntab ads,GNAT Directory_Operations Iteration g-diopit ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id72}@anchor{361}@anchor{gnat_rm/the_gnat_library gnat-dynamic-htables-g-dynhta-ads}@anchor{362} +@anchor{gnat_rm/the_gnat_library gnat-dynamic-htables-g-dynhta-ads}@anchor{361}@anchor{gnat_rm/the_gnat_library id72}@anchor{362} @section @code{GNAT.Dynamic_HTables} (@code{g-dynhta.ads}) @@ -24070,7 +24070,7 @@ dynamic instances of the table, while an instantiation of @code{GNAT.Table} creates a single instance of the table type. @node GNAT Encode_String g-encstr ads,GNAT Encode_UTF8_String g-enutst ads,GNAT Dynamic_Tables g-dyntab ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id74}@anchor{365}@anchor{gnat_rm/the_gnat_library gnat-encode-string-g-encstr-ads}@anchor{366} +@anchor{gnat_rm/the_gnat_library gnat-encode-string-g-encstr-ads}@anchor{365}@anchor{gnat_rm/the_gnat_library id74}@anchor{366} @section @code{GNAT.Encode_String} (@code{g-encstr.ads}) @@ -24140,7 +24140,7 @@ Provides an interface allowing to control automatic output upon exception occurrences. @node GNAT Exceptions g-except ads,GNAT Expect g-expect ads,GNAT Exception_Traces g-exctra ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id78}@anchor{36d}@anchor{gnat_rm/the_gnat_library gnat-exceptions-g-except-ads}@anchor{36e} +@anchor{gnat_rm/the_gnat_library gnat-exceptions-g-except-ads}@anchor{36d}@anchor{gnat_rm/the_gnat_library id78}@anchor{36e} @section @code{GNAT.Exceptions} (@code{g-except.ads}) @@ -24161,7 +24161,7 @@ predefined exceptions, and for example allow raising @code{Constraint_Error} with a message from a pure subprogram. @node GNAT Expect g-expect ads,GNAT Expect TTY g-exptty ads,GNAT Exceptions g-except ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id79}@anchor{36f}@anchor{gnat_rm/the_gnat_library gnat-expect-g-expect-ads}@anchor{370} +@anchor{gnat_rm/the_gnat_library gnat-expect-g-expect-ads}@anchor{36f}@anchor{gnat_rm/the_gnat_library id79}@anchor{370} @section @code{GNAT.Expect} (@code{g-expect.ads}) @@ -24177,7 +24177,7 @@ It is not implemented for cross ports, and in particular is not implemented for VxWorks or LynxOS. @node GNAT Expect TTY g-exptty ads,GNAT Float_Control g-flocon ads,GNAT Expect g-expect ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id80}@anchor{371}@anchor{gnat_rm/the_gnat_library gnat-expect-tty-g-exptty-ads}@anchor{372} +@anchor{gnat_rm/the_gnat_library gnat-expect-tty-g-exptty-ads}@anchor{371}@anchor{gnat_rm/the_gnat_library id80}@anchor{372} @section @code{GNAT.Expect.TTY} (@code{g-exptty.ads}) @@ -24189,7 +24189,7 @@ ports. It is not implemented for cross ports, and in particular is not implemented for VxWorks or LynxOS. @node GNAT Float_Control g-flocon ads,GNAT Formatted_String g-forstr ads,GNAT Expect TTY g-exptty ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id81}@anchor{373}@anchor{gnat_rm/the_gnat_library gnat-float-control-g-flocon-ads}@anchor{374} +@anchor{gnat_rm/the_gnat_library gnat-float-control-g-flocon-ads}@anchor{373}@anchor{gnat_rm/the_gnat_library id81}@anchor{374} @section @code{GNAT.Float_Control} (@code{g-flocon.ads}) @@ -24203,7 +24203,7 @@ library calls may cause this mode to be modified, and the Reset procedure in this package can be used to reestablish the required mode. @node GNAT Formatted_String g-forstr ads,GNAT Heap_Sort g-heasor ads,GNAT Float_Control g-flocon ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id82}@anchor{375}@anchor{gnat_rm/the_gnat_library gnat-formatted-string-g-forstr-ads}@anchor{376} +@anchor{gnat_rm/the_gnat_library gnat-formatted-string-g-forstr-ads}@anchor{375}@anchor{gnat_rm/the_gnat_library id82}@anchor{376} @section @code{GNAT.Formatted_String} (@code{g-forstr.ads}) @@ -24218,7 +24218,7 @@ derived from Integer, Float or enumerations as values for the formatted string. @node GNAT Heap_Sort g-heasor ads,GNAT Heap_Sort_A g-hesora ads,GNAT Formatted_String g-forstr ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id83}@anchor{377}@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-heasor-ads}@anchor{378} +@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-heasor-ads}@anchor{377}@anchor{gnat_rm/the_gnat_library id83}@anchor{378} @section @code{GNAT.Heap_Sort} (@code{g-heasor.ads}) @@ -24248,7 +24248,7 @@ This differs from @code{GNAT.Heap_Sort} in having a less convenient interface, but may be slightly more efficient. @node GNAT Heap_Sort_G g-hesorg ads,GNAT HTable g-htable ads,GNAT Heap_Sort_A g-hesora ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id85}@anchor{37b}@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-g-hesorg-ads}@anchor{37c} +@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-g-hesorg-ads}@anchor{37b}@anchor{gnat_rm/the_gnat_library id85}@anchor{37c} @section @code{GNAT.Heap_Sort_G} (@code{g-hesorg.ads}) @@ -24262,7 +24262,7 @@ if the procedures can be inlined, at the expense of duplicating code for multiple instantiations. @node GNAT HTable g-htable ads,GNAT IO g-io ads,GNAT Heap_Sort_G g-hesorg ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id86}@anchor{37d}@anchor{gnat_rm/the_gnat_library gnat-htable-g-htable-ads}@anchor{37e} +@anchor{gnat_rm/the_gnat_library gnat-htable-g-htable-ads}@anchor{37d}@anchor{gnat_rm/the_gnat_library id86}@anchor{37e} @section @code{GNAT.HTable} (@code{g-htable.ads}) @@ -24275,7 +24275,7 @@ data. Provides two approaches, one a simple static approach, and the other allowing arbitrary dynamic hash tables. @node GNAT IO g-io ads,GNAT IO_Aux g-io_aux ads,GNAT HTable g-htable ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id87}@anchor{37f}@anchor{gnat_rm/the_gnat_library gnat-io-g-io-ads}@anchor{380} +@anchor{gnat_rm/the_gnat_library gnat-io-g-io-ads}@anchor{37f}@anchor{gnat_rm/the_gnat_library id87}@anchor{380} @section @code{GNAT.IO} (@code{g-io.ads}) @@ -24291,7 +24291,7 @@ Standard_Input, and writing characters, strings and integers to either Standard_Output or Standard_Error. @node GNAT IO_Aux g-io_aux ads,GNAT Lock_Files g-locfil ads,GNAT IO g-io ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id88}@anchor{381}@anchor{gnat_rm/the_gnat_library gnat-io-aux-g-io-aux-ads}@anchor{382} +@anchor{gnat_rm/the_gnat_library gnat-io-aux-g-io-aux-ads}@anchor{381}@anchor{gnat_rm/the_gnat_library id88}@anchor{382} @section @code{GNAT.IO_Aux} (@code{g-io_aux.ads}) @@ -24305,7 +24305,7 @@ Provides some auxiliary functions for use with Text_IO, including a test for whether a file exists, and functions for reading a line of text. @node GNAT Lock_Files g-locfil ads,GNAT MBBS_Discrete_Random g-mbdira ads,GNAT IO_Aux g-io_aux ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id89}@anchor{383}@anchor{gnat_rm/the_gnat_library gnat-lock-files-g-locfil-ads}@anchor{384} +@anchor{gnat_rm/the_gnat_library gnat-lock-files-g-locfil-ads}@anchor{383}@anchor{gnat_rm/the_gnat_library id89}@anchor{384} @section @code{GNAT.Lock_Files} (@code{g-locfil.ads}) @@ -24319,7 +24319,7 @@ Provides a general interface for using files as locks. Can be used for providing program level synchronization. @node GNAT MBBS_Discrete_Random g-mbdira ads,GNAT MBBS_Float_Random g-mbflra ads,GNAT Lock_Files g-locfil ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id90}@anchor{385}@anchor{gnat_rm/the_gnat_library gnat-mbbs-discrete-random-g-mbdira-ads}@anchor{386} +@anchor{gnat_rm/the_gnat_library gnat-mbbs-discrete-random-g-mbdira-ads}@anchor{385}@anchor{gnat_rm/the_gnat_library id90}@anchor{386} @section @code{GNAT.MBBS_Discrete_Random} (@code{g-mbdira.ads}) @@ -24331,7 +24331,7 @@ The original implementation of @code{Ada.Numerics.Discrete_Random}. Uses a modified version of the Blum-Blum-Shub generator. @node GNAT MBBS_Float_Random g-mbflra ads,GNAT MD5 g-md5 ads,GNAT MBBS_Discrete_Random g-mbdira ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id91}@anchor{387}@anchor{gnat_rm/the_gnat_library gnat-mbbs-float-random-g-mbflra-ads}@anchor{388} +@anchor{gnat_rm/the_gnat_library gnat-mbbs-float-random-g-mbflra-ads}@anchor{387}@anchor{gnat_rm/the_gnat_library id91}@anchor{388} @section @code{GNAT.MBBS_Float_Random} (@code{g-mbflra.ads}) @@ -24343,7 +24343,7 @@ The original implementation of @code{Ada.Numerics.Float_Random}. Uses a modified version of the Blum-Blum-Shub generator. @node GNAT MD5 g-md5 ads,GNAT Memory_Dump g-memdum ads,GNAT MBBS_Float_Random g-mbflra ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id92}@anchor{389}@anchor{gnat_rm/the_gnat_library gnat-md5-g-md5-ads}@anchor{38a} +@anchor{gnat_rm/the_gnat_library gnat-md5-g-md5-ads}@anchor{389}@anchor{gnat_rm/the_gnat_library id92}@anchor{38a} @section @code{GNAT.MD5} (@code{g-md5.ads}) @@ -24356,7 +24356,7 @@ the HMAC-MD5 message authentication function as described in RFC 2104 and FIPS PUB 198. @node GNAT Memory_Dump g-memdum ads,GNAT Most_Recent_Exception g-moreex ads,GNAT MD5 g-md5 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id93}@anchor{38b}@anchor{gnat_rm/the_gnat_library gnat-memory-dump-g-memdum-ads}@anchor{38c} +@anchor{gnat_rm/the_gnat_library gnat-memory-dump-g-memdum-ads}@anchor{38b}@anchor{gnat_rm/the_gnat_library id93}@anchor{38c} @section @code{GNAT.Memory_Dump} (@code{g-memdum.ads}) @@ -24429,7 +24429,7 @@ Provides random number capabilities which extend those available in the standard Ada library and are more convenient to use. @node GNAT Regexp g-regexp ads,GNAT Registry g-regist ads,GNAT Random_Numbers g-rannum ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id98}@anchor{395}@anchor{gnat_rm/the_gnat_library gnat-regexp-g-regexp-ads}@anchor{25a} +@anchor{gnat_rm/the_gnat_library gnat-regexp-g-regexp-ads}@anchor{25a}@anchor{gnat_rm/the_gnat_library id98}@anchor{395} @section @code{GNAT.Regexp} (@code{g-regexp.ads}) @@ -24442,10 +24442,10 @@ standard Ada library and are more convenient to use. A simple implementation of regular expressions, using a subset of regular expression syntax copied from familiar Unix style utilities. This is the simplest of the three pattern matching packages provided, and is particularly -suitable for 'file globbing' applications. +suitable for ‘file globbing’ applications. @node GNAT Registry g-regist ads,GNAT Regpat g-regpat ads,GNAT Regexp g-regexp ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id99}@anchor{396}@anchor{gnat_rm/the_gnat_library gnat-registry-g-regist-ads}@anchor{397} +@anchor{gnat_rm/the_gnat_library gnat-registry-g-regist-ads}@anchor{396}@anchor{gnat_rm/the_gnat_library id99}@anchor{397} @section @code{GNAT.Registry} (@code{g-regist.ads}) @@ -24459,7 +24459,7 @@ registry API, but at a lower level of abstraction, refer to the Win32.Winreg package provided with the Win32Ada binding @node GNAT Regpat g-regpat ads,GNAT Rewrite_Data g-rewdat ads,GNAT Registry g-regist ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id100}@anchor{398}@anchor{gnat_rm/the_gnat_library gnat-regpat-g-regpat-ads}@anchor{399} +@anchor{gnat_rm/the_gnat_library gnat-regpat-g-regpat-ads}@anchor{398}@anchor{gnat_rm/the_gnat_library id100}@anchor{399} @section @code{GNAT.Regpat} (@code{g-regpat.ads}) @@ -24474,7 +24474,7 @@ from the original V7 style regular expression library written in C by Henry Spencer (and binary compatible with this C library). @node GNAT Rewrite_Data g-rewdat ads,GNAT Secondary_Stack_Info g-sestin ads,GNAT Regpat g-regpat ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id101}@anchor{39a}@anchor{gnat_rm/the_gnat_library gnat-rewrite-data-g-rewdat-ads}@anchor{39b} +@anchor{gnat_rm/the_gnat_library gnat-rewrite-data-g-rewdat-ads}@anchor{39a}@anchor{gnat_rm/the_gnat_library id101}@anchor{39b} @section @code{GNAT.Rewrite_Data} (@code{g-rewdat.ads}) @@ -24496,11 +24496,11 @@ this interface usable for large files or socket streams. @geindex Secondary Stack Info -Provide the capability to query the high water mark of the current task's +Provide the capability to query the high water mark of the current task’s secondary stack. @node GNAT Semaphores g-semaph ads,GNAT Serial_Communications g-sercom ads,GNAT Secondary_Stack_Info g-sestin ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id103}@anchor{39e}@anchor{gnat_rm/the_gnat_library gnat-semaphores-g-semaph-ads}@anchor{39f} +@anchor{gnat_rm/the_gnat_library gnat-semaphores-g-semaph-ads}@anchor{39e}@anchor{gnat_rm/the_gnat_library id103}@anchor{39f} @section @code{GNAT.Semaphores} (@code{g-semaph.ads}) @@ -24562,7 +24562,7 @@ and the HMAC-SHA256 message authentication function as described in RFC 2104 and FIPS PUB 198. @node GNAT SHA384 g-sha384 ads,GNAT SHA512 g-sha512 ads,GNAT SHA256 g-sha256 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id108}@anchor{3a8}@anchor{gnat_rm/the_gnat_library gnat-sha384-g-sha384-ads}@anchor{3a9} +@anchor{gnat_rm/the_gnat_library gnat-sha384-g-sha384-ads}@anchor{3a8}@anchor{gnat_rm/the_gnat_library id108}@anchor{3a9} @section @code{GNAT.SHA384} (@code{g-sha384.ads}) @@ -24575,7 +24575,7 @@ and the HMAC-SHA384 message authentication function as described in RFC 2104 and FIPS PUB 198. @node GNAT SHA512 g-sha512 ads,GNAT Signals g-signal ads,GNAT SHA384 g-sha384 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id109}@anchor{3aa}@anchor{gnat_rm/the_gnat_library gnat-sha512-g-sha512-ads}@anchor{3ab} +@anchor{gnat_rm/the_gnat_library gnat-sha512-g-sha512-ads}@anchor{3aa}@anchor{gnat_rm/the_gnat_library id109}@anchor{3ab} @section @code{GNAT.SHA512} (@code{g-sha512.ads}) @@ -24670,7 +24670,7 @@ the SNOBOL4 dynamic pattern construction and matching capabilities, using the efficient algorithm developed by Robert Dewar for the SPITBOL system. @node GNAT Spitbol g-spitbo ads,GNAT Spitbol Table_Boolean g-sptabo ads,GNAT Spitbol Patterns g-spipat ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id116}@anchor{3b8}@anchor{gnat_rm/the_gnat_library gnat-spitbol-g-spitbo-ads}@anchor{3b9} +@anchor{gnat_rm/the_gnat_library gnat-spitbol-g-spitbo-ads}@anchor{3b8}@anchor{gnat_rm/the_gnat_library id116}@anchor{3b9} @section @code{GNAT.Spitbol} (@code{g-spitbo.ads}) @@ -24717,7 +24717,7 @@ for type @code{Standard.Integer}, giving an implementation of maps from string to integer values. @node GNAT Spitbol Table_VString g-sptavs ads,GNAT SSE g-sse ads,GNAT Spitbol Table_Integer g-sptain ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id119}@anchor{3be}@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-vstring-g-sptavs-ads}@anchor{3bf} +@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-vstring-g-sptavs-ads}@anchor{3be}@anchor{gnat_rm/the_gnat_library id119}@anchor{3bf} @section @code{GNAT.Spitbol.Table_VString} (@code{g-sptavs.ads}) @@ -24734,7 +24734,7 @@ a variable length string type, giving an implementation of general maps from strings to strings. @node GNAT SSE g-sse ads,GNAT SSE Vector_Types g-ssvety ads,GNAT Spitbol Table_VString g-sptavs ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id120}@anchor{3c0}@anchor{gnat_rm/the_gnat_library gnat-sse-g-sse-ads}@anchor{3c1} +@anchor{gnat_rm/the_gnat_library gnat-sse-g-sse-ads}@anchor{3c0}@anchor{gnat_rm/the_gnat_library id120}@anchor{3c1} @section @code{GNAT.SSE} (@code{g-sse.ads}) @@ -24767,7 +24767,7 @@ Provides a generic hash function working on arrays of scalars. Both the scalar type and the hash result type are parameters. @node GNAT Strings g-string ads,GNAT String_Split g-strspl ads,GNAT String_Hash g-strhas ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id123}@anchor{3c6}@anchor{gnat_rm/the_gnat_library gnat-strings-g-string-ads}@anchor{3c7} +@anchor{gnat_rm/the_gnat_library gnat-strings-g-string-ads}@anchor{3c6}@anchor{gnat_rm/the_gnat_library id123}@anchor{3c7} @section @code{GNAT.Strings} (@code{g-string.ads}) @@ -24791,7 +24791,7 @@ to the resulting slices. This package is instantiated from @code{GNAT.Array_Split}. @node GNAT Table g-table ads,GNAT Task_Lock g-tasloc ads,GNAT String_Split g-strspl ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id125}@anchor{3ca}@anchor{gnat_rm/the_gnat_library gnat-table-g-table-ads}@anchor{3cb} +@anchor{gnat_rm/the_gnat_library gnat-table-g-table-ads}@anchor{3ca}@anchor{gnat_rm/the_gnat_library id125}@anchor{3cb} @section @code{GNAT.Table} (@code{g-table.ads}) @@ -24811,7 +24811,7 @@ while an instantiation of @code{GNAT.Dynamic_Tables} creates a type that can be used to define dynamic instances of the table. @node GNAT Task_Lock g-tasloc ads,GNAT Time_Stamp g-timsta ads,GNAT Table g-table ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id126}@anchor{3cc}@anchor{gnat_rm/the_gnat_library gnat-task-lock-g-tasloc-ads}@anchor{3cd} +@anchor{gnat_rm/the_gnat_library gnat-task-lock-g-tasloc-ads}@anchor{3cc}@anchor{gnat_rm/the_gnat_library id126}@anchor{3cd} @section @code{GNAT.Task_Lock} (@code{g-tasloc.ads}) @@ -24828,7 +24828,7 @@ single global task lock. Appropriate for use in situations where contention between tasks is very rarely expected. @node GNAT Time_Stamp g-timsta ads,GNAT Threads g-thread ads,GNAT Task_Lock g-tasloc ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id127}@anchor{3ce}@anchor{gnat_rm/the_gnat_library gnat-time-stamp-g-timsta-ads}@anchor{3cf} +@anchor{gnat_rm/the_gnat_library gnat-time-stamp-g-timsta-ads}@anchor{3ce}@anchor{gnat_rm/the_gnat_library id127}@anchor{3cf} @section @code{GNAT.Time_Stamp} (@code{g-timsta.ads}) @@ -24860,7 +24860,7 @@ further details if your program has threads that are created by a non-Ada environment which then accesses Ada code. @node GNAT Traceback g-traceb ads,GNAT Traceback Symbolic g-trasym ads,GNAT Threads g-thread ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id129}@anchor{3d2}@anchor{gnat_rm/the_gnat_library gnat-traceback-g-traceb-ads}@anchor{3d3} +@anchor{gnat_rm/the_gnat_library gnat-traceback-g-traceb-ads}@anchor{3d2}@anchor{gnat_rm/the_gnat_library id129}@anchor{3d3} @section @code{GNAT.Traceback} (@code{g-traceb.ads}) @@ -24872,7 +24872,7 @@ Provides a facility for obtaining non-symbolic traceback information, useful in various debugging situations. @node GNAT Traceback Symbolic g-trasym ads,GNAT UTF_32 g-table ads,GNAT Traceback g-traceb ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id130}@anchor{3d4}@anchor{gnat_rm/the_gnat_library gnat-traceback-symbolic-g-trasym-ads}@anchor{3d5} +@anchor{gnat_rm/the_gnat_library gnat-traceback-symbolic-g-trasym-ads}@anchor{3d4}@anchor{gnat_rm/the_gnat_library id130}@anchor{3d5} @section @code{GNAT.Traceback.Symbolic} (@code{g-trasym.ads}) @@ -24881,7 +24881,7 @@ in various debugging situations. @geindex Trace back facilities @node GNAT UTF_32 g-table ads,GNAT Wide_Spelling_Checker g-u3spch ads,GNAT Traceback Symbolic g-trasym ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id131}@anchor{3d6}@anchor{gnat_rm/the_gnat_library gnat-utf-32-g-table-ads}@anchor{3d7} +@anchor{gnat_rm/the_gnat_library gnat-utf-32-g-table-ads}@anchor{3d6}@anchor{gnat_rm/the_gnat_library id131}@anchor{3d7} @section @code{GNAT.UTF_32} (@code{g-table.ads}) @@ -24925,7 +24925,7 @@ Provides a function for determining whether one wide string is a plausible near misspelling of another wide string. @node GNAT Wide_String_Split g-wistsp ads,GNAT Wide_Wide_Spelling_Checker g-zspche ads,GNAT Wide_Spelling_Checker g-wispch ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id134}@anchor{3dc}@anchor{gnat_rm/the_gnat_library gnat-wide-string-split-g-wistsp-ads}@anchor{3dd} +@anchor{gnat_rm/the_gnat_library gnat-wide-string-split-g-wistsp-ads}@anchor{3dc}@anchor{gnat_rm/the_gnat_library id134}@anchor{3dd} @section @code{GNAT.Wide_String_Split} (@code{g-wistsp.ads}) @@ -24965,7 +24965,7 @@ to the resulting slices. This package is instantiated from @code{GNAT.Array_Split}. @node Interfaces C Extensions i-cexten ads,Interfaces C Streams i-cstrea ads,GNAT Wide_Wide_String_Split g-zistsp ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library interfaces-c-extensions-i-cexten-ads}@anchor{3e2}@anchor{gnat_rm/the_gnat_library id137}@anchor{3e3} +@anchor{gnat_rm/the_gnat_library id137}@anchor{3e2}@anchor{gnat_rm/the_gnat_library interfaces-c-extensions-i-cexten-ads}@anchor{3e3} @section @code{Interfaces.C.Extensions} (@code{i-cexten.ads}) @@ -24989,7 +24989,7 @@ This package is a binding for the most commonly used operations on C streams. @node Interfaces Packed_Decimal i-pacdec ads,Interfaces VxWorks i-vxwork ads,Interfaces C Streams i-cstrea ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library interfaces-packed-decimal-i-pacdec-ads}@anchor{3e6}@anchor{gnat_rm/the_gnat_library id139}@anchor{3e7} +@anchor{gnat_rm/the_gnat_library id139}@anchor{3e6}@anchor{gnat_rm/the_gnat_library interfaces-packed-decimal-i-pacdec-ads}@anchor{3e7} @section @code{Interfaces.Packed_Decimal} (@code{i-pacdec.ads}) @@ -25004,7 +25004,7 @@ from a packed decimal format compatible with that used on IBM mainframes. @node Interfaces VxWorks i-vxwork ads,Interfaces VxWorks Int_Connection i-vxinco ads,Interfaces Packed_Decimal i-pacdec ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library interfaces-vxworks-i-vxwork-ads}@anchor{3e8}@anchor{gnat_rm/the_gnat_library id140}@anchor{3e9} +@anchor{gnat_rm/the_gnat_library id140}@anchor{3e8}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-i-vxwork-ads}@anchor{3e9} @section @code{Interfaces.VxWorks} (@code{i-vxwork.ads}) @@ -25020,7 +25020,7 @@ In particular, it interfaces with the VxWorks hardware interrupt facilities. @node Interfaces VxWorks Int_Connection i-vxinco ads,Interfaces VxWorks IO i-vxwoio ads,Interfaces VxWorks i-vxwork ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library interfaces-vxworks-int-connection-i-vxinco-ads}@anchor{3ea}@anchor{gnat_rm/the_gnat_library id141}@anchor{3eb} +@anchor{gnat_rm/the_gnat_library id141}@anchor{3ea}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-int-connection-i-vxinco-ads}@anchor{3eb} @section @code{Interfaces.VxWorks.Int_Connection} (@code{i-vxinco.ads}) @@ -25036,7 +25036,7 @@ intConnect() with a custom routine for installing interrupt handlers. @node Interfaces VxWorks IO i-vxwoio ads,System Address_Image s-addima ads,Interfaces VxWorks Int_Connection i-vxinco ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library interfaces-vxworks-io-i-vxwoio-ads}@anchor{3ec}@anchor{gnat_rm/the_gnat_library id142}@anchor{3ed} +@anchor{gnat_rm/the_gnat_library id142}@anchor{3ec}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-io-i-vxwoio-ads}@anchor{3ed} @section @code{Interfaces.VxWorks.IO} (@code{i-vxwoio.ads}) @@ -25059,7 +25059,7 @@ function codes. A particular use of this package is to enable the use of Get_Immediate under VxWorks. @node System Address_Image s-addima ads,System Assertions s-assert ads,Interfaces VxWorks IO i-vxwoio ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-address-image-s-addima-ads}@anchor{3ee}@anchor{gnat_rm/the_gnat_library id143}@anchor{3ef} +@anchor{gnat_rm/the_gnat_library id143}@anchor{3ee}@anchor{gnat_rm/the_gnat_library system-address-image-s-addima-ads}@anchor{3ef} @section @code{System.Address_Image} (@code{s-addima.ads}) @@ -25105,7 +25105,7 @@ on most targets, including all Alpha, ia64, PowerPC, SPARC V9, x86, and x86_64 platforms. @node System Memory s-memory ads,System Multiprocessors s-multip ads,System Atomic_Counters s-atocou ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-memory-s-memory-ads}@anchor{3f4}@anchor{gnat_rm/the_gnat_library id146}@anchor{3f5} +@anchor{gnat_rm/the_gnat_library id146}@anchor{3f4}@anchor{gnat_rm/the_gnat_library system-memory-s-memory-ads}@anchor{3f5} @section @code{System.Memory} (@code{s-memory.ads}) @@ -25136,7 +25136,7 @@ in GNAT we also make it available in Ada 95 and Ada 2005 (where it is technically an implementation-defined addition). @node System Multiprocessors Dispatching_Domains s-mudido ads,System Partition_Interface s-parint ads,System Multiprocessors s-multip ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-multiprocessors-dispatching-domains-s-mudido-ads}@anchor{3f8}@anchor{gnat_rm/the_gnat_library id148}@anchor{3f9} +@anchor{gnat_rm/the_gnat_library id148}@anchor{3f8}@anchor{gnat_rm/the_gnat_library system-multiprocessors-dispatching-domains-s-mudido-ads}@anchor{3f9} @section @code{System.Multiprocessors.Dispatching_Domains} (@code{s-mudido.ads}) @@ -25179,7 +25179,7 @@ declared. It uses malloc/free to allocate/free and does not attempt to do any automatic reclamation. @node System Pool_Local s-pooloc ads,System Restrictions s-restri ads,System Pool_Global s-pooglo ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-pool-local-s-pooloc-ads}@anchor{3fe}@anchor{gnat_rm/the_gnat_library id151}@anchor{3ff} +@anchor{gnat_rm/the_gnat_library id151}@anchor{3fe}@anchor{gnat_rm/the_gnat_library system-pool-local-s-pooloc-ads}@anchor{3ff} @section @code{System.Pool_Local} (@code{s-pooloc.ads}) @@ -25212,7 +25212,7 @@ compiler determined information on which restrictions are violated by one or more packages in the partition. @node System Rident s-rident ads,System Strings Stream_Ops s-ststop ads,System Restrictions s-restri ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-rident-s-rident-ads}@anchor{402}@anchor{gnat_rm/the_gnat_library id153}@anchor{403} +@anchor{gnat_rm/the_gnat_library id153}@anchor{402}@anchor{gnat_rm/the_gnat_library system-rident-s-rident-ads}@anchor{403} @section @code{System.Rident} (@code{s-rident.ads}) @@ -25244,7 +25244,7 @@ stream attributes are applied to string types, but the subprograms in this package can be used directly by application programs. @node System Unsigned_Types s-unstyp ads,System Wch_Cnv s-wchcnv ads,System Strings Stream_Ops s-ststop ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-unsigned-types-s-unstyp-ads}@anchor{406}@anchor{gnat_rm/the_gnat_library id155}@anchor{407} +@anchor{gnat_rm/the_gnat_library id155}@anchor{406}@anchor{gnat_rm/the_gnat_library system-unsigned-types-s-unstyp-ads}@anchor{407} @section @code{System.Unsigned_Types} (@code{s-unstyp.ads}) @@ -25257,7 +25257,7 @@ also contains some related definitions for other specialized types used by the compiler in connection with packed array types. @node System Wch_Cnv s-wchcnv ads,System Wch_Con s-wchcon ads,System Unsigned_Types s-unstyp ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-wch-cnv-s-wchcnv-ads}@anchor{408}@anchor{gnat_rm/the_gnat_library id156}@anchor{409} +@anchor{gnat_rm/the_gnat_library id156}@anchor{408}@anchor{gnat_rm/the_gnat_library system-wch-cnv-s-wchcnv-ads}@anchor{409} @section @code{System.Wch_Cnv} (@code{s-wchcnv.ads}) @@ -25290,7 +25290,7 @@ in ordinary strings. These definitions are used by the package @code{System.Wch_Cnv}. @node Interfacing to Other Languages,Specialized Needs Annexes,The GNAT Library,Top -@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-other-languages}@anchor{11}@anchor{gnat_rm/interfacing_to_other_languages doc}@anchor{40c}@anchor{gnat_rm/interfacing_to_other_languages id1}@anchor{40d} +@anchor{gnat_rm/interfacing_to_other_languages doc}@anchor{40c}@anchor{gnat_rm/interfacing_to_other_languages id1}@anchor{40d}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-other-languages}@anchor{11} @chapter Interfacing to Other Languages @@ -25308,7 +25308,7 @@ provided. @end menu @node Interfacing to C,Interfacing to C++,,Interfacing to Other Languages -@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-c}@anchor{40e}@anchor{gnat_rm/interfacing_to_other_languages id2}@anchor{40f} +@anchor{gnat_rm/interfacing_to_other_languages id2}@anchor{40e}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-c}@anchor{40f} @section Interfacing to C @@ -25448,7 +25448,7 @@ of the length corresponding to the @code{type'Size} value in Ada. @end itemize @node Interfacing to C++,Interfacing to COBOL,Interfacing to C,Interfacing to Other Languages -@anchor{gnat_rm/interfacing_to_other_languages id4}@anchor{410}@anchor{gnat_rm/interfacing_to_other_languages id3}@anchor{47} +@anchor{gnat_rm/interfacing_to_other_languages id3}@anchor{47}@anchor{gnat_rm/interfacing_to_other_languages id4}@anchor{410} @section Interfacing to C++ @@ -25523,7 +25523,7 @@ multi-dimensional array causes the array to be stored in column-major order as required for convenient interface to Fortran. @node Interfacing to non-GNAT Ada code,,Interfacing to Fortran,Interfacing to Other Languages -@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-non-gnat-ada-code}@anchor{415}@anchor{gnat_rm/interfacing_to_other_languages id7}@anchor{416} +@anchor{gnat_rm/interfacing_to_other_languages id7}@anchor{415}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-non-gnat-ada-code}@anchor{416} @section Interfacing to non-GNAT Ada code @@ -25547,7 +25547,7 @@ values or simple record types without variants, or simple array types with fixed bounds. @node Specialized Needs Annexes,Implementation of Specific Ada Features,Interfacing to Other Languages,Top -@anchor{gnat_rm/specialized_needs_annexes specialized-needs-annexes}@anchor{12}@anchor{gnat_rm/specialized_needs_annexes doc}@anchor{417}@anchor{gnat_rm/specialized_needs_annexes id1}@anchor{418} +@anchor{gnat_rm/specialized_needs_annexes doc}@anchor{417}@anchor{gnat_rm/specialized_needs_annexes id1}@anchor{418}@anchor{gnat_rm/specialized_needs_annexes specialized-needs-annexes}@anchor{12} @chapter Specialized Needs Annexes @@ -25588,7 +25588,7 @@ in Ada 2005) is fully implemented. @end table @node Implementation of Specific Ada Features,Implementation of Ada 2012 Features,Specialized Needs Annexes,Top -@anchor{gnat_rm/implementation_of_specific_ada_features implementation-of-specific-ada-features}@anchor{13}@anchor{gnat_rm/implementation_of_specific_ada_features doc}@anchor{419}@anchor{gnat_rm/implementation_of_specific_ada_features id1}@anchor{41a} +@anchor{gnat_rm/implementation_of_specific_ada_features doc}@anchor{419}@anchor{gnat_rm/implementation_of_specific_ada_features id1}@anchor{41a}@anchor{gnat_rm/implementation_of_specific_ada_features implementation-of-specific-ada-features}@anchor{13} @chapter Implementation of Specific Ada Features @@ -25606,7 +25606,7 @@ facilities. @end menu @node Machine Code Insertions,GNAT Implementation of Tasking,,Implementation of Specific Ada Features -@anchor{gnat_rm/implementation_of_specific_ada_features machine-code-insertions}@anchor{166}@anchor{gnat_rm/implementation_of_specific_ada_features id2}@anchor{41b} +@anchor{gnat_rm/implementation_of_specific_ada_features id2}@anchor{41b}@anchor{gnat_rm/implementation_of_specific_ada_features machine-code-insertions}@anchor{166} @section Machine Code Insertions @@ -25671,7 +25671,7 @@ result. The possible values for constraint are the same as those used in the RTL, and are dependent on the configuration file used to build the GCC back end. If there are no output operands, then this argument may either be omitted, or explicitly given as @code{No_Output_Operands}. -No support is provided for GNU C's symbolic names for output parameters. +No support is provided for GNU C’s symbolic names for output parameters. The second argument of @code{my_float'Asm_Output} functions as though it were an @code{out} parameter, which is a little curious, but @@ -25690,7 +25690,7 @@ to be a static expression, and is the constraint for the parameter, value to be used as the input argument. The possible values for the constraint are the same as those used in the RTL, and are dependent on the configuration file used to built the GCC back end. -No support is provided for GNU C's symbolic names for input parameters. +No support is provided for GNU C’s symbolic names for input parameters. If there are no input operands, this argument may either be omitted, or explicitly given as @code{No_Input_Operands}. The fourth argument, not @@ -25715,11 +25715,11 @@ Generally it is strongly advisable to use Volatile for any ASM statement that is missing either input or output operands or to avoid unwanted optimizations. A warning is generated if this advice is not followed. -No support is provided for GNU C's @code{asm goto} feature. +No support is provided for GNU C’s @code{asm goto} feature. The @code{Asm} subprograms may be used in two ways. First the procedure forms can be used anywhere a procedure call would be valid, and -correspond to what the RM calls 'intrinsic' routines. Such calls can +correspond to what the RM calls ‘intrinsic’ routines. Such calls can be used to intersperse machine instructions with other Ada statements. Second, the function forms, which return a dummy value of the limited private type @code{Asm_Insn}, can be used in code statements, and indeed @@ -25774,7 +25774,7 @@ according to normal visibility rules. In particular if there is no qualification is required. @node GNAT Implementation of Tasking,GNAT Implementation of Shared Passive Packages,Machine Code Insertions,Implementation of Specific Ada Features -@anchor{gnat_rm/implementation_of_specific_ada_features id3}@anchor{41c}@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-tasking}@anchor{41d} +@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-tasking}@anchor{41c}@anchor{gnat_rm/implementation_of_specific_ada_features id3}@anchor{41d} @section GNAT Implementation of Tasking @@ -25790,11 +25790,11 @@ to compliance with the Real-Time Systems Annex. @end menu @node Mapping Ada Tasks onto the Underlying Kernel Threads,Ensuring Compliance with the Real-Time Annex,,GNAT Implementation of Tasking -@anchor{gnat_rm/implementation_of_specific_ada_features mapping-ada-tasks-onto-the-underlying-kernel-threads}@anchor{41e}@anchor{gnat_rm/implementation_of_specific_ada_features id4}@anchor{41f} +@anchor{gnat_rm/implementation_of_specific_ada_features id4}@anchor{41e}@anchor{gnat_rm/implementation_of_specific_ada_features mapping-ada-tasks-onto-the-underlying-kernel-threads}@anchor{41f} @subsection Mapping Ada Tasks onto the Underlying Kernel Threads -GNAT's run-time support comprises two layers: +GNAT’s run-time support comprises two layers: @itemize * @@ -25806,12 +25806,12 @@ GNARL (GNAT Run-time Layer) GNULL (GNAT Low-level Library) @end itemize -In GNAT, Ada's tasking services rely on a platform and OS independent +In GNAT, Ada’s tasking services rely on a platform and OS independent layer known as GNARL. This code is responsible for implementing the -correct semantics of Ada's task creation, rendezvous, protected +correct semantics of Ada’s task creation, rendezvous, protected operations etc. -GNARL decomposes Ada's tasking semantics into simpler lower level +GNARL decomposes Ada’s tasking semantics into simpler lower level operations such as create a thread, set the priority of a thread, yield, create a lock, lock/unlock, etc. The spec for these low-level operations constitutes GNULLI, the GNULL Interface. This interface is @@ -25859,7 +25859,7 @@ support this functionality when the parent contains more than one task. @geindex Forking a new process @node Ensuring Compliance with the Real-Time Annex,Support for Locking Policies,Mapping Ada Tasks onto the Underlying Kernel Threads,GNAT Implementation of Tasking -@anchor{gnat_rm/implementation_of_specific_ada_features id5}@anchor{420}@anchor{gnat_rm/implementation_of_specific_ada_features ensuring-compliance-with-the-real-time-annex}@anchor{421} +@anchor{gnat_rm/implementation_of_specific_ada_features ensuring-compliance-with-the-real-time-annex}@anchor{420}@anchor{gnat_rm/implementation_of_specific_ada_features id5}@anchor{421} @subsection Ensuring Compliance with the Real-Time Annex @@ -25932,19 +25932,19 @@ and VxWorks. @code{Concurrent_Readers_Locking} is supported on Linux. Notes about @code{Ceiling_Locking} on Linux: -If the process is running as 'root', ceiling locking is used. +If the process is running as ‘root’, ceiling locking is used. If the capabilities facility is installed -("sudo apt-get --assume-yes install libcap-dev" on Ubuntu, +(“sudo apt-get –assume-yes install libcap-dev” on Ubuntu, for example), and the program is linked against that library -("-largs -lcap"), +(“-largs -lcap”), and the executable file has the cap_sys_nice capability -("sudo /sbin/setcap cap_sys_nice=ep executable_file_name"), +(“sudo /sbin/setcap cap_sys_nice=ep executable_file_name”), then ceiling locking is used. Otherwise, the @code{Ceiling_Locking} policy is ignored. @node GNAT Implementation of Shared Passive Packages,Code Generation for Array Aggregates,GNAT Implementation of Tasking,Implementation of Specific Ada Features -@anchor{gnat_rm/implementation_of_specific_ada_features id6}@anchor{423}@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-shared-passive-packages}@anchor{424} +@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-shared-passive-packages}@anchor{423}@anchor{gnat_rm/implementation_of_specific_ada_features id6}@anchor{424} @section GNAT Implementation of Shared Passive Packages @@ -26073,7 +26073,7 @@ component values and static subtypes also lead to simpler code. @end menu @node Static constant aggregates with static bounds,Constant aggregates with unconstrained nominal types,,Code Generation for Array Aggregates -@anchor{gnat_rm/implementation_of_specific_ada_features static-constant-aggregates-with-static-bounds}@anchor{427}@anchor{gnat_rm/implementation_of_specific_ada_features id8}@anchor{428} +@anchor{gnat_rm/implementation_of_specific_ada_features id8}@anchor{427}@anchor{gnat_rm/implementation_of_specific_ada_features static-constant-aggregates-with-static-bounds}@anchor{428} @subsection Static constant aggregates with static bounds @@ -26135,7 +26135,7 @@ Cr_Unc : constant One_Unc := (12,24,36); @end example @node Aggregates with static bounds,Aggregates with nonstatic bounds,Constant aggregates with unconstrained nominal types,Code Generation for Array Aggregates -@anchor{gnat_rm/implementation_of_specific_ada_features id10}@anchor{42b}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-static-bounds}@anchor{42c} +@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-static-bounds}@anchor{42b}@anchor{gnat_rm/implementation_of_specific_ada_features id10}@anchor{42c} @subsection Aggregates with static bounds @@ -26163,7 +26163,7 @@ end loop; @end example @node Aggregates with nonstatic bounds,Aggregates in assignment statements,Aggregates with static bounds,Code Generation for Array Aggregates -@anchor{gnat_rm/implementation_of_specific_ada_features id11}@anchor{42d}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-nonstatic-bounds}@anchor{42e} +@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-nonstatic-bounds}@anchor{42d}@anchor{gnat_rm/implementation_of_specific_ada_features id11}@anchor{42e} @subsection Aggregates with nonstatic bounds @@ -26174,7 +26174,7 @@ have to be applied to sub-arrays individually, if they do not have statically compatible subtypes. @node Aggregates in assignment statements,,Aggregates with nonstatic bounds,Code Generation for Array Aggregates -@anchor{gnat_rm/implementation_of_specific_ada_features id12}@anchor{42f}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-in-assignment-statements}@anchor{430} +@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-in-assignment-statements}@anchor{42f}@anchor{gnat_rm/implementation_of_specific_ada_features id12}@anchor{430} @subsection Aggregates in assignment statements @@ -26265,8 +26265,8 @@ object, and place it on the stack. This maximum size approach has been a source of surprise to some users, who expect the default values of the discriminants to determine the size reserved for an -unconstrained object: "If the default is 15, why should the object occupy -a larger size?" +unconstrained object: “If the default is 15, why should the object occupy +a larger size?” The answer, of course, is that the discriminant may be later modified, and its full range of values must be taken into account. This is why the declaration: @@ -26283,7 +26283,7 @@ is flagged by the compiler with a warning: an attempt to create @code{Too_Large} will raise @code{Storage_Error}, because the required size includes @code{Positive'Last} bytes. As the first example indicates, the proper approach is to declare an -index type of 'reasonable' range so that unconstrained objects are not too +index type of ‘reasonable’ range so that unconstrained objects are not too large. One final wrinkle: if the object is declared to be @code{aliased}, or if it is @@ -26296,7 +26296,7 @@ say) must be consistent, so it is imperative that the object, once created, remain invariant. @node Strict Conformance to the Ada Reference Manual,,The Size of Discriminated Records with Default Discriminants,Implementation of Specific Ada Features -@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{433}@anchor{gnat_rm/implementation_of_specific_ada_features id14}@anchor{434} +@anchor{gnat_rm/implementation_of_specific_ada_features id14}@anchor{433}@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{434} @section Strict Conformance to the Ada Reference Manual @@ -26323,7 +26323,7 @@ behavior (although at the cost of a significant performance penalty), so infinite and NaN values are properly generated. @node Implementation of Ada 2012 Features,Obsolescent Features,Implementation of Specific Ada Features,Top -@anchor{gnat_rm/implementation_of_ada_2012_features doc}@anchor{435}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{436} +@anchor{gnat_rm/implementation_of_ada_2012_features doc}@anchor{435}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{436}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14} @chapter Implementation of Ada 2012 Features @@ -26357,10 +26357,10 @@ subsequent releases. A date of 0000-00-00 means that GNAT has always implemented the feature, or implemented it as soon as it appeared as a binding interpretation. -Each feature corresponds to an Ada Issue ('AI') approved by the Ada +Each feature corresponds to an Ada Issue (‘AI’) approved by the Ada standardization group (ISO/IEC JTC1/SC22/WG9) for inclusion in Ada 2012. The features are ordered based on the relevant sections of the Ada -Reference Manual ("RM"). When a given AI relates to multiple points +Reference Manual (“RM”). When a given AI relates to multiple points in the RM, the earliest is used. A complete description of the AIs may be found in @@ -26446,7 +26446,7 @@ RM References: 2.08 (7) 2.08 (16) @itemize * @item -@emph{AI-0080 'View of' not needed if clear from context (0000-00-00)} +@emph{AI-0080 ‘View of’ not needed if clear from context (0000-00-00)} This is an editorial change only, described as non-testable in the AI. @@ -26462,7 +26462,7 @@ RM References: 3.01 (7) @emph{AI-0183 Aspect specifications (2010-08-16)} Aspect specifications have been fully implemented except for pre and post- -conditions, and type invariants, which have their own separate AI's. All +conditions, and type invariants, which have their own separate AI’s. All forms of declarations listed in the AI are supported. The following is a list of the aspects supported (with GNAT implementation aspects marked) @end itemize @@ -26483,7 +26483,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26491,7 +26491,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26535,7 +26535,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26555,7 +26555,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26569,7 +26569,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26577,7 +26577,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26597,7 +26597,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26611,7 +26611,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26643,7 +26643,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26651,7 +26651,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26659,7 +26659,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26697,7 +26697,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26705,7 +26705,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26713,7 +26713,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26733,7 +26733,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26741,7 +26741,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26749,7 +26749,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26757,7 +26757,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26771,7 +26771,7 @@ Source @tab --- GNAT +– GNAT @item @@ -26791,7 +26791,7 @@ Source @tab --- GNAT +– GNAT @end multitable @@ -26819,8 +26819,8 @@ RM References: 3.02.01 (3) 3.02.02 (2) 3.03.01 (2/2) 3.08 (6) @item @emph{AI-0128 Inequality is a primitive operation (0000-00-00)} -If an equality operator ("=") is declared for a type, then the implicitly -declared inequality operator ("/=") is a primitive operation of the type. +If an equality operator (“=”) is declared for a type, then the implicitly +declared inequality operator (“/=”) is a primitive operation of the type. This is the only reasonable interpretation, and is the one always implemented by GNAT, but the RM was not entirely clear in making this point. @@ -26884,7 +26884,7 @@ RM References: 3.03 (23) 3.10.02 (26/2) 4.01 (9) 6.04.01 (17) 8.05.01 ( @emph{AI-0093 Additional rules use immutably limited (0000-00-00)} This is an editorial change only, to make more widespread use of the Ada 2012 -'immutably limited'. +‘immutably limited’. RM References: 3.03 (23.4/3) @end itemize @@ -26952,7 +26952,7 @@ RM References: 3.05 (56/2) Ada 2012 relaxes the restriction that forbids discriminants of tagged types to have default expressions by allowing them when the type is limited. It is often useful to define a default value for a discriminant even though -it can't be changed by assignment. +it can’t be changed by assignment. RM References: 3.07 (9.1/2) 3.07.02 (3) @end itemize @@ -27011,7 +27011,7 @@ RM References: 3.09 (7.4/2) 3.09 (12.4/2) @emph{AI-0076 function with controlling result (0000-00-00)} This is an editorial change only. The RM defines calls with controlling -results, but uses the term 'function with controlling result' without an +results, but uses the term ‘function with controlling result’ without an explicit definition. RM References: 3.09.02 (2/2) @@ -27565,10 +27565,10 @@ RM References: 7.05 (5/2) 12.05.01 (5.1/2) @item @emph{AI-0099 Tag determines whether finalization needed (0000-00-00)} -This AI clarifies that 'needs finalization' is part of dynamic semantics, +This AI clarifies that ‘needs finalization’ is part of dynamic semantics, and therefore depends on the run-time characteristics of an object (i.e. its -tag) and not on its nominal type. As the AI indicates: "we do not expect -this to affect any implementation'@w{'}. +tag) and not on its nominal type. As the AI indicates: “we do not expect +this to affect any implementation’’. RM References: 7.06.01 (6) 7.06.01 (7) 7.06.01 (8) 7.06.01 (9/2) @end itemize @@ -27698,7 +27698,7 @@ C.06 (4) C.06 (6) C.06 (9) C.06 (13) C.06 (14) @itemize * @item -@emph{AI-0072 Task signalling using 'Terminated (0000-00-00)} +@emph{AI-0072 Task signalling using ‘Terminated (0000-00-00)} This AI clarifies that task signalling for reading @code{'Terminated} only occurs if the result is True. GNAT semantics has always been consistent with @@ -27838,7 +27838,7 @@ RM References: 10.02.01 (15.1/2) 10.02.01 (15.4/2) 10.02.01 (15.5/2) 10.0 @emph{AI-0219 Pure permissions and limited parameters (2010-05-25)} This AI refines the rules for the cases with limited parameters which do not -allow the implementations to omit 'redundant'. GNAT now properly conforms +allow the implementations to omit ‘redundant’. GNAT now properly conforms to the requirements of this binding interpretation. RM References: 10.02.01 (18/2) @@ -28117,7 +28117,7 @@ RM References: 13.13.02 (1.2/2) @itemize * @item -@emph{AI-0109 Redundant check in S'Class'Input (0000-00-00)} +@emph{AI-0109 Redundant check in S’Class’Input (0000-00-00)} This AI is an editorial change only. It removes the need for a tag check that can never fail. @@ -28179,7 +28179,7 @@ RM References: 13.14 (2) 13.14 (3/1) 13.14 (8.1/1) 13.14 (10) 13.14 (14 @item @emph{AI-0017 Freezing and incomplete types (0000-00-00)} -So-called 'Taft-amendment types' (i.e., types that are completed in package +So-called ‘Taft-amendment types’ (i.e., types that are completed in package bodies) are not frozen by the occurrence of bodies in the enclosing declarative part. GNAT always implemented this properly. @@ -28489,7 +28489,7 @@ RM References: H.04 (8/1) @end itemize @node Obsolescent Features,Compatibility and Porting Guide,Implementation of Ada 2012 Features,Top -@anchor{gnat_rm/obsolescent_features id1}@anchor{437}@anchor{gnat_rm/obsolescent_features doc}@anchor{438}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{15} +@anchor{gnat_rm/obsolescent_features doc}@anchor{437}@anchor{gnat_rm/obsolescent_features id1}@anchor{438}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{15} @chapter Obsolescent Features @@ -28513,7 +28513,7 @@ compatibility purposes. The pragma @code{No_Run_Time} is used to achieve an affect similar -to the use of the "Zero Foot Print" configurable run time, but without +to the use of the “Zero Foot Print” configurable run time, but without requiring a specially configured run time. The result of using this pragma, which must be used for all units in a partition, is to restrict the use of any language features requiring run-time support code. The @@ -28530,7 +28530,7 @@ The pragma @code{Ravenscar} has exactly the same effect as pragma is part of the new Ada 2005 standard. @node pragma Restricted_Run_Time,pragma Task_Info,pragma Ravenscar,Obsolescent Features -@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{43d}@anchor{gnat_rm/obsolescent_features id4}@anchor{43e} +@anchor{gnat_rm/obsolescent_features id4}@anchor{43d}@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{43e} @section pragma Restricted_Run_Time @@ -28540,7 +28540,7 @@ preferred since the Ada 2005 pragma @code{Profile} is intended for this kind of implementation dependent addition. @node pragma Task_Info,package System Task_Info s-tasinf ads,pragma Restricted_Run_Time,Obsolescent Features -@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{43f}@anchor{gnat_rm/obsolescent_features id5}@anchor{440} +@anchor{gnat_rm/obsolescent_features id5}@anchor{43f}@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{440} @section pragma Task_Info @@ -28573,10 +28573,10 @@ library. This package provides target dependent functionality that is used to support the @code{Task_Info} pragma. The predefined Ada package @code{System.Multiprocessors} and the @code{CPU} aspect now provide a -standard replacement for GNAT's @code{Task_Info} functionality. +standard replacement for GNAT’s @code{Task_Info} functionality. @node Compatibility and Porting Guide,GNU Free Documentation License,Obsolescent Features,Top -@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{16}@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{443}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{444} +@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{443}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{16}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{444} @chapter Compatibility and Porting Guide @@ -28613,7 +28613,7 @@ type F1 is delta 1.0 range -128.0 .. +128.0; then the implementation is allowed to choose -128.0 .. +127.0 if it likes, but is not required to do so. -This leads to possible portability problems, so let's have a closer +This leads to possible portability problems, so let’s have a closer look at this, and figure out how to avoid these problems. First, why does this freedom exist, and why would an implementation @@ -28623,11 +28623,11 @@ it would need 9 bits to hold the largest positive value (and typically that means 16 bits on all machines). But if the implementation chooses the +127.0 bound then it can fit values of the type in 8 bits. -Why not make the user write +127.0 if that's what is wanted? +Why not make the user write +127.0 if that’s what is wanted? The rationale is that if you are thinking of fixed point -as a kind of 'poor man's floating-point', then you don't want +as a kind of ‘poor man’s floating-point’, then you don’t want to be thinking about the scaled integers that are used in its -representation. Let's take another example: +representation. Let’s take another example: @example type F2 is delta 2.0**(-15) range -1.0 .. +1.0; @@ -28643,7 +28643,7 @@ type F2 is delta 2.0**(-15) range -1.0 .. +1.0-(2.0**(-15)); @end example and the Ada language design team felt that this was too annoying -to require. We don't need to debate this decision at this point, +to require. We don’t need to debate this decision at this point, since it is well established (the rule about narrowing the ranges dates to Ada 83). @@ -28770,7 +28770,7 @@ For example: for Char in 'A' .. 'Z' loop ... end loop; @end example -The problem is that 'A' and 'Z' could be from either +The problem is that ‘A’ and ‘Z’ could be from either @code{Character} or @code{Wide_Character}. The simplest correction is to make the type explicit; e.g.: @@ -28833,7 +28833,7 @@ In Ada 83, it was permissible to pass an indefinite type (e.g, @code{String}) as the actual for a generic formal private type, but then the instantiation would be illegal if there were any instances of declarations of variables of this type in the generic body. In Ada 95, to avoid this clear violation -of the methodological principle known as the 'contract model', +of the methodological principle known as the ‘contract model’, the generic declaration explicitly indicates whether or not such instantiations are permitted. If a generic formal parameter has explicit unknown discriminants, indicated by using @code{(<>)} after the @@ -28848,7 +28848,7 @@ the fix is usually simply to add the @code{(<>)} to the generic declaration. @end itemize @node More deterministic semantics,Changed semantics,Legal Ada 83 programs that are illegal in Ada 95,Compatibility with Ada 83 -@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{44b}@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{44c} +@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{44b}@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{44c} @subsection More deterministic semantics @@ -28876,7 +28876,7 @@ which open select branches are executed. @end itemize @node Changed semantics,Other language compatibility issues,More deterministic semantics,Compatibility with Ada 83 -@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{44d}@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{44e} +@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{44d}@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{44e} @subsection Changed semantics @@ -28918,7 +28918,7 @@ covers only the restricted range. @end itemize @node Other language compatibility issues,,Changed semantics,Compatibility with Ada 83 -@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{44f}@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{450} +@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{44f}@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{450} @subsection Other language compatibility issues @@ -28936,7 +28936,7 @@ as identifiers as in Ada 83. However, in practice, it is usually advisable to make the necessary modifications to the program to remove the need for using this switch. See the @code{Compiling Different Versions of Ada} section in -the @cite{GNAT User's Guide}. +the @cite{GNAT User’s Guide}. @item Support for removed Ada 83 pragmas and attributes @@ -29008,7 +29008,7 @@ now need to be considered in expression resolution. @item @emph{Fixed-point multiplication and division.} -Certain expressions involving '*' or '/' for a fixed-point type, which +Certain expressions involving ‘*’ or ‘/’ for a fixed-point type, which were legal in Ada 95 and invoked the predefined versions of these operations, are now ambiguous. The ambiguity may be resolved either by applying a type conversion to the @@ -29023,7 +29023,7 @@ can declare a function returning a value from an anonymous access type. @end itemize @node Implementation-dependent characteristics,Compatibility with Other Ada Systems,Compatibility between Ada 95 and Ada 2005,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{453}@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{454} +@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{453}@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{454} @section Implementation-dependent characteristics @@ -29046,7 +29046,7 @@ transition from certain Ada 83 compilers. @end menu @node Implementation-defined pragmas,Implementation-defined attributes,,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{455}@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{456} +@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{455}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{456} @subsection Implementation-defined pragmas @@ -29054,7 +29054,7 @@ Ada compilers are allowed to supplement the language-defined pragmas, and these are a potential source of non-portability. All GNAT-defined pragmas are described in @ref{7,,Implementation Defined Pragmas}, and these include several that are specifically -intended to correspond to other vendors' Ada 83 pragmas. +intended to correspond to other vendors’ Ada 83 pragmas. For migrating from VADS, the pragma @code{Use_VADS_Size} may be useful. For compatibility with HP Ada 83, GNAT supplies the pragmas @code{Extend_System}, @code{Ident}, @code{Inline_Generic}, @@ -29076,13 +29076,13 @@ Analogous to pragmas, the set of attributes may be extended by an implementation. All GNAT-defined attributes are described in @ref{8,,Implementation Defined Attributes}, and these include several that are specifically intended -to correspond to other vendors' Ada 83 attributes. For migrating from VADS, +to correspond to other vendors’ Ada 83 attributes. For migrating from VADS, the attribute @code{VADS_Size} may be useful. For compatibility with HP Ada 83, GNAT supplies the attributes @code{Bit}, @code{Machine_Size} and @code{Type_Class}. @node Libraries,Elaboration order,Implementation-defined attributes,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{459}@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{45a} +@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{459}@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{45a} @subsection Libraries @@ -29117,7 +29117,7 @@ be preferable to retrofit the application using modular types. The implementation can choose any elaboration order consistent with the unit dependency relationship. This freedom means that some orders can result in -Program_Error being raised due to an 'Access Before Elaboration': an attempt +Program_Error being raised due to an ‘Access Before Elaboration’: an attempt to invoke a subprogram before its body has been elaborated, or to instantiate a generic before the generic body has been elaborated. By default GNAT attempts to choose a safe order (one that will not encounter access before @@ -29126,7 +29126,7 @@ elaboration problems) by implicitly inserting @code{Elaborate} or needed. However, this can lead to the creation of elaboration circularities and a resulting rejection of the program by gnatbind. This issue is thoroughly described in the @emph{Elaboration Order Handling in GNAT} appendix -in the @cite{GNAT User's Guide}. +in the @cite{GNAT User’s Guide}. In brief, there are several ways to deal with this situation: @@ -29147,7 +29147,7 @@ pragmas either globally (as an effect of the @emph{-gnatE} switch) or locally @end itemize @node Target-specific aspects,,Elaboration order,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{45d}@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{45e} +@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{45d}@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{45e} @subsection Target-specific aspects @@ -29160,10 +29160,10 @@ on the robustness of the original design. Moreover, Ada 95 (and thus Ada 2005 and Ada 2012) are sometimes incompatible with typical Ada 83 compiler practices regarding implicit packing, the meaning of the Size attribute, and the size of access values. -GNAT's approach to these issues is described in @ref{45f,,Representation Clauses}. +GNAT’s approach to these issues is described in @ref{45f,,Representation Clauses}. @node Compatibility with Other Ada Systems,Representation Clauses,Implementation-dependent characteristics,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{460}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{461} +@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{460}@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{461} @section Compatibility with Other Ada Systems @@ -29206,7 +29206,7 @@ far beyond this minimal set, as described in the next section. @end itemize @node Representation Clauses,Compatibility with HP Ada 83,Compatibility with Other Ada Systems,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{45f}@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{462} +@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{462}@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{45f} @section Representation Clauses @@ -29236,7 +29236,7 @@ Some Ada 83 compilers allowed a Size specification to cause implicit packing of an array or record. This could cause expensive implicit conversions for change of representation in the presence of derived types, and the Ada design intends to avoid this possibility. -Subsequent AI's were issued to make it clear that such implicit +Subsequent AI’s were issued to make it clear that such implicit change of representation in response to a Size clause is inadvisable, and this recommendation is represented explicitly in the Ada 95 (and Ada 2005) Reference Manuals as implementation advice that is followed by GNAT. @@ -29254,7 +29254,7 @@ on a 32-bit machine, the size of @code{Natural} will typically be 31 and not 32 (since no sign bit is required). Some Ada 83 compilers gave 31, and some 32 in this situation. This problem will usually show up as a compile time error, but not always. It is a good idea to check all uses of the -'Size attribute when porting Ada 83 code. The GNAT specific attribute +‘Size attribute when porting Ada 83 code. The GNAT specific attribute Object_Size can provide a useful way of duplicating the behavior of some Ada 83 compiler systems. @@ -29265,14 +29265,14 @@ A common assumption in Ada 83 code is that an access type is in fact a pointer, and that therefore it will be the same size as a System.Address value. This assumption is true for GNAT in most cases with one exception. For the case of a pointer to an unconstrained array type (where the bounds may vary from one -value of the access type to another), the default is to use a 'fat pointer', +value of the access type to another), the default is to use a ‘fat pointer’, which is represented as two separate pointers, one to the bounds, and one to the array. This representation has a number of advantages, including improved efficiency. However, it may cause some difficulties in porting existing Ada 83 code which makes the assumption that, for example, pointers fit in 32 bits on a machine with 32-bit addressing. -To get around this problem, GNAT also permits the use of 'thin pointers' for +To get around this problem, GNAT also permits the use of ‘thin pointers’ for access types in this case (where the designated type is an unconstrained array type). These thin pointers are indeed the same size as a System.Address value. To specify a thin pointer, use a size clause for the type, for example: @@ -29329,7 +29329,7 @@ extension of package System. @end itemize @node GNU Free Documentation License,Index,Compatibility and Porting Guide,Top -@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{465}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{466} +@anchor{share/gnu_free_documentation_license doc}@anchor{465}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{466} @chapter GNU Free Documentation License @@ -29344,14 +29344,14 @@ license document, but changing it is not allowed. @strong{Preamble} The purpose of this License is to make a manual, textbook, or other -functional and useful document "free" in the sense of freedom: to +functional and useful document “free” in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. -This License is a kind of "copyleft", which means that derivative +This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. @@ -29372,17 +29372,17 @@ distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The @strong{Document}, below, refers to any such manual or work. Any member of the public is a -licensee, and is addressed as "@strong{you}". You accept the license if you +licensee, and is addressed as “@strong{you}”. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. -A "@strong{Modified Version}" of the Document means any work containing the +A “@strong{Modified Version}” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. -A "@strong{Secondary Section}" is a named appendix or a front-matter section of +A “@strong{Secondary Section}” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the -publishers or authors of the Document to the Document's overall subject +publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any @@ -29391,7 +29391,7 @@ connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. -The "@strong{Invariant Sections}" are certain Secondary Sections whose titles +The “@strong{Invariant Sections}” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not @@ -29399,12 +29399,12 @@ allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. -The "@strong{Cover Texts}" are certain short passages of text that are listed, +The “@strong{Cover Texts}” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. -A "@strong{Transparent}" copy of the Document means a machine-readable copy, +A “@strong{Transparent}” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of @@ -29415,7 +29415,7 @@ to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount -of text. A copy that is not "Transparent" is called @strong{Opaque}. +of text. A copy that is not “Transparent” is called @strong{Opaque}. Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML @@ -29428,24 +29428,24 @@ processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. -The "@strong{Title Page}" means, for a printed book, the title page itself, +The “@strong{Title Page}” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in -formats which do not have any title page as such, "Title Page" means -the text near the most prominent appearance of the work's title, +formats which do not have any title page as such, “Title Page” means +the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text. -The "@strong{publisher}" means any person or entity that distributes +The “@strong{publisher}” means any person or entity that distributes copies of the Document to the public. -A section "@strong{Entitled XYZ}" means a named subunit of the Document whose +A section “@strong{Entitled XYZ}” means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a -specific section name mentioned below, such as "@strong{Acknowledgements}", -"@strong{Dedications}", "@strong{Endorsements}", or "@strong{History}".) -To "@strong{Preserve the Title}" +specific section name mentioned below, such as “@strong{Acknowledgements}”, +“@strong{Dedications}”, “@strong{Endorsements}”, or “@strong{History}”.) +To “@strong{Preserve the Title}” of such a section when you modify the Document means that it remains a -section "Entitled XYZ" according to this definition. +section “Entitled XYZ” according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty @@ -29473,7 +29473,7 @@ you may publicly display copies. If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the -Document's license notice requires Cover Texts, you must enclose the +Document’s license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify @@ -29550,16 +29550,16 @@ terms of this License, in the form shown in the Addendum below. @item Preserve in that license notice the full lists of Invariant Sections -and required Cover Texts given in the Document's license notice. +and required Cover Texts given in the Document’s license notice. @item Include an unaltered copy of this License. @item -Preserve the section Entitled "History", Preserve its Title, and add +Preserve the section Entitled “History”, Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If -there is no section Entitled "History" in the Document, create one +there is no section Entitled “History” in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. @@ -29568,13 +29568,13 @@ Version as stated in the previous sentence. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions -it was based on. These may be placed in the "History" section. +it was based on. These may be placed in the “History” section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. @item -For any section Entitled "Acknowledgements" or "Dedications", +For any section Entitled “Acknowledgements” or “Dedications”, Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. @@ -29585,11 +29585,11 @@ unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. @item -Delete any section Entitled "Endorsements". Such a section +Delete any section Entitled “Endorsements”. Such a section may not be included in the Modified Version. @item -Do not retitle any existing section to be Entitled "Endorsements" +Do not retitle any existing section to be Entitled “Endorsements” or to conflict in title with any Invariant Section. @item @@ -29600,12 +29600,12 @@ If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the -list of Invariant Sections in the Modified Version's license notice. +list of Invariant Sections in the Modified Version’s license notice. These titles must be distinct from any other section titles. -You may add a section Entitled "Endorsements", provided it contains +You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various -parties---for example, statements of peer review or that the text has +parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. @@ -29641,11 +29641,11 @@ author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. -In the combination, you must combine any sections Entitled "History" +In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled -"History"; likewise combine any sections Entitled "Acknowledgements", -and any sections Entitled "Dedications". You must delete all sections -Entitled "Endorsements". +“History”; likewise combine any sections Entitled “Acknowledgements”, +and any sections Entitled “Dedications”. You must delete all sections +Entitled “Endorsements”. @strong{6. COLLECTIONS OF DOCUMENTS} @@ -29664,16 +29664,16 @@ other respects regarding verbatim copying of that document. A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or -distribution medium, is called an "aggregate" if the copyright +distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights -of the compilation's users beyond what the individual works permit. +of the compilation’s users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of -the entire aggregate, the Document's Cover Texts may be placed on +the entire aggregate, the Document’s Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole @@ -29694,8 +29694,8 @@ of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. -If a section in the Document is Entitled "Acknowledgements", -"Dedications", or "History", the requirement (section 4) to Preserve +If a section in the Document is Entitled “Acknowledgements”, +“Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. @@ -29736,37 +29736,37 @@ differ in detail to address new problems or concerns. See Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this -License "or any later version" applies to it, you have the option of +License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this -License can be used, that proxy's public statement of acceptance of a +License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document. @strong{11. RELICENSING} -"Massive Multiauthor Collaboration Site" (or "MMC Site") means any +“Massive Multiauthor Collaboration Site” (or “MMC Site”) means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A -"Massive Multiauthor Collaboration" (or "MMC") contained in the +“Massive Multiauthor Collaboration” (or “MMC”) contained in the site means any set of copyrightable works thus published on the MMC site. -"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 +“CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization. -"Incorporate" means to publish or republish a Document, in whole or +“Incorporate” means to publish or republish a Document, in whole or in part, as part of another Document. -An MMC is "eligible for relicensing" if it is licensed under this +An MMC is “eligible for relicensing” if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, @@ -29789,12 +29789,12 @@ Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. -A copy of the license is included in the section entitled "GNU -Free Documentation License". +A copy of the license is included in the section entitled “GNU +Free Documentation License”. @end quotation If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, -replace the "with ... Texts." line with this: +replace the “with … Texts.” line with this: @quotation diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index ef68b82..713a662 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -3,7 +3,7 @@ @setfilename gnat_ugn.info @documentencoding UTF-8 @ifinfo -@*Generated by Sphinx 1.4.6.@* +@*Generated by Sphinx 4.0.2.@* @end ifinfo @settitle GNAT User's Guide for Native Platforms @defindex ge @@ -21,7 +21,7 @@ @copying @quotation -GNAT User's Guide for Native Platforms , Apr 12, 2021 +GNAT User's Guide for Native Platforms , Jun 23, 2021 AdaCore @@ -41,7 +41,7 @@ Copyright @copyright{} 2008-2021, Free Software Foundation @c %** end of user preamble @ifnottex -@node Top, About This Guide +@node Top @top GNAT User's Guide for Native Platforms @insertcopying @end ifnottex @@ -59,7 +59,7 @@ Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being -"GNAT User's Guide for Native Platforms", +“GNAT User’s Guide for Native Platforms”, and with no Back-Cover Texts. A copy of the license is included in the section entitled @ref{1,,GNU Free Documentation License}. @@ -538,7 +538,7 @@ Other Asm Functionality @end menu @node About This Guide,Getting Started with GNAT,Top,Top -@anchor{gnat_ugn/about_this_guide about-this-guide}@anchor{2}@anchor{gnat_ugn/about_this_guide doc}@anchor{3}@anchor{gnat_ugn/about_this_guide gnat-user-s-guide-for-native-platforms}@anchor{4}@anchor{gnat_ugn/about_this_guide id1}@anchor{5} +@anchor{gnat_ugn/about_this_guide doc}@anchor{2}@anchor{gnat_ugn/about_this_guide about-this-guide}@anchor{3}@anchor{gnat_ugn/about_this_guide gnat-user-s-guide-for-native-platforms}@anchor{4}@anchor{gnat_ugn/about_this_guide id1}@anchor{5} @chapter About This Guide @@ -554,7 +554,7 @@ invoked in Ada 83 compatibility mode. By default, GNAT assumes Ada 2012, but you can override with a compiler switch (@ref{6,,Compiling Different Versions of Ada}) to explicitly specify the language version. -Throughout this manual, references to 'Ada' without a year suffix +Throughout this manual, references to ‘Ada’ without a year suffix apply to all Ada versions of the language, starting with Ada 95. @menu @@ -721,22 +721,22 @@ Commands that are entered by the user are shown as preceded by a prompt string comprising the @code{$} character followed by a space. @item -Full file names are shown with the '/' character +Full file names are shown with the ‘/’ character as the directory separator; e.g., @code{parent-dir/subdir/myfile.adb}. If you are using GNAT on a Windows platform, please note that -the '\' character should be used instead. +the ‘' character should be used instead. @end itemize @node Getting Started with GNAT,The GNAT Compilation Model,About This Guide,Top -@anchor{gnat_ugn/getting_started_with_gnat getting-started-with-gnat}@anchor{8}@anchor{gnat_ugn/getting_started_with_gnat doc}@anchor{14}@anchor{gnat_ugn/getting_started_with_gnat id1}@anchor{15} +@anchor{gnat_ugn/getting_started_with_gnat doc}@anchor{14}@anchor{gnat_ugn/getting_started_with_gnat getting-started-with-gnat}@anchor{8}@anchor{gnat_ugn/getting_started_with_gnat id1}@anchor{15} @chapter Getting Started with GNAT -This chapter describes how to use GNAT's command line interface to build +This chapter describes how to use GNAT’s command line interface to build executable Ada programs. On most platforms a visually oriented Integrated Development Environment is also available: GNAT Studio. -GNAT Studio offers a graphical "look and feel", support for development in +GNAT Studio offers a graphical “look and feel”, support for development in other programming languages, comprehensive browsing features, and many other capabilities. For information on GNAT Studio please refer to the @@ -780,7 +780,7 @@ machine performing the run. This can be achieved by setting the @code{Object_Dir project file attribute. @node Running GNAT,Running a Simple Ada Program,System Requirements,Getting Started with GNAT -@anchor{gnat_ugn/getting_started_with_gnat running-gnat}@anchor{18}@anchor{gnat_ugn/getting_started_with_gnat id3}@anchor{19} +@anchor{gnat_ugn/getting_started_with_gnat id3}@anchor{18}@anchor{gnat_ugn/getting_started_with_gnat running-gnat}@anchor{19} @section Running GNAT @@ -805,7 +805,7 @@ utility program that, given the name of the main program, automatically performs the necessary compilation, binding and linking steps. @node Running a Simple Ada Program,Running a Program with Multiple Units,Running GNAT,Getting Started with GNAT -@anchor{gnat_ugn/getting_started_with_gnat running-a-simple-ada-program}@anchor{1a}@anchor{gnat_ugn/getting_started_with_gnat id4}@anchor{1b} +@anchor{gnat_ugn/getting_started_with_gnat id4}@anchor{1a}@anchor{gnat_ugn/getting_started_with_gnat running-a-simple-ada-program}@anchor{1b} @section Running a Simple Ada Program @@ -862,7 +862,7 @@ switch must always be present.) This compile command generates a file @code{hello.o}, which is the object file corresponding to your Ada program. It also generates -an 'Ada Library Information' file @code{hello.ali}, +an ‘Ada Library Information’ file @code{hello.ali}, which contains additional information used to check that an Ada program is consistent. @@ -871,7 +871,7 @@ the name of the main file: these tools are builders that will take care of all the necessary build steps in the correct order. In particular, these builders automatically recompile any sources that have been modified since they were last compiled, or sources that depend -on such modified sources, so that 'version skew' is avoided. +on such modified sources, so that ‘version skew’ is avoided. @geindex Version skew (avoided by `@w{`}gnatmake`@w{`}) @@ -972,7 +972,7 @@ $ gnatmake gmain.adb @c -- Example: A |withing| unit has a |with| clause, it |withs| a |withed| unit @node The GNAT Compilation Model,Building Executable Programs with GNAT,Getting Started with GNAT,Top -@anchor{gnat_ugn/the_gnat_compilation_model doc}@anchor{20}@anchor{gnat_ugn/the_gnat_compilation_model the-gnat-compilation-model}@anchor{9}@anchor{gnat_ugn/the_gnat_compilation_model id1}@anchor{21} +@anchor{gnat_ugn/the_gnat_compilation_model doc}@anchor{20}@anchor{gnat_ugn/the_gnat_compilation_model id1}@anchor{21}@anchor{gnat_ugn/the_gnat_compilation_model the-gnat-compilation-model}@anchor{9} @chapter The GNAT Compilation Model @@ -1054,7 +1054,7 @@ Topics related to source file makeup and naming @end menu @node Source Representation,Foreign Language Representation,,The GNAT Compilation Model -@anchor{gnat_ugn/the_gnat_compilation_model source-representation}@anchor{22}@anchor{gnat_ugn/the_gnat_compilation_model id2}@anchor{2f} +@anchor{gnat_ugn/the_gnat_compilation_model id2}@anchor{2f}@anchor{gnat_ugn/the_gnat_compilation_model source-representation}@anchor{22} @section Source Representation @@ -1205,7 +1205,7 @@ of the compiler (@ref{31,,Character Set Control}). The basic character set is Latin-1. This character set is defined by ISO standard 8859, part 1. The lower half (character codes @code{16#00#} -... @code{16#7F#)} is identical to standard ASCII coding, but the upper +… @code{16#7F#)} is identical to standard ASCII coding, but the upper half is used to represent additional characters. These include extended letters used by European languages, such as French accents, the vowels with umlauts used in German, and the extra letter A-ring used in Swedish. @@ -1220,7 +1220,7 @@ string literals. In addition, the extended characters that represent letters can be used in identifiers. @node Other 8-Bit Codes,Wide_Character Encodings,Latin-1,Foreign Language Representation -@anchor{gnat_ugn/the_gnat_compilation_model other-8-bit-codes}@anchor{34}@anchor{gnat_ugn/the_gnat_compilation_model id5}@anchor{35} +@anchor{gnat_ugn/the_gnat_compilation_model id5}@anchor{34}@anchor{gnat_ugn/the_gnat_compilation_model other-8-bit-codes}@anchor{35} @subsection Other 8-Bit Codes @@ -1368,7 +1368,7 @@ This scheme is compatible with use of the full Wide_Character set. @geindex Upper-Half Coding The wide character with encoding @code{16#abcd#} where the upper bit is on -(in other words, 'a' is in the range 8-F) is represented as two bytes, +(in other words, ‘a’ is in the range 8-F) is represented as two bytes, @code{16#ab#} and @code{16#cd#}. The second byte cannot be a format control character, but is not required to be in the upper half. This method can be also used for shift-JIS or EUC, where the internal coding matches the @@ -1429,7 +1429,7 @@ character sequence: where @code{a}, @code{b}, @code{c}, @code{d} are the four hexadecimal characters (using uppercase letters) of the wide character code. For -example, ['A345'] is used to represent the wide character with code +example, [‘A345’] is used to represent the wide character with code @code{16#A345#}. It is also possible (though not required) to use the Brackets coding for upper half characters. For example, the code @code{16#A3#} can be represented as @code{['A3']}. @@ -1491,7 +1491,7 @@ twelve byte character sequence: where @code{a-h} are the six or eight hexadecimal characters (using uppercase letters) of the wide wide character code. For -example, ["1F4567"] is used to represent the wide wide character with code +example, [“1F4567”] is used to represent the wide wide character with code @code{16#001F_4567#}. This scheme is compatible with use of the full Wide_Wide_Character set, @@ -1500,7 +1500,7 @@ ACATS (Ada Conformity Assessment Test Suite) test suite distributions. @end table @node File Naming Topics and Utilities,Configuration Pragmas,Foreign Language Representation,The GNAT Compilation Model -@anchor{gnat_ugn/the_gnat_compilation_model id8}@anchor{3a}@anchor{gnat_ugn/the_gnat_compilation_model file-naming-topics-and-utilities}@anchor{24} +@anchor{gnat_ugn/the_gnat_compilation_model file-naming-topics-and-utilities}@anchor{24}@anchor{gnat_ugn/the_gnat_compilation_model id8}@anchor{3a} @section File Naming Topics and Utilities @@ -1626,7 +1626,7 @@ Following these rules can result in excessively long file names if corresponding unit names are long (for example, if child units or subunits are heavily nested). An option is available to shorten such long file names -(called file name 'krunching'). This may be particularly useful when +(called file name ‘krunching’). This may be particularly useful when programs being developed with GNAT are to be used on operating systems with limited file name lengths. @ref{3d,,Using gnatkr}. @@ -1707,7 +1707,7 @@ then it must be included in the @code{gnatmake} command, it may not be omitted. @node Alternative File Naming Schemes,Handling Arbitrary File Naming Conventions with gnatname,Using Other File Names,File Naming Topics and Utilities -@anchor{gnat_ugn/the_gnat_compilation_model id11}@anchor{40}@anchor{gnat_ugn/the_gnat_compilation_model alternative-file-naming-schemes}@anchor{41} +@anchor{gnat_ugn/the_gnat_compilation_model alternative-file-naming-schemes}@anchor{40}@anchor{gnat_ugn/the_gnat_compilation_model id11}@anchor{41} @subsection Alternative File Naming Schemes @@ -1825,7 +1825,7 @@ pragma Source_File_Name @end example Our final example implements a scheme typically used with one of the -Ada 83 compilers, where the separator character for subunits was '__' +Ada 83 compilers, where the separator character for subunits was ‘__’ (two underscores), specs were identified by adding @code{_.ADA}, bodies by adding @code{.ADA}, and subunits by adding @code{.SEP}. All file names were @@ -1881,7 +1881,7 @@ a configuration pragmas file (@ref{25,,Configuration Pragmas}) or a project file. When the non-standard file naming conventions are well-defined, a small number of pragmas @code{Source_File_Name} specifying a naming pattern -(@ref{41,,Alternative File Naming Schemes}) may be sufficient. However, +(@ref{40,,Alternative File Naming Schemes}) may be sufficient. However, if the file naming conventions are irregular or arbitrary, a number of pragma @code{Source_File_Name} for individual compilation units must be defined. @@ -1891,7 +1891,7 @@ GNAT provides a tool @code{gnatname} to generate the required pragmas for a set of files. @node Running gnatname,Switches for gnatname,Arbitrary File Naming Conventions,Handling Arbitrary File Naming Conventions with gnatname -@anchor{gnat_ugn/the_gnat_compilation_model running-gnatname}@anchor{46}@anchor{gnat_ugn/the_gnat_compilation_model id14}@anchor{47} +@anchor{gnat_ugn/the_gnat_compilation_model id14}@anchor{46}@anchor{gnat_ugn/the_gnat_compilation_model running-gnatname}@anchor{47} @subsubsection Running @code{gnatname} @@ -1934,7 +1934,7 @@ Examples of Naming Patterns are: For a more complete description of the syntax of Naming Patterns, see the second kind of regular expressions described in @code{g-regexp.ads} -(the 'Glob' regular expressions). +(the ‘Glob’ regular expressions). When invoked without the switch @code{-P}, @code{gnatname} will create a configuration pragmas file @code{gnat.adc} in the current working directory, @@ -2084,7 +2084,7 @@ When a switch @code{-P} is specified, no switch @code{-c} may be specified. On all platforms, except on VMS, when @code{gnatname} is invoked for an existing project file .gpr, a backup copy of the project file is created -in the project directory with file name .gpr.saved_x. 'x' is the first +in the project directory with file name .gpr.saved_x. ‘x’ is the first non negative number that makes this backup copy a new file. @geindex -v (gnatname) @@ -2172,7 +2172,7 @@ applying this shortening. @end menu @node About gnatkr,Using gnatkr,,File Name Krunching with gnatkr -@anchor{gnat_ugn/the_gnat_compilation_model id18}@anchor{4e}@anchor{gnat_ugn/the_gnat_compilation_model about-gnatkr}@anchor{4f} +@anchor{gnat_ugn/the_gnat_compilation_model about-gnatkr}@anchor{4e}@anchor{gnat_ugn/the_gnat_compilation_model id18}@anchor{4f} @subsubsection About @code{gnatkr} @@ -2202,7 +2202,7 @@ respectively. @end itemize The @code{-gnatk@emph{nn}} -switch of the compiler activates a 'krunching' +switch of the compiler activates a ‘krunching’ circuit that limits file names to nn characters (where nn is a decimal integer). @@ -2377,7 +2377,7 @@ program @code{gnatkr} is supplied for conveniently determining the krunched name of a file. @node Examples of gnatkr Usage,,Krunching Method,File Name Krunching with gnatkr -@anchor{gnat_ugn/the_gnat_compilation_model id21}@anchor{53}@anchor{gnat_ugn/the_gnat_compilation_model examples-of-gnatkr-usage}@anchor{54} +@anchor{gnat_ugn/the_gnat_compilation_model examples-of-gnatkr-usage}@anchor{53}@anchor{gnat_ugn/the_gnat_compilation_model id21}@anchor{54} @subsubsection Examples of @code{gnatkr} Usage @@ -2411,7 +2411,7 @@ files to meet the standard GNAT default file naming conventions. @end menu @node Handling Files with Multiple Units,Operating gnatchop in Compilation Mode,,Renaming Files with gnatchop -@anchor{gnat_ugn/the_gnat_compilation_model id23}@anchor{56}@anchor{gnat_ugn/the_gnat_compilation_model handling-files-with-multiple-units}@anchor{57} +@anchor{gnat_ugn/the_gnat_compilation_model handling-files-with-multiple-units}@anchor{56}@anchor{gnat_ugn/the_gnat_compilation_model id23}@anchor{57} @subsubsection Handling Files with Multiple Units @@ -2427,7 +2427,7 @@ Generated or modified project files can be processed by GNAT. See @ref{42,,Handling Arbitrary File Naming Conventions with gnatname} for more details on how to use @cite{gnatname}. -Alternatively, if you want to permanently restructure a set of 'foreign' +Alternatively, if you want to permanently restructure a set of ‘foreign’ files so that they match the GNAT rules, and do the remaining development using the GNAT structure, you can simply use @code{gnatchop} once, generate the new set of files and work with them from that point on. @@ -2438,7 +2438,7 @@ will each start with a copy of this BOM, meaning that they can be compiled automatically in UTF-8 mode without needing to specify an explicit encoding. @node Operating gnatchop in Compilation Mode,Command Line for gnatchop,Handling Files with Multiple Units,Renaming Files with gnatchop -@anchor{gnat_ugn/the_gnat_compilation_model operating-gnatchop-in-compilation-mode}@anchor{58}@anchor{gnat_ugn/the_gnat_compilation_model id24}@anchor{59} +@anchor{gnat_ugn/the_gnat_compilation_model id24}@anchor{58}@anchor{gnat_ugn/the_gnat_compilation_model operating-gnatchop-in-compilation-mode}@anchor{59} @subsubsection Operating gnatchop in Compilation Mode @@ -2454,7 +2454,7 @@ find this default to be what they want. In this default mode it is incorrect to submit a file containing only configuration pragmas, or one that ends in configuration pragmas, to @code{gnatchop}. -However, using a special option to activate 'compilation mode', +However, using a special option to activate ‘compilation mode’, @code{gnatchop} can perform another function, which is to provide exactly the semantics required by the RM for handling of configuration pragmas in a compilation. @@ -2498,7 +2498,7 @@ switch provides the required behavior, and is for example the mode in which GNAT processes the ACVC tests. @node Command Line for gnatchop,Switches for gnatchop,Operating gnatchop in Compilation Mode,Renaming Files with gnatchop -@anchor{gnat_ugn/the_gnat_compilation_model id25}@anchor{5a}@anchor{gnat_ugn/the_gnat_compilation_model command-line-for-gnatchop}@anchor{5b} +@anchor{gnat_ugn/the_gnat_compilation_model command-line-for-gnatchop}@anchor{5a}@anchor{gnat_ugn/the_gnat_compilation_model id25}@anchor{5b} @subsubsection Command Line for @code{gnatchop} @@ -2572,7 +2572,7 @@ no source files written @end example @node Switches for gnatchop,Examples of gnatchop Usage,Command Line for gnatchop,Renaming Files with gnatchop -@anchor{gnat_ugn/the_gnat_compilation_model switches-for-gnatchop}@anchor{5c}@anchor{gnat_ugn/the_gnat_compilation_model id26}@anchor{5d} +@anchor{gnat_ugn/the_gnat_compilation_model id26}@anchor{5c}@anchor{gnat_ugn/the_gnat_compilation_model switches-for-gnatchop}@anchor{5d} @subsubsection Switches for @code{gnatchop} @@ -2738,7 +2738,7 @@ no attempt is made to add the prefix to the GNAT parser executable. @end table @node Examples of gnatchop Usage,,Switches for gnatchop,Renaming Files with gnatchop -@anchor{gnat_ugn/the_gnat_compilation_model id27}@anchor{5e}@anchor{gnat_ugn/the_gnat_compilation_model examples-of-gnatchop-usage}@anchor{5f} +@anchor{gnat_ugn/the_gnat_compilation_model examples-of-gnatchop-usage}@anchor{5e}@anchor{gnat_ugn/the_gnat_compilation_model id27}@anchor{5f} @subsubsection Examples of @code{gnatchop} Usage @@ -2779,7 +2779,7 @@ be the one that is output, and earlier duplicate occurrences for a given unit will be skipped. @node Configuration Pragmas,Generating Object Files,File Naming Topics and Utilities,The GNAT Compilation Model -@anchor{gnat_ugn/the_gnat_compilation_model id28}@anchor{60}@anchor{gnat_ugn/the_gnat_compilation_model configuration-pragmas}@anchor{25} +@anchor{gnat_ugn/the_gnat_compilation_model configuration-pragmas}@anchor{25}@anchor{gnat_ugn/the_gnat_compilation_model id28}@anchor{60} @section Configuration Pragmas @@ -2889,7 +2889,7 @@ Wide_Character_Encoding @end menu @node Handling of Configuration Pragmas,The Configuration Pragmas Files,,Configuration Pragmas -@anchor{gnat_ugn/the_gnat_compilation_model id29}@anchor{61}@anchor{gnat_ugn/the_gnat_compilation_model handling-of-configuration-pragmas}@anchor{3f} +@anchor{gnat_ugn/the_gnat_compilation_model handling-of-configuration-pragmas}@anchor{3f}@anchor{gnat_ugn/the_gnat_compilation_model id29}@anchor{61} @subsection Handling of Configuration Pragmas @@ -2900,7 +2900,7 @@ all compilations performed in a given compilation environment. GNAT also provides the @code{gnatchop} utility to provide an automatic way to handle configuration pragmas following the semantics for compilations (that is, files with multiple units), described in the RM. -See @ref{58,,Operating gnatchop in Compilation Mode} for details. +See @ref{59,,Operating gnatchop in Compilation Mode} for details. However, for most purposes, it will be more convenient to edit the @code{gnat.adc} file that contains configuration pragmas directly, as described in the following section. @@ -2930,7 +2930,7 @@ relevant units). It can appear on a subunit only if it has previously appeared in the body of spec. @node The Configuration Pragmas Files,,Handling of Configuration Pragmas,Configuration Pragmas -@anchor{gnat_ugn/the_gnat_compilation_model the-configuration-pragmas-files}@anchor{62}@anchor{gnat_ugn/the_gnat_compilation_model id30}@anchor{63} +@anchor{gnat_ugn/the_gnat_compilation_model id30}@anchor{62}@anchor{gnat_ugn/the_gnat_compilation_model the-configuration-pragmas-files}@anchor{63} @subsection The Configuration Pragmas Files @@ -2966,7 +2966,7 @@ Files containing configuration pragmas specified with switches temporary files. A file is considered temporary if its name ends in @code{.tmp} or @code{.TMP}. Certain tools follow this naming convention because they pass information to @code{gcc} via -temporary files that are immediately deleted; it doesn't make sense to +temporary files that are immediately deleted; it doesn’t make sense to depend on a file that no longer exists. Such tools include @code{gprbuild}, @code{gnatmake}, and @code{gnatcheck}. @@ -3057,7 +3057,7 @@ checking mode, use the @code{-gnatc} switch. A given object file clearly depends on the source file which is compiled -to produce it. Here we are using "depends" in the sense of a typical +to produce it. Here we are using “depends” in the sense of a typical @code{make} utility; in other words, an object file depends on a source file if changes to the source file require the object file to be recompiled. @@ -3214,7 +3214,7 @@ see the source of the body of unit @code{Lib.Writ}, contained in file @code{lib-writ.adb} in the GNAT compiler sources. @node Binding an Ada Program,GNAT and Libraries,The Ada Library Information Files,The GNAT Compilation Model -@anchor{gnat_ugn/the_gnat_compilation_model id34}@anchor{67}@anchor{gnat_ugn/the_gnat_compilation_model binding-an-ada-program}@anchor{29} +@anchor{gnat_ugn/the_gnat_compilation_model binding-an-ada-program}@anchor{29}@anchor{gnat_ugn/the_gnat_compilation_model id34}@anchor{67} @section Binding an Ada Program @@ -3259,7 +3259,7 @@ object files for the Ada units of the program. This section describes how to build and use libraries with GNAT, and also shows how to recompile the GNAT run-time library. You should be familiar with the Project Manager facility (see the @emph{GNAT_Project_Manager} chapter of the -@emph{GPRbuild User's Guide}) before reading this chapter. +@emph{GPRbuild User’s Guide}) before reading this chapter. @menu * Introduction to Libraries in GNAT:: @@ -3270,7 +3270,7 @@ Project Manager facility (see the @emph{GNAT_Project_Manager} chapter of the @end menu @node Introduction to Libraries in GNAT,General Ada Libraries,,GNAT and Libraries -@anchor{gnat_ugn/the_gnat_compilation_model introduction-to-libraries-in-gnat}@anchor{69}@anchor{gnat_ugn/the_gnat_compilation_model id36}@anchor{6a} +@anchor{gnat_ugn/the_gnat_compilation_model id36}@anchor{69}@anchor{gnat_ugn/the_gnat_compilation_model introduction-to-libraries-in-gnat}@anchor{6a} @subsection Introduction to Libraries in GNAT @@ -3312,7 +3312,7 @@ inlined routine. In the case of @emph{stand-alone libraries} those exposed units are called @emph{interface units} (@ref{6b,,Stand-alone Ada Libraries}). All compilation units comprising an application, including those in a library, -need to be elaborated in an order partially defined by Ada's semantics. GNAT +need to be elaborated in an order partially defined by Ada’s semantics. GNAT computes the elaboration order from the @code{ALI} files and this is why they constitute a mandatory part of GNAT libraries. @emph{Stand-alone libraries} are the exception to this rule because a specific @@ -3339,7 +3339,7 @@ using the library. The easiest way to build a library is to use the Project Manager, which supports a special type of project called a @emph{Library Project} (see the @emph{Library Projects} section in the @emph{GNAT Project Manager} -chapter of the @emph{GPRbuild User's Guide}). +chapter of the @emph{GPRbuild User’s Guide}). A project is considered a library project, when two project-level attributes are defined in it: @code{Library_Name} and @code{Library_Dir}. In order to @@ -3465,7 +3465,7 @@ or @code{lib@emph{xxx}.so} (or @code{lib@emph{xxx}.dll} on Windows) in order to be accessed by the directive @code{-l@emph{xxx}} at link time. @node Installing a library,Using a library,Building a library,General Ada Libraries -@anchor{gnat_ugn/the_gnat_compilation_model installing-a-library}@anchor{71}@anchor{gnat_ugn/the_gnat_compilation_model id39}@anchor{72} +@anchor{gnat_ugn/the_gnat_compilation_model id39}@anchor{71}@anchor{gnat_ugn/the_gnat_compilation_model installing-a-library}@anchor{72} @subsubsection Installing a library @@ -3475,14 +3475,14 @@ be accessed by the directive @code{-l@emph{xxx}} at link time. If you use project files, library installation is part of the library build process (see the @emph{Installing a Library with Project Files} section of the -@emph{GNAT Project Manager} chapter of the @emph{GPRbuild User's Guide}). +@emph{GNAT Project Manager} chapter of the @emph{GPRbuild User’s Guide}). When project files are not an option, it is also possible, but not recommended, to install the library so that the sources needed to use the library are on the Ada source path and the ALI files & libraries be on the Ada Object path (see @ref{73,,Search Paths and the Run-Time Library (RTL)}. Alternatively, the system administrator can place general-purpose libraries in the default compiler -paths, by specifying the libraries' location in the configuration files +paths, by specifying the libraries’ location in the configuration files @code{ada_source_path} and @code{ada_object_path}. These configuration files must be located in the GNAT installation tree at the same place as the gcc spec file. The location of the gcc spec file can be determined as follows: @@ -3522,7 +3522,7 @@ library must be installed before the GNAT library if it redefines any part of it. @node Using a library,,Installing a library,General Ada Libraries -@anchor{gnat_ugn/the_gnat_compilation_model using-a-library}@anchor{74}@anchor{gnat_ugn/the_gnat_compilation_model id40}@anchor{75} +@anchor{gnat_ugn/the_gnat_compilation_model id40}@anchor{74}@anchor{gnat_ugn/the_gnat_compilation_model using-a-library}@anchor{75} @subsubsection Using a library @@ -3539,7 +3539,7 @@ project My_Proj is end My_Proj; @end example -Even if you have a third-party, non-Ada library, you can still use GNAT's +Even if you have a third-party, non-Ada library, you can still use GNAT’s Project Manager facility to provide a wrapper for it. For example, the following project, when @emph{with}ed by your main project, will link with the third-party library @code{liba.a}: @@ -3616,7 +3616,7 @@ in the directory @code{share/examples/gnat/plugins} within the GNAT install area. @node Stand-alone Ada Libraries,Rebuilding the GNAT Run-Time Library,General Ada Libraries,GNAT and Libraries -@anchor{gnat_ugn/the_gnat_compilation_model stand-alone-ada-libraries}@anchor{6b}@anchor{gnat_ugn/the_gnat_compilation_model id41}@anchor{77} +@anchor{gnat_ugn/the_gnat_compilation_model id41}@anchor{77}@anchor{gnat_ugn/the_gnat_compilation_model stand-alone-ada-libraries}@anchor{6b} @subsection Stand-alone Ada Libraries @@ -3631,11 +3631,11 @@ install area. @end menu @node Introduction to Stand-alone Libraries,Building a Stand-alone Library,,Stand-alone Ada Libraries -@anchor{gnat_ugn/the_gnat_compilation_model introduction-to-stand-alone-libraries}@anchor{78}@anchor{gnat_ugn/the_gnat_compilation_model id42}@anchor{79} +@anchor{gnat_ugn/the_gnat_compilation_model id42}@anchor{78}@anchor{gnat_ugn/the_gnat_compilation_model introduction-to-stand-alone-libraries}@anchor{79} @subsubsection Introduction to Stand-alone Libraries -A Stand-alone Library (abbreviated 'SAL') is a library that contains the +A Stand-alone Library (abbreviated ‘SAL’) is a library that contains the necessary code to elaborate the Ada units that are included in the library. In contrast with an ordinary library, which consists of all sources, objects and @code{ALI} @@ -3643,10 +3643,10 @@ files of the library, a SAL may specify a restricted subset of compilation units to serve as a library interface. In this case, the fully self-sufficient set of files will normally consist of an objects -archive, the sources of interface units' specs, and the @code{ALI} +archive, the sources of interface units’ specs, and the @code{ALI} files of interface units. If an interface spec contains a generic unit or an inlined subprogram, -the body's +the body’s source must also be provided; if the units that must be provided in the source form depend on other units, the source and @code{ALI} files of those must also be provided. @@ -3659,24 +3659,24 @@ version, controlled by @code{Library_Version} attribute, is not changed, then the clients do not need to be relinked. SALs also allow the library providers to minimize the amount of library source -text exposed to the clients. Such 'information hiding' might be useful or +text exposed to the clients. Such ‘information hiding’ might be useful or necessary for various reasons. Stand-alone libraries are also well suited to be used in an executable whose main routine is not written in Ada. @node Building a Stand-alone Library,Creating a Stand-alone Library to be used in a non-Ada context,Introduction to Stand-alone Libraries,Stand-alone Ada Libraries -@anchor{gnat_ugn/the_gnat_compilation_model id43}@anchor{7a}@anchor{gnat_ugn/the_gnat_compilation_model building-a-stand-alone-library}@anchor{7b} +@anchor{gnat_ugn/the_gnat_compilation_model building-a-stand-alone-library}@anchor{7a}@anchor{gnat_ugn/the_gnat_compilation_model id43}@anchor{7b} @subsubsection Building a Stand-alone Library -GNAT's Project facility provides a simple way of building and installing +GNAT’s Project facility provides a simple way of building and installing stand-alone libraries; see the @emph{Stand-alone Library Projects} section -in the @emph{GNAT Project Manager} chapter of the @emph{GPRbuild User's Guide}. +in the @emph{GNAT Project Manager} chapter of the @emph{GPRbuild User’s Guide}. To be a Stand-alone Library Project, in addition to the two attributes that make a project a Library Project (@code{Library_Name} and @code{Library_Dir}; see the @emph{Library Projects} section in the -@emph{GNAT Project Manager} chapter of the @emph{GPRbuild User's Guide}), +@emph{GNAT Project Manager} chapter of the @emph{GPRbuild User’s Guide}), the attribute @code{Library_Interface} must be defined. For example: @example @@ -3780,12 +3780,12 @@ the object directory. Copy the @code{ALI} files of the interface to the library directory, add in this copy an indication that it is an interface to a SAL (i.e., add a word @code{SL} on the line in the @code{ALI} file that starts -with letter 'P') and make the modified copy of the @code{ALI} file +with letter ‘P’) and make the modified copy of the @code{ALI} file read-only. @end itemize Using SALs is not different from using other libraries -(see @ref{74,,Using a library}). +(see @ref{75,,Using a library}). @node Creating a Stand-alone Library to be used in a non-Ada context,Restrictions in Stand-alone Libraries,Building a Stand-alone Library,Stand-alone Ada Libraries @anchor{gnat_ugn/the_gnat_compilation_model creating-a-stand-alone-library-to-be-used-in-a-non-ada-context}@anchor{7c}@anchor{gnat_ugn/the_gnat_compilation_model id44}@anchor{7d} @@ -3813,7 +3813,7 @@ package My_Package is end My_Package; @end example -On the foreign language side, you must provide a 'foreign' view of the +On the foreign language side, you must provide a ‘foreign’ view of the library interface; remember that it should contain elaboration routines in addition to interface subprograms. @@ -3955,7 +3955,7 @@ experiments or debugging, and is not supported. @geindex Conditional compilation @node Conditional Compilation,Mixed Language Programming,GNAT and Libraries,The GNAT Compilation Model -@anchor{gnat_ugn/the_gnat_compilation_model id47}@anchor{82}@anchor{gnat_ugn/the_gnat_compilation_model conditional-compilation}@anchor{2b} +@anchor{gnat_ugn/the_gnat_compilation_model conditional-compilation}@anchor{2b}@anchor{gnat_ugn/the_gnat_compilation_model id47}@anchor{82} @section Conditional Compilation @@ -3972,7 +3972,7 @@ gnatprep preprocessor utility. @end menu @node Modeling Conditional Compilation in Ada,Preprocessing with gnatprep,,Conditional Compilation -@anchor{gnat_ugn/the_gnat_compilation_model modeling-conditional-compilation-in-ada}@anchor{83}@anchor{gnat_ugn/the_gnat_compilation_model id48}@anchor{84} +@anchor{gnat_ugn/the_gnat_compilation_model id48}@anchor{83}@anchor{gnat_ugn/the_gnat_compilation_model modeling-conditional-compilation-in-ada}@anchor{84} @subsection Modeling Conditional Compilation in Ada @@ -4167,7 +4167,7 @@ the @code{-gnata} switch is often the most convenient method of controlling the status of these pragmas. Note that a pragma is not a statement, so in contexts where a statement -sequence is required, you can't just write a pragma on its own. You have +sequence is required, you can’t just write a pragma on its own. You have to add a @code{null} statement. @example @@ -4245,7 +4245,7 @@ constant was introduced as @code{System.Default_Bit_Order}, so you do not need to define this one yourself). @node Use of Alternative Implementations,Preprocessing,Conditionalizing Declarations,Modeling Conditional Compilation in Ada -@anchor{gnat_ugn/the_gnat_compilation_model use-of-alternative-implementations}@anchor{8b}@anchor{gnat_ugn/the_gnat_compilation_model id52}@anchor{8c} +@anchor{gnat_ugn/the_gnat_compilation_model id52}@anchor{8b}@anchor{gnat_ugn/the_gnat_compilation_model use-of-alternative-implementations}@anchor{8c} @subsubsection Use of Alternative Implementations @@ -4279,7 +4279,7 @@ end if; where @code{Ada_2005} is a Boolean constant. -But this won't work when @code{Ada_2005} is set to @code{False}, +But this won’t work when @code{Ada_2005} is set to @code{False}, since the @code{then} clause will be illegal for an Ada 95 compiler. (Recall that although such unreachable code would eventually be deleted by the compiler, it still needs to be legal. If it uses features @@ -4308,7 +4308,7 @@ have two files and the build script renames the appropriate file to @code{file_queries-insert.adb} and then carries out the compilation. -This can also be done with project files' naming schemes. For example: +This can also be done with project files’ naming schemes. For example: @example for body ("File_Queries.Insert") use "file_queries-insert-2005.ada"; @@ -4365,11 +4365,11 @@ VMS-compatible AST handling. The GNAT build script knows the architecture and operating system, and automatically selects the right version, renaming it if necessary to @code{s-asthan.adb} before the run-time build. -Another style for arranging alternative implementations is through Ada's +Another style for arranging alternative implementations is through Ada’s access-to-subprogram facility. In case some functionality is to be conditionally included, you can declare an access-to-procedure variable @code{Ref} that is initialized -to designate a 'do nothing' procedure, and then invoke @code{Ref.all} +to designate a ‘do nothing’ procedure, and then invoke @code{Ref.all} when appropriate. In some library package, set @code{Ref} to @code{Proc'Access} for some procedure @code{Proc} that performs the relevant processing. @@ -4379,7 +4379,7 @@ The same idea can also be implemented using tagged types and dispatching calls. @node Preprocessing,,Use of Alternative Implementations,Modeling Conditional Compilation in Ada -@anchor{gnat_ugn/the_gnat_compilation_model preprocessing}@anchor{8d}@anchor{gnat_ugn/the_gnat_compilation_model id53}@anchor{8e} +@anchor{gnat_ugn/the_gnat_compilation_model id53}@anchor{8d}@anchor{gnat_ugn/the_gnat_compilation_model preprocessing}@anchor{8e} @subsubsection Preprocessing @@ -4433,7 +4433,7 @@ For more details on this approach, see @ref{90,,Integrated Preprocessing}. @geindex Preprocessing (gnatprep) -This section discusses how to use GNAT's @code{gnatprep} utility for simple +This section discusses how to use GNAT’s @code{gnatprep} utility for simple preprocessing. Although designed for use with GNAT, @code{gnatprep} does not depend on any special GNAT features. @@ -4460,7 +4460,7 @@ normal Ada (case-insensitive) rules for its syntax, with the restriction that all characters need to be in the ASCII set (no accented letters). @node Using gnatprep,Switches for gnatprep,Preprocessing Symbols,Preprocessing with gnatprep -@anchor{gnat_ugn/the_gnat_compilation_model using-gnatprep}@anchor{94}@anchor{gnat_ugn/the_gnat_compilation_model id56}@anchor{95} +@anchor{gnat_ugn/the_gnat_compilation_model id56}@anchor{94}@anchor{gnat_ugn/the_gnat_compilation_model using-gnatprep}@anchor{95} @subsubsection Using @code{gnatprep} @@ -4518,7 +4518,7 @@ optional, and can be replaced by the use of the @code{-D} switch. @end itemize @node Switches for gnatprep,Form of Definitions File,Using gnatprep,Preprocessing with gnatprep -@anchor{gnat_ugn/the_gnat_compilation_model switches-for-gnatprep}@anchor{96}@anchor{gnat_ugn/the_gnat_compilation_model id57}@anchor{97} +@anchor{gnat_ugn/the_gnat_compilation_model id57}@anchor{96}@anchor{gnat_ugn/the_gnat_compilation_model switches-for-gnatprep}@anchor{97} @subsubsection Switches for @code{gnatprep} @@ -4699,7 +4699,7 @@ the usual @code{--}, and comments may be added to the definitions lines. @node Form of Input Text for gnatprep,,Form of Definitions File,Preprocessing with gnatprep -@anchor{gnat_ugn/the_gnat_compilation_model id59}@anchor{9a}@anchor{gnat_ugn/the_gnat_compilation_model form-of-input-text-for-gnatprep}@anchor{9b} +@anchor{gnat_ugn/the_gnat_compilation_model form-of-input-text-for-gnatprep}@anchor{9a}@anchor{gnat_ugn/the_gnat_compilation_model id59}@anchor{9b} @subsubsection Form of Input Text for @code{gnatprep} @@ -4741,8 +4741,8 @@ In this example, is defined by the following grammar: ::= ( ) @end example -Note the following restriction: it is not allowed to have "and" or "or" -following "not" in the same expression without parentheses. For example, this +Note the following restriction: it is not allowed to have “and” or “or” +following “not” in the same expression without parentheses. For example, this is not allowed: @example @@ -4768,7 +4768,7 @@ literal integer as defined in the Ada Reference Manual, such as 3, 16#FF# or 2#11#. The symbol value must also be a non negative integer. Integer values in the range 0 .. 2**31-1 are supported. -The test ( ::= 'Defined) is true only if +The test ( ::= ’Defined) is true only if the symbol has been defined in the definition file or by a @code{-D} switch on the command line. Otherwise, the test is false. @@ -4784,8 +4784,8 @@ or @code{False}. The use of the @code{not} operator inverts the sense of this logical test. The @code{not} operator cannot be combined with the @code{or} or @code{and} -operators, without parentheses. For example, "if not X or Y then" is not -allowed, but "if (not X) or Y then" and "if not (X or Y) then" are. +operators, without parentheses. For example, “if not X or Y then” is not +allowed, but “if (not X) or Y then” and “if not (X or Y) then” are. The @code{then} keyword is optional as shown @@ -4905,7 +4905,7 @@ that relate to integrated preprocessing. This switch specifies the file name (without directory information) of the preprocessor data file. Either place this file in one of the source directories, or, when using project -files, reference the project file's directory via the +files, reference the project file’s directory via the @code{project_name'Project_Dir} project attribute; e.g: @quotation @@ -4931,7 +4931,7 @@ preprocessing. Empty lines and comments (using Ada syntax) are also permitted, with no semantic effect. -Here's an example of a preprocessor data file: +Here’s an example of a preprocessor data file: @quotation @@ -4970,7 +4970,7 @@ A preprocessor control line has the following syntax: @end quotation Thus each preprocessor control line starts with either a literal string or -the character '*': +the character ‘*’: @itemize * @@ -4980,16 +4980,16 @@ A literal string is the file name (without directory information) of the source file that will be input to the preprocessor. @item -The character '*' is a wild-card indicator; the additional parameters on the line +The character ‘*’ is a wild-card indicator; the additional parameters on the line indicate the preprocessing for all the sources that are not specified explicitly on other lines (the order of the lines is not significant). @end itemize It is an error to have two lines with the same file name or two -lines starting with the character '*'. +lines starting with the character ‘*’. -After the file name or '*', an optional literal string specifies the name of +After the file name or ‘*’, an optional literal string specifies the name of the definition file to be used for preprocessing (@ref{98,,Form of Definitions File}). The definition files are found by the compiler in one of the source directories. In some cases, when compiling @@ -5014,7 +5014,7 @@ it cancels the effect of @code{-c}. Causes both preprocessor lines and the lines deleted by preprocessing to be retained as comments marked -with the special string '@cite{--!}'. +with the special string ‘@cite{–!}’. @item @code{-D@emph{symbol}=@emph{new_value}} @@ -5083,7 +5083,7 @@ the output file will be @code{foo.adb.prep}. @end table @node Mixed Language Programming,GNAT and Other Compilation Models,Conditional Compilation,The GNAT Compilation Model -@anchor{gnat_ugn/the_gnat_compilation_model mixed-language-programming}@anchor{2c}@anchor{gnat_ugn/the_gnat_compilation_model id61}@anchor{9d} +@anchor{gnat_ugn/the_gnat_compilation_model id61}@anchor{9d}@anchor{gnat_ugn/the_gnat_compilation_model mixed-language-programming}@anchor{2c} @section Mixed Language Programming @@ -5102,13 +5102,13 @@ with a focus on combining Ada with C or C++. @end menu @node Interfacing to C,Calling Conventions,,Mixed Language Programming -@anchor{gnat_ugn/the_gnat_compilation_model interfacing-to-c}@anchor{9e}@anchor{gnat_ugn/the_gnat_compilation_model id62}@anchor{9f} +@anchor{gnat_ugn/the_gnat_compilation_model id62}@anchor{9e}@anchor{gnat_ugn/the_gnat_compilation_model interfacing-to-c}@anchor{9f} @subsection Interfacing to C Interfacing Ada with a foreign language such as C involves using compiler directives to import and/or export entity definitions in each -language -- using @code{extern} statements in C, for instance, and the +language – using @code{extern} statements in C, for instance, and the @code{Import}, @code{Export}, and @code{Convention} pragmas in Ada. A full treatment of these topics is provided in Appendix B, section 1 of the Ada Reference Manual. @@ -5283,7 +5283,7 @@ end Unit2; @end example The build procedure for this application is similar to the last -example's: +example’s: @itemize * @@ -5436,7 +5436,7 @@ in section B.4 of the Ada Reference Manual. Data will be passed according to the conventions described in section B.3 of the Ada Reference Manual. -A note on interfacing to a C 'varargs' function: +A note on interfacing to a C ‘varargs’ function: @quotation @@ -5542,7 +5542,7 @@ The return type must be the same as the type of the first argument. The size of this type can only be 8, 16, 32, or 64. @item -Binary arithmetic operators: '+', '-', '*', '/'. +Binary arithmetic operators: ‘+’, ‘-‘, ‘*’, ‘/’. The corresponding operator declaration must have parameters and result type that have the same root numeric type (for example, all three are long_float types). This simplifies the definition of operations that use type checking @@ -5579,7 +5579,7 @@ pragma Import (Intrinsic, builtin_sqrt, "__builtin_sqrtf"); @end example Most of the GCC builtins are accessible this way, and as for other -import conventions (e.g. C), it is the user's responsibility to ensure +import conventions (e.g. C), it is the user’s responsibility to ensure that the Ada subprogram profile matches the underlying builtin expectations. @end itemize @@ -5653,7 +5653,7 @@ identifier (for example in an @code{Import} pragma) with the same meaning as Fortran. @node Building Mixed Ada and C++ Programs,Generating Ada Bindings for C and C++ headers,Calling Conventions,Mixed Language Programming -@anchor{gnat_ugn/the_gnat_compilation_model id64}@anchor{a3}@anchor{gnat_ugn/the_gnat_compilation_model building-mixed-ada-and-c-programs}@anchor{a4} +@anchor{gnat_ugn/the_gnat_compilation_model building-mixed-ada-and-c-programs}@anchor{a3}@anchor{gnat_ugn/the_gnat_compilation_model id64}@anchor{a4} @subsection Building Mixed Ada and C++ Programs @@ -5677,7 +5677,7 @@ challenge. This section gives a few hints that should make this task easier. GNAT supports interfacing with the G++ compiler (or any C++ compiler generating code that is compatible with the G++ Application Binary -Interface ---see @indicateurl{http://www.codesourcery.com/archives/cxx-abi}). +Interface —see @indicateurl{http://www.codesourcery.com/archives/cxx-abi}). Interfacing can be done at 3 levels: simple data, subprograms, and classes. In the first two cases, GNAT offers a specific @code{Convention C_Plus_Plus} @@ -5751,7 +5751,7 @@ important to note that environment variables such as at the same time and may make one of the two compilers operate improperly if set during invocation of the wrong compiler. It is also very important that the linker uses the proper @code{libgcc.a} GCC -library -- that is, the one from the C++ compiler installation. The +library – that is, the one from the C++ compiler installation. The implicit link command as suggested in the @code{gnatmake} command from the former example can be replaced by an explicit link command with the full-verbosity option in order to verify which library is used: @@ -5793,7 +5793,7 @@ $ gnatlink ada_unit file1.o file2.o --LINK=./my_script where CC is the name of the non-GNU C++ compiler. -If the "zero cost" exception mechanism is used, and the platform +If the “zero cost” exception mechanism is used, and the platform supports automatic registration of exception tables (e.g., Solaris), paths to more objects are required: @@ -5806,8 +5806,8 @@ gcc -print-file-name=crtend.o $ gnatlink ada_unit file1.o file2.o --LINK=./my_script @end example -If the "zero cost exception" mechanism is used, and the platform -doesn't support automatic registration of exception tables (e.g., HP-UX +If the “zero cost exception” mechanism is used, and the platform +doesn’t support automatic registration of exception tables (e.g., HP-UX or AIX), the simple approach described above will not work and a pre-linking phase using GNAT will be necessary. @end itemize @@ -5817,7 +5817,7 @@ which has a large knowledge base and knows how to link Ada and C++ code together automatically in most cases. @node A Simple Example,Interfacing with C++ constructors,Linking a Mixed C++ & Ada Program,Building Mixed Ada and C++ Programs -@anchor{gnat_ugn/the_gnat_compilation_model id67}@anchor{aa}@anchor{gnat_ugn/the_gnat_compilation_model a-simple-example}@anchor{ab} +@anchor{gnat_ugn/the_gnat_compilation_model a-simple-example}@anchor{aa}@anchor{gnat_ugn/the_gnat_compilation_model id67}@anchor{ab} @subsubsection A Simple Example @@ -6143,7 +6143,7 @@ by means of a limited aggregate. Any further action associated with the constructor can be placed inside the construct. @node Interfacing with C++ at the Class Level,,Interfacing with C++ constructors,Building Mixed Ada and C++ Programs -@anchor{gnat_ugn/the_gnat_compilation_model interfacing-with-c-at-the-class-level}@anchor{ae}@anchor{gnat_ugn/the_gnat_compilation_model id69}@anchor{af} +@anchor{gnat_ugn/the_gnat_compilation_model id69}@anchor{af}@anchor{gnat_ugn/the_gnat_compilation_model interfacing-with-c-at-the-class-level}@anchor{ae} @subsubsection Interfacing with C++ at the Class Level @@ -6389,7 +6389,7 @@ int main () @end example @node Generating Ada Bindings for C and C++ headers,Generating C Headers for Ada Specifications,Building Mixed Ada and C++ Programs,Mixed Language Programming -@anchor{gnat_ugn/the_gnat_compilation_model id70}@anchor{b0}@anchor{gnat_ugn/the_gnat_compilation_model generating-ada-bindings-for-c-and-c-headers}@anchor{a7} +@anchor{gnat_ugn/the_gnat_compilation_model generating-ada-bindings-for-c-and-c-headers}@anchor{a7}@anchor{gnat_ugn/the_gnat_compilation_model id70}@anchor{b0} @subsection Generating Ada Bindings for C and C++ headers @@ -6457,7 +6457,7 @@ $ gcc -c *.ads will generate, under GNU/Linux, the following files: @code{time_h.ads}, @code{bits_time_h.ads}, @code{stddef_h.ads}, @code{bits_types_h.ads} which correspond to the files @code{/usr/include/time.h}, -@code{/usr/include/bits/time.h}, etc..., and will then compile these Ada specs +@code{/usr/include/bits/time.h}, etc…, and will then compile these Ada specs in Ada 2005 mode. The @code{-C} switch tells @code{gcc} to extract comments from headers, @@ -6534,7 +6534,7 @@ $ g++ -c -fdump-ada-spec readline1.h @end example @node Generating Bindings for C++ Headers,Switches,Running the Binding Generator,Generating Ada Bindings for C and C++ headers -@anchor{gnat_ugn/the_gnat_compilation_model id72}@anchor{b3}@anchor{gnat_ugn/the_gnat_compilation_model generating-bindings-for-c-headers}@anchor{b4} +@anchor{gnat_ugn/the_gnat_compilation_model generating-bindings-for-c-headers}@anchor{b3}@anchor{gnat_ugn/the_gnat_compilation_model id72}@anchor{b4} @subsubsection Generating Bindings for C++ Headers @@ -6794,7 +6794,7 @@ You can then @code{include} @code{pack1.h} from a C source file and use the type call subprograms, reference objects, and constants. @node GNAT and Other Compilation Models,Using GNAT Files with External Tools,Mixed Language Programming,The GNAT Compilation Model -@anchor{gnat_ugn/the_gnat_compilation_model id74}@anchor{ba}@anchor{gnat_ugn/the_gnat_compilation_model gnat-and-other-compilation-models}@anchor{2d} +@anchor{gnat_ugn/the_gnat_compilation_model gnat-and-other-compilation-models}@anchor{2d}@anchor{gnat_ugn/the_gnat_compilation_model id74}@anchor{ba} @section GNAT and Other Compilation Models @@ -6816,7 +6816,7 @@ used for Ada 83. The GNAT model of compilation is close to the C and C++ models. You can think of Ada specs as corresponding to header files in C. As in C, you -don't need to compile specs; they are compiled when they are used. The +don’t need to compile specs; they are compiled when they are used. The Ada @emph{with} is similar in effect to the @code{#include} of a C header. @@ -6854,7 +6854,7 @@ model, as described in the Ada Reference Manual. @geindex GNAT library -In GNAT, there is no 'library' in the normal sense. Instead, the set of +In GNAT, there is no ‘library’ in the normal sense. Instead, the set of source files themselves acts as the library. Compiling Ada programs does not generate any centralized information, but rather an object file and a ALI file, which are of interest only to the binder and linker. @@ -6912,7 +6912,7 @@ of rules saying what source files must be present when a file is compiled. @node Using GNAT Files with External Tools,,GNAT and Other Compilation Models,The GNAT Compilation Model -@anchor{gnat_ugn/the_gnat_compilation_model using-gnat-files-with-external-tools}@anchor{2e}@anchor{gnat_ugn/the_gnat_compilation_model id77}@anchor{bf} +@anchor{gnat_ugn/the_gnat_compilation_model id77}@anchor{bf}@anchor{gnat_ugn/the_gnat_compilation_model using-gnat-files-with-external-tools}@anchor{2e} @section Using GNAT Files with External Tools @@ -6926,7 +6926,7 @@ used with tools designed for other languages. @end menu @node Using Other Utility Programs with GNAT,The External Symbol Naming Scheme of GNAT,,Using GNAT Files with External Tools -@anchor{gnat_ugn/the_gnat_compilation_model using-other-utility-programs-with-gnat}@anchor{c0}@anchor{gnat_ugn/the_gnat_compilation_model id78}@anchor{c1} +@anchor{gnat_ugn/the_gnat_compilation_model id78}@anchor{c0}@anchor{gnat_ugn/the_gnat_compilation_model using-other-utility-programs-with-gnat}@anchor{c1} @subsection Using Other Utility Programs with GNAT @@ -6941,7 +6941,7 @@ gprof (a profiling program), gdb (the FSF debugger), and utilities such as Purify. @node The External Symbol Naming Scheme of GNAT,,Using Other Utility Programs with GNAT,Using GNAT Files with External Tools -@anchor{gnat_ugn/the_gnat_compilation_model the-external-symbol-naming-scheme-of-gnat}@anchor{c2}@anchor{gnat_ugn/the_gnat_compilation_model id79}@anchor{c3} +@anchor{gnat_ugn/the_gnat_compilation_model id79}@anchor{c2}@anchor{gnat_ugn/the_gnat_compilation_model the-external-symbol-naming-scheme-of-gnat}@anchor{c3} @subsection The External Symbol Naming Scheme of GNAT @@ -7000,7 +7000,7 @@ the external name of this procedure will be @code{_ada_hello}. @c -- Example: A |withing| unit has a |with| clause, it |withs| a |withed| unit @node Building Executable Programs with GNAT,GNAT Utility Programs,The GNAT Compilation Model,Top -@anchor{gnat_ugn/building_executable_programs_with_gnat building-executable-programs-with-gnat}@anchor{a}@anchor{gnat_ugn/building_executable_programs_with_gnat doc}@anchor{c4}@anchor{gnat_ugn/building_executable_programs_with_gnat id1}@anchor{c5} +@anchor{gnat_ugn/building_executable_programs_with_gnat doc}@anchor{c4}@anchor{gnat_ugn/building_executable_programs_with_gnat building-executable-programs-with-gnat}@anchor{a}@anchor{gnat_ugn/building_executable_programs_with_gnat id1}@anchor{c5} @chapter Building Executable Programs with GNAT @@ -7031,7 +7031,7 @@ in a GNAT context (see @ref{70,,Using the GNU make Utility}). @end menu @node Building with gnatmake,Compiling with gcc,,Building Executable Programs with GNAT -@anchor{gnat_ugn/building_executable_programs_with_gnat the-gnat-make-program-gnatmake}@anchor{c6}@anchor{gnat_ugn/building_executable_programs_with_gnat building-with-gnatmake}@anchor{ca} +@anchor{gnat_ugn/building_executable_programs_with_gnat building-with-gnatmake}@anchor{ca}@anchor{gnat_ugn/building_executable_programs_with_gnat the-gnat-make-program-gnatmake}@anchor{c6} @section Building with @code{gnatmake} @@ -7080,7 +7080,7 @@ dependencies, they will always be tracked exactly correctly by Note that for advanced forms of project structure, we recommend creating a project file as explained in the @emph{GNAT_Project_Manager} chapter in the -@emph{GPRbuild User's Guide}, and using the +@emph{GPRbuild User’s Guide}, and using the @code{gprbuild} tool which supports building with project files and works similarly to @code{gnatmake}. @@ -7095,7 +7095,7 @@ to @code{gnatmake}. @end menu @node Running gnatmake,Switches for gnatmake,,Building with gnatmake -@anchor{gnat_ugn/building_executable_programs_with_gnat running-gnatmake}@anchor{cb}@anchor{gnat_ugn/building_executable_programs_with_gnat id2}@anchor{cc} +@anchor{gnat_ugn/building_executable_programs_with_gnat id2}@anchor{cb}@anchor{gnat_ugn/building_executable_programs_with_gnat running-gnatmake}@anchor{cc} @subsection Running @code{gnatmake} @@ -7130,7 +7130,7 @@ All @code{gnatmake} output (except when you specify @code{-M}) is sent to @code{-M} switch is sent to @code{stdout}. @node Switches for gnatmake,Mode Switches for gnatmake,Running gnatmake,Building with gnatmake -@anchor{gnat_ugn/building_executable_programs_with_gnat switches-for-gnatmake}@anchor{cd}@anchor{gnat_ugn/building_executable_programs_with_gnat id3}@anchor{ce} +@anchor{gnat_ugn/building_executable_programs_with_gnat id3}@anchor{cd}@anchor{gnat_ugn/building_executable_programs_with_gnat switches-for-gnatmake}@anchor{ce} @subsection Switches for @code{gnatmake} @@ -7218,7 +7218,7 @@ itself must not include any embedded spaces. @item @code{--create-map-file} When linking an executable, create a map file. The name of the map file -has the same name as the executable with extension ".map". +has the same name as the executable with extension “.map”. @item @code{--create-map-file=@emph{mapfile}} @@ -7266,7 +7266,7 @@ to process the project files, especially when looking for sources that take a long time. If the source info file exists but cannot be parsed successfully, the Project Manager will attempt to recreate it. If the Project Manager fails to create the source info file, a message is issued, but gnatmake does not -fail. @code{gnatmake} "trusts" the source info file. This means that +fail. @code{gnatmake} “trusts” the source info file. This means that if the source files have changed (addition, deletion, moving to a different source directory), then the source info file need to be deleted and recreated. @end table @@ -7346,7 +7346,7 @@ the objects. Use a temporary mapping file. A mapping file is a way to communicate to the compiler two mappings: from unit names to file names (without any directory information) and from file names to path names (with -full directory information). A mapping file can make the compiler's +full directory information). A mapping file can make the compiler’s file searches faster, especially if there are many source directories, or the sources are read over a slow network connection. If @code{-P} is used, a mapping file is always used, so @@ -7433,7 +7433,7 @@ directories, but is not needed in other cases. @geindex naming scheme This also assumes that no directory matches the naming scheme for files (for -instance that you do not have a directory called "sources.ads" when using the +instance that you do not have a directory called “sources.ads” when using the default GNAT naming scheme). When you do not have to use this switch (i.e., by default), gnatmake is able to @@ -7462,7 +7462,7 @@ instead of standard error. @item @code{-f} Force recompilations. Recompile all sources, even though some object -files may be up to date, but don't recompile predefined or GNAT internal +files may be up to date, but don’t recompile predefined or GNAT internal files or locked files (files with a write-protected ALI file), unless the @code{-a} switch is also specified. @end table @@ -7540,7 +7540,7 @@ rerun the make process with n set to 1 to get a clean list of messages. @item @code{-k} Keep going. Continue as much as possible after a compilation error. To -ease the programmer's task in case of compilation errors, the list of +ease the programmer’s task in case of compilation errors, the list of sources for which the compile fails is given when @code{gnatmake} terminates. @@ -7624,7 +7624,7 @@ are never reported. @item @code{-n} -Don't compile, bind, or link. Checks if all objects are up to date. +Don’t compile, bind, or link. Checks if all objects are up to date. If they are not, the full name of the first file that needs to be recompiled is printed. Repeated use of this option, followed by compiling the indicated source @@ -7691,7 +7691,7 @@ Quiet. When this flag is not set, the commands carried out by Recompile if compiler switches have changed since last compilation. All compiler switches but -I and -o are taken into account in the following way: -orders between different 'first letter' switches are ignored, but +orders between different ‘first letter’ switches are ignored, but orders between same switches are taken into account. For example, @code{-O -O2} is different than @code{-O2 -O}, but @code{-g -O} is equivalent to @code{-O -g}. @@ -8095,12 +8095,12 @@ that the debugging information may be out of date. @end itemize @node How gnatmake Works,Examples of gnatmake Usage,Notes on the Command Line,Building with gnatmake -@anchor{gnat_ugn/building_executable_programs_with_gnat id6}@anchor{d4}@anchor{gnat_ugn/building_executable_programs_with_gnat how-gnatmake-works}@anchor{d5} +@anchor{gnat_ugn/building_executable_programs_with_gnat how-gnatmake-works}@anchor{d4}@anchor{gnat_ugn/building_executable_programs_with_gnat id6}@anchor{d5} @subsection How @code{gnatmake} Works Generally @code{gnatmake} automatically performs all necessary -recompilations and you don't need to worry about how it works. However, +recompilations and you don’t need to worry about how it works. However, it may be useful to have some basic understanding of the @code{gnatmake} approach and in particular to understand how it uses the results of previous compilations without incorrectly depending on them. @@ -8123,7 +8123,7 @@ files. This process ensures that @code{gnatmake} only trusts the dependencies in an existing ALI file if they are known to be correct. Otherwise it always recompiles to determine a new, guaranteed accurate set of -dependencies. As a result the program is compiled 'upside down' from what may +dependencies. As a result the program is compiled ‘upside down’ from what may be more familiar as the required order of compilation in some other Ada systems. In particular, clients are compiled before the units on which they depend. The ability of GNAT to compile in any order is critical in @@ -8365,7 +8365,7 @@ names separated by colons (semicolons when working with the NT version). The content of the @code{ada_source_path} file which is part of the GNAT installation tree and is used to store standard libraries such as the GNAT Run Time Library (RTL) source files. -@ref{71,,Installing a library} +@ref{72,,Installing a library} @end itemize Specifying the switch @code{-I-} @@ -8448,7 +8448,7 @@ described above), or you will receive a fatal error message. @end itemize @node Examples,,Order of Compilation Issues,Compiling with gcc -@anchor{gnat_ugn/building_executable_programs_with_gnat id12}@anchor{df}@anchor{gnat_ugn/building_executable_programs_with_gnat examples}@anchor{e0} +@anchor{gnat_ugn/building_executable_programs_with_gnat examples}@anchor{df}@anchor{gnat_ugn/building_executable_programs_with_gnat id12}@anchor{e0} @subsection Examples @@ -8515,7 +8515,7 @@ compilation units. @end menu @node Alphabetical List of All Switches,Output and Error Message Control,,Compiler Switches -@anchor{gnat_ugn/building_executable_programs_with_gnat id13}@anchor{e2}@anchor{gnat_ugn/building_executable_programs_with_gnat alphabetical-list-of-all-switches}@anchor{e3} +@anchor{gnat_ugn/building_executable_programs_with_gnat alphabetical-list-of-all-switches}@anchor{e2}@anchor{gnat_ugn/building_executable_programs_with_gnat id13}@anchor{e3} @subsection Alphabetical List of All Switches @@ -8541,7 +8541,7 @@ system configuration. You must have a GNAT cross-compiler built if Load compiler executables (for example, @code{gnat1}, the Ada compiler) from @code{dir} instead of the default location. Only use this switch when multiple versions of the GNAT compiler are available. -See the "Options for Directory Search" section in the +See the “Options for Directory Search” section in the @cite{Using the GNU Compiler Collection (GCC)} manual for further details. You would normally use the @code{-b} or @code{-V} switch instead. @end table @@ -8888,7 +8888,7 @@ Generate brief messages to @code{stderr} even if verbose mode set. @item @code{-gnatB} -Assume no invalid (bad) values except for 'Valid attribute use +Assume no invalid (bad) values except for ‘Valid attribute use (@ref{e7,,Validity Checking}). @end table @@ -9015,7 +9015,7 @@ ALI files. Specify a configuration pragma file (the equal sign is optional) -(@ref{62,,The Configuration Pragmas Files}). +(@ref{63,,The Configuration Pragmas Files}). @end table @geindex -gnateC (gcc) @@ -9505,7 +9505,7 @@ and attribute_definition_clause for the following attributes: Address, Alignment, Bit_Order, Component_Size, Machine_Radix, Object_Size, Scalar_Storage_Order, Size, Small, Stream_Size, and Value_Size. Pragma Default_Scalar_Storage_Order is also ignored. -Note that this option should be used only for compiling -- the +Note that this option should be used only for compiling – the code is likely to malfunction at run time. @end table @@ -9554,7 +9554,7 @@ Calls to subprograms defined in instances Entry calls @item -Indirect calls using 'Access +Indirect calls using ‘Access @item Requeue statements @@ -9764,7 +9764,7 @@ Cancel effect of previous @code{-gnatp} switch. @item @code{-gnatq} -Don't quit. Try semantics, even if parse errors. +Don’t quit. Try semantics, even if parse errors. @end table @geindex -gnatQ (gcc) @@ -9774,7 +9774,7 @@ Don't quit. Try semantics, even if parse errors. @item @code{-gnatQ} -Don't quit. Generate @code{ALI} and tree files even if illegalities. +Don’t quit. Generate @code{ALI} and tree files even if illegalities. Note that code generation is still suppressed in the presence of any errors, so even with @code{-gnatQ} no object file is generated. @end table @@ -9849,7 +9849,7 @@ List units for this compilation. @item @code{-gnatU} -Tag all error messages with the unique string 'error:' +Tag all error messages with the unique string ‘error:’ @end table @geindex -gnatv (gcc) @@ -10088,7 +10088,7 @@ exit status. @item @code{--RTS=@emph{rts-path}} Specifies the default location of the run-time library. Same meaning as the -equivalent @code{gnatmake} flag (@ref{cd,,Switches for gnatmake}). +equivalent @code{gnatmake} flag (@ref{ce,,Switches for gnatmake}). @end table @geindex -S (gcc) @@ -10197,27 +10197,27 @@ switches, and only one of them may appear in the command line. The switch @code{-gnat-p} may not be combined with any other switch. @item -Once a 'y' appears in the string (that is a use of the @code{-gnaty} +Once a ‘y’ appears in the string (that is a use of the @code{-gnaty} switch), then all further characters in the switch are interpreted as style modifiers (see description of @code{-gnaty}). @item -Once a 'd' appears in the string (that is a use of the @code{-gnatd} +Once a ‘d’ appears in the string (that is a use of the @code{-gnatd} switch), then all further characters in the switch are interpreted as debug flags (see description of @code{-gnatd}). @item -Once a 'w' appears in the string (that is a use of the @code{-gnatw} +Once a ‘w’ appears in the string (that is a use of the @code{-gnatw} switch), then all further characters in the switch are interpreted as warning mode modifiers (see description of @code{-gnatw}). @item -Once a 'V' appears in the string (that is a use of the @code{-gnatV} +Once a ‘V’ appears in the string (that is a use of the @code{-gnatV} switch), then all further characters in the switch are interpreted as validity checking options (@ref{e7,,Validity Checking}). @item -Option 'em', 'ec', 'ep', 'l=' and 'R' must be the last options in +Option ‘em’, ‘ec’, ‘ep’, ‘l=’ and ‘R’ must be the last options in a combined list of options. @end itemize @@ -10228,7 +10228,7 @@ a combined list of options. @geindex stderr -The standard default format for error messages is called 'brief format'. +The standard default format for error messages is called ‘brief format’. Brief format messages are written to @code{stderr} (the standard error file) and have the following form: @@ -10352,7 +10352,7 @@ then the output is written to file xyz.adb.lst. @item @code{-gnatU} This switch forces all error messages to be preceded by the unique -string 'error:'. This means that error messages take a few more +string ‘error:’. This means that error messages take a few more characters in space, but allows easy searching for and identification of error messages. @end table @@ -10480,7 +10480,7 @@ is longer than nn characters. @item @code{-gnatq} -The @code{q} stands for quit (really 'don't quit'). +The @code{q} stands for quit (really ‘don’t quit’). In normal operation mode, the compiler first parses the program and determines if there are any syntax errors. If there are, appropriate error messages are generated and compilation is immediately terminated. @@ -10517,7 +10517,7 @@ since ALI files are never generated if @code{-gnats} is set. @end table @node Warning Message Control,Debugging and Assertion Control,Output and Error Message Control,Compiler Switches -@anchor{gnat_ugn/building_executable_programs_with_gnat warning-message-control}@anchor{eb}@anchor{gnat_ugn/building_executable_programs_with_gnat id15}@anchor{f0} +@anchor{gnat_ugn/building_executable_programs_with_gnat id15}@anchor{f0}@anchor{gnat_ugn/building_executable_programs_with_gnat warning-message-control}@anchor{eb} @subsection Warning Message Control @@ -10950,10 +10950,10 @@ for conditional compilation in Ada, and this would generate too many false positive warnings. This warning option also activates a special test for comparisons using -the operators '>=' and' <='. +the operators ‘>=’ and’ <=’. If the compiler can tell that only the equality condition is possible, -then it will warn that the '>' or '<' part of the test -is useless and that the operator could be replaced by '='. +then it will warn that the ‘>’ or ‘<’ part of the test +is useless and that the operator could be replaced by ‘=’. An example would be comparing a @code{Natural} variable <= 0. This warning option also generates warnings if @@ -11119,7 +11119,7 @@ of the pragma @code{Restriction_Warnings}. @emph{[warning-as-error]} Used to tag warning messages that have been converted to error messages by use of the pragma Warning_As_Error. Note that such warnings are prefixed by -the string "error: " rather than "warning: ". +the string “error: ” rather than “warning: “. @item @emph{[enabled by default]} @@ -11356,7 +11356,7 @@ implementation unit, defined as any unit from the @code{Ada}, or @code{System} hierarchies that is not documented in either the Ada Reference Manual or the GNAT -Programmer's Reference Manual. Such units are intended only +Programmer’s Reference Manual. Such units are intended only for internal implementation purposes and should not be @emph{with}ed by user programs. The default is that such warnings are generated @end table @@ -11575,8 +11575,8 @@ This switch suppresses warnings for possible elaboration problems. @emph{List inherited aspects.} This switch causes the compiler to list inherited invariants, -preconditions, and postconditions from Type_Invariant'Class, Invariant'Class, -Pre'Class, and Post'Class aspects. Also list inherited subtype predicates. +preconditions, and postconditions from Type_Invariant’Class, Invariant’Class, +Pre’Class, and Post’Class aspects. Also list inherited subtype predicates. @end table @geindex -gnatw.L (gcc) @@ -11821,7 +11821,7 @@ ordering when the list of arguments are all simple identifiers that match the names of the formals, but are in a different order. The warning is suppressed if any use of named parameter notation is used, so this is the appropriate way to suppress a false positive (and -serves to emphasize that the "misordering" is deliberate). The +serves to emphasize that the “misordering” is deliberate). The default is that such warnings are not given. @end table @@ -11911,7 +11911,7 @@ then the remaining components whose length is fixed and not a multiple of the storage unit, @item -then the remaining components whose length doesn't depend on discriminants +then the remaining components whose length doesn’t depend on discriminants (that is to say, with variable but uniform length for all objects), @item @@ -12188,7 +12188,7 @@ This switch activates warnings to be generated for entities that are declared but not referenced, and for units that are @emph{with}ed and not referenced. In the case of packages, a warning is also generated if -no entities in the package are referenced. This means that if a with'ed +no entities in the package are referenced. This means that if a with’ed package is referenced but the only references are in @code{use} clauses or @code{renames} declarations, a warning is still generated. A warning is also generated @@ -12297,7 +12297,7 @@ may not be properly initialized. @emph{Activate info messages for non-default bit order.} -This switch activates messages (labeled "info", they are not warnings, +This switch activates messages (labeled “info”, they are not warnings, just informational messages) about the effects of non-default bit-order on records to which a component clause is applied. The effect of specifying non-default bit ordering is a bit subtle (and changed with Ada 2005), so @@ -12330,7 +12330,7 @@ non-default bit order on record components with component clauses. @emph{Activate warnings on wrong low bound assumption.} This switch activates warnings for indexing an unconstrained string parameter -with a literal or S'Length. This is a case where the code is assuming that the +with a literal or S’Length. This is a case where the code is assuming that the low bound is one, which is in general not true (for example when a slice is passed). The default is that such warnings are generated. @end table @@ -12345,7 +12345,7 @@ passed). The default is that such warnings are generated. @emph{Suppress warnings on wrong low bound assumption.} This switch suppresses warnings for indexing an unconstrained string parameter -with a literal or S'Length. Note that this warning can also be suppressed +with a literal or S’Length. Note that this warning can also be suppressed in a particular case by adding an assertion that the lower bound is 1, as shown in the following example: @@ -12865,7 +12865,7 @@ pragma Assertion_Policy @end example The pragmas @code{Assert} and @code{Debug} normally have no effect and -are ignored. This switch, where @code{a} stands for 'assert', causes +are ignored. This switch, where @code{a} stands for ‘assert’, causes pragmas @code{Assert} and @code{Debug} to be activated. This switch also causes preconditions, postconditions, subtype predicates, and type invariants to be activated. @@ -12907,7 +12907,7 @@ is @code{False}, the exception @code{Assert_Failure} is raised. @end table @node Validity Checking,Style Checking,Debugging and Assertion Control,Compiler Switches -@anchor{gnat_ugn/building_executable_programs_with_gnat validity-checking}@anchor{e7}@anchor{gnat_ugn/building_executable_programs_with_gnat id17}@anchor{f3} +@anchor{gnat_ugn/building_executable_programs_with_gnat id17}@anchor{f3}@anchor{gnat_ugn/building_executable_programs_with_gnat validity-checking}@anchor{e7} @subsection Validity Checking @@ -13209,7 +13209,7 @@ enforce specified style rules. A limited set of style rules has been used in writing the GNAT sources themselves. This switch allows user programs to activate all or some of these checks. If the source program fails a specified style check, an appropriate message is given, preceded by -the character sequence '(style)'. This message does not prevent +the character sequence ‘(style)’. This message does not prevent successful compilation (unless the @code{-gnatwe} switch is used). Note that this is by no means intended to be a general facility for @@ -13747,7 +13747,7 @@ with declarations. @emph{Check separate specs.} -Separate declarations ('specs') are required for subprograms (a +Separate declarations (‘specs’) are required for subprograms (a body is not allowed to serve as its own declaration). The only exception is that parameterless library level procedures are not required to have a separate declaration. This exception covers @@ -13923,7 +13923,7 @@ a requirement for no following space. If any of these style rules is violated, a message is generated giving details on the violation. The initial characters of such messages are -always '@cite{(style)}'. Note that these messages are treated as warning +always ‘@cite{(style)}’. Note that these messages are treated as warning messages, so they normally do not prevent the generation of an object file. The @code{-gnatwe} switch can be used to treat warning messages, including style messages, as fatal errors. @@ -13936,7 +13936,7 @@ built-in standard style check options are enabled. The switch @code{-gnatyN} clears any previously set style checks. @node Run-Time Checks,Using gcc for Syntax Checking,Style Checking,Compiler Switches -@anchor{gnat_ugn/building_executable_programs_with_gnat run-time-checks}@anchor{ea}@anchor{gnat_ugn/building_executable_programs_with_gnat id19}@anchor{f5} +@anchor{gnat_ugn/building_executable_programs_with_gnat id19}@anchor{f5}@anchor{gnat_ugn/building_executable_programs_with_gnat run-time-checks}@anchor{ea} @subsection Run-Time Checks @@ -13984,7 +13984,7 @@ required, to omit the checking code. If the run-time cost of the checking code is zero or near-zero, the compiler will generate it even if checks are suppressed. In particular, if the compiler can prove that a certain check will necessarily fail, it will generate code to -do an unconditional 'raise', even if checks are suppressed. The +do an unconditional ‘raise’, even if checks are suppressed. The compiler warns in this case. Another case in which checks may not be eliminated is when they are embedded in certain run-time routines such as math library routines. @@ -14050,8 +14050,8 @@ This switch cancels the effect of a previous @code{gnatp} switch. This switch controls the mode used for computing intermediate arithmetic integer operations, and also enables overflow checking. For a full description of overflow mode and checking control, see -the 'Overflow Check Handling in GNAT' appendix in this -User's Guide. +the ‘Overflow Check Handling in GNAT’ appendix in this +User’s Guide. Overflow checks are always enabled by this switch. The argument controls the mode, using the codes @@ -14168,7 +14168,7 @@ the program source. @item @code{-gnats} -The @code{s} stands for 'syntax'. +The @code{s} stands for ‘syntax’. Run GNAT in syntax checking only mode. For example, the command @@ -14225,7 +14225,7 @@ together. This is primarily used by the @code{gnatchop} utility @item @code{-gnatc} -The @code{c} stands for 'check'. +The @code{c} stands for ‘check’. Causes the compiler to operate in semantic check mode, with full checking for all illegalities specified in the Ada Reference Manual, but without generation of any object code @@ -14408,7 +14408,7 @@ extensions, see the GNAT reference manual, @code{Pragma Extensions_Allowed}. @end table @node Character Set Control,File Naming Control,Compiling Different Versions of Ada,Compiler Switches -@anchor{gnat_ugn/building_executable_programs_with_gnat id23}@anchor{fb}@anchor{gnat_ugn/building_executable_programs_with_gnat character-set-control}@anchor{31} +@anchor{gnat_ugn/building_executable_programs_with_gnat character-set-control}@anchor{31}@anchor{gnat_ugn/building_executable_programs_with_gnat id23}@anchor{fb} @subsection Character Set Control @@ -14591,7 +14591,7 @@ methods see @ref{37,,Wide_Character Encodings}. Note that brackets coding is always accepted, even if one of the other options is specified, so for example @code{-gnatW8} specifies that both brackets and UTF-8 encodings will be recognized. The units that are -with'ed directly or indirectly will be scanned using the specified +with’ed directly or indirectly will be scanned using the specified representation scheme, and so if one of the non-brackets scheme is used, it must be used consistently throughout the program. However, since brackets encoding is always recognized, it may be conveniently @@ -14646,7 +14646,7 @@ This is a common mode for many programs with foreign language comments. @item @code{-gnatk@emph{n}} -Activates file name 'krunching'. @code{n}, a decimal integer in the range +Activates file name ‘krunching’. @code{n}, a decimal integer in the range 1-999, indicates the maximum allowable length of a file name (not including the @code{.ads} or @code{.adb} extension). The default is not to enable file name krunching. @@ -14655,7 +14655,7 @@ For the source file naming rules, @ref{3b,,File Naming Rules}. @end table @node Subprogram Inlining Control,Auxiliary Output Control,File Naming Control,Compiler Switches -@anchor{gnat_ugn/building_executable_programs_with_gnat subprogram-inlining-control}@anchor{fe}@anchor{gnat_ugn/building_executable_programs_with_gnat id25}@anchor{ff} +@anchor{gnat_ugn/building_executable_programs_with_gnat id25}@anchor{fe}@anchor{gnat_ugn/building_executable_programs_with_gnat subprogram-inlining-control}@anchor{ff} @subsection Subprogram Inlining Control @@ -14666,7 +14666,7 @@ For the source file naming rules, @ref{3b,,File Naming Rules}. @item @code{-gnatn[12]} -The @code{n} here is intended to suggest the first syllable of the word 'inline'. +The @code{n} here is intended to suggest the first syllable of the word ‘inline’. GNAT recognizes and processes @code{Inline} pragmas. However, for inlining to actually occur, optimization must be enabled and, by default, inlining of subprograms across units is not performed. If you want to additionally @@ -15020,7 +15020,7 @@ is set). For @code{-gnatR3}, symbolic expressions for values that are computed at run time for records are included. These symbolic expressions have a mostly obvious format with #n being used to represent the value of the -n'th discriminant. See source files @code{repinfo.ads/adb} in the +n’th discriminant. See source files @code{repinfo.ads/adb} in the GNAT sources for full details on the format of @code{-gnatR3} output. For @code{-gnatR4}, information for relevant compiler-generated types @@ -15097,10 +15097,10 @@ emitted in the debug information. Historically, old debug formats like stabs were not powerful enough to express some Ada types (for instance, variant records or fixed-point types). To work around this, GNAT introduced proprietary encodings that embed the -missing information ("GNAT encodings"). +missing information (“GNAT encodings”). Recent versions of the DWARF debug information format are now able to -correctly describe most of these Ada constructs ("standard DWARF"). As +correctly describe most of these Ada constructs (“standard DWARF”). As third-party tools started to use this format, GNAT has been enhanced to generate it. However, most tools (including GDB) are still relying on GNAT encodings. @@ -15127,7 +15127,7 @@ encodings for the rest. @end table @node Exception Handling Control,Units to Sources Mapping Files,Debugging Control,Compiler Switches -@anchor{gnat_ugn/building_executable_programs_with_gnat id28}@anchor{105}@anchor{gnat_ugn/building_executable_programs_with_gnat exception-handling-control}@anchor{106} +@anchor{gnat_ugn/building_executable_programs_with_gnat exception-handling-control}@anchor{105}@anchor{gnat_ugn/building_executable_programs_with_gnat id28}@anchor{106} @subsection Exception Handling Control @@ -15139,7 +15139,7 @@ need for tracing stack frames. This method provides very fast exception propagation, but introduces significant overhead for the use of exception handlers, even if no exception is raised. -The other approach is called 'zero cost' exception handling. +The other approach is called ‘zero cost’ exception handling. With this method, the compiler builds static tables to describe the exception ranges. No dynamic code is required when entering a frame containing an exception handler. When an exception is @@ -15150,7 +15150,7 @@ the propagation of exceptions, but there is no overhead for exception handlers if no exception is raised. Note that in this mode and in the context of mixed Ada and C/C++ programming, to propagate an exception through a C/C++ code, the C/C++ code -must be compiled with the @code{-funwind-tables} GCC's +must be compiled with the @code{-funwind-tables} GCC’s option. The following switches may be used to control which of the @@ -15195,7 +15195,7 @@ is available for the target in use, otherwise it will generate an error. The same option @code{--RTS} must be used both for @code{gcc} and @code{gnatbind}. Passing this option to @code{gnatmake} -(@ref{cd,,Switches for gnatmake}) will ensure the required consistency +(@ref{ce,,Switches for gnatmake}) will ensure the required consistency through the compilation and binding steps. @node Units to Sources Mapping Files,Code Generation Control,Exception Handling Control,Compiler Switches @@ -15280,7 +15280,7 @@ there is no point in using @code{-m} switches to improve performance unless you actually see a performance improvement. @node Linker Switches,Binding with gnatbind,Compiler Switches,Building Executable Programs with GNAT -@anchor{gnat_ugn/building_executable_programs_with_gnat linker-switches}@anchor{10a}@anchor{gnat_ugn/building_executable_programs_with_gnat id31}@anchor{10b} +@anchor{gnat_ugn/building_executable_programs_with_gnat id31}@anchor{10a}@anchor{gnat_ugn/building_executable_programs_with_gnat linker-switches}@anchor{10b} @section Linker Switches @@ -15351,7 +15351,7 @@ to be read by the @code{gnatlink} utility used to link the Ada application. @end menu @node Running gnatbind,Switches for gnatbind,,Binding with gnatbind -@anchor{gnat_ugn/building_executable_programs_with_gnat running-gnatbind}@anchor{10d}@anchor{gnat_ugn/building_executable_programs_with_gnat id33}@anchor{10e} +@anchor{gnat_ugn/building_executable_programs_with_gnat id33}@anchor{10d}@anchor{gnat_ugn/building_executable_programs_with_gnat running-gnatbind}@anchor{10e} @subsection Running @code{gnatbind} @@ -15594,7 +15594,7 @@ Output complete list of elaboration-order dependencies. @item @code{-Ea} Store tracebacks in exception occurrences when the target supports it. -The "a" is for "address"; tracebacks will contain hexadecimal addresses, +The “a” is for “address”; tracebacks will contain hexadecimal addresses, unless symbolic tracebacks are enabled. See also the packages @code{GNAT.Traceback} and @@ -15611,7 +15611,7 @@ Note that on x86 ports, you must not use @code{-fomit-frame-pointer} @item @code{-Es} Store tracebacks in exception occurrences when the target supports it. -The "s" is for "symbolic"; symbolic tracebacks are enabled. +The “s” is for “symbolic”; symbolic tracebacks are enabled. @end table @geindex -E (gnatbind) @@ -15759,10 +15759,10 @@ limitations: @itemize * @item -Starting the program's execution in the debugger will cause it to +Starting the program’s execution in the debugger will cause it to stop at the start of the @code{main} function instead of the main subprogram. This can be worked around by manually inserting a breakpoint on that -subprogram and resuming the program's execution until reaching that breakpoint. +subprogram and resuming the program’s execution until reaching that breakpoint. @item Programs using GNAT.Compiler_Version will not link. @@ -15791,7 +15791,7 @@ Do not look for library files in the system default directory. @item @code{--RTS=@emph{rts-path}} Specifies the default location of the run-time library. Same meaning as the -equivalent @code{gnatmake} flag (@ref{cd,,Switches for gnatmake}). +equivalent @code{gnatmake} flag (@ref{ce,,Switches for gnatmake}). @geindex -o (gnatbind) @@ -15943,7 +15943,7 @@ scheduling policy to @code{FIFO_Within_Priorities}. Enable dynamic stack usage, with @code{n} results stored and displayed at program termination. A result is generated when a task -terminates. Results that can't be stored are displayed on the fly, at +terminates. Results that can’t be stored are displayed on the fly, at task termination. This option is currently not supported on Itanium platforms. (See @ref{113,,Dynamic Stack Usage Analysis} for details.) @@ -16079,7 +16079,7 @@ case the checking against sources has already been performed by @end table @node Binder Error Message Control,Elaboration Control,Consistency-Checking Modes,Switches for gnatbind -@anchor{gnat_ugn/building_executable_programs_with_gnat id36}@anchor{116}@anchor{gnat_ugn/building_executable_programs_with_gnat binder-error-message-control}@anchor{117} +@anchor{gnat_ugn/building_executable_programs_with_gnat binder-error-message-control}@anchor{116}@anchor{gnat_ugn/building_executable_programs_with_gnat id36}@anchor{117} @subsubsection Binder Error Message Control @@ -16189,7 +16189,7 @@ with extreme care. @end table @node Elaboration Control,Output Control,Binder Error Message Control,Switches for gnatbind -@anchor{gnat_ugn/building_executable_programs_with_gnat id37}@anchor{118}@anchor{gnat_ugn/building_executable_programs_with_gnat elaboration-control}@anchor{111} +@anchor{gnat_ugn/building_executable_programs_with_gnat elaboration-control}@anchor{111}@anchor{gnat_ugn/building_executable_programs_with_gnat id37}@anchor{118} @subsubsection Elaboration Control @@ -16205,10 +16205,10 @@ order. For further details see @ref{f,,Elaboration Order Handling in GNAT}. Force elaboration order. -@code{elab-order} should be the name of a "forced elaboration order file", that +@code{elab-order} should be the name of a “forced elaboration order file”, that is, a text file containing library item names, one per line. A name of the -form "some.unit%s" or "some.unit (spec)" denotes the spec of Some.Unit. A -name of the form "some.unit%b" or "some.unit (body)" denotes the body of +form “some.unit%s” or “some.unit (spec)” denotes the spec of Some.Unit. A +name of the form “some.unit%b” or “some.unit (body)” denotes the body of Some.Unit. Each pair of lines is taken to mean that there is an elaboration dependence of the second line on the first. For example, if the file contains: @@ -16229,11 +16229,11 @@ forcing the body of This to be elaborated before the spec of That. The given order must be consistent with Ada rules, or else @code{gnatbind} will give elaboration cycle errors. For example, if you say x (body) should be elaborated before x (spec), there will be a cycle, because Ada rules require -x (spec) to be elaborated before x (body); you can't have the spec and body +x (spec) to be elaborated before x (body); you can’t have the spec and body both elaborated before each other. -If you later add "with That;" to the body of This, there will be a cycle, in -which case you should erase either "this (body)" or "that (spec)" from the +If you later add “with That;” to the body of This, there will be a cycle, in +which case you should erase either “this (body)” or “that (spec)” from the above forced elaboration order file. Blank lines and Ada-style comments are ignored. Unit names that do not exist @@ -16274,7 +16274,7 @@ debugging/experimental use. @end table @node Output Control,Dynamic Allocation Control,Elaboration Control,Switches for gnatbind -@anchor{gnat_ugn/building_executable_programs_with_gnat output-control}@anchor{119}@anchor{gnat_ugn/building_executable_programs_with_gnat id38}@anchor{11a} +@anchor{gnat_ugn/building_executable_programs_with_gnat id38}@anchor{119}@anchor{gnat_ugn/building_executable_programs_with_gnat output-control}@anchor{11a} @subsubsection Output Control @@ -16359,7 +16359,7 @@ be used to improve code generation in some cases. @subsubsection Dynamic Allocation Control -The heap control switches -- @code{-H32} and @code{-H64} -- +The heap control switches – @code{-H32} and @code{-H64} – determine whether dynamic allocation uses 32-bit or 64-bit memory. They only affect compiler-generated allocations via @code{__gnat_malloc}; explicit calls to @code{malloc} and related functions from the C @@ -16508,7 +16508,7 @@ the binder switch @end table @node Command-Line Access,Search Paths for gnatbind,Switches for gnatbind,Binding with gnatbind -@anchor{gnat_ugn/building_executable_programs_with_gnat id42}@anchor{11f}@anchor{gnat_ugn/building_executable_programs_with_gnat command-line-access}@anchor{120} +@anchor{gnat_ugn/building_executable_programs_with_gnat command-line-access}@anchor{11f}@anchor{gnat_ugn/building_executable_programs_with_gnat id42}@anchor{120} @subsection Command-Line Access @@ -16538,7 +16538,7 @@ required, your main program must set @code{gnat_argc} and it. @node Search Paths for gnatbind,Examples of gnatbind Usage,Command-Line Access,Binding with gnatbind -@anchor{gnat_ugn/building_executable_programs_with_gnat search-paths-for-gnatbind}@anchor{76}@anchor{gnat_ugn/building_executable_programs_with_gnat id43}@anchor{121} +@anchor{gnat_ugn/building_executable_programs_with_gnat id43}@anchor{121}@anchor{gnat_ugn/building_executable_programs_with_gnat search-paths-for-gnatbind}@anchor{76} @subsection Search Paths for @code{gnatbind} @@ -16595,7 +16595,7 @@ of GNAT). The content of the @code{ada_object_path} file which is part of the GNAT installation tree and is used to store standard libraries such as the GNAT Run-Time Library (RTL) unless the switch @code{-nostdlib} is -specified. See @ref{71,,Installing a library} +specified. See @ref{72,,Installing a library} @end itemize @geindex -I (gnatbind) @@ -16642,7 +16642,7 @@ in compiling sources from multiple directories. This can make development environments much more flexible. @node Examples of gnatbind Usage,,Search Paths for gnatbind,Binding with gnatbind -@anchor{gnat_ugn/building_executable_programs_with_gnat id44}@anchor{122}@anchor{gnat_ugn/building_executable_programs_with_gnat examples-of-gnatbind-usage}@anchor{123} +@anchor{gnat_ugn/building_executable_programs_with_gnat examples-of-gnatbind-usage}@anchor{122}@anchor{gnat_ugn/building_executable_programs_with_gnat id44}@anchor{123} @subsection Examples of @code{gnatbind} Usage @@ -16895,7 +16895,7 @@ for further details. You would normally use the @code{-b} or @item @code{-M} When linking an executable, create a map file. The name of the map file -has the same name as the executable with extension ".map". +has the same name as the executable with extension “.map”. @end table @geindex -M= (gnatlink) @@ -16956,7 +16956,7 @@ switch. @end table @node Using the GNU make Utility,,Linking with gnatlink,Building Executable Programs with GNAT -@anchor{gnat_ugn/building_executable_programs_with_gnat using-the-gnu-make-utility}@anchor{70}@anchor{gnat_ugn/building_executable_programs_with_gnat id48}@anchor{12b} +@anchor{gnat_ugn/building_executable_programs_with_gnat id48}@anchor{12b}@anchor{gnat_ugn/building_executable_programs_with_gnat using-the-gnu-make-utility}@anchor{70} @section Using the GNU @code{make} Utility @@ -16981,7 +16981,7 @@ is the same, these examples use some advanced features found only in @end menu @node Using gnatmake in a Makefile,Automatically Creating a List of Directories,,Using the GNU make Utility -@anchor{gnat_ugn/building_executable_programs_with_gnat using-gnatmake-in-a-makefile}@anchor{12c}@anchor{gnat_ugn/building_executable_programs_with_gnat id49}@anchor{12d} +@anchor{gnat_ugn/building_executable_programs_with_gnat id49}@anchor{12c}@anchor{gnat_ugn/building_executable_programs_with_gnat using-gnatmake-in-a-makefile}@anchor{12d} @subsection Using gnatmake in a Makefile @@ -17080,7 +17080,7 @@ clean:: @end example @node Automatically Creating a List of Directories,Generating the Command Line Switches,Using gnatmake in a Makefile,Using the GNU make Utility -@anchor{gnat_ugn/building_executable_programs_with_gnat id50}@anchor{12f}@anchor{gnat_ugn/building_executable_programs_with_gnat automatically-creating-a-list-of-directories}@anchor{12e} +@anchor{gnat_ugn/building_executable_programs_with_gnat automatically-creating-a-list-of-directories}@anchor{12e}@anchor{gnat_ugn/building_executable_programs_with_gnat id50}@anchor{12f} @subsection Automatically Creating a List of Directories @@ -17153,7 +17153,7 @@ DIRS := $@{shell find $@{ROOT_DIRECTORY@} -type d -print@} @end example @node Generating the Command Line Switches,Overcoming Command Line Length Limits,Automatically Creating a List of Directories,Using the GNU make Utility -@anchor{gnat_ugn/building_executable_programs_with_gnat id51}@anchor{130}@anchor{gnat_ugn/building_executable_programs_with_gnat generating-the-command-line-switches}@anchor{131} +@anchor{gnat_ugn/building_executable_programs_with_gnat generating-the-command-line-switches}@anchor{130}@anchor{gnat_ugn/building_executable_programs_with_gnat id51}@anchor{131} @subsection Generating the Command Line Switches @@ -17179,7 +17179,7 @@ all: @end example @node Overcoming Command Line Length Limits,,Generating the Command Line Switches,Using the GNU make Utility -@anchor{gnat_ugn/building_executable_programs_with_gnat overcoming-command-line-length-limits}@anchor{132}@anchor{gnat_ugn/building_executable_programs_with_gnat id52}@anchor{133} +@anchor{gnat_ugn/building_executable_programs_with_gnat id52}@anchor{132}@anchor{gnat_ugn/building_executable_programs_with_gnat overcoming-command-line-length-limits}@anchor{133} @subsection Overcoming Command Line Length Limits @@ -17299,7 +17299,7 @@ generated files and executable files. @end menu @node Running gnatclean,Switches for gnatclean,,The File Cleanup Utility gnatclean -@anchor{gnat_ugn/gnat_utility_programs running-gnatclean}@anchor{139}@anchor{gnat_ugn/gnat_utility_programs id3}@anchor{13a} +@anchor{gnat_ugn/gnat_utility_programs id3}@anchor{139}@anchor{gnat_ugn/gnat_utility_programs running-gnatclean}@anchor{13a} @subsection Running @code{gnatclean} @@ -17525,7 +17525,7 @@ where @code{gnatclean} was invoked. @end table @node The GNAT Library Browser gnatls,,The File Cleanup Utility gnatclean,GNAT Utility Programs -@anchor{gnat_ugn/gnat_utility_programs the-gnat-library-browser-gnatls}@anchor{137}@anchor{gnat_ugn/gnat_utility_programs id5}@anchor{13d} +@anchor{gnat_ugn/gnat_utility_programs id5}@anchor{13d}@anchor{gnat_ugn/gnat_utility_programs the-gnat-library-browser-gnatls}@anchor{137} @section The GNAT Library Browser @code{gnatls} @@ -17741,7 +17741,7 @@ Several such switches may be specified simultaneously. @item @code{-aO@emph{dir}}, @code{-aI@emph{dir}}, @code{-I@emph{dir}}, @code{-I-}, @code{-nostdinc} Source path manipulation. Same meaning as the equivalent @code{gnatmake} -flags (@ref{cd,,Switches for gnatmake}). +flags (@ref{ce,,Switches for gnatmake}). @end table @geindex -aP (gnatls) @@ -17762,7 +17762,7 @@ Add @code{dir} at the beginning of the project search dir. @item @code{--RTS=@emph{rts-path}} Specifies the default location of the runtime library. Same meaning as the -equivalent @code{gnatmake} flag (@ref{cd,,Switches for gnatmake}). +equivalent @code{gnatmake} flag (@ref{ce,,Switches for gnatmake}). @end table @geindex -v (gnatls) @@ -17808,7 +17808,7 @@ by the user. @end table @node Example of gnatls Usage,,Switches for gnatls,The GNAT Library Browser gnatls -@anchor{gnat_ugn/gnat_utility_programs id8}@anchor{142}@anchor{gnat_ugn/gnat_utility_programs example-of-gnatls-usage}@anchor{143} +@anchor{gnat_ugn/gnat_utility_programs example-of-gnatls-usage}@anchor{142}@anchor{gnat_ugn/gnat_utility_programs id8}@anchor{143} @subsection Example of @code{gnatls} Usage @@ -17897,7 +17897,7 @@ instr.ads @c -- Example: A |withing| unit has a |with| clause, it |withs| a |withed| unit @node GNAT and Program Execution,Platform-Specific Information,GNAT Utility Programs,Top -@anchor{gnat_ugn/gnat_and_program_execution gnat-and-program-execution}@anchor{c}@anchor{gnat_ugn/gnat_and_program_execution doc}@anchor{144}@anchor{gnat_ugn/gnat_and_program_execution id1}@anchor{145} +@anchor{gnat_ugn/gnat_and_program_execution doc}@anchor{144}@anchor{gnat_ugn/gnat_and_program_execution gnat-and-program-execution}@anchor{c}@anchor{gnat_ugn/gnat_and_program_execution id1}@anchor{145} @chapter GNAT and Program Execution @@ -17994,7 +17994,7 @@ the incorrect user program. @end menu @node The GNAT Debugger GDB,Running GDB,,Running and Debugging Ada Programs -@anchor{gnat_ugn/gnat_and_program_execution the-gnat-debugger-gdb}@anchor{14e}@anchor{gnat_ugn/gnat_and_program_execution id3}@anchor{14f} +@anchor{gnat_ugn/gnat_and_program_execution id3}@anchor{14e}@anchor{gnat_ugn/gnat_and_program_execution the-gnat-debugger-gdb}@anchor{14f} @subsection The GNAT Debugger GDB @@ -18078,7 +18078,7 @@ exactly as if the debugger were not present. The following section describes some of the additional commands that can be given to @code{GDB}. @node Introduction to GDB Commands,Using Ada Expressions,Running GDB,Running and Debugging Ada Programs -@anchor{gnat_ugn/gnat_and_program_execution introduction-to-gdb-commands}@anchor{152}@anchor{gnat_ugn/gnat_and_program_execution id5}@anchor{153} +@anchor{gnat_ugn/gnat_and_program_execution id5}@anchor{152}@anchor{gnat_ugn/gnat_and_program_execution introduction-to-gdb-commands}@anchor{153} @subsection Introduction to GDB Commands @@ -18319,12 +18319,12 @@ Thus, for brevity, the debugger acts as if there were implicit @code{with} and @code{use} clauses in effect for all user-written packages, thus making it unnecessary to fully qualify most names with their packages, regardless of context. Where this causes ambiguity, -@code{GDB} asks the user's intent. +@code{GDB} asks the user’s intent. For details on the supported Ada syntax, see @cite{Debugging with GDB}. @node Calling User-Defined Subprograms,Using the next Command in a Function,Using Ada Expressions,Running and Debugging Ada Programs -@anchor{gnat_ugn/gnat_and_program_execution id7}@anchor{156}@anchor{gnat_ugn/gnat_and_program_execution calling-user-defined-subprograms}@anchor{157} +@anchor{gnat_ugn/gnat_and_program_execution calling-user-defined-subprograms}@anchor{156}@anchor{gnat_ugn/gnat_and_program_execution id7}@anchor{157} @subsection Calling User-Defined Subprograms @@ -18383,7 +18383,7 @@ elements directly from GDB, you can write a callable procedure that prints the elements in the desired format. @node Using the next Command in a Function,Stopping When Ada Exceptions Are Raised,Calling User-Defined Subprograms,Running and Debugging Ada Programs -@anchor{gnat_ugn/gnat_and_program_execution using-the-next-command-in-a-function}@anchor{158}@anchor{gnat_ugn/gnat_and_program_execution id8}@anchor{159} +@anchor{gnat_ugn/gnat_and_program_execution id8}@anchor{158}@anchor{gnat_ugn/gnat_and_program_execution using-the-next-command-in-a-function}@anchor{159} @subsection Using the @emph{next} Command in a Function @@ -18391,7 +18391,7 @@ When you use the @code{next} command in a function, the current source location will advance to the next statement as usual. A special case arises in the case of a @code{return} statement. -Part of the code for a return statement is the 'epilogue' of the function. +Part of the code for a return statement is the ‘epilogue’ of the function. This is the code that returns to the caller. There is only one copy of this epilogue code, and it is typically associated with the last return statement in the function if there is more than one return. In some @@ -18406,7 +18406,7 @@ The value returned is always that from the first return statement that was stepped through. @node Stopping When Ada Exceptions Are Raised,Ada Tasks,Using the next Command in a Function,Running and Debugging Ada Programs -@anchor{gnat_ugn/gnat_and_program_execution stopping-when-ada-exceptions-are-raised}@anchor{15a}@anchor{gnat_ugn/gnat_and_program_execution id9}@anchor{15b} +@anchor{gnat_ugn/gnat_and_program_execution id9}@anchor{15a}@anchor{gnat_ugn/gnat_and_program_execution stopping-when-ada-exceptions-are-raised}@anchor{15b} @subsection Stopping When Ada Exceptions Are Raised @@ -18501,7 +18501,7 @@ to refer to tasks in the following commands. @itemize * @item -@code{break`@w{`}*linespec* `@w{`}task} @emph{taskid}, @code{break} @emph{linespec} @code{task} @emph{taskid} @code{if} ... +@code{break`@w{`}*linespec* `@w{`}task} @emph{taskid}, @code{break} @emph{linespec} @code{task} @emph{taskid} @code{if} … @quotation @@ -18609,7 +18609,7 @@ other units. @geindex Remote Debugging with gdbserver @node Remote Debugging with gdbserver,GNAT Abnormal Termination or Failure to Terminate,Debugging Generic Units,Running and Debugging Ada Programs -@anchor{gnat_ugn/gnat_and_program_execution remote-debugging-with-gdbserver}@anchor{160}@anchor{gnat_ugn/gnat_and_program_execution id12}@anchor{161} +@anchor{gnat_ugn/gnat_and_program_execution id12}@anchor{160}@anchor{gnat_ugn/gnat_and_program_execution remote-debugging-with-gdbserver}@anchor{161} @subsection Remote Debugging with gdbserver @@ -18722,7 +18722,7 @@ Finally, you can start @code{gdb} directly on the @code{gnat1} executable. @code{gnat1} is the front-end of GNAT, and can be run independently (normally it is just called from @code{gcc}). You can use @code{gdb} on @code{gnat1} as you -would on a C program (but @ref{14e,,The GNAT Debugger GDB} for caveats). The +would on a C program (but @ref{14f,,The GNAT Debugger GDB} for caveats). The @code{where} command is the first line of attack; the variable @code{lineno} (seen by @code{print lineno}), used by the second phase of @code{gnat1} and by the @code{gcc} backend, indicates the source line at @@ -18731,7 +18731,7 @@ the source file. @end itemize @node Naming Conventions for GNAT Source Files,Getting Internal Debugging Information,GNAT Abnormal Termination or Failure to Terminate,Running and Debugging Ada Programs -@anchor{gnat_ugn/gnat_and_program_execution naming-conventions-for-gnat-source-files}@anchor{164}@anchor{gnat_ugn/gnat_and_program_execution id14}@anchor{165} +@anchor{gnat_ugn/gnat_and_program_execution id14}@anchor{164}@anchor{gnat_ugn/gnat_and_program_execution naming-conventions-for-gnat-source-files}@anchor{165} @subsection Naming Conventions for GNAT Source Files @@ -18812,7 +18812,7 @@ the other @code{.c} files are modifications of common @code{gcc} files. @end itemize @node Getting Internal Debugging Information,Stack Traceback,Naming Conventions for GNAT Source Files,Running and Debugging Ada Programs -@anchor{gnat_ugn/gnat_and_program_execution id15}@anchor{166}@anchor{gnat_ugn/gnat_and_program_execution getting-internal-debugging-information}@anchor{167} +@anchor{gnat_ugn/gnat_and_program_execution getting-internal-debugging-information}@anchor{166}@anchor{gnat_ugn/gnat_and_program_execution id15}@anchor{167} @subsection Getting Internal Debugging Information @@ -18840,7 +18840,7 @@ are replaced with run-time calls. @geindex stack unwinding @node Stack Traceback,Pretty-Printers for the GNAT runtime,Getting Internal Debugging Information,Running and Debugging Ada Programs -@anchor{gnat_ugn/gnat_and_program_execution stack-traceback}@anchor{168}@anchor{gnat_ugn/gnat_and_program_execution id16}@anchor{169} +@anchor{gnat_ugn/gnat_and_program_execution id16}@anchor{168}@anchor{gnat_ugn/gnat_and_program_execution stack-traceback}@anchor{169} @subsection Stack Traceback @@ -18869,7 +18869,7 @@ is enabled, and no exception is raised during program execution. @end menu @node Non-Symbolic Traceback,Symbolic Traceback,,Stack Traceback -@anchor{gnat_ugn/gnat_and_program_execution non-symbolic-traceback}@anchor{16a}@anchor{gnat_ugn/gnat_and_program_execution id17}@anchor{16b} +@anchor{gnat_ugn/gnat_and_program_execution id17}@anchor{16a}@anchor{gnat_ugn/gnat_and_program_execution non-symbolic-traceback}@anchor{16b} @subsubsection Non-Symbolic Traceback @@ -18996,7 +18996,7 @@ From this traceback we can see that the exception was raised in @code{stb.adb} at line 5, which was reached from a procedure call in @code{stb.adb} at line 10, and so on. The @code{b~std.adb} is the binder file, which contains the call to the main program. -@ref{10d,,Running gnatbind}. The remaining entries are assorted runtime routines, +@ref{10e,,Running gnatbind}. The remaining entries are assorted runtime routines, and the output will vary from platform to platform. It is also possible to use @code{GDB} with these traceback addresses to debug @@ -19148,7 +19148,7 @@ In STB.P1 : 16#0040_F1E4# 16#0040_14F2# 16#0040_170B# 16#0040_171C# You can then get further information by invoking the @code{addr2line} tool as described earlier (note that the hexadecimal addresses -need to be specified in C format, with a leading '0x'). +need to be specified in C format, with a leading ‘0x’). @geindex traceback @geindex symbolic @@ -19286,7 +19286,7 @@ program. @subsection Pretty-Printers for the GNAT runtime -As discussed in @cite{Calling User-Defined Subprograms}, GDB's +As discussed in @cite{Calling User-Defined Subprograms}, GDB’s @code{print} command only knows about the physical layout of program data structures and therefore normally displays only low-level dumps, which are often hard to understand. @@ -19351,7 +19351,7 @@ python import gnatdbg; gnatdbg.setup() @end example @end quotation -Once this is done, GDB's @code{print} command will automatically use +Once this is done, GDB’s @code{print} command will automatically use these pretty-printers when appropriate. Using the previous example: @quotation @@ -19368,8 +19368,8 @@ $1 = pp.int_to_nat.map of length 3 = @{ Pretty-printers are invoked each time GDB tries to display a value, including when displaying the arguments of a called subprogram (in -GDB's @code{backtrace} command) or when printing the value returned by a -function (in GDB's @code{finish} command). +GDB’s @code{backtrace} command) or when printing the value returned by a +function (in GDB’s @code{finish} command). To display a value without involving pretty-printers, @code{print} can be invoked with its @code{/r} option: @@ -19389,7 +19389,7 @@ for more information. @geindex Profiling @node Profiling,Improving Performance,Running and Debugging Ada Programs,GNAT and Program Execution -@anchor{gnat_ugn/gnat_and_program_execution profiling}@anchor{147}@anchor{gnat_ugn/gnat_and_program_execution id20}@anchor{170} +@anchor{gnat_ugn/gnat_and_program_execution id20}@anchor{170}@anchor{gnat_ugn/gnat_and_program_execution profiling}@anchor{147} @section Profiling @@ -19410,7 +19410,7 @@ This section describes how to use the @code{gprof} profiler tool on Ada programs This section is not meant to be an exhaustive documentation of @code{gprof}. -Full documentation for it can be found in the @cite{GNU Profiler User's Guide} +Full documentation for it can be found in the @cite{GNU Profiler User’s Guide} documentation that is part of this GNAT distribution. Profiling a program helps determine the parts of a program that are executed @@ -19459,7 +19459,7 @@ to interpret the results. @end menu @node Compilation for profiling,Program execution,,Profiling an Ada Program with gprof -@anchor{gnat_ugn/gnat_and_program_execution id22}@anchor{173}@anchor{gnat_ugn/gnat_and_program_execution compilation-for-profiling}@anchor{174} +@anchor{gnat_ugn/gnat_and_program_execution compilation-for-profiling}@anchor{173}@anchor{gnat_ugn/gnat_and_program_execution id22}@anchor{174} @subsubsection Compilation for profiling @@ -19487,7 +19487,7 @@ be profiled; if you need to profile your whole project, use the @code{-f} gnatmake switch to force full recompilation. @node Program execution,Running gprof,Compilation for profiling,Profiling an Ada Program with gprof -@anchor{gnat_ugn/gnat_and_program_execution program-execution}@anchor{175}@anchor{gnat_ugn/gnat_and_program_execution id23}@anchor{176} +@anchor{gnat_ugn/gnat_and_program_execution id23}@anchor{175}@anchor{gnat_ugn/gnat_and_program_execution program-execution}@anchor{176} @subsubsection Program execution @@ -19502,7 +19502,7 @@ generated in the directory where the program was launched from. If this file already exists, it will be overwritten. @node Running gprof,Interpretation of profiling results,Program execution,Profiling an Ada Program with gprof -@anchor{gnat_ugn/gnat_and_program_execution running-gprof}@anchor{177}@anchor{gnat_ugn/gnat_and_program_execution id24}@anchor{178} +@anchor{gnat_ugn/gnat_and_program_execution id24}@anchor{177}@anchor{gnat_ugn/gnat_and_program_execution running-gprof}@anchor{178} @subsubsection Running gprof @@ -19535,7 +19535,7 @@ $ gprof [switches] [executable [data-file]] @code{gprof} supports numerous switches. The order of these switch does not matter. The full list of options can be found in -the GNU Profiler User's Guide documentation that comes with this documentation. +the GNU Profiler User’s Guide documentation that comes with this documentation. The following is the subset of those switches that is most relevant: @@ -19564,7 +19564,7 @@ compiler, in particular Ada symbols generated by GNAT can be demangled using The @code{-e @emph{function}} option tells @code{gprof} not to print information about the function @code{function_name} (and its -children...) in the call graph. The function will still be listed +children…) in the call graph. The function will still be listed as a child of any functions that call it, but its index number will be shown as @code{[not printed]}. More than one @code{-e} option may be given; only one @code{function_name} may be indicated with each @code{-e} @@ -19594,7 +19594,7 @@ the call graph. More than one @code{-E} option may be given; only one The @code{-f @emph{function}} option causes @code{gprof} to limit the call graph to the function @code{function_name} and its children (and -their children...). More than one @code{-f} option may be given; +their children…). More than one @code{-f} option may be given; only one @code{function_name} may be indicated with each @code{-f} option. @end table @@ -19608,7 +19608,7 @@ option. The @code{-F @emph{function}} option works like the @code{-f} option, but only time spent in the function and its children (and their -children...) will be used to determine total-time and +children…) will be used to determine total-time and percentages-of-time for the call graph. More than one @code{-F} option may be given; only one @code{function_name} may be indicated with each @code{-F} option. The @code{-F} option overrides the @code{-E} option. @@ -19620,8 +19620,8 @@ may be given; only one @code{function_name} may be indicated with each The results of the profiling analysis are represented by two arrays: the -'flat profile' and the 'call graph'. Full documentation of those outputs -can be found in the GNU Profiler User's Guide. +‘flat profile’ and the ‘call graph’. Full documentation of those outputs +can be found in the GNU Profiler User’s Guide. The flat profile shows the time spent in each function of the program, and how many time it has been called. This allows you to locate easily the most @@ -19632,7 +19632,7 @@ and the subprograms that it calls. It also provides an estimate of the time spent in each of those callers/called subprograms. @node Improving Performance,Overflow Check Handling in GNAT,Profiling,GNAT and Program Execution -@anchor{gnat_ugn/gnat_and_program_execution improving-performance}@anchor{17b}@anchor{gnat_ugn/gnat_and_program_execution id26}@anchor{148} +@anchor{gnat_ugn/gnat_and_program_execution id26}@anchor{148}@anchor{gnat_ugn/gnat_and_program_execution improving-performance}@anchor{17b} @section Improving Performance @@ -19653,7 +19653,7 @@ which can reduce the size of program executables. @end menu @node Performance Considerations,Text_IO Suggestions,,Improving Performance -@anchor{gnat_ugn/gnat_and_program_execution performance-considerations}@anchor{17c}@anchor{gnat_ugn/gnat_and_program_execution id27}@anchor{17d} +@anchor{gnat_ugn/gnat_and_program_execution id27}@anchor{17c}@anchor{gnat_ugn/gnat_and_program_execution performance-considerations}@anchor{17d} @subsection Performance Considerations @@ -19714,7 +19714,7 @@ some guidelines on debugging optimized code. @end menu @node Controlling Run-Time Checks,Use of Restrictions,,Performance Considerations -@anchor{gnat_ugn/gnat_and_program_execution id28}@anchor{17e}@anchor{gnat_ugn/gnat_and_program_execution controlling-run-time-checks}@anchor{17f} +@anchor{gnat_ugn/gnat_and_program_execution controlling-run-time-checks}@anchor{17e}@anchor{gnat_ugn/gnat_and_program_execution id28}@anchor{17f} @subsubsection Controlling Run-Time Checks @@ -19808,7 +19808,7 @@ possibility of an immediate abort at any point. @geindex -O (gcc) Without any optimization option, -the compiler's goal is to reduce the cost of +the compiler’s goal is to reduce the cost of compilation and to make debugging produce the expected results. Statements are independent: if you stop the program with a breakpoint between statements, you can then assign a new value to any variable or change @@ -19845,7 +19845,7 @@ generates unoptimized code but has the fastest compilation time. Note that many other compilers do substantial optimization even -if 'no optimization' is specified. With gcc, it is very unusual +if ‘no optimization’ is specified. With gcc, it is very unusual to use @code{-O0} for production if execution time is of any concern, since @code{-O0} means (almost) no optimization. This difference between gcc and other compilers should be kept in mind when @@ -19963,7 +19963,7 @@ These are the most common cases: @itemize * @item -@emph{The 'hopping Program Counter':} Repeated @code{step} or @code{next} +@emph{The ‘hopping Program Counter’:} Repeated @code{step} or @code{next} commands show the PC bouncing back and forth in the code. This may result from any of the following optimizations: @@ -19992,7 +19992,7 @@ expected side-effects. @end itemize @item -@emph{The 'big leap':} More commonly known as @emph{cross-jumping}, in which +@emph{The ‘big leap’:} More commonly known as @emph{cross-jumping}, in which two identical pieces of code are merged and the program counter suddenly jumps to a statement that is not supposed to be executed, simply because it (and the code following) translates to the same thing as the code @@ -20001,7 +20001,7 @@ sequences that end in a jump, such as a @code{goto}, a @code{return}, or a @code{break} in a C @code{switch} statement. @item -@emph{The 'roving variable':} The symptom is an unexpected value in a variable. +@emph{The ‘roving variable’:} The symptom is an unexpected value in a variable. There are various reasons for this effect: @@ -20009,7 +20009,7 @@ There are various reasons for this effect: @item In a subprogram prologue, a parameter may not yet have been moved to its -'home'. +‘home’. @item A variable may be dead, and its register re-used. This is @@ -20038,7 +20038,7 @@ values (one must apply the procedure recursively to those other values); or re-running the code and stopping a little earlier (perhaps before the call) and stepping to better see how the variable obtained the value in question; or continuing to step @emph{from} the point of the -strange value to see if code motion had simply moved the variable's +strange value to see if code motion had simply moved the variable’s assignments later. @end itemize @@ -20254,7 +20254,7 @@ by default at this level, using @code{-O3} directly is recommended. You also need to make sure that the target architecture features a supported SIMD instruction set. For example, for the x86 architecture, you should at -least specify @code{-msse2} to get significant vectorization (but you don't +least specify @code{-msse2} to get significant vectorization (but you don’t need to specify it for x86-64 as it is part of the base 64-bit architecture). Similarly, for the PowerPC architecture, you should specify @code{-maltivec}. @@ -20391,7 +20391,7 @@ placed immediately within the loop will tell the compiler that it can safely omit the non-vectorized version of the loop as well as the run-time test. @node Other Optimization Switches,Optimization and Strict Aliasing,Vectorization of loops,Performance Considerations -@anchor{gnat_ugn/gnat_and_program_execution other-optimization-switches}@anchor{18a}@anchor{gnat_ugn/gnat_and_program_execution id35}@anchor{18b} +@anchor{gnat_ugn/gnat_and_program_execution id35}@anchor{18a}@anchor{gnat_ugn/gnat_and_program_execution other-optimization-switches}@anchor{18b} @subsubsection Other Optimization Switches @@ -20408,7 +20408,7 @@ the @emph{Submodel Options} section in the @emph{Hardware Models and Configurati chapter of @cite{Using the GNU Compiler Collection (GCC)}. @node Optimization and Strict Aliasing,Aliased Variables and Optimization,Other Optimization Switches,Performance Considerations -@anchor{gnat_ugn/gnat_and_program_execution optimization-and-strict-aliasing}@anchor{e4}@anchor{gnat_ugn/gnat_and_program_execution id36}@anchor{18c} +@anchor{gnat_ugn/gnat_and_program_execution id36}@anchor{18c}@anchor{gnat_ugn/gnat_and_program_execution optimization-and-strict-aliasing}@anchor{e4} @subsubsection Optimization and Strict Aliasing @@ -20451,7 +20451,7 @@ In this example, since the variable @code{Int1V} can only access objects of type @code{Int1}, and @code{Int2V} can only access objects of type @code{Int2}, there is no possibility that the assignment to @code{Int2V.all} affects the value of @code{Int1V.all}. This means that -the compiler optimizer can "know" that the value @code{Int1V.all} is constant +the compiler optimizer can “know” that the value @code{Int1V.all} is constant for all iterations of the loop and avoid the extra memory reference required to dereference it each time through the loop. @@ -20505,7 +20505,7 @@ end; @end quotation This program prints out 0 in @code{-O0} or @code{-O1} -mode, but it prints out 1 in @code{-O2} mode. That's +mode, but it prints out 1 in @code{-O2} mode. That’s because in strict aliasing mode, the compiler can and does assume that the assignment to @code{v2.all} could not affect the value of @code{v1.all}, since different types @@ -20515,7 +20515,7 @@ This behavior is not a case of non-conformance with the standard, since the Ada RM specifies that an unchecked conversion where the resulting bit pattern is not a correct value of the target type can result in an abnormal value and attempting to reference an abnormal value makes the -execution of a program erroneous. That's the case here since the result +execution of a program erroneous. That’s the case here since the result does not point to an object of type @code{int2}. This means that the effect is entirely unpredictable. @@ -20538,7 +20538,7 @@ p2.adb:5:07: warning: or use "pragma No_Strict_Aliasing (a2);" @end quotation Unfortunately the problem is recognized when compiling the body of -package @code{p2}, but the actual "bad" code is generated while +package @code{p2}, but the actual “bad” code is generated while compiling the body of @code{m} and this latter compilation does not see the suspicious @code{Unchecked_Conversion}. @@ -20559,7 +20559,7 @@ the switch can be painful, so a more reasonable approach is to compile the entire program with options @code{-O2} and @code{-fno-strict-aliasing}. If the performance is satisfactory with this combination of options, then the -advantage is that the entire issue of possible "wrong" +advantage is that the entire issue of possible “wrong” optimization due to strict aliasing is avoided. To avoid the use of compiler switches, the configuration @@ -20597,7 +20597,7 @@ conversion to the unit in which the type is declared. In this example, we would move the instantiation of @code{Unchecked_Conversion} from the body of package @code{p2} to the spec of package @code{p1}. Now the -warning disappears. That's because any use of the +warning disappears. That’s because any use of the access type knows there is a suspicious unchecked conversion, and the strict aliasing optimization is automatically suppressed for the type. @@ -20638,7 +20638,7 @@ application code where the time is increased by up to 5% by turning this optimization off. If you have code that includes significant usage of unchecked conversion, you might want to just stick with @code{-O1} and avoid the entire issue. If you get adequate -performance at this level of optimization level, that's probably +performance at this level of optimization level, that’s probably the safest approach. If tests show that you really need higher levels of optimization, then you can experiment with @code{-O2} and @code{-O2 -fno-strict-aliasing} to see how much effect this @@ -20648,7 +20648,7 @@ review any uses of unchecked conversion of access types, particularly if you are getting the warnings described above. @node Aliased Variables and Optimization,Atomic Variables and Optimization,Optimization and Strict Aliasing,Performance Considerations -@anchor{gnat_ugn/gnat_and_program_execution id37}@anchor{18d}@anchor{gnat_ugn/gnat_and_program_execution aliased-variables-and-optimization}@anchor{18e} +@anchor{gnat_ugn/gnat_and_program_execution aliased-variables-and-optimization}@anchor{18d}@anchor{gnat_ugn/gnat_and_program_execution id37}@anchor{18e} @subsubsection Aliased Variables and Optimization @@ -20659,7 +20659,7 @@ use low level techniques to modify variables that otherwise might be considered to be unassigned. For example, a variable can be passed to a procedure by reference, which takes the address of the parameter and uses the address to modify the -variable's value, even though it is passed as an IN parameter. +variable’s value, even though it is passed as an IN parameter. Consider the following example: @quotation @@ -20699,10 +20699,10 @@ seems to work with no optimization to start failing at high levels of optimzization. What the compiler does for such cases is to assume that marking -a variable as aliased indicates that some "funny business" may +a variable as aliased indicates that some “funny business” may be going on. The optimizer recognizes the aliased keyword and inhibits optimizations that assume the value cannot be assigned. -This means that the above example will in fact "work" reliably, +This means that the above example will in fact “work” reliably, that is, it will produce the expected results. @node Atomic Variables and Optimization,Passive Task Optimization,Aliased Variables and Optimization,Performance Considerations @@ -20773,7 +20773,7 @@ Now the reference to RV must read the whole variable. Actually one can imagine some compiler which figures out that the whole copy is not required (because only the B field is actually accessed), but GNAT -certainly won't do that, and we don't know of any +certainly won’t do that, and we don’t know of any compiler that would not handle this right, and the above code will in practice work portably across all architectures (that permit the Atomic declaration). @@ -20787,7 +20787,7 @@ such synchronization code is not required, it may be useful to disable it. @node Passive Task Optimization,,Atomic Variables and Optimization,Performance Considerations -@anchor{gnat_ugn/gnat_and_program_execution passive-task-optimization}@anchor{191}@anchor{gnat_ugn/gnat_and_program_execution id39}@anchor{192} +@anchor{gnat_ugn/gnat_and_program_execution id39}@anchor{191}@anchor{gnat_ugn/gnat_and_program_execution passive-task-optimization}@anchor{192} @subsubsection Passive Task Optimization @@ -20811,7 +20811,7 @@ operations will be optimized, and furthermore this optimized performance is fully portable. Although it would theoretically be possible for GNAT to attempt to -do this optimization, but it really doesn't make sense in the +do this optimization, but it really doesn’t make sense in the context of Ada 95, and none of the Ada 95 compilers implement this optimization as far as we know. In particular GNAT never attempts to perform this optimization. @@ -20832,7 +20832,7 @@ that typically clients of the tasks who call entries, will not have to be modified, only the task definition itself. @node Text_IO Suggestions,Reducing Size of Executables with Unused Subprogram/Data Elimination,Performance Considerations,Improving Performance -@anchor{gnat_ugn/gnat_and_program_execution text-io-suggestions}@anchor{193}@anchor{gnat_ugn/gnat_and_program_execution id40}@anchor{194} +@anchor{gnat_ugn/gnat_and_program_execution id40}@anchor{193}@anchor{gnat_ugn/gnat_and_program_execution text-io-suggestions}@anchor{194} @subsection @code{Text_IO} Suggestions @@ -20872,7 +20872,7 @@ your executable just by setting options at compilation time. @end menu @node About unused subprogram/data elimination,Compilation options,,Reducing Size of Executables with Unused Subprogram/Data Elimination -@anchor{gnat_ugn/gnat_and_program_execution id42}@anchor{197}@anchor{gnat_ugn/gnat_and_program_execution about-unused-subprogram-data-elimination}@anchor{198} +@anchor{gnat_ugn/gnat_and_program_execution about-unused-subprogram-data-elimination}@anchor{197}@anchor{gnat_ugn/gnat_and_program_execution id42}@anchor{198} @subsubsection About unused subprogram/data elimination @@ -20888,7 +20888,7 @@ architecture and on all cross platforms using the ELF binary file format. In both cases GNU binutils version 2.16 or later are required to enable it. @node Compilation options,Example of unused subprogram/data elimination,About unused subprogram/data elimination,Reducing Size of Executables with Unused Subprogram/Data Elimination -@anchor{gnat_ugn/gnat_and_program_execution id43}@anchor{199}@anchor{gnat_ugn/gnat_and_program_execution compilation-options}@anchor{19a} +@anchor{gnat_ugn/gnat_and_program_execution compilation-options}@anchor{199}@anchor{gnat_ugn/gnat_and_program_execution id43}@anchor{19a} @subsubsection Compilation options @@ -21013,7 +21013,7 @@ This section explains how to control the handling of overflow checks. @end menu @node Background,Management of Overflows in GNAT,,Overflow Check Handling in GNAT -@anchor{gnat_ugn/gnat_and_program_execution id46}@anchor{19e}@anchor{gnat_ugn/gnat_and_program_execution background}@anchor{19f} +@anchor{gnat_ugn/gnat_and_program_execution background}@anchor{19e}@anchor{gnat_ugn/gnat_and_program_execution id46}@anchor{19f} @subsection Background @@ -21090,7 +21090,7 @@ and then the application is moved to a compiler where the check is performed on the intermediate result and an unexpected exception is raised. -Furthermore, when using Ada 2012's preconditions and other +Furthermore, when using Ada 2012’s preconditions and other assertion forms, another issue arises. Consider: @quotation @@ -21148,7 +21148,7 @@ mathematical versus run-time interpretation of the expressions in assertions, GNAT provides comprehensive control over the handling of intermediate overflow. GNAT can operate in three modes, and furthemore, permits separate selection of operating modes for -the expressions within assertions (here the term 'assertions' +the expressions within assertions (here the term ‘assertions’ is used in the technical sense, which includes preconditions and so forth) and for expressions appearing outside assertions. @@ -21253,7 +21253,7 @@ out in the normal manner (with infinite values always failing all range checks). @node Specifying the Desired Mode,Default Settings,Management of Overflows in GNAT,Overflow Check Handling in GNAT -@anchor{gnat_ugn/gnat_and_program_execution specifying-the-desired-mode}@anchor{e9}@anchor{gnat_ugn/gnat_and_program_execution id48}@anchor{1a2} +@anchor{gnat_ugn/gnat_and_program_execution id48}@anchor{1a2}@anchor{gnat_ugn/gnat_and_program_execution specifying-the-desired-mode}@anchor{e9} @subsection Specifying the Desired Mode @@ -21302,8 +21302,8 @@ pragma Overflow_Mode @end quotation specifies that general expressions outside assertions be evaluated -in 'minimize intermediate overflows' mode, and expressions within -assertions be evaluated in 'eliminate intermediate overflows' mode. +in ‘minimize intermediate overflows’ mode, and expressions within +assertions be evaluated in ‘eliminate intermediate overflows’ mode. This is often a reasonable choice, avoiding excessive overhead outside assertions, but assuring a high degree of portability when importing code from another compiler, while incurring @@ -21377,7 +21377,7 @@ causing all intermediate operations to be computed using the base type (@code{STRICT} mode). @node Default Settings,Implementation Notes,Specifying the Desired Mode,Overflow Check Handling in GNAT -@anchor{gnat_ugn/gnat_and_program_execution id49}@anchor{1a3}@anchor{gnat_ugn/gnat_and_program_execution default-settings}@anchor{1a4} +@anchor{gnat_ugn/gnat_and_program_execution default-settings}@anchor{1a3}@anchor{gnat_ugn/gnat_and_program_execution id49}@anchor{1a4} @subsection Default Settings @@ -21424,7 +21424,7 @@ checking, but it has no effect on the method used for computing intermediate results. @node Implementation Notes,,Default Settings,Overflow Check Handling in GNAT -@anchor{gnat_ugn/gnat_and_program_execution implementation-notes}@anchor{1a5}@anchor{gnat_ugn/gnat_and_program_execution id50}@anchor{1a6} +@anchor{gnat_ugn/gnat_and_program_execution id50}@anchor{1a5}@anchor{gnat_ugn/gnat_and_program_execution implementation-notes}@anchor{1a6} @subsection Implementation Notes @@ -21472,7 +21472,7 @@ platforms for which @code{Long_Long_Integer} is 64-bits (nearly all GNAT platforms). @node Performing Dimensionality Analysis in GNAT,Stack Related Facilities,Overflow Check Handling in GNAT,GNAT and Program Execution -@anchor{gnat_ugn/gnat_and_program_execution performing-dimensionality-analysis-in-gnat}@anchor{1a7}@anchor{gnat_ugn/gnat_and_program_execution id51}@anchor{14a} +@anchor{gnat_ugn/gnat_and_program_execution id51}@anchor{14a}@anchor{gnat_ugn/gnat_and_program_execution performing-dimensionality-analysis-in-gnat}@anchor{1a7} @section Performing Dimensionality Analysis in GNAT @@ -21706,7 +21706,7 @@ aspect. @end quotation The @code{Dimension} aspect of a dimensioned subtype @code{S} defines a mapping -from the base type's Unit_Names to integer (or, more generally, rational) +from the base type’s Unit_Names to integer (or, more generally, rational) values. This mapping is the @emph{dimension vector} (also referred to as the @emph{dimensionality}) for that subtype, denoted by @code{DV(S)}, and thus for each object of that subtype. Intuitively, the value specified for each @@ -21749,7 +21749,7 @@ then @emph{expr} is dimensionless; @code{DV(@emph{expr})} is the empty vector. @code{DV(@emph{op expr})}, where @emph{op} is a unary operator, is @code{DV(@emph{expr})} @item -@code{DV(@emph{expr1 op expr2})} where @emph{op} is "+" or "-" is @code{DV(@emph{expr1})} +@code{DV(@emph{expr1 op expr2})} where @emph{op} is “+” or “-” is @code{DV(@emph{expr1})} provided that @code{DV(@emph{expr1})} = @code{DV(@emph{expr2})}. If this condition is not met then the construct is illegal. @@ -21765,13 +21765,13 @@ provided that @emph{power} is a static rational value. If this condition is not met then the construct is illegal. @end itemize -Note that, by the above rules, it is illegal to use binary "+" or "-" to +Note that, by the above rules, it is illegal to use binary “+” or “-” to combine a dimensioned and dimensionless value. Thus an expression such as @code{acc-10.0} is illegal, where @code{acc} is an object of subtype @code{Acceleration}. The dimensionality checks for relationals use the same rules as -for "+" and "-", except when comparing to a literal; thus +for “+” and “-“, except when comparing to a literal; thus @quotation @@ -21826,7 +21826,7 @@ converted, for example, to a mass in pounds. If @code{T} is the base type for @emph{expr} (and the dimensionless root type of the dimension system), then @code{DV(T(@emph{expr}))} is @code{DV(expr)}. Thus, if @emph{expr} is of a dimensioned subtype of @code{T}, the conversion may -be regarded as a "view conversion" that preserves dimensionality. +be regarded as a “view conversion” that preserves dimensionality. This rule makes it possible to write generic code that can be instantiated with compatible dimensioned subtypes. The generic unit will contain @@ -21859,7 +21859,7 @@ passing (the dimension vector for the actual parameter must be equal to the dimension vector for the formal parameter). @node Stack Related Facilities,Memory Management Issues,Performing Dimensionality Analysis in GNAT,GNAT and Program Execution -@anchor{gnat_ugn/gnat_and_program_execution stack-related-facilities}@anchor{1a8}@anchor{gnat_ugn/gnat_and_program_execution id52}@anchor{14b} +@anchor{gnat_ugn/gnat_and_program_execution id52}@anchor{14b}@anchor{gnat_ugn/gnat_and_program_execution stack-related-facilities}@anchor{1a8} @section Stack Related Facilities @@ -21889,7 +21889,7 @@ some other task exceeds the available stack space, then unpredictable behavior will occur. Most native systems offer some level of protection by adding a guard page at the end of each task stack. This mechanism is usually not enough for dealing properly with stack overflow situations because -a large local variable could "jump" above the guard page. +a large local variable could “jump” above the guard page. Furthermore, when the guard page is hit, there may not be any space left on the stack for executing the exception propagation code. Enabling stack checking avoids @@ -21969,7 +21969,7 @@ subprogram whose stack usage might be larger than the specified amount of bytes. The wording is in keeping with the qualifier documented above. @node Dynamic Stack Usage Analysis,,Static Stack Usage Analysis,Stack Related Facilities -@anchor{gnat_ugn/gnat_and_program_execution id55}@anchor{1ab}@anchor{gnat_ugn/gnat_and_program_execution dynamic-stack-usage-analysis}@anchor{113} +@anchor{gnat_ugn/gnat_and_program_execution dynamic-stack-usage-analysis}@anchor{113}@anchor{gnat_ugn/gnat_and_program_execution id55}@anchor{1ab} @subsection Dynamic Stack Usage Analysis @@ -22028,7 +22028,7 @@ where: @item @emph{Stack Usage} is the measure done by the stack analyzer. In order to prevent overflow, the stack -is not entirely analyzed, and it's not possible to know exactly how +is not entirely analyzed, and it’s not possible to know exactly how much has actually been used. @end itemize @@ -22057,7 +22057,7 @@ stack-usage reports at run time. See its body for the details. This section describes some useful memory pools provided in the GNAT library and in particular the GNAT Debug Pool facility, which can be used to detect -incorrect uses of access values (including 'dangling references'). +incorrect uses of access values (including ‘dangling references’). @menu @@ -22311,7 +22311,7 @@ Debug Pool info: @c -- E.g. Ada |nbsp| 95 @node Platform-Specific Information,Example of Binder Output File,GNAT and Program Execution,Top -@anchor{gnat_ugn/platform_specific_information platform-specific-information}@anchor{d}@anchor{gnat_ugn/platform_specific_information doc}@anchor{1b1}@anchor{gnat_ugn/platform_specific_information id1}@anchor{1b2} +@anchor{gnat_ugn/platform_specific_information doc}@anchor{1b1}@anchor{gnat_ugn/platform_specific_information id1}@anchor{1b2}@anchor{gnat_ugn/platform_specific_information platform-specific-information}@anchor{d} @chapter Platform-Specific Information @@ -22357,7 +22357,7 @@ For exception handling, either or both of two models are supplied: @itemize * @item -@strong{Zero-Cost Exceptions} ("ZCX"), +@strong{Zero-Cost Exceptions} (“ZCX”), which uses binder-generated tables that are interrogated at run time to locate a handler. @@ -22366,7 +22366,7 @@ are interrogated at run time to locate a handler. @geindex SJLJ (setjmp/longjmp Exception Model) @item -@strong{setjmp / longjmp} ('SJLJ'), +@strong{setjmp / longjmp} (‘SJLJ’), which uses dynamically-set data to establish the set of handlers @end itemize @@ -22390,7 +22390,7 @@ are supplied on various GNAT platforms. @end menu @node Summary of Run-Time Configurations,,,Run-Time Libraries -@anchor{gnat_ugn/platform_specific_information summary-of-run-time-configurations}@anchor{1b5}@anchor{gnat_ugn/platform_specific_information id3}@anchor{1b6} +@anchor{gnat_ugn/platform_specific_information id3}@anchor{1b5}@anchor{gnat_ugn/platform_specific_information summary-of-run-time-configurations}@anchor{1b6} @subsection Summary of Run-Time Configurations @@ -22490,7 +22490,7 @@ ZCX @node Specifying a Run-Time Library,GNU/Linux Topics,Run-Time Libraries,Platform-Specific Information -@anchor{gnat_ugn/platform_specific_information specifying-a-run-time-library}@anchor{1b7}@anchor{gnat_ugn/platform_specific_information id4}@anchor{1b8} +@anchor{gnat_ugn/platform_specific_information id4}@anchor{1b7}@anchor{gnat_ugn/platform_specific_information specifying-a-run-time-library}@anchor{1b8} @section Specifying a Run-Time Library @@ -22641,7 +22641,7 @@ Ignore : constant Boolean := @end example @end quotation -It gets the effective user id, and if it's not 0 (i.e. root), it raises +It gets the effective user id, and if it’s not 0 (i.e. root), it raises Program_Error. @geindex Linux @@ -22649,7 +22649,7 @@ Program_Error. @geindex GNU/Linux @node GNU/Linux Topics,Microsoft Windows Topics,Specifying a Run-Time Library,Platform-Specific Information -@anchor{gnat_ugn/platform_specific_information id6}@anchor{1bb}@anchor{gnat_ugn/platform_specific_information gnu-linux-topics}@anchor{1bc} +@anchor{gnat_ugn/platform_specific_information gnu-linux-topics}@anchor{1bb}@anchor{gnat_ugn/platform_specific_information id6}@anchor{1bc} @section GNU/Linux Topics @@ -22665,7 +22665,7 @@ This section describes topics that are specific to GNU/Linux platforms. @subsection Required Packages on GNU/Linux -GNAT requires the C library developer's package to be installed. +GNAT requires the C library developer’s package to be installed. The name of of that package depends on your GNU/Linux distribution: @@ -22679,7 +22679,7 @@ Debian, Ubuntu: @code{libc6-dev} (normally installed by default). @end itemize If using the 32-bit version of GNAT on a 64-bit version of GNU/Linux, -you'll need the 32-bit version of the following packages: +you’ll need the 32-bit version of the following packages: @itemize * @@ -22697,7 +22697,7 @@ for those packages. @geindex Windows @node Microsoft Windows Topics,Mac OS Topics,GNU/Linux Topics,Platform-Specific Information -@anchor{gnat_ugn/platform_specific_information microsoft-windows-topics}@anchor{1bf}@anchor{gnat_ugn/platform_specific_information id8}@anchor{1c0} +@anchor{gnat_ugn/platform_specific_information id8}@anchor{1bf}@anchor{gnat_ugn/platform_specific_information microsoft-windows-topics}@anchor{1c0} @section Microsoft Windows Topics @@ -22718,7 +22718,7 @@ platforms. @end menu @node Using GNAT on Windows,Using a network installation of GNAT,,Microsoft Windows Topics -@anchor{gnat_ugn/platform_specific_information using-gnat-on-windows}@anchor{1c1}@anchor{gnat_ugn/platform_specific_information id9}@anchor{1c2} +@anchor{gnat_ugn/platform_specific_information id9}@anchor{1c1}@anchor{gnat_ugn/platform_specific_information using-gnat-on-windows}@anchor{1c2} @subsection Using GNAT on Windows @@ -22777,7 +22777,7 @@ import libraries. Interfacing must be done by the mean of DLLs. @item It is possible to link against Microsoft C libraries. Yet the preferred solution is to use C/C++ compiler that comes with GNAT, since it -doesn't require having two different development environments and makes the +doesn’t require having two different development environments and makes the inter-language debugging experience smoother. @item @@ -22822,7 +22822,7 @@ transfer of large amounts of data across the network and will likely cause serious performance penalty. @node CONSOLE and WINDOWS subsystems,Temporary Files,Using a network installation of GNAT,Microsoft Windows Topics -@anchor{gnat_ugn/platform_specific_information id11}@anchor{1c5}@anchor{gnat_ugn/platform_specific_information console-and-windows-subsystems}@anchor{1c6} +@anchor{gnat_ugn/platform_specific_information console-and-windows-subsystems}@anchor{1c5}@anchor{gnat_ugn/platform_specific_information id11}@anchor{1c6} @subsection CONSOLE and WINDOWS subsystems @@ -23087,7 +23087,7 @@ native SEH support is used. @end menu @node Windows Calling Conventions,Introduction to Dynamic Link Libraries DLLs,,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information windows-calling-conventions}@anchor{1cf}@anchor{gnat_ugn/platform_specific_information id14}@anchor{1d0} +@anchor{gnat_ugn/platform_specific_information id14}@anchor{1cf}@anchor{gnat_ugn/platform_specific_information windows-calling-conventions}@anchor{1d0} @subsubsection Windows Calling Conventions @@ -23100,9 +23100,9 @@ calling convention. All convention specifiers are ignored on this platform. When a subprogram @code{F} (caller) calls a subprogram @code{G} -(callee), there are several ways to push @code{G}'s parameters on the +(callee), there are several ways to push @code{G}’s parameters on the stack and there are several possible scenarios to clean up the stack -upon @code{G}'s return. A calling convention is an agreed upon software +upon @code{G}’s return. A calling convention is an agreed upon software protocol whereby the responsibilities between the caller (@code{F}) and the callee (@code{G}) are clearly defined. Several calling conventions are available for Windows: @@ -23177,7 +23177,7 @@ DLL (in which case you should use the @code{Stdcall} calling convention, @ref{1d3,,Stdcall Calling Convention}). @node Stdcall Calling Convention,Win32 Calling Convention,C Calling Convention,Windows Calling Conventions -@anchor{gnat_ugn/platform_specific_information stdcall-calling-convention}@anchor{1d3}@anchor{gnat_ugn/platform_specific_information id16}@anchor{1d4} +@anchor{gnat_ugn/platform_specific_information id16}@anchor{1d4}@anchor{gnat_ugn/platform_specific_information stdcall-calling-convention}@anchor{1d3} @subsubsection @code{Stdcall} Calling Convention @@ -23245,7 +23245,7 @@ then the imported routine is @code{retrieve_val}, that is, there is no decoration at all. No leading underscore and no Stdcall suffix @code{@@@emph{nn}}. -This is especially important as in some special cases a DLL's entry +This is especially important as in some special cases a DLL’s entry point name lacks a trailing @code{@@@emph{nn}} while the exported name generated for a call has it. @@ -23274,7 +23274,7 @@ Note that to ease building cross-platform bindings this convention will be handled as a @code{C} calling convention on non-Windows platforms. @node Win32 Calling Convention,DLL Calling Convention,Stdcall Calling Convention,Windows Calling Conventions -@anchor{gnat_ugn/platform_specific_information win32-calling-convention}@anchor{1d5}@anchor{gnat_ugn/platform_specific_information id17}@anchor{1d6} +@anchor{gnat_ugn/platform_specific_information id17}@anchor{1d5}@anchor{gnat_ugn/platform_specific_information win32-calling-convention}@anchor{1d6} @subsubsection @code{Win32} Calling Convention @@ -23282,7 +23282,7 @@ This convention, which is GNAT-specific is fully equivalent to the @code{Stdcall} calling convention described above. @node DLL Calling Convention,,Win32 Calling Convention,Windows Calling Conventions -@anchor{gnat_ugn/platform_specific_information id18}@anchor{1d7}@anchor{gnat_ugn/platform_specific_information dll-calling-convention}@anchor{1d8} +@anchor{gnat_ugn/platform_specific_information dll-calling-convention}@anchor{1d7}@anchor{gnat_ugn/platform_specific_information id18}@anchor{1d8} @subsubsection @code{DLL} Calling Convention @@ -23367,7 +23367,7 @@ application, a conflict will occur and the application will run incorrectly. Hence, when possible, it is always preferable to use and build relocatable DLLs. Both relocatable and non-relocatable DLLs are supported by GNAT. Note that the @code{-s} linker option (see GNU Linker -User's Guide) removes the debugging symbols from the DLL but the DLL can +User’s Guide) removes the debugging symbols from the DLL but the DLL can still be relocated. As a side note, an interesting difference between Microsoft DLLs and @@ -23396,7 +23396,7 @@ header files provided with the DLL. The import library (@code{libAPI.dll.a} or @code{API.lib}). As previously mentioned an import library is a statically linked library containing the import table which will be filled at load time to point to the actual -@code{API.dll} routines. Sometimes you don't have an import library for the +@code{API.dll} routines. Sometimes you don’t have an import library for the DLL you want to use. The following sections will explain how to build one. Note that this is optional. @@ -23468,7 +23468,7 @@ example a fictitious DLL called @code{API.dll}. @end menu @node Creating an Ada Spec for the DLL Services,Creating an Import Library,,Using DLLs with GNAT -@anchor{gnat_ugn/platform_specific_information id21}@anchor{1dd}@anchor{gnat_ugn/platform_specific_information creating-an-ada-spec-for-the-dll-services}@anchor{1de} +@anchor{gnat_ugn/platform_specific_information creating-an-ada-spec-for-the-dll-services}@anchor{1dd}@anchor{gnat_ugn/platform_specific_information id21}@anchor{1de} @subsubsection Creating an Ada Spec for the DLL Services @@ -23508,7 +23508,7 @@ end API; @end quotation @node Creating an Import Library,,Creating an Ada Spec for the DLL Services,Using DLLs with GNAT -@anchor{gnat_ugn/platform_specific_information id22}@anchor{1df}@anchor{gnat_ugn/platform_specific_information creating-an-import-library}@anchor{1e0} +@anchor{gnat_ugn/platform_specific_information creating-an-import-library}@anchor{1df}@anchor{gnat_ugn/platform_specific_information id22}@anchor{1e0} @subsubsection Creating an Import Library @@ -23570,7 +23570,7 @@ EXPORTS @end table Note that you must specify the correct suffix (@code{@@@emph{nn}}) -(see @ref{1cf,,Windows Calling Conventions}) for a Stdcall +(see @ref{1d0,,Windows Calling Conventions}) for a Stdcall calling convention function in the exported symbols list. There can actually be other sections in a definition file, but these @@ -23590,8 +23590,8 @@ $ dlltool API.dll -z API.def --export-all-symbols @end example Note that if some routines in the DLL have the @code{Stdcall} convention -(@ref{1cf,,Windows Calling Conventions}) with stripped @code{@@@emph{nn}} -suffix then you'll have to edit @code{api.def} to add it, and specify +(@ref{1d0,,Windows Calling Conventions}) with stripped @code{@@@emph{nn}} +suffix then you’ll have to edit @code{api.def} to add it, and specify @code{-k} to @code{gnatdll} when creating the import library. Here are some hints to find the right @code{@@@emph{nn}} suffix. @@ -23648,7 +23648,7 @@ tools (@ref{1cc,,Mixed-Language Programming on Windows}). To create a Microsoft-style import library for @code{API.dll} you should create the .def file, then build the actual import library using -Microsoft's @code{lib} utility: +Microsoft’s @code{lib} utility: @quotation @@ -23668,7 +23668,7 @@ See the Microsoft documentation for further details about the usage of @end quotation @node Building DLLs with GNAT Project files,Building DLLs with GNAT,Using DLLs with GNAT,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information id23}@anchor{1e5}@anchor{gnat_ugn/platform_specific_information building-dlls-with-gnat-project-files}@anchor{1ce} +@anchor{gnat_ugn/platform_specific_information building-dlls-with-gnat-project-files}@anchor{1ce}@anchor{gnat_ugn/platform_specific_information id23}@anchor{1e5} @subsubsection Building DLLs with GNAT Project files @@ -23677,7 +23677,7 @@ See the Microsoft documentation for further details about the usage of There is nothing specific to Windows in the build process. See the @emph{Library Projects} section in the @emph{GNAT Project Manager} -chapter of the @emph{GPRbuild User's Guide}. +chapter of the @emph{GPRbuild User’s Guide}. Due to a system limitation, it is not possible under Windows to create threads when inside the @code{DllMain} routine which is used for auto-initialization @@ -23724,7 +23724,7 @@ $ gcc -shared -shared-libgcc -o api.dll api.def obj1.o obj2.o ... If you use a definition file you must export the elaboration procedures for every package that required one. Elaboration procedures are named -using the package name followed by "_E". +using the package name followed by “_E”. @item Preparing DLL to be used. @@ -23813,7 +23813,7 @@ binutils tool will not be relocatable anymore. To build a DLL without debug information pass @code{-largs -s} to @code{gnatdll}. This restriction does not apply to a DLL built using a Library Project. See the @emph{Library Projects} section in the @emph{GNAT Project Manager} -chapter of the @emph{GPRbuild User's Guide}. +chapter of the @emph{GPRbuild User’s Guide}. @c Limitations_When_Using_Ada_DLLs_from Ada: @@ -23975,12 +23975,12 @@ directly from @code{DllMain} without having to provide an explicit initialization routine. Unfortunately, it is not possible to call @code{adainit} from the @code{DllMain} if your program has library level tasks because access to the @code{DllMain} entry point is serialized by -the system (that is, only a single thread can execute 'through' it at a +the system (that is, only a single thread can execute ‘through’ it at a time), which means that the GNAT run-time will deadlock waiting for the newly created task to complete its initialization. @node Ada DLLs and Finalization,Creating a Spec for Ada DLLs,Building DLLs with gnatdll,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information id28}@anchor{1f1}@anchor{gnat_ugn/platform_specific_information ada-dlls-and-finalization}@anchor{1ec} +@anchor{gnat_ugn/platform_specific_information ada-dlls-and-finalization}@anchor{1ec}@anchor{gnat_ugn/platform_specific_information id28}@anchor{1f1} @subsubsection Ada DLLs and Finalization @@ -23998,7 +23998,7 @@ during the DLL build process by the @code{gnatdll} tool (@ref{1e3,,Using gnatdll}). @node Creating a Spec for Ada DLLs,GNAT and Windows Resources,Ada DLLs and Finalization,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information id29}@anchor{1f2}@anchor{gnat_ugn/platform_specific_information creating-a-spec-for-ada-dlls}@anchor{1f3} +@anchor{gnat_ugn/platform_specific_information creating-a-spec-for-ada-dlls}@anchor{1f2}@anchor{gnat_ugn/platform_specific_information id29}@anchor{1f3} @subsubsection Creating a Spec for Ada DLLs @@ -24092,7 +24092,7 @@ EXPORTS @end quotation @node Using gnatdll,,Creating the Definition File,Creating a Spec for Ada DLLs -@anchor{gnat_ugn/platform_specific_information using-gnatdll}@anchor{1e3}@anchor{gnat_ugn/platform_specific_information id31}@anchor{1f5} +@anchor{gnat_ugn/platform_specific_information id31}@anchor{1f5}@anchor{gnat_ugn/platform_specific_information using-gnatdll}@anchor{1e3} @subsubsection Using @code{gnatdll} @@ -24196,7 +24196,7 @@ object files needed to build the DLL. @item @code{-k} -Removes the @code{@@@emph{nn}} suffix from the import library's exported +Removes the @code{@@@emph{nn}} suffix from the import library’s exported names, but keeps them for the link names. You must specify this option if you want to use a @code{Stdcall} function in a DLL for which the @code{@@@emph{nn}} suffix has been removed. This is the case for most @@ -24401,7 +24401,7 @@ DLL in the static import library generated by @code{dlltool} with switch @item @code{-k} Kill @code{@@@emph{nn}} from exported names -(@ref{1cf,,Windows Calling Conventions} +(@ref{1d0,,Windows Calling Conventions} for a discussion about @code{Stdcall}-style symbols. @end table @@ -24614,7 +24614,7 @@ $ windres -i myres.res -o myres.o @end quotation @node Using Resources,,Compiling Resources,GNAT and Windows Resources -@anchor{gnat_ugn/platform_specific_information using-resources}@anchor{1fd}@anchor{gnat_ugn/platform_specific_information id35}@anchor{1fe} +@anchor{gnat_ugn/platform_specific_information id35}@anchor{1fd}@anchor{gnat_ugn/platform_specific_information using-resources}@anchor{1fe} @subsubsection Using Resources @@ -24652,7 +24652,7 @@ cookbook-style sequence of steps to follow: @item First develop and build the GNAT shared library using a library project -(let's assume the project is @code{mylib.gpr}, producing the library @code{libmylib.dll}): +(let’s assume the project is @code{mylib.gpr}, producing the library @code{libmylib.dll}): @end enumerate @quotation @@ -24695,7 +24695,7 @@ $ lib -machine:IX86 -def:libmylib.def -out:libmylib.lib @end example @end quotation -If you are using a 64-bit toolchain, the above becomes... +If you are using a 64-bit toolchain, the above becomes… @quotation @@ -24727,7 +24727,7 @@ or copy the DLL into into the directory containing the .exe. @end enumerate @node Debugging a DLL,Setting Stack Size from gnatlink,Using GNAT DLLs from Microsoft Visual Studio Applications,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information id36}@anchor{201}@anchor{gnat_ugn/platform_specific_information debugging-a-dll}@anchor{202} +@anchor{gnat_ugn/platform_specific_information debugging-a-dll}@anchor{201}@anchor{gnat_ugn/platform_specific_information id36}@anchor{202} @subsubsection Debugging a DLL @@ -24771,7 +24771,7 @@ tools suite used to build the DLL. This is the simplest case. Both the DLL and the program have @code{GDB} compatible debugging information. It is then possible to break anywhere in -the process. Let's suppose here that the main procedure is named +the process. Let’s suppose here that the main procedure is named @code{ada_main} and that in the DLL there is an entry point named @code{ada_dll}. @@ -24815,7 +24815,7 @@ you can use the standard approach to debug the whole program (@ref{14d,,Running and Debugging Ada Programs}). @node Program Built with Foreign Tools and DLL Built with GCC/GNAT,,Program and DLL Both Built with GCC/GNAT,Debugging a DLL -@anchor{gnat_ugn/platform_specific_information program-built-with-foreign-tools-and-dll-built-with-gcc-gnat}@anchor{205}@anchor{gnat_ugn/platform_specific_information id38}@anchor{206} +@anchor{gnat_ugn/platform_specific_information id38}@anchor{205}@anchor{gnat_ugn/platform_specific_information program-built-with-foreign-tools-and-dll-built-with-gcc-gnat}@anchor{206} @subsubsection Program Built with Foreign Tools and DLL Built with GCC/GNAT @@ -24926,7 +24926,7 @@ $ main @end example @item -Use the Windows @emph{Task Manager} to find the process ID. Let's say +Use the Windows @emph{Task Manager} to find the process ID. Let’s say that the process PID for @code{main.exe} is 208. @item @@ -24971,7 +24971,7 @@ approach to debug a program as described in @ref{14d,,Running and Debugging Ada Programs}. @node Setting Stack Size from gnatlink,Setting Heap Size from gnatlink,Debugging a DLL,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information setting-stack-size-from-gnatlink}@anchor{127}@anchor{gnat_ugn/platform_specific_information id39}@anchor{207} +@anchor{gnat_ugn/platform_specific_information id39}@anchor{207}@anchor{gnat_ugn/platform_specific_information setting-stack-size-from-gnatlink}@anchor{127} @subsubsection Setting Stack Size from @code{gnatlink} @@ -25014,7 +25014,7 @@ because the comma is a separator for this option. @end itemize @node Setting Heap Size from gnatlink,,Setting Stack Size from gnatlink,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information setting-heap-size-from-gnatlink}@anchor{128}@anchor{gnat_ugn/platform_specific_information id40}@anchor{208} +@anchor{gnat_ugn/platform_specific_information id40}@anchor{208}@anchor{gnat_ugn/platform_specific_information setting-heap-size-from-gnatlink}@anchor{128} @subsubsection Setting Heap Size from @code{gnatlink} @@ -25047,7 +25047,7 @@ because the comma is a separator for this option. @end itemize @node Windows Specific Add-Ons,,Mixed-Language Programming on Windows,Microsoft Windows Topics -@anchor{gnat_ugn/platform_specific_information windows-specific-add-ons}@anchor{209}@anchor{gnat_ugn/platform_specific_information win32-specific-addons}@anchor{20a} +@anchor{gnat_ugn/platform_specific_information win32-specific-addons}@anchor{209}@anchor{gnat_ugn/platform_specific_information windows-specific-add-ons}@anchor{20a} @subsection Windows Specific Add-Ons @@ -25060,7 +25060,7 @@ This section describes the Windows specific add-ons. @end menu @node Win32Ada,wPOSIX,,Windows Specific Add-Ons -@anchor{gnat_ugn/platform_specific_information win32ada}@anchor{20b}@anchor{gnat_ugn/platform_specific_information id41}@anchor{20c} +@anchor{gnat_ugn/platform_specific_information id41}@anchor{20b}@anchor{gnat_ugn/platform_specific_information win32ada}@anchor{20c} @subsubsection Win32Ada @@ -25081,7 +25081,7 @@ end P; @end quotation To build the application you just need to call gprbuild for the -application's project, here p.gpr: +application’s project, here p.gpr: @quotation @@ -25114,7 +25114,7 @@ end P; @end quotation To build the application you just need to call gprbuild for the -application's project, here p.gpr: +application’s project, here p.gpr: @quotation @@ -25124,13 +25124,13 @@ gprbuild p.gpr @end quotation @node Mac OS Topics,,Microsoft Windows Topics,Platform-Specific Information -@anchor{gnat_ugn/platform_specific_information mac-os-topics}@anchor{20f}@anchor{gnat_ugn/platform_specific_information id43}@anchor{210} +@anchor{gnat_ugn/platform_specific_information id43}@anchor{20f}@anchor{gnat_ugn/platform_specific_information mac-os-topics}@anchor{210} @section Mac OS Topics @geindex OS X -This section describes topics that are specific to Apple's OS X +This section describes topics that are specific to Apple’s OS X platform. @menu @@ -25166,7 +25166,7 @@ Start the Keychain Access application (in @item Select the Keychain Access -> Certificate Assistant -> -Create a Certificate... menu +Create a Certificate… menu @item Then: @@ -25176,28 +25176,28 @@ Then: @item Choose a name for the new certificate (this procedure will use -"gdb-cert" as an example) +“gdb-cert” as an example) @item -Set "Identity Type" to "Self Signed Root" +Set “Identity Type” to “Self Signed Root” @item -Set "Certificate Type" to "Code Signing" +Set “Certificate Type” to “Code Signing” @item -Activate the "Let me override defaults" option +Activate the “Let me override defaults” option @end itemize @item -Click several times on "Continue" until the "Specify a Location -For The Certificate" screen appears, then set "Keychain" to "System" +Click several times on “Continue” until the “Specify a Location +For The Certificate” screen appears, then set “Keychain” to “System” @item -Click on "Continue" until the certificate is created +Click on “Continue” until the certificate is created @item Finally, in the view, double-click on the new certificate, -and set "When using this certificate" to "Always Trust" +and set “When using this certificate” to “Always Trust” @item Exit the Keychain Access application and restart the computer @@ -25214,20 +25214,20 @@ $ codesign -f -s "gdb-cert" /bin/gdb @end example @end quotation -where "gdb-cert" should be replaced by the actual certificate +where “gdb-cert” should be replaced by the actual certificate name chosen above, and should be replaced by the location where you installed GNAT. Also, be sure that users are in the Unix group @code{_developer}. @node Example of Binder Output File,Elaboration Order Handling in GNAT,Platform-Specific Information,Top -@anchor{gnat_ugn/example_of_binder_output example-of-binder-output-file}@anchor{e}@anchor{gnat_ugn/example_of_binder_output doc}@anchor{212}@anchor{gnat_ugn/example_of_binder_output id1}@anchor{213} +@anchor{gnat_ugn/example_of_binder_output doc}@anchor{212}@anchor{gnat_ugn/example_of_binder_output example-of-binder-output-file}@anchor{e}@anchor{gnat_ugn/example_of_binder_output id1}@anchor{213} @chapter Example of Binder Output File @geindex Binder output (example) This Appendix displays the source code for the output file -generated by @emph{gnatbind} for a simple 'Hello World' program. +generated by @emph{gnatbind} for a simple ‘Hello World’ program. Comments have been added for clarification purposes. @example @@ -25972,7 +25972,7 @@ elaboration code in your own application). @c -- Example: A |withing| unit has a |with| clause, it |withs| a |withed| unit @node Elaboration Order Handling in GNAT,Inline Assembler,Example of Binder Output File,Top -@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-order-handling-in-gnat}@anchor{f}@anchor{gnat_ugn/elaboration_order_handling_in_gnat doc}@anchor{214}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id1}@anchor{215} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat doc}@anchor{214}@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-order-handling-in-gnat}@anchor{f}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id1}@anchor{215} @chapter Elaboration Order Handling in GNAT @@ -26284,11 +26284,11 @@ body of Main @end example @end quotation -The elaboration of @code{Server}'s spec materializes function @code{Func}, making it -callable. The elaboration of @code{Client}'s spec elaborates the declaration of +The elaboration of @code{Server}’s spec materializes function @code{Func}, making it +callable. The elaboration of @code{Client}’s spec elaborates the declaration of @code{Val}. This invokes function @code{Server.Func}, however the body of -@code{Server.Func} has not been elaborated yet because @code{Server}'s body comes -after @code{Client}'s spec in the elaboration order. As a result, the value of +@code{Server.Func} has not been elaborated yet because @code{Server}’s body comes +after @code{Client}’s spec in the elaboration order. As a result, the value of constant @code{Val} is now undefined. Without any guarantees from the language, an undetected ABE problem may hinder @@ -26319,7 +26319,7 @@ however a compiler may not always find such an order due to complications with respect to control and data flow. @node Checking the Elaboration Order,Controlling the Elaboration Order in Ada,Elaboration Order,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id4}@anchor{21a}@anchor{gnat_ugn/elaboration_order_handling_in_gnat checking-the-elaboration-order}@anchor{21b} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat checking-the-elaboration-order}@anchor{21a}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id4}@anchor{21b} @section Checking the Elaboration Order @@ -26447,7 +26447,7 @@ but still strong enough to prevent ABE problems within a unit. Pragma @code{Elaborate_Body} requires that the body of a unit is elaborated immediately after its spec. This restriction guarantees that no client scenario can invoke a server target before the target body has been -elaborated because the spec and body are effectively "glued" together. +elaborated because the spec and body are effectively “glued” together. @example package Server is @@ -26708,7 +26708,7 @@ is that the program continues to stay in the last state (one or more correct orders exist) even if maintenance changes the bodies of targets. @node Controlling the Elaboration Order in GNAT,Mixing Elaboration Models,Controlling the Elaboration Order in Ada,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id6}@anchor{21e}@anchor{gnat_ugn/elaboration_order_handling_in_gnat controlling-the-elaboration-order-in-gnat}@anchor{21f} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat controlling-the-elaboration-order-in-gnat}@anchor{21e}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id6}@anchor{21f} @section Controlling the Elaboration Order in GNAT @@ -26838,7 +26838,7 @@ The dynamic, legacy, and static models can be relaxed using compiler switch may not diagnose certain elaboration issues or install run-time checks. @node Mixing Elaboration Models,ABE Diagnostics,Controlling the Elaboration Order in GNAT,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat mixing-elaboration-models}@anchor{220}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id7}@anchor{221} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id7}@anchor{220}@anchor{gnat_ugn/elaboration_order_handling_in_gnat mixing-elaboration-models}@anchor{221} @section Mixing Elaboration Models @@ -26918,7 +26918,7 @@ end Guaranteed_ABE; @end example @end quotation -In the example above, the elaboration of @code{Guaranteed_ABE}'s body elaborates +In the example above, the elaboration of @code{Guaranteed_ABE}’s body elaborates the declaration of @code{Val}. This invokes function @code{ABE}, however the body of @code{ABE} has not been elaborated yet. GNAT emits the following diagnostic: @@ -26992,7 +26992,7 @@ declaration @code{Safe} because the body of function @code{ABE} has already been elaborated at that point. @node SPARK Diagnostics,Elaboration Circularities,ABE Diagnostics,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat spark-diagnostics}@anchor{224}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id9}@anchor{225} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id9}@anchor{224}@anchor{gnat_ugn/elaboration_order_handling_in_gnat spark-diagnostics}@anchor{225} @section SPARK Diagnostics @@ -27018,7 +27018,7 @@ rules. @end quotation @node Elaboration Circularities,Resolving Elaboration Circularities,SPARK Diagnostics,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id10}@anchor{226}@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-circularities}@anchor{227} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-circularities}@anchor{226}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id10}@anchor{227} @section Elaboration Circularities @@ -27389,7 +27389,7 @@ Use the relaxed dynamic-elaboration model, with compiler switches @end itemize @node Elaboration-related Compiler Switches,Summary of Procedures for Elaboration Control,Resolving Elaboration Circularities,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id12}@anchor{22a}@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-related-compiler-switches}@anchor{22b} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-related-compiler-switches}@anchor{22a}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id12}@anchor{22b} @section Elaboration-related Compiler Switches @@ -27493,7 +27493,7 @@ eliminate some diagnostics and run-time checks. @item @code{-gnatw.f} -Turn on warnings for suspicious Subp'Access +Turn on warnings for suspicious Subp’Access When this switch is in effect, GNAT will treat @code{'Access} of an entry, operator, or subprogram as a potential call to the target and issue warnings: @@ -27771,7 +27771,7 @@ gdbstr (body) @end quotation @node Inline Assembler,GNU Free Documentation License,Elaboration Order Handling in GNAT,Top -@anchor{gnat_ugn/inline_assembler inline-assembler}@anchor{10}@anchor{gnat_ugn/inline_assembler doc}@anchor{230}@anchor{gnat_ugn/inline_assembler id1}@anchor{231} +@anchor{gnat_ugn/inline_assembler doc}@anchor{230}@anchor{gnat_ugn/inline_assembler id1}@anchor{231}@anchor{gnat_ugn/inline_assembler inline-assembler}@anchor{10} @chapter Inline Assembler @@ -27830,13 +27830,13 @@ and with assembly language programming. @end menu @node Basic Assembler Syntax,A Simple Example of Inline Assembler,,Inline Assembler -@anchor{gnat_ugn/inline_assembler id2}@anchor{232}@anchor{gnat_ugn/inline_assembler basic-assembler-syntax}@anchor{233} +@anchor{gnat_ugn/inline_assembler basic-assembler-syntax}@anchor{232}@anchor{gnat_ugn/inline_assembler id2}@anchor{233} @section Basic Assembler Syntax The assembler used by GNAT and gcc is based not on the Intel assembly language, but rather on a language that descends from the AT&T Unix -assembler @code{as} (and which is often referred to as 'AT&T syntax'). +assembler @code{as} (and which is often referred to as ‘AT&T syntax’). The following table summarizes the main features of @code{as} syntax and points out the differences from the Intel conventions. See the gcc @code{as} and @code{gas} (an @code{as} macro @@ -27846,7 +27846,7 @@ pre-processor) documentation for further information. @display @emph{Register names}@w{ } @display -gcc / @code{as}: Prefix with '%'; for example @code{%eax}@w{ } +gcc / @code{as}: Prefix with ‘%’; for example @code{%eax}@w{ } Intel: No extra punctuation; for example @code{eax}@w{ } @end display @end display @@ -27857,7 +27857,7 @@ Intel: No extra punctuation; for example @code{eax}@w{ } @display @emph{Immediate operand}@w{ } @display -gcc / @code{as}: Prefix with '$'; for example @code{$4}@w{ } +gcc / @code{as}: Prefix with ‘$’; for example @code{$4}@w{ } Intel: No extra punctuation; for example @code{4}@w{ } @end display @end display @@ -27868,7 +27868,7 @@ Intel: No extra punctuation; for example @code{4}@w{ } @display @emph{Address}@w{ } @display -gcc / @code{as}: Prefix with '$'; for example @code{$loc}@w{ } +gcc / @code{as}: Prefix with ‘$’; for example @code{$loc}@w{ } Intel: No extra punctuation; for example @code{loc}@w{ } @end display @end display @@ -27901,8 +27901,8 @@ Intel: Square brackets; for example @code{[eax]}@w{ } @display @emph{Hexadecimal numbers}@w{ } @display -gcc / @code{as}: Leading '0x' (C language syntax); for example @code{0xA0}@w{ } -Intel: Trailing 'h'; for example @code{A0h}@w{ } +gcc / @code{as}: Leading ‘0x’ (C language syntax); for example @code{0xA0}@w{ } +Intel: Trailing ‘h’; for example @code{A0h}@w{ } @end display @end display @@ -28069,9 +28069,9 @@ L1: The assembly code you included is clearly indicated by the compiler, between the @code{#APP} and @code{#NO_APP} -delimiters. The character before the 'APP' and 'NOAPP' -can differ on different targets. For example, GNU/Linux uses '#APP' while -on NT you will see '/APP'. +delimiters. The character before the ‘APP’ and ‘NOAPP’ +can differ on different targets. For example, GNU/Linux uses ‘#APP’ while +on NT you will see ‘/APP’. If you make a mistake in your assembler code (such as using the wrong size modifier, or using a wrong operand for the instruction) GNAT @@ -28235,7 +28235,7 @@ Unsigned_32'Asm_Output ("=r", Flags); uses the @code{"r"} (register) constraint, telling the compiler to store the variable in a register. -If the constraint is preceded by the equal character '=', it tells +If the constraint is preceded by the equal character ‘=’, it tells the compiler that the variable will be used to store data into it. In the @code{Get_Flags} example, we used the @code{"g"} (global) constraint, @@ -28558,7 +28558,7 @@ _increment__incr.1: For a short subprogram such as the @code{Incr} function in the previous section, the overhead of the call and return (creating / deleting the stack frame) can be significant, compared to the amount of code in the subprogram -body. A solution is to apply Ada's @code{Inline} pragma to the subprogram, +body. A solution is to apply Ada’s @code{Inline} pragma to the subprogram, which directs the compiler to expand invocations of the subprogram at the point(s) of call, instead of setting up a stack frame for out-of-line calls. Here is the resulting program: @@ -28622,7 +28622,7 @@ movl %esi,%eax thus saving the overhead of stack frame setup and an out-of-line call. @node Other Asm Functionality,,Inlining Inline Assembler Code,Inline Assembler -@anchor{gnat_ugn/inline_assembler other-asm-functionality}@anchor{23c}@anchor{gnat_ugn/inline_assembler id7}@anchor{23d} +@anchor{gnat_ugn/inline_assembler id7}@anchor{23c}@anchor{gnat_ugn/inline_assembler other-asm-functionality}@anchor{23d} @section Other @code{Asm} Functionality @@ -28637,7 +28637,7 @@ and @code{Volatile}, which inhibits unwanted optimizations. @end menu @node The Clobber Parameter,The Volatile Parameter,,Other Asm Functionality -@anchor{gnat_ugn/inline_assembler the-clobber-parameter}@anchor{23e}@anchor{gnat_ugn/inline_assembler id8}@anchor{23f} +@anchor{gnat_ugn/inline_assembler id8}@anchor{23e}@anchor{gnat_ugn/inline_assembler the-clobber-parameter}@anchor{23f} @subsection The @code{Clobber} Parameter @@ -28650,7 +28650,7 @@ the eax register). But more generally, the compiler needs an explicit identification of the registers that are used by the Inline Assembly statements. -Using a register that the compiler doesn't know about +Using a register that the compiler doesn’t know about could be a side effect of an instruction (like @code{mull} storing its result in both eax and edx). It can also arise from explicit register usage in your @@ -28694,14 +28694,14 @@ The @code{Clobber} parameter has several additional uses: @itemize * @item -Use 'register' name @code{cc} to indicate that flags might have changed +Use ‘register’ name @code{cc} to indicate that flags might have changed @item -Use 'register' name @code{memory} if you changed a memory location +Use ‘register’ name @code{memory} if you changed a memory location @end itemize @node The Volatile Parameter,,The Clobber Parameter,Other Asm Functionality -@anchor{gnat_ugn/inline_assembler the-volatile-parameter}@anchor{240}@anchor{gnat_ugn/inline_assembler id9}@anchor{241} +@anchor{gnat_ugn/inline_assembler id9}@anchor{240}@anchor{gnat_ugn/inline_assembler the-volatile-parameter}@anchor{241} @subsection The @code{Volatile} Parameter @@ -28733,11 +28733,11 @@ By default, @code{Volatile} is set to @code{False} unless there is no Although setting @code{Volatile} to @code{True} prevents unwanted optimizations, it will also disable other optimizations that might be important for efficiency. In general, you should set @code{Volatile} -to @code{True} only if the compiler's optimizations have created +to @code{True} only if the compiler’s optimizations have created problems. @node GNU Free Documentation License,Index,Inline Assembler,Top -@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{242}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{243} +@anchor{share/gnu_free_documentation_license doc}@anchor{242}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{243} @chapter GNU Free Documentation License @@ -28752,14 +28752,14 @@ license document, but changing it is not allowed. @strong{Preamble} The purpose of this License is to make a manual, textbook, or other -functional and useful document "free" in the sense of freedom: to +functional and useful document “free” in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. -This License is a kind of "copyleft", which means that derivative +This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. @@ -28780,17 +28780,17 @@ distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The @strong{Document}, below, refers to any such manual or work. Any member of the public is a -licensee, and is addressed as "@strong{you}". You accept the license if you +licensee, and is addressed as “@strong{you}”. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. -A "@strong{Modified Version}" of the Document means any work containing the +A “@strong{Modified Version}” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. -A "@strong{Secondary Section}" is a named appendix or a front-matter section of +A “@strong{Secondary Section}” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the -publishers or authors of the Document to the Document's overall subject +publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any @@ -28799,7 +28799,7 @@ connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. -The "@strong{Invariant Sections}" are certain Secondary Sections whose titles +The “@strong{Invariant Sections}” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not @@ -28807,12 +28807,12 @@ allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. -The "@strong{Cover Texts}" are certain short passages of text that are listed, +The “@strong{Cover Texts}” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. -A "@strong{Transparent}" copy of the Document means a machine-readable copy, +A “@strong{Transparent}” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of @@ -28823,7 +28823,7 @@ to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount -of text. A copy that is not "Transparent" is called @strong{Opaque}. +of text. A copy that is not “Transparent” is called @strong{Opaque}. Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML @@ -28836,24 +28836,24 @@ processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. -The "@strong{Title Page}" means, for a printed book, the title page itself, +The “@strong{Title Page}” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in -formats which do not have any title page as such, "Title Page" means -the text near the most prominent appearance of the work's title, +formats which do not have any title page as such, “Title Page” means +the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text. -The "@strong{publisher}" means any person or entity that distributes +The “@strong{publisher}” means any person or entity that distributes copies of the Document to the public. -A section "@strong{Entitled XYZ}" means a named subunit of the Document whose +A section “@strong{Entitled XYZ}” means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a -specific section name mentioned below, such as "@strong{Acknowledgements}", -"@strong{Dedications}", "@strong{Endorsements}", or "@strong{History}".) -To "@strong{Preserve the Title}" +specific section name mentioned below, such as “@strong{Acknowledgements}”, +“@strong{Dedications}”, “@strong{Endorsements}”, or “@strong{History}”.) +To “@strong{Preserve the Title}” of such a section when you modify the Document means that it remains a -section "Entitled XYZ" according to this definition. +section “Entitled XYZ” according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty @@ -28881,7 +28881,7 @@ you may publicly display copies. If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the -Document's license notice requires Cover Texts, you must enclose the +Document’s license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify @@ -28958,16 +28958,16 @@ terms of this License, in the form shown in the Addendum below. @item Preserve in that license notice the full lists of Invariant Sections -and required Cover Texts given in the Document's license notice. +and required Cover Texts given in the Document’s license notice. @item Include an unaltered copy of this License. @item -Preserve the section Entitled "History", Preserve its Title, and add +Preserve the section Entitled “History”, Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If -there is no section Entitled "History" in the Document, create one +there is no section Entitled “History” in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. @@ -28976,13 +28976,13 @@ Version as stated in the previous sentence. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions -it was based on. These may be placed in the "History" section. +it was based on. These may be placed in the “History” section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. @item -For any section Entitled "Acknowledgements" or "Dedications", +For any section Entitled “Acknowledgements” or “Dedications”, Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. @@ -28993,11 +28993,11 @@ unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. @item -Delete any section Entitled "Endorsements". Such a section +Delete any section Entitled “Endorsements”. Such a section may not be included in the Modified Version. @item -Do not retitle any existing section to be Entitled "Endorsements" +Do not retitle any existing section to be Entitled “Endorsements” or to conflict in title with any Invariant Section. @item @@ -29008,12 +29008,12 @@ If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the -list of Invariant Sections in the Modified Version's license notice. +list of Invariant Sections in the Modified Version’s license notice. These titles must be distinct from any other section titles. -You may add a section Entitled "Endorsements", provided it contains +You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various -parties---for example, statements of peer review or that the text has +parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. @@ -29049,11 +29049,11 @@ author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. -In the combination, you must combine any sections Entitled "History" +In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled -"History"; likewise combine any sections Entitled "Acknowledgements", -and any sections Entitled "Dedications". You must delete all sections -Entitled "Endorsements". +“History”; likewise combine any sections Entitled “Acknowledgements”, +and any sections Entitled “Dedications”. You must delete all sections +Entitled “Endorsements”. @strong{6. COLLECTIONS OF DOCUMENTS} @@ -29072,16 +29072,16 @@ other respects regarding verbatim copying of that document. A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or -distribution medium, is called an "aggregate" if the copyright +distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights -of the compilation's users beyond what the individual works permit. +of the compilation’s users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of -the entire aggregate, the Document's Cover Texts may be placed on +the entire aggregate, the Document’s Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole @@ -29102,8 +29102,8 @@ of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. -If a section in the Document is Entitled "Acknowledgements", -"Dedications", or "History", the requirement (section 4) to Preserve +If a section in the Document is Entitled “Acknowledgements”, +“Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. @@ -29144,37 +29144,37 @@ differ in detail to address new problems or concerns. See Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this -License "or any later version" applies to it, you have the option of +License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this -License can be used, that proxy's public statement of acceptance of a +License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document. @strong{11. RELICENSING} -"Massive Multiauthor Collaboration Site" (or "MMC Site") means any +“Massive Multiauthor Collaboration Site” (or “MMC Site”) means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A -"Massive Multiauthor Collaboration" (or "MMC") contained in the +“Massive Multiauthor Collaboration” (or “MMC”) contained in the site means any set of copyrightable works thus published on the MMC site. -"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 +“CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization. -"Incorporate" means to publish or republish a Document, in whole or +“Incorporate” means to publish or republish a Document, in whole or in part, as part of another Document. -An MMC is "eligible for relicensing" if it is licensed under this +An MMC is “eligible for relicensing” if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, @@ -29197,12 +29197,12 @@ Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. -A copy of the license is included in the section entitled "GNU -Free Documentation License". +A copy of the license is included in the section entitled “GNU +Free Documentation License”. @end quotation If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, -replace the "with ... Texts." line with this: +replace the “with … Texts.” line with this: @quotation @@ -29225,8 +29225,8 @@ to permit their use in free software. @printindex ge -@anchor{gnat_ugn/gnat_utility_programs switches-related-to-project-files}@w{ } @anchor{cf}@w{ } +@anchor{gnat_ugn/gnat_utility_programs switches-related-to-project-files}@w{ } @c %**end of body @bye -- cgit v1.1 From be8749f939a933bca6de19d9cf1a510d5954c2fa Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Mon, 5 Jul 2021 21:05:10 +0200 Subject: i386: Implement 4-byte vector (V4QI/V2HI) constant permutations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2021-07-05 Uroš Bizjak gcc/ * config/i386/i386-expand.c (ix86_split_mmx_punpck): Handle V4QI and V2HI modes. (expand_vec_perm_blend): Allow 4-byte vector modes with TARGET_SSE4_1. Handle V4QI mode. Emit mmx_pblendvb32 for 4-byte modes. (expand_vec_perm_pshufb): Rewrite to use switch statemets. Handle 4-byte dual operands with TARGET_XOP and single operands with TARGET_SSSE3. Emit mmx_ppermv32 for TARGET_XOP and mmx_pshufbv4qi3 for TARGET_SSSE3. (expand_vec_perm_pblendv): Allow 4-byte vector modes with TARGET_SSE4_1. (expand_vec_perm_interleave2): Allow 4-byte vector modes. (expand_vec_perm_pshufb2): Allow 4-byte vector modes with TARGET_SSSE3. (expand_vec_perm_even_odd_1): Handle V4QI mode. (expand_vec_perm_broadcast_1): Handle V4QI mode. (ix86_vectorize_vec_perm_const): Handle V4QI mode. * config/i386/mmx.md (mmx_ppermv32): New insn pattern. (mmx_pshufbv4qi3): Ditto. (*mmx_pblendw32): Ditto. (*mmx_pblendw64): Rename from *mmx_pblendw. (mmx_punpckhbw_low): New insn_and_split pattern. (mmx_punpcklbw_low): Ditto. --- gcc/config/i386/i386-expand.c | 469 ++++++++++++++++++++++++++---------------- gcc/config/i386/mmx.md | 86 +++++++- 2 files changed, 370 insertions(+), 185 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index b37642e..58c208e 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -933,6 +933,7 @@ ix86_split_mmx_punpck (rtx operands[], bool high_p) switch (mode) { + case E_V4QImode: case E_V8QImode: sse_mode = V16QImode; double_sse_mode = V32QImode; @@ -949,6 +950,7 @@ ix86_split_mmx_punpck (rtx operands[], bool high_p) break; case E_V4HImode: + case E_V2HImode: sse_mode = V8HImode; double_sse_mode = V16HImode; mask = gen_rtx_PARALLEL (VOIDmode, @@ -991,7 +993,7 @@ ix86_split_mmx_punpck (rtx operands[], bool high_p) rtx insn = gen_rtx_SET (dest, op2); emit_insn (insn); - /* Move bits 64:127 to bits 0:63. */ + /* Move high bits to low bits. */ if (high_p) { if (sse_mode == V4SFmode) @@ -1004,9 +1006,19 @@ ix86_split_mmx_punpck (rtx operands[], bool high_p) } else { - mask = gen_rtx_PARALLEL (VOIDmode, - gen_rtvec (4, GEN_INT (2), GEN_INT (3), - GEN_INT (0), GEN_INT (1))); + int sz = GET_MODE_SIZE (mode); + + if (sz == 4) + mask = gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (4, GEN_INT (1), GEN_INT (0), + GEN_INT (0), GEN_INT (1))); + else if (sz == 8) + mask = gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (4, GEN_INT (2), GEN_INT (3), + GEN_INT (0), GEN_INT (1))); + else + gcc_unreachable (); + dest = lowpart_subreg (V4SImode, dest, GET_MODE (dest)); op1 = gen_rtx_VEC_SELECT (V4SImode, dest, mask); } @@ -17331,7 +17343,8 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d) else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode)) ; else if (TARGET_SSE4_1 && (GET_MODE_SIZE (vmode) == 16 - || GET_MODE_SIZE (vmode) == 8)) + || GET_MODE_SIZE (vmode) == 8 + || GET_MODE_SIZE (vmode) == 4)) ; else return false; @@ -17408,7 +17421,9 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d) vperm = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, rperm)); vperm = force_reg (vmode, vperm); - if (GET_MODE_SIZE (vmode) == 8) + if (GET_MODE_SIZE (vmode) == 4) + emit_insn (gen_mmx_pblendvb32 (target, op0, op1, vperm)); + else if (GET_MODE_SIZE (vmode) == 8) emit_insn (gen_mmx_pblendvb64 (target, op0, op1, vperm)); else if (GET_MODE_SIZE (vmode) == 16) emit_insn (gen_sse4_1_pblendvb (target, op0, op1, vperm)); @@ -17440,6 +17455,16 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d) vmode = V4HImode; goto do_subreg; + case E_V4QImode: + for (i = 0; i < 4; i += 2) + if (d->perm[i] + 1 != d->perm[i + 1]) + goto use_pblendvb; + + for (i = 0; i < 2; ++i) + mask |= (d->perm[i * 2] >= 4) << i; + vmode = V2HImode; + goto do_subreg; + case E_V32QImode: /* See if bytes move in pairs. If not, vpblendvb must be used. */ for (i = 0; i < 32; i += 2) @@ -17697,163 +17722,176 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d) nelt = d->nelt; if (!d->one_operand_p) - { - if (GET_MODE_SIZE (d->vmode) == 8) - { - if (!TARGET_XOP) - return false; - vmode = V8QImode; - } - else if (GET_MODE_SIZE (d->vmode) == 16) - { - if (!TARGET_XOP) - return false; - } - else if (GET_MODE_SIZE (d->vmode) == 32) - { - if (!TARGET_AVX2) - return false; + switch (GET_MODE_SIZE (d->vmode)) + { + case 4: + if (!TARGET_XOP) + return false; + vmode = V4QImode; + break; - if (valid_perm_using_mode_p (V2TImode, d)) - { - if (d->testing_p) - return true; + case 8: + if (!TARGET_XOP) + return false; + vmode = V8QImode; + break; - /* Use vperm2i128 insn. The pattern uses - V4DImode instead of V2TImode. */ - target = d->target; - if (d->vmode != V4DImode) - target = gen_reg_rtx (V4DImode); - op0 = gen_lowpart (V4DImode, d->op0); - op1 = gen_lowpart (V4DImode, d->op1); - rperm[0] - = GEN_INT ((d->perm[0] / (nelt / 2)) - | ((d->perm[nelt / 2] / (nelt / 2)) * 16)); - emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0])); - if (target != d->target) - emit_move_insn (d->target, gen_lowpart (d->vmode, target)); - return true; - } + case 16: + if (!TARGET_XOP) return false; - } - else + break; + + case 32: + if (!TARGET_AVX2) + return false; + + if (valid_perm_using_mode_p (V2TImode, d)) + { + if (d->testing_p) + return true; + + /* Use vperm2i128 insn. The pattern uses + V4DImode instead of V2TImode. */ + target = d->target; + if (d->vmode != V4DImode) + target = gen_reg_rtx (V4DImode); + op0 = gen_lowpart (V4DImode, d->op0); + op1 = gen_lowpart (V4DImode, d->op1); + rperm[0] + = GEN_INT ((d->perm[0] / (nelt / 2)) + | ((d->perm[nelt / 2] / (nelt / 2)) * 16)); + emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0])); + if (target != d->target) + emit_move_insn (d->target, gen_lowpart (d->vmode, target)); + return true; + } + /* FALLTHRU */ + + default: return false; - } + } else - { - if (GET_MODE_SIZE (d->vmode) == 8) - { - if (!TARGET_SSSE3) - return false; - vmode = V8QImode; - } - else if (GET_MODE_SIZE (d->vmode) == 16) - { - if (!TARGET_SSSE3) - return false; - } - else if (GET_MODE_SIZE (d->vmode) == 32) - { - if (!TARGET_AVX2) - return false; + switch (GET_MODE_SIZE (d->vmode)) + { + case 4: + if (!TARGET_SSSE3) + return false; + vmode = V4QImode; + break; - /* V4DImode should be already handled through - expand_vselect by vpermq instruction. */ - gcc_assert (d->vmode != V4DImode); + case 8: + if (!TARGET_SSSE3) + return false; + vmode = V8QImode; + break; - vmode = V32QImode; - if (d->vmode == V8SImode - || d->vmode == V16HImode - || d->vmode == V32QImode) - { - /* First see if vpermq can be used for - V8SImode/V16HImode/V32QImode. */ - if (valid_perm_using_mode_p (V4DImode, d)) - { - for (i = 0; i < 4; i++) - perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3; - if (d->testing_p) + case 16: + if (!TARGET_SSSE3) + return false; + break; + + case 32: + if (!TARGET_AVX2) + return false; + + /* V4DImode should be already handled through + expand_vselect by vpermq instruction. */ + gcc_assert (d->vmode != V4DImode); + + vmode = V32QImode; + if (d->vmode == V8SImode + || d->vmode == V16HImode + || d->vmode == V32QImode) + { + /* First see if vpermq can be used for + V8SImode/V16HImode/V32QImode. */ + if (valid_perm_using_mode_p (V4DImode, d)) + { + for (i = 0; i < 4; i++) + perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3; + if (d->testing_p) + return true; + target = gen_reg_rtx (V4DImode); + if (expand_vselect (target, gen_lowpart (V4DImode, d->op0), + perm, 4, false)) + { + emit_move_insn (d->target, + gen_lowpart (d->vmode, target)); return true; - target = gen_reg_rtx (V4DImode); - if (expand_vselect (target, gen_lowpart (V4DImode, d->op0), - perm, 4, false)) - { - emit_move_insn (d->target, - gen_lowpart (d->vmode, target)); - return true; - } - return false; - } + } + return false; + } - /* Next see if vpermd can be used. */ - if (valid_perm_using_mode_p (V8SImode, d)) - vmode = V8SImode; - } - /* Or if vpermps can be used. */ - else if (d->vmode == V8SFmode) - vmode = V8SImode; + /* Next see if vpermd can be used. */ + if (valid_perm_using_mode_p (V8SImode, d)) + vmode = V8SImode; + } + /* Or if vpermps can be used. */ + else if (d->vmode == V8SFmode) + vmode = V8SImode; - if (vmode == V32QImode) - { - /* vpshufb only works intra lanes, it is not - possible to shuffle bytes in between the lanes. */ - for (i = 0; i < nelt; ++i) - if ((d->perm[i] ^ i) & (nelt / 2)) - return false; - } - } - else if (GET_MODE_SIZE (d->vmode) == 64) - { - if (!TARGET_AVX512BW) - return false; + if (vmode == V32QImode) + { + /* vpshufb only works intra lanes, it is not + possible to shuffle bytes in between the lanes. */ + for (i = 0; i < nelt; ++i) + if ((d->perm[i] ^ i) & (nelt / 2)) + return false; + } + break; - /* If vpermq didn't work, vpshufb won't work either. */ - if (d->vmode == V8DFmode || d->vmode == V8DImode) - return false; + case 64: + if (!TARGET_AVX512BW) + return false; - vmode = V64QImode; - if (d->vmode == V16SImode - || d->vmode == V32HImode - || d->vmode == V64QImode) - { - /* First see if vpermq can be used for - V16SImode/V32HImode/V64QImode. */ - if (valid_perm_using_mode_p (V8DImode, d)) - { - for (i = 0; i < 8; i++) - perm[i] = (d->perm[i * nelt / 8] * 8 / nelt) & 7; - if (d->testing_p) + /* If vpermq didn't work, vpshufb won't work either. */ + if (d->vmode == V8DFmode || d->vmode == V8DImode) + return false; + + vmode = V64QImode; + if (d->vmode == V16SImode + || d->vmode == V32HImode + || d->vmode == V64QImode) + { + /* First see if vpermq can be used for + V16SImode/V32HImode/V64QImode. */ + if (valid_perm_using_mode_p (V8DImode, d)) + { + for (i = 0; i < 8; i++) + perm[i] = (d->perm[i * nelt / 8] * 8 / nelt) & 7; + if (d->testing_p) + return true; + target = gen_reg_rtx (V8DImode); + if (expand_vselect (target, gen_lowpart (V8DImode, d->op0), + perm, 8, false)) + { + emit_move_insn (d->target, + gen_lowpart (d->vmode, target)); return true; - target = gen_reg_rtx (V8DImode); - if (expand_vselect (target, gen_lowpart (V8DImode, d->op0), - perm, 8, false)) - { - emit_move_insn (d->target, - gen_lowpart (d->vmode, target)); - return true; - } - return false; - } + } + return false; + } - /* Next see if vpermd can be used. */ - if (valid_perm_using_mode_p (V16SImode, d)) - vmode = V16SImode; - } - /* Or if vpermps can be used. */ - else if (d->vmode == V16SFmode) - vmode = V16SImode; - if (vmode == V64QImode) - { - /* vpshufb only works intra lanes, it is not - possible to shuffle bytes in between the lanes. */ - for (i = 0; i < nelt; ++i) - if ((d->perm[i] ^ i) & (3 * nelt / 4)) - return false; - } - } - else + /* Next see if vpermd can be used. */ + if (valid_perm_using_mode_p (V16SImode, d)) + vmode = V16SImode; + } + /* Or if vpermps can be used. */ + else if (d->vmode == V16SFmode) + vmode = V16SImode; + if (vmode == V64QImode) + { + /* vpshufb only works intra lanes, it is not + possible to shuffle bytes in between the lanes. */ + for (i = 0; i < nelt; ++i) + if ((d->perm[i] ^ i) & (3 * nelt / 4)) + return false; + } + break; + + default: return false; - } + } if (d->testing_p) return true; @@ -17893,23 +17931,28 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d) machine_mode vpmode = vmode; - if (vmode == V8QImode) + if (vmode == V4QImode + || vmode == V8QImode) { rtx m128 = GEN_INT (-128); /* Remap elements from the second operand, as we have to - account for inactive top 8 elements from the first operand. */ + account for inactive top elements from the first operand. */ if (!d->one_operand_p) - for (i = 0; i < nelt; ++i) - { - int ival = INTVAL (rperm[i]); - if (ival >= 8) - ival += 8; - rperm[i] = GEN_INT (ival); - } + { + int sz = GET_MODE_SIZE (vmode); - /* V8QI is emulated with V16QI instruction, fill inactive - elements in the top 8 positions with zeros. */ + for (i = 0; i < nelt; ++i) + { + int ival = INTVAL (rperm[i]); + if (ival >= sz) + ival += 16-sz; + rperm[i] = GEN_INT (ival); + } + } + + /* V4QI/V8QI is emulated with V16QI instruction, fill inactive + elements in the top positions with zeros. */ for (i = nelt; i < 16; ++i) rperm[i] = m128; @@ -17931,7 +17974,9 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d) { rtx (*gen) (rtx, rtx, rtx); - if (vmode == V8QImode) + if (vmode == V4QImode) + gen = gen_mmx_pshufbv4qi3; + else if (vmode == V8QImode) gen = gen_mmx_pshufbv8qi3; else if (vmode == V16QImode) gen = gen_ssse3_pshufbv16qi3; @@ -17958,7 +18003,9 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d) op1 = gen_lowpart (vmode, d->op1); - if (vmode == V8QImode) + if (vmode == V4QImode) + gen = gen_mmx_ppermv32; + else if (vmode == V8QImode) gen = gen_mmx_ppermv64; else if (vmode == V16QImode) gen = gen_xop_pperm; @@ -18405,7 +18452,8 @@ expand_vec_perm_pblendv (struct expand_vec_perm_d *d) ; else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode)) ; - else if (TARGET_SSE4_1 && (GET_MODE_SIZE (vmode) == 8 + else if (TARGET_SSE4_1 && (GET_MODE_SIZE (vmode) == 4 + || GET_MODE_SIZE (vmode) == 8 || GET_MODE_SIZE (vmode) == 16)) ; else @@ -18485,7 +18533,8 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d) rtx_insn *seq; bool ok, same_halves = false; - if (GET_MODE_SIZE (d->vmode) == 8 + if (GET_MODE_SIZE (d->vmode) == 4 + || GET_MODE_SIZE (d->vmode) == 8 || GET_MODE_SIZE (d->vmode) == 16) { if (d->one_operand_p) @@ -18521,7 +18570,8 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d) memset (remap, 0xff, sizeof (remap)); dremap = *d; - if (GET_MODE_SIZE (d->vmode) == 8) + if (GET_MODE_SIZE (d->vmode) == 4 + || GET_MODE_SIZE (d->vmode) == 8) { unsigned HOST_WIDE_INT h1, h2, h3, h4; @@ -19269,7 +19319,8 @@ expand_vec_perm_2perm_pblendv (struct expand_vec_perm_d *d, bool two_insn) else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode)) ; else if (TARGET_SSE4_1 && (GET_MODE_SIZE (vmode) == 16 - || GET_MODE_SIZE (vmode) == 8)) + || GET_MODE_SIZE (vmode) == 8 + || GET_MODE_SIZE (vmode) == 4)) ; else return false; @@ -19530,7 +19581,8 @@ expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d) rtx (*gen) (rtx, rtx, rtx); if (!TARGET_SSSE3 || (GET_MODE_SIZE (d->vmode) != 16 - && GET_MODE_SIZE (d->vmode) != 8)) + && GET_MODE_SIZE (d->vmode) != 8 + && GET_MODE_SIZE (d->vmode) != 4)) return false; gcc_assert (!d->one_operand_p); @@ -19539,6 +19591,10 @@ expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d) switch (GET_MODE_SIZE (d->vmode)) { + case 4: + mode = V4QImode; + gen = gen_mmx_pshufbv4qi3; + break; case 8: mode = V8QImode; gen = gen_mmx_pshufbv8qi3; @@ -20025,6 +20081,26 @@ expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd) return false; break; + case E_V4QImode: + if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB) + return expand_vec_perm_pshufb2 (d); + else + { + if (d->testing_p) + break; + /* We need 2*log2(N)-1 operations to achieve odd/even + with interleave. */ + t1 = gen_reg_rtx (V4QImode); + emit_insn (gen_mmx_punpckhbw_low (t1, d->op0, d->op1)); + emit_insn (gen_mmx_punpcklbw_low (d->target, d->op0, d->op1)); + if (odd) + t2 = gen_mmx_punpckhbw_low (d->target, d->target, t1); + else + t2 = gen_mmx_punpcklbw_low (d->target, d->target, t1); + emit_insn (t2); + } + break; + case E_V4HImode: if (TARGET_SSE4_1) return expand_vec_perm_even_odd_pack (d); @@ -20214,6 +20290,7 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d) { unsigned elt = d->perm[0], nelt2 = d->nelt / 2; machine_mode vmode = d->vmode; + rtx (*gen) (rtx, rtx, rtx); unsigned char perm2[4]; rtx op0 = d->op0, dest; bool ok; @@ -20238,24 +20315,48 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d) /* These are always implementable using standard shuffle patterns. */ gcc_unreachable (); + case E_V4QImode: + /* This can be implemented via interleave and pshuflw. */ + if (d->testing_p) + return true; + + if (elt >= nelt2) + { + gen = gen_mmx_punpckhbw_low; + elt -= nelt2; + } + else + gen = gen_mmx_punpcklbw_low; + + dest = gen_reg_rtx (vmode); + emit_insn (gen (dest, op0, op0)); + vmode = get_mode_wider_vector (vmode); + op0 = gen_lowpart (vmode, dest); + + memset (perm2, elt, 2); + dest = gen_reg_rtx (vmode); + ok = expand_vselect (dest, op0, perm2, 2, d->testing_p); + gcc_assert (ok); + + emit_move_insn (d->target, gen_lowpart (d->vmode, dest)); + return true; + case E_V8QImode: - /* These can be implemented via interleave. We save one insn by + /* This can be implemented via interleave. We save one insn by stopping once we have promoted to V2SImode and then use pshufd. */ if (d->testing_p) return true; do { - rtx dest; - rtx (*gen) (rtx, rtx, rtx) - = vmode == V8QImode ? gen_mmx_punpcklbw - : gen_mmx_punpcklwd; - if (elt >= nelt2) { gen = vmode == V8QImode ? gen_mmx_punpckhbw : gen_mmx_punpckhwd; elt -= nelt2; } + else + gen = vmode == V8QImode ? gen_mmx_punpcklbw + : gen_mmx_punpcklwd; nelt2 /= 2; dest = gen_reg_rtx (vmode); @@ -20266,11 +20367,11 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d) while (vmode != V2SImode); memset (perm2, elt, 2); - dest = gen_reg_rtx (V2SImode); + dest = gen_reg_rtx (vmode); ok = expand_vselect (dest, op0, perm2, 2, d->testing_p); gcc_assert (ok); - if (!d->testing_p) - emit_move_insn (d->target, gen_lowpart (d->vmode, dest)); + + emit_move_insn (d->target, gen_lowpart (d->vmode, dest)); return true; case E_V8HImode: @@ -20281,17 +20382,15 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d) return true; do { - rtx dest; - rtx (*gen) (rtx, rtx, rtx) - = vmode == V16QImode ? gen_vec_interleave_lowv16qi - : gen_vec_interleave_lowv8hi; - if (elt >= nelt2) { gen = vmode == V16QImode ? gen_vec_interleave_highv16qi : gen_vec_interleave_highv8hi; elt -= nelt2; } + else + gen = vmode == V16QImode ? gen_vec_interleave_lowv16qi + : gen_vec_interleave_lowv8hi; nelt2 /= 2; dest = gen_reg_rtx (vmode); @@ -20302,11 +20401,11 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d) while (vmode != V4SImode); memset (perm2, elt, 4); - dest = gen_reg_rtx (V4SImode); + dest = gen_reg_rtx (vmode); ok = expand_vselect (dest, op0, perm2, 4, d->testing_p); gcc_assert (ok); - if (!d->testing_p) - emit_move_insn (d->target, gen_lowpart (d->vmode, dest)); + + emit_move_insn (d->target, gen_lowpart (d->vmode, dest)); return true; case E_V64QImode: @@ -20787,6 +20886,10 @@ ix86_vectorize_vec_perm_const (machine_mode vmode, rtx target, rtx op0, if (d.testing_p) return true; break; + case E_V4QImode: + if (!TARGET_SSE2) + return false; + break; case E_V2DImode: case E_V2DFmode: if (!TARGET_SSE) diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index 5f105727..4ead8be 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -2362,6 +2362,18 @@ [(set_attr "type" "sse4arg") (set_attr "mode" "TI")]) +(define_insn "mmx_ppermv32" + [(set (match_operand:V4QI 0 "register_operand" "=x") + (unspec:V4QI + [(match_operand:V4QI 1 "register_operand" "x") + (match_operand:V4QI 2 "register_operand" "x") + (match_operand:V16QI 3 "nonimmediate_operand" "xm")] + UNSPEC_XOP_PERMUTE))] + "TARGET_XOP" + "vpperm\t{%3, %2, %1, %0|%0, %1, %2, %3}" + [(set_attr "type" "sse4arg") + (set_attr "mode" "TI")]) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Parallel integral logical operations @@ -2550,6 +2562,23 @@ (set_attr "type" "mmxcvt,sselog,sselog") (set_attr "mode" "DI,TI,TI")]) +(define_insn_and_split "mmx_punpckhbw_low" + [(set (match_operand:V4QI 0 "register_operand" "=x,Yw") + (vec_select:V4QI + (vec_concat:V8QI + (match_operand:V4QI 1 "register_operand" "0,Yw") + (match_operand:V4QI 2 "register_operand" "x,Yw")) + (parallel [(const_int 2) (const_int 6) + (const_int 3) (const_int 7)])))] + "TARGET_SSE2" + "#" + "&& reload_completed" + [(const_int 0)] + "ix86_split_mmx_punpck (operands, true); DONE;" + [(set_attr "isa" "noavx,avx") + (set_attr "type" "sselog") + (set_attr "mode" "TI")]) + (define_insn_and_split "mmx_punpcklbw" [(set (match_operand:V8QI 0 "register_operand" "=y,x,Yw") (vec_select:V8QI @@ -2573,6 +2602,23 @@ (set_attr "type" "mmxcvt,sselog,sselog") (set_attr "mode" "DI,TI,TI")]) +(define_insn_and_split "mmx_punpcklbw_low" + [(set (match_operand:V4QI 0 "register_operand" "=x,Yw") + (vec_select:V4QI + (vec_concat:V8QI + (match_operand:V4QI 1 "register_operand" "0,Yw") + (match_operand:V4QI 2 "register_operand" "x,Yw")) + (parallel [(const_int 0) (const_int 4) + (const_int 1) (const_int 5)])))] + "TARGET_SSE2" + "#" + "&& reload_completed" + [(const_int 0)] + "ix86_split_mmx_punpck (operands, false); DONE;" + [(set_attr "isa" "noavx,avx") + (set_attr "type" "sselog") + (set_attr "mode" "TI")]) + (define_insn_and_split "mmx_punpckhwd" [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yw") (vec_select:V4HI @@ -2930,6 +2976,24 @@ (set_attr "btver2_decode" "vector") (set_attr "mode" "TI")]) +(define_insn "mmx_pshufbv4qi3" + [(set (match_operand:V4QI 0 "register_operand" "=x,Yw") + (unspec:V4QI + [(match_operand:V4QI 1 "register_operand" "0,Yw") + (match_operand:V16QI 2 "vector_operand" "xBm,Ywm")] + UNSPEC_PSHUFB))] + "TARGET_SSSE3" + "@ + pshufb\t{%2, %0|%0, %2} + vpshufb\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "noavx,avx") + (set_attr "type" "sselog1") + (set_attr "prefix_data16" "1,*") + (set_attr "prefix_extra" "1") + (set_attr "prefix" "orig,maybe_evex") + (set_attr "btver2_decode" "vector") + (set_attr "mode" "TI")]) + (define_expand "mmx_pshufw" [(match_operand:V4HI 0 "register_operand") (match_operand:V4HI 1 "register_mmxmem_operand") @@ -3002,12 +3066,12 @@ (set_attr "length_immediate" "1") (set_attr "mode" "TI")]) -(define_insn "*mmx_pblendw" +(define_insn "*mmx_pblendw64" [(set (match_operand:V4HI 0 "register_operand" "=Yr,*x,x") (vec_merge:V4HI (match_operand:V4HI 2 "register_operand" "Yr,*x,x") (match_operand:V4HI 1 "register_operand" "0,0,x") - (match_operand:SI 3 "const_0_to_63_operand" "n,n,n")))] + (match_operand:SI 3 "const_0_to_15_operand" "n,n,n")))] "TARGET_SSE4_1 && TARGET_MMX_WITH_SSE" "@ pblendw\t{%3, %2, %0|%0, %2, %3} @@ -3020,6 +3084,24 @@ (set_attr "prefix" "orig,orig,vex") (set_attr "mode" "TI")]) +(define_insn "*mmx_pblendw32" + [(set (match_operand:V2HI 0 "register_operand" "=Yr,*x,x") + (vec_merge:V2HI + (match_operand:V2HI 2 "register_operand" "Yr,*x,x") + (match_operand:V2HI 1 "register_operand" "0,0,x") + (match_operand:SI 3 "const_0_to_7_operand" "n,n,n")))] + "TARGET_SSE4_1" + "@ + pblendw\t{%3, %2, %0|%0, %2, %3} + pblendw\t{%3, %2, %0|%0, %2, %3} + vpblendw\t{%3, %2, %1, %0|%0, %1, %2, %3}" + [(set_attr "isa" "noavx,noavx,avx") + (set_attr "type" "ssemov") + (set_attr "prefix_extra" "1") + (set_attr "length_immediate" "1") + (set_attr "prefix" "orig,orig,vex") + (set_attr "mode" "TI")]) + ;; Optimize V2SImode load from memory, swapping the elements and ;; storing back into the memory into DImode rotate of the memory by 32. (define_split -- cgit v1.1 From 3b5e8ee4f1ecc6d407f391695f65960bcbd63cff Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Sun, 13 Dec 2020 17:21:16 +0000 Subject: Darwin, configury : Allow for specification and detection of dsymutil. In order to enable DWARF versions > 2 we need a sufficiently modern version of dsymutil (in addition to the assembler / linker). This allows the user to configure a different path from the installed one. In addition, there are several sources of dsymutil so we differentiate these in order to be get accurate version information. Signed-off-by: Iain Sandoe gcc/ChangeLog: * configure.ac: Handle --with-dsymutil in the same way as we do for the assembler and linker. (DEFAULT_DSYMUTIL): New. Extract the type and version for the dsymutil configured or found by the default searches. * config.in: Regenerated. * configure: Regenerated. * collect2.c (do_dsymutil): Handle locating dsymutil in the same way as for the assembler and linker. * config/darwin.h (DSYMUTIL): Delete. * gcc.c: Report a configured dsymutil correctly. * exec-tool.in: Allow for dsymutil. ChangeLog: * Makefile.def: Add dsymutil defs. * Makefile.in: Regenerated. * Makefile.tpl: Add dsymutil to flags. * configure: Regenerated. * configure.ac: Add dsymutil to target and build recipes. --- gcc/collect2.c | 40 ++++++++++++- gcc/config.in | 12 ++++ gcc/config/darwin.h | 2 - gcc/configure | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++-- gcc/configure.ac | 96 +++++++++++++++++++++++++++++- gcc/exec-tool.in | 8 +++ gcc/gcc.c | 5 ++ 7 files changed, 318 insertions(+), 11 deletions(-) (limited to 'gcc') diff --git a/gcc/collect2.c b/gcc/collect2.c index b08c6e7..07092c2 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -3040,15 +3040,49 @@ process_args (int *argcp, char **argv) { static void do_dsymutil (const char *output_file) { - const char *dsymutil = DSYMUTIL + 1; + const char *dsymutil = 0; struct pex_obj *pex; - char **real_argv = XCNEWVEC (char *, 3); + char **real_argv = XCNEWVEC (char *, verbose ? 4 : 3); const char ** argv = CONST_CAST2 (const char **, char **, real_argv); +/* For cross-builds search the PATH using target-qualified name if we + have not already found a suitable dsymutil. In practice, all modern + versions of dsymutil handle all supported archs, however the approach + here is consistent with the way other installations work (and one can + always symlink a multitarget dsymutil with a target-specific name). */ + const char *dsname = "dsymutil"; +#ifdef CROSS_DIRECTORY_STRUCTURE + const char *qname = concat (target_machine, "-", dsname, NULL); +#else + const char *qname = dsname; +#endif +#ifdef DEFAULT_DSYMUTIL + /* Configured default takes priority. */ + if (dsymutil == 0 && access (DEFAULT_DSYMUTIL, X_OK) == 0) + dsymutil = DEFAULT_DSYMUTIL; + if (dsymutil == 0) +#endif +#ifdef DSYMUTIL + /* Followed by one supplied in the target header, somewhat like the + REAL_XX_NAME used elsewhere. */ + dsymutil = find_a_file (&cpath, DSYMUTIL, X_OK); + if (dsymutil == 0) + dsymutil = find_a_file (&path, DSYMUTIL, X_OK); + if (dsymutil == 0) +#endif + dsymutil = find_a_file (&cpath, dsname, X_OK); + if (dsymutil == 0) + dsymutil = find_a_file (&path, qname, X_OK); argv[0] = dsymutil; argv[1] = output_file; - argv[2] = (char *) 0; + if (verbose) + { + argv[2] = "-v"; + argv[3] = (char *) 0; + } + else + argv[2] = (char *) 0; pex = collect_execute (dsymutil, real_argv, NULL, NULL, PEX_LAST | PEX_SEARCH, false, NULL); diff --git a/gcc/config.in b/gcc/config.in index 18e6271..2abac53 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -55,6 +55,12 @@ #endif +/* Define to enable the use of a default debug linker. */ +#ifndef USED_FOR_TARGET +#undef DEFAULT_DSYMUTIL +#endif + + /* Define to enable the use of a default linker. */ #ifndef USED_FOR_TARGET #undef DEFAULT_LINKER @@ -94,6 +100,12 @@ #endif +/* Define to the dsymutil version. */ +#ifndef USED_FOR_TARGET +#undef DSYMUTIL_VERSION +#endif + + /* Define 0/1 if static analyzer feature is enabled. */ #ifndef USED_FOR_TARGET #undef ENABLE_ANALYZER diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index 5f11978..20d6b1e 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -240,8 +240,6 @@ extern GTY(()) int darwin_ms_struct; DARWIN_NOCOMPACT_UNWIND \ "}}}}}}} %&1`; then + dsymutil_flag=yes + fi + fi + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_DSYMUTIL "$DEFAULT_DSYMUTIL" +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a default dsymutil was specified" >&5 +$as_echo_n "checking whether a default dsymutil was specified... " >&6; } +if test x"${DEFAULT_DSYMUTIL+set}" = x"set"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($DEFAULT_DSYMUTIL)" >&5 +$as_echo "yes ($DEFAULT_DSYMUTIL)" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + # ---------------------- # Find default assembler # ---------------------- @@ -19435,7 +19480,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 19438 "configure" +#line 19483 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -19541,7 +19586,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 19544 "configure" +#line 19589 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -23439,6 +23484,71 @@ else $as_echo "$gcc_cv_otool" >&6; } fi +# Figure out the dsymutil we will use. +if ${gcc_cv_dsymutil+:} false; then : + +else + +if test -x "$DEFAULT_DSYMUTIL"; then + gcc_cv_dsymutil="$DEFAULT_DSYMUTIL" +elif test -x dsymutil$build_exeext; then + gcc_cv_dsymutil=./dsymutil$build_exeext +elif ( set dummy $DSYMUTIL_FOR_TARGET; test -x $2 ); then + gcc_cv_dsymutil=$DSYMUTIL_FOR_TARGET +elif ( set dummy $DSYMUTIL; test -x $2 ); then + gcc_cv_dsymutil=$DSYMUTIL +else + # Extract the first word of "$DSYMUTIL_FOR_TARGET", so it can be a program name with args. +set dummy $DSYMUTIL_FOR_TARGET; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_gcc_cv_dsymutil+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $gcc_cv_dsymutil in + [\\/]* | ?:[\\/]*) + ac_cv_path_gcc_cv_dsymutil="$gcc_cv_dsymutil" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_gcc_cv_dsymutil="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +gcc_cv_dsymutil=$ac_cv_path_gcc_cv_dsymutil +if test -n "$gcc_cv_dsymutil"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_dsymutil" >&5 +$as_echo "$gcc_cv_dsymutil" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +fi + +ORIGINAL_DSYMUTIL_FOR_TARGET=$gcc_cv_dsymutil + +case "$ORIGINAL_DSYMUTIL_FOR_TARGET" in + ./dsymutil | ./dsymutil$build_exeext) ;; + *) ac_config_files="$ac_config_files dsymutil:exec-tool.in" + ;; +esac + # Figure out what assembler alignment features are present. { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler flags" >&5 $as_echo_n "checking assembler flags... " >&6; } @@ -30303,6 +30413,52 @@ _ACEOF fi +if test x"$dsymutil_flag" = x"yes"; then + + # If the user specified a dsymutil path, then we will already have the + # version string, otherwise, pick it up. + if test x"$gcc_cv_dsymutil" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: dsymutil is a required tool for this system, but not found" >&5 +$as_echo "$as_me: WARNING: dsymutil is a required tool for this system, but not found" >&2;} + dsymutil_vers="tool unspecified" + elif test x"$dsymutil_vers" = x; then + dsymutil_vers=`$gcc_cv_dsymutil -v /dev/null 2>&1` + fi + + dsymutil_temp=`echo $dsymutil_vers | sed 1q` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dsymutil version \"$dsymutil_temp\"" >&5 +$as_echo_n "checking dsymutil version \"$dsymutil_temp\"... " >&6; } + if echo $dsymutil_temp | grep dwarfutils- > /dev/null; then + dsymutil_kind=DWARFUTILS + dsymutil_vers=`echo $dsymutil_temp | sed 's/.*dwarfutils-\([0-9\.]*\).*/\1/'` + elif echo $dsymutil_temp | grep clang- > /dev/null; then + dsymutil_kind=CLANG + dsymutil_vers=`echo $dsymutil_temp | sed 's/.*clang-\([0-9\.]*\).*/\1/'` + elif echo $dsymutil_temp | grep 'LLVM version ' > /dev/null; then + dsymutil_kind=LLVM + dsymutil_vers=`echo $dsymutil_temp | sed 's/.*LLVM\ version\ \([0-9\.]*\).*/\1/'` + else + dsymutil_kind=UNKNOWN + dsymutil_vers="0.0" + fi + dsymutil_major=`expr "$dsymutil_vers" : '\([0-9]*\)'` + dsymutil_minor=`expr "$dsymutil_vers" : '[0-9]*\.\([0-9]*\)'` + dsymutil_tiny=`expr "$dsymutil_vers" : '[0-9]*\.[0-9]*\.\([0-9]*\)'` + if test x"${dsymutil_minor}" = x; then + dsymutil_minor=0 + fi + if test x"${dsymutil_tiny}" = x; then + dsymutil_tiny=0 + fi + +cat >>confdefs.h <<_ACEOF +#define DSYMUTIL_VERSION $dsymutil_kind,${dsymutil_major},${dsymutil_minor},${dsymutil_tiny} +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dsymutil_vers : $dsymutil_kind ${dsymutil_major} ${dsymutil_minor} ${dsymutil_tiny} " >&5 +$as_echo "$dsymutil_vers : $dsymutil_kind ${dsymutil_major} ${dsymutil_minor} ${dsymutil_tiny} " >&6; } +fi + case $target_os in win32 | pe | cygwin* | mingw32*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking broken PE linker dwarf5 support" >&5 @@ -33014,6 +33170,7 @@ do "as") CONFIG_FILES="$CONFIG_FILES as:exec-tool.in" ;; "collect-ld") CONFIG_FILES="$CONFIG_FILES collect-ld:exec-tool.in" ;; "nm") CONFIG_FILES="$CONFIG_FILES nm:exec-tool.in" ;; + "dsymutil") CONFIG_FILES="$CONFIG_FILES dsymutil:exec-tool.in" ;; "clearcap.map") CONFIG_LINKS="$CONFIG_LINKS clearcap.map:${srcdir}/config/$clearcap_map" ;; "$all_outputs") CONFIG_FILES="$CONFIG_FILES $all_outputs" ;; "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; @@ -33648,6 +33805,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} "as":F) chmod +x as ;; "collect-ld":F) chmod +x collect-ld ;; "nm":F) chmod +x nm ;; + "dsymutil":F) chmod +x dsymutil ;; "default":C) case ${CONFIG_HEADERS} in *auto-host.h:config.in*) diff --git a/gcc/configure.ac b/gcc/configure.ac index 7008939..26da073 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -316,8 +316,14 @@ gnu_ld_flag="$with_gnu_ld", gnu_ld_flag=no) case $target in - *darwin*) ld64_flag=yes;; # Darwin can only use a ld64-compatible linker. - *) ld64_flag=no;; + *darwin*) + ld64_flag=yes # Darwin can only use a ld64-compatible linker. + dsymutil_flag=yes # Darwin uses dsymutil to link debug. + ;; + *) + ld64_flag=no + dsymutil_flag=no + ;; esac # With pre-defined ld @@ -353,6 +359,31 @@ AC_ARG_WITH(demangler-in-ld, demangler_in_ld="$with_demangler_in_ld", demangler_in_ld=yes) +# Allow the user to specify a dsymutil executable (used on Darwin only, so far) +AC_ARG_WITH(dsymutil, +[AS_HELP_STRING([--with-dsymutil], [arrange to use the specified dsymutil (full pathname)])], +DEFAULT_DSYMUTIL="$with_dsymutil") + +dsymutil_vers= +if test x"${DEFAULT_DSYMUTIL+set}" = x"set"; then + if test ! -x "$DEFAULT_DSYMUTIL"; then + AC_MSG_ERROR([cannot execute: $DEFAULT_DSYMUTIL: check --with-dsymutil or env. var. DEFAULT_DSYMUTIL]) + else + if dsymutil_vers=`$DEFAULT_DSYMUTIL -v /dev/null 2>&1`; then + dsymutil_flag=yes + fi + fi + AC_DEFINE_UNQUOTED(DEFAULT_DSYMUTIL,"$DEFAULT_DSYMUTIL", + [Define to enable the use of a default debug linker.]) +fi + +AC_MSG_CHECKING([whether a default dsymutil was specified]) +if test x"${DEFAULT_DSYMUTIL+set}" = x"set"; then + AC_MSG_RESULT([yes ($DEFAULT_DSYMUTIL)]) +else + AC_MSG_RESULT(no) +fi + # ---------------------- # Find default assembler # ---------------------- @@ -2852,6 +2883,27 @@ else AC_MSG_RESULT($gcc_cv_otool) fi +# Figure out the dsymutil we will use. +AS_VAR_SET_IF(gcc_cv_dsymutil,, [ +if test -x "$DEFAULT_DSYMUTIL"; then + gcc_cv_dsymutil="$DEFAULT_DSYMUTIL" +elif test -x dsymutil$build_exeext; then + gcc_cv_dsymutil=./dsymutil$build_exeext +elif ( set dummy $DSYMUTIL_FOR_TARGET; test -x $[2] ); then + gcc_cv_dsymutil=$DSYMUTIL_FOR_TARGET +elif ( set dummy $DSYMUTIL; test -x $[2] ); then + gcc_cv_dsymutil=$DSYMUTIL +else + AC_PATH_PROG(gcc_cv_dsymutil, $DSYMUTIL_FOR_TARGET) +fi]) + +ORIGINAL_DSYMUTIL_FOR_TARGET=$gcc_cv_dsymutil +AC_SUBST(ORIGINAL_DSYMUTIL_FOR_TARGET) +case "$ORIGINAL_DSYMUTIL_FOR_TARGET" in + ./dsymutil | ./dsymutil$build_exeext) ;; + *) AC_CONFIG_FILES(dsymutil:exec-tool.in, [chmod +x dsymutil]) ;; +esac + # Figure out what assembler alignment features are present. gcc_GAS_CHECK_FEATURE([.balign and .p2align], gcc_cv_as_balign_and_p2align, [2,6,0],, @@ -6240,6 +6292,46 @@ if test x"$ld64_flag" = x"yes"; then [Define to 1 if ld64 supports '-export_dynamic'.]) fi +if test x"$dsymutil_flag" = x"yes"; then + + # If the user specified a dsymutil path, then we will already have the + # version string, otherwise, pick it up. + if test x"$gcc_cv_dsymutil" = x; then + AC_MSG_WARN([dsymutil is a required tool for this system, but not found]) + dsymutil_vers="tool unspecified" + elif test x"$dsymutil_vers" = x; then + dsymutil_vers=`$gcc_cv_dsymutil -v /dev/null 2>&1` + fi + + dsymutil_temp=`echo $dsymutil_vers | sed 1q` + AC_MSG_CHECKING(dsymutil version "$dsymutil_temp") + if echo $dsymutil_temp | grep dwarfutils- > /dev/null; then + dsymutil_kind=DWARFUTILS + dsymutil_vers=`echo $dsymutil_temp | sed 's/.*dwarfutils-\([[0-9\.]]*\).*/\1/'` + elif echo $dsymutil_temp | grep clang- > /dev/null; then + dsymutil_kind=CLANG + dsymutil_vers=`echo $dsymutil_temp | sed 's/.*clang-\([[0-9\.]]*\).*/\1/'` + elif echo $dsymutil_temp | grep 'LLVM version ' > /dev/null; then + dsymutil_kind=LLVM + dsymutil_vers=`echo $dsymutil_temp | sed 's/.*LLVM\ version\ \([[0-9\.]]*\).*/\1/'` + else + dsymutil_kind=UNKNOWN + dsymutil_vers="0.0" + fi + dsymutil_major=`expr "$dsymutil_vers" : '\([[0-9]]*\)'` + dsymutil_minor=`expr "$dsymutil_vers" : '[[0-9]]*\.\([[0-9]]*\)'` + dsymutil_tiny=`expr "$dsymutil_vers" : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` + if test x"${dsymutil_minor}" = x; then + dsymutil_minor=0 + fi + if test x"${dsymutil_tiny}" = x; then + dsymutil_tiny=0 + fi + AC_DEFINE_UNQUOTED(DSYMUTIL_VERSION, [$dsymutil_kind,${dsymutil_major},${dsymutil_minor},${dsymutil_tiny}], + [Define to the dsymutil version.]) + AC_MSG_RESULT($dsymutil_vers : $dsymutil_kind ${dsymutil_major} ${dsymutil_minor} ${dsymutil_tiny} ) +fi + case $target_os in win32 | pe | cygwin* | mingw32*) AC_MSG_CHECKING(broken PE linker dwarf5 support) diff --git a/gcc/exec-tool.in b/gcc/exec-tool.in index 9884601..c206a25 100644 --- a/gcc/exec-tool.in +++ b/gcc/exec-tool.in @@ -25,6 +25,7 @@ ORIGINAL_LD_BFD_FOR_TARGET="@ORIGINAL_LD_BFD_FOR_TARGET@" ORIGINAL_LD_GOLD_FOR_TARGET="@ORIGINAL_LD_GOLD_FOR_TARGET@" ORIGINAL_PLUGIN_LD_FOR_TARGET="@ORIGINAL_PLUGIN_LD_FOR_TARGET@" ORIGINAL_NM_FOR_TARGET="@ORIGINAL_NM_FOR_TARGET@" +ORIGINAL_DSYMUTIL_FOR_TARGET="@ORIGINAL_DSYMUTIL_FOR_TARGET@" exeext=@host_exeext@ fast_install=@enable_fast_install@ objdir=@objdir@ @@ -71,6 +72,13 @@ case "$invoked" in prog=nm-new$exeext dir=binutils ;; + dsymutil) + original=$ORIGINAL_DSYMUTIL_FOR_TARGET + # We do not build this in tree - but still want to be able to execute + # a configured version from the build dir. + prog= + dir= + ;; esac case "$original" in diff --git a/gcc/gcc.c b/gcc/gcc.c index c8dbff6..36a88fc 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -3062,6 +3062,11 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode, return xstrdup (DEFAULT_LINKER); #endif +#ifdef DEFAULT_DSYMUTIL + if (! strcmp (name, "dsymutil") && access (DEFAULT_DSYMUTIL, mode) == 0) + return xstrdup (DEFAULT_DSYMUTIL); +#endif + /* Determine the filename to execute (special case for absolute paths). */ if (IS_ABSOLUTE_PATH (name)) -- cgit v1.1 From 3c44b412fec8d5ab7fc064065414314a8ae05c87 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Mon, 28 Jun 2021 20:48:44 -0700 Subject: Fix PR 101237: Remove element_type call when used with the functions from real HONOR_SIGNED_ZEROS, HONOR_SIGN_DEPENDENT_ROUNDING, and HONOR_SNANS all have an overload for taking a tree type now, so we should do that instead. OK? Bootstrapped and tested on x86_64-linux-gnu. gcc/ChangeLog: PR middle-end/101237 * fold-const.c (negate_expr_p): Remove call to element_mode and TREE_MODE/TREE_TYPE when calling HONOR_SIGNED_ZEROS, HONOR_SIGN_DEPENDENT_ROUNDING, and HONOR_SNANS. (fold_negate_expr_1): Likewise. (const_unop): Likewise. (fold_cond_expr_with_comparison): Likewise. (fold_binary_loc): Likewise. (fold_ternary_loc): Likewise. (tree_call_nonnegative_warnv_p): Likewise. * match.pd (-(A + B) -> (-B) - A): Likewise. --- gcc/fold-const.c | 46 +++++++++++++++++++++++----------------------- gcc/match.pd | 4 ++-- 2 files changed, 25 insertions(+), 25 deletions(-) (limited to 'gcc') diff --git a/gcc/fold-const.c b/gcc/fold-const.c index dfccbae..e0cdb75 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -432,8 +432,8 @@ negate_expr_p (tree t) return negate_expr_p (TREE_OPERAND (t, 0)); case PLUS_EXPR: - if (HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)) - || HONOR_SIGNED_ZEROS (element_mode (type)) + if (HONOR_SIGN_DEPENDENT_ROUNDING (type) + || HONOR_SIGNED_ZEROS (type) || (ANY_INTEGRAL_TYPE_P (type) && ! TYPE_OVERFLOW_WRAPS (type))) return false; @@ -445,8 +445,8 @@ negate_expr_p (tree t) case MINUS_EXPR: /* We can't turn -(A-B) into B-A when we honor signed zeros. */ - return !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)) - && !HONOR_SIGNED_ZEROS (element_mode (type)) + return !HONOR_SIGN_DEPENDENT_ROUNDING (type) + && !HONOR_SIGNED_ZEROS (type) && (! ANY_INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_WRAPS (type)); @@ -468,7 +468,7 @@ negate_expr_p (tree t) /* Fall through. */ case RDIV_EXPR: - if (! HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (TREE_TYPE (t)))) + if (! HONOR_SIGN_DEPENDENT_ROUNDING (t)) return negate_expr_p (TREE_OPERAND (t, 1)) || negate_expr_p (TREE_OPERAND (t, 0)); break; @@ -605,8 +605,8 @@ fold_negate_expr_1 (location_t loc, tree t) break; case PLUS_EXPR: - if (!HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)) - && !HONOR_SIGNED_ZEROS (element_mode (type))) + if (!HONOR_SIGN_DEPENDENT_ROUNDING (type) + && !HONOR_SIGNED_ZEROS (type)) { /* -(A + B) -> (-B) - A. */ if (negate_expr_p (TREE_OPERAND (t, 1))) @@ -628,8 +628,8 @@ fold_negate_expr_1 (location_t loc, tree t) case MINUS_EXPR: /* - (A - B) -> B - A */ - if (!HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)) - && !HONOR_SIGNED_ZEROS (element_mode (type))) + if (!HONOR_SIGN_DEPENDENT_ROUNDING (type) + && !HONOR_SIGNED_ZEROS (type)) return fold_build2_loc (loc, MINUS_EXPR, type, TREE_OPERAND (t, 1), TREE_OPERAND (t, 0)); break; @@ -641,7 +641,7 @@ fold_negate_expr_1 (location_t loc, tree t) /* Fall through. */ case RDIV_EXPR: - if (! HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))) + if (! HONOR_SIGN_DEPENDENT_ROUNDING (type)) { tem = TREE_OPERAND (t, 1); if (negate_expr_p (tem)) @@ -1725,7 +1725,7 @@ const_unop (enum tree_code code, tree type, tree arg0) /* Don't perform the operation, other than NEGATE and ABS, if flag_signaling_nans is on and the operand is a signaling NaN. */ if (TREE_CODE (arg0) == REAL_CST - && HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))) + && HONOR_SNANS (arg0) && REAL_VALUE_ISSIGNALING_NAN (TREE_REAL_CST (arg0)) && code != NEGATE_EXPR && code != ABS_EXPR @@ -2135,7 +2135,7 @@ fold_convert_const_real_from_real (tree type, const_tree arg1) /* Don't perform the operation if flag_signaling_nans is on and the operand is a signaling NaN. */ - if (HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))) + if (HONOR_SNANS (arg1) && REAL_VALUE_ISSIGNALING_NAN (TREE_REAL_CST (arg1))) return NULL_TREE; @@ -5773,7 +5773,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type, Note that all these transformations are correct if A is NaN, since the two alternatives (A and -A) are also NaNs. */ - if (!HONOR_SIGNED_ZEROS (element_mode (type)) + if (!HONOR_SIGNED_ZEROS (type) && (FLOAT_TYPE_P (TREE_TYPE (arg01)) ? real_zerop (arg01) : integer_zerop (arg01)) @@ -5842,7 +5842,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type, both transformations are correct when A is NaN: A != 0 is then true, and A == 0 is false. */ - if (!HONOR_SIGNED_ZEROS (element_mode (type)) + if (!HONOR_SIGNED_ZEROS (type) && integer_zerop (arg01) && integer_zerop (arg2)) { if (comp_code == NE_EXPR) @@ -5877,7 +5877,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type, a number and A is not. The conditions in the original expressions will be false, so all four give B. The min() and max() versions would give a NaN instead. */ - if (!HONOR_SIGNED_ZEROS (element_mode (type)) + if (!HONOR_SIGNED_ZEROS (type) && operand_equal_for_comparison_p (arg01, arg2) /* Avoid these transformations if the COND_EXPR may be used as an lvalue in the C++ front-end. PR c++/19199. */ @@ -11005,8 +11005,8 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type, /* Fold __complex__ ( x, 0 ) + __complex__ ( 0, y ) to __complex__ ( x, y ). This is not the same for SNaNs or if signed zeros are involved. */ - if (!HONOR_SNANS (element_mode (arg0)) - && !HONOR_SIGNED_ZEROS (element_mode (arg0)) + if (!HONOR_SNANS (arg0) + && !HONOR_SIGNED_ZEROS (arg0) && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0))) { tree rtype = TREE_TYPE (TREE_TYPE (arg0)); @@ -11404,8 +11404,8 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type, /* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to __complex__ ( x, -y ). This is not the same for SNaNs or if signed zeros are involved. */ - if (!HONOR_SNANS (element_mode (arg0)) - && !HONOR_SIGNED_ZEROS (element_mode (arg0)) + if (!HONOR_SNANS (arg0) + && !HONOR_SIGNED_ZEROS (arg0) && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0))) { tree rtype = TREE_TYPE (TREE_TYPE (arg0)); @@ -11509,7 +11509,7 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type, This is not the same for NaNs or if signed zeros are involved. */ if (!HONOR_NANS (arg0) - && !HONOR_SIGNED_ZEROS (element_mode (arg0)) + && !HONOR_SIGNED_ZEROS (arg0) && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)) && TREE_CODE (arg1) == COMPLEX_CST && real_zerop (TREE_REALPART (arg1))) @@ -12819,7 +12819,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type, Also try swapping the arguments and inverting the conditional. */ if (COMPARISON_CLASS_P (arg0) && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), op1) - && !HONOR_SIGNED_ZEROS (element_mode (op1))) + && !HONOR_SIGNED_ZEROS (op1)) { tem = fold_cond_expr_with_comparison (loc, type, TREE_CODE (arg0), TREE_OPERAND (arg0, 0), @@ -12831,7 +12831,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type, if (COMPARISON_CLASS_P (arg0) && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), op2) - && !HONOR_SIGNED_ZEROS (element_mode (op2))) + && !HONOR_SIGNED_ZEROS (op2)) { enum tree_code comp_code = TREE_CODE (arg0); tree arg00 = TREE_OPERAND (arg0, 0); @@ -14713,7 +14713,7 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, CASE_CFN_SQRT: CASE_CFN_SQRT_FN: /* sqrt(-0.0) is -0.0. */ - if (!HONOR_SIGNED_ZEROS (element_mode (type))) + if (!HONOR_SIGNED_ZEROS (type)) return true; return RECURSE (arg0); diff --git a/gcc/match.pd b/gcc/match.pd index 8205271..4e10d54 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1458,8 +1458,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* -(A + B) -> (-B) - A. */ (simplify (negate (plus:c @0 negate_expr_p@1)) - (if (!HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)) - && !HONOR_SIGNED_ZEROS (element_mode (type))) + (if (!HONOR_SIGN_DEPENDENT_ROUNDING (type) + && !HONOR_SIGNED_ZEROS (type)) (minus (negate @1) @0))) /* -(A - B) -> B - A. */ -- cgit v1.1 From cd48e550d1dc58307ab1c0ab490745673f748ccc Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Fri, 11 Jun 2021 13:21:34 -0700 Subject: Allow match-and-simplified phiopt to run in early phiopt To move a few things more to match-and-simplify from phiopt, we need to allow match_simplify_replacement to run in early phiopt. To do this we add a replacement for gimple_simplify that is explictly for phiopt. OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions. gcc/ChangeLog: * tree-ssa-phiopt.c (match_simplify_replacement): Add early_p argument. Call gimple_simplify_phiopt instead of gimple_simplify. (tree_ssa_phiopt_worker): Update call to match_simplify_replacement and allow unconditionally. (phiopt_early_allow): New function. (gimple_simplify_phiopt): New function. --- gcc/tree-ssa-phiopt.c | 89 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 19 deletions(-) (limited to 'gcc') diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index ab12e85..17bc597 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -50,12 +50,13 @@ along with GCC; see the file COPYING3. If not see #include "gimple-fold.h" #include "internal-fn.h" #include "gimple-range.h" +#include "gimple-match.h" static unsigned int tree_ssa_phiopt_worker (bool, bool, bool); static bool two_value_replacement (basic_block, basic_block, edge, gphi *, tree, tree); static bool match_simplify_replacement (basic_block, basic_block, - edge, edge, gphi *, tree, tree); + edge, edge, gphi *, tree, tree, bool); static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree, gimple *); static int value_replacement (basic_block, basic_block, @@ -345,9 +346,9 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p) /* Do the replacement of conditional if it can be done. */ if (!early_p && two_value_replacement (bb, bb1, e2, phi, arg0, arg1)) cfgchanged = true; - else if (!early_p - && match_simplify_replacement (bb, bb1, e1, e2, phi, - arg0, arg1)) + else if (match_simplify_replacement (bb, bb1, e1, e2, phi, + arg0, arg1, + early_p)) cfgchanged = true; else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) cfgchanged = true; @@ -811,6 +812,67 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb, return true; } +/* Return TRUE if CODE should be allowed during early phiopt. + Currently this is to allow MIN/MAX and ABS/NEGATE. */ +static bool +phiopt_early_allow (enum tree_code code) +{ + switch (code) + { + case MIN_EXPR: + case MAX_EXPR: + case ABS_EXPR: + case ABSU_EXPR: + case NEGATE_EXPR: + case SSA_NAME: + return true; + default: + return false; + } +} + +/* gimple_simplify_phiopt is like gimple_simplify but designed for PHIOPT. + Return NULL if nothing can be simplified or the resulting simplified value + with parts pushed if EARLY_P was true. Also rejects non allowed tree code + if EARLY_P is set. + Takes the comparison from COMP_STMT and two args, ARG0 and ARG1 and tries + to simplify CMP ? ARG0 : ARG1. */ +static tree +gimple_simplify_phiopt (bool early_p, tree type, gimple *comp_stmt, + tree arg0, tree arg1, + gimple_seq *seq) +{ + tree result; + enum tree_code comp_code = gimple_cond_code (comp_stmt); + location_t loc = gimple_location (comp_stmt); + tree cmp0 = gimple_cond_lhs (comp_stmt); + tree cmp1 = gimple_cond_rhs (comp_stmt); + /* To handle special cases like floating point comparison, it is easier and + less error-prone to build a tree and gimplify it on the fly though it is + less efficient. + Don't use fold_build2 here as that might create (bool)a instead of just + "a != 0". */ + tree cond = build2_loc (loc, comp_code, boolean_type_node, + cmp0, cmp1); + gimple_match_op op (gimple_match_cond::UNCOND, + COND_EXPR, type, cond, arg0, arg1); + + if (op.resimplify (early_p ? NULL : seq, follow_all_ssa_edges)) + { + /* Early we want only to allow some generated tree codes. */ + if (!early_p + || op.code.is_tree_code () + || phiopt_early_allow ((tree_code)op.code)) + { + result = maybe_push_res_to_seq (&op, seq); + if (result) + return result; + } + } + + return NULL; +} + /* The function match_simplify_replacement does the main work of doing the replacement using match and simplify. Return true if the replacement is done. Otherwise return false. @@ -820,10 +882,9 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb, static bool match_simplify_replacement (basic_block cond_bb, basic_block middle_bb, edge e0, edge e1, gphi *phi, - tree arg0, tree arg1) + tree arg0, tree arg1, bool early_p) { gimple *stmt; - tree cond; gimple_stmt_iterator gsi; edge true_edge, false_edge; gimple_seq seq = NULL; @@ -884,15 +945,6 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb, stmt = last_stmt (cond_bb); - /* To handle special cases like floating point comparison, it is easier and - less error-prone to build a tree and gimplify it on the fly though it is - less efficient. - Don't use fold_build2 here as that might create (bool)a instead of just - "a != 0". */ - cond = build2_loc (gimple_location (stmt), - gimple_cond_code (stmt), boolean_type_node, - gimple_cond_lhs (stmt), gimple_cond_rhs (stmt)); - /* We need to know which is the true edge and which is the false edge so that we know when to invert the condition below. */ extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge); @@ -900,10 +952,9 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb, std::swap (arg0, arg1); tree type = TREE_TYPE (gimple_phi_result (phi)); - result = gimple_simplify (COND_EXPR, type, - cond, - arg0, arg1, - &seq, NULL); + result = gimple_simplify_phiopt (early_p, type, stmt, + arg0, arg1, + &seq); if (!result) return false; -- cgit v1.1 From a50cecb20a10a729b3f5f157b154d28f9937a652 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Sat, 12 Jun 2021 19:14:46 -0700 Subject: Try inverted comparison for match_simplify in phiopt Since match and simplify does not have all of the inverted comparison patterns, it make sense to just have phi-opt try to do the inversion and try match and simplify again. OK? Bootstrapped and tested on x86_64-linux-gnu. Thanks, Andrew Pinski gcc/ChangeLog: * tree-ssa-phiopt.c (gimple_simplify_phiopt): If "A ? B : C" fails to simplify, try "(!A) ? C : B". --- gcc/tree-ssa-phiopt.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 17bc597..f8d7ae1 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -836,7 +836,8 @@ phiopt_early_allow (enum tree_code code) with parts pushed if EARLY_P was true. Also rejects non allowed tree code if EARLY_P is set. Takes the comparison from COMP_STMT and two args, ARG0 and ARG1 and tries - to simplify CMP ? ARG0 : ARG1. */ + to simplify CMP ? ARG0 : ARG1. + Also try to simplify (!CMP) ? ARG1 : ARG0 if the non-inverse failed. */ static tree gimple_simplify_phiopt (bool early_p, tree type, gimple *comp_stmt, tree arg0, tree arg1, @@ -869,6 +870,30 @@ gimple_simplify_phiopt (bool early_p, tree type, gimple *comp_stmt, return result; } } + /* Try the inverted comparison, that is !COMP ? ARG1 : ARG0. */ + comp_code = invert_tree_comparison (comp_code, HONOR_NANS (cmp0)); + + if (comp_code == ERROR_MARK) + return NULL; + + cond = build2_loc (loc, + comp_code, boolean_type_node, + cmp0, cmp1); + gimple_match_op op1 (gimple_match_cond::UNCOND, + COND_EXPR, type, cond, arg1, arg0); + + if (op1.resimplify (early_p ? NULL : seq, follow_all_ssa_edges)) + { + /* Early we want only to allow some generated tree codes. */ + if (!early_p + || op1.code.is_tree_code () + || phiopt_early_allow ((tree_code)op1.code)) + { + result = maybe_push_res_to_seq (&op1, seq); + if (result) + return result; + } + } return NULL; } -- cgit v1.1 From 7d6979197274a662da7bdc564314afe8415865c1 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Sat, 12 Jun 2021 19:45:20 -0700 Subject: Port most of the A CMP 0 ? A : -A to match To improve phiopt and be able to remove abs_replacement, this ports most of "A CMP 0 ? A : -A" from fold_cond_expr_with_comparison to match.pd. There is a few extra changes that are needed to remove the "A CMP 0 ? A : -A" part from fold_cond_expr_with_comparison: * Need to handle (A - B) case * Need to handle UN* comparisons. I will handle those in a different patch. Note phi-opt-15.c test needed to be updated as we get ABSU now instead of not getting ABS. When ABSU was added phiopt was not updated even to use ABSU instead of not creating ABS. OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions. gcc/ChangeLog: PR tree-optimization/101039 * match.pd (A CMP 0 ? A : -A): New patterns. * tree-ssa-phiopt.c (abs_replacement): Delete function. (tree_ssa_phiopt_worker): Don't call abs_replacement. Update comment about abs_replacement. gcc/testsuite/ChangeLog: PR tree-optimization/101039 * gcc.dg/tree-ssa/phi-opt-15.c: Update test to expect ABSU and still not expect ABS_EXPR. * gcc.dg/tree-ssa/phi-opt-23.c: New test. * gcc.dg/tree-ssa/phi-opt-24.c: New test. --- gcc/match.pd | 60 +++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c | 4 +- gcc/testsuite/gcc.dg/tree-ssa/phi-opt-23.c | 44 ++++++++++ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-24.c | 44 ++++++++++ gcc/tree-ssa-phiopt.c | 134 +---------------------------- 5 files changed, 152 insertions(+), 134 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-23.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-24.c (limited to 'gcc') diff --git a/gcc/match.pd b/gcc/match.pd index 4e10d54..72860fb 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3976,6 +3976,66 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (cnd (logical_inverted_value truth_valued_p@0) @1 @2) (cnd @0 @2 @1))) +/* abs/negative simplifications moved from fold_cond_expr_with_comparison, + Need to handle (A - B) case as fold_cond_expr_with_comparison does. + Need to handle UN* comparisons. + + None of these transformations work for modes with signed + zeros. If A is +/-0, the first two transformations will + change the sign of the result (from +0 to -0, or vice + versa). The last four will fix the sign of the result, + even though the original expressions could be positive or + negative, depending on the sign of A. + + Note that all these transformations are correct if A is + NaN, since the two alternatives (A and -A) are also NaNs. */ + +(for cnd (cond vec_cond) + /* A == 0 ? A : -A same as -A */ + (for cmp (eq uneq) + (simplify + (cnd (cmp @0 zerop) @0 (negate@1 @0)) + (if (!HONOR_SIGNED_ZEROS (type)) + @1)) + (simplify + (cnd (cmp @0 zerop) integer_zerop (negate@1 @0)) + (if (!HONOR_SIGNED_ZEROS (type)) + @1)) + ) + /* A != 0 ? A : -A same as A */ + (for cmp (ne ltgt) + (simplify + (cnd (cmp @0 zerop) @0 (negate @0)) + (if (!HONOR_SIGNED_ZEROS (type)) + @0)) + (simplify + (cnd (cmp @0 zerop) @0 integer_zerop) + (if (!HONOR_SIGNED_ZEROS (type)) + @0)) + ) + /* A >=/> 0 ? A : -A same as abs (A) */ + (for cmp (ge gt) + (simplify + (cnd (cmp @0 zerop) @0 (negate @0)) + (if (!HONOR_SIGNED_ZEROS (type) + && !TYPE_UNSIGNED (type)) + (abs @0)))) + /* A <=/< 0 ? A : -A same as -abs (A) */ + (for cmp (le lt) + (simplify + (cnd (cmp @0 zerop) @0 (negate @0)) + (if (!HONOR_SIGNED_ZEROS (type) + && !TYPE_UNSIGNED (type)) + (if (ANY_INTEGRAL_TYPE_P (type) + && !TYPE_OVERFLOW_WRAPS (type)) + (with { + tree utype = unsigned_type_for (type); + } + (convert (negate (absu:utype @0)))) + (negate (abs @0))))) + ) +) + /* -(type)!A -> (type)A - 1. */ (simplify (negate (convert?:s (logical_inverted_value:s @0))) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c index ac3018e..6aec689 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c @@ -9,4 +9,6 @@ foo (int i) return i; } -/* { dg-final { scan-tree-dump-not "ABS" "optimized" } } */ +/* We should not have ABS_EXPR but ABSU_EXPR instead. */ +/* { dg-final { scan-tree-dump-not "ABS_EXPR" "optimized" } } */ +/* { dg-final { scan-tree-dump "ABSU" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-23.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-23.c new file mode 100644 index 0000000..ff658cd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-23.c @@ -0,0 +1,44 @@ +/* { dg-options "-O2 -fdump-tree-phiopt" } */ + +int f0(int A) +{ +// A == 0? A : -A same as -A + if (A == 0) return A; + return -A; +} + +int f1(int A) +{ +// A != 0? A : -A same as A + if (A != 0) return A; + return -A; +} +int f2(int A) +{ +// A >= 0? A : -A same as abs (A) + if (A >= 0) return A; + return -A; +} +int f3(int A) +{ +// A > 0? A : -A same as abs (A) + if (A > 0) return A; + return -A; +} +int f4(int A) +{ +// A <= 0? A : -A same as -abs (A) + if (A <= 0) return A; + return -A; +} +int f5(int A) +{ +// A < 0? A : -A same as -abs (A) + if (A < 0) return A; + return -A; +} + +/* These should be optimized in phiopt1 but is confused by predicts. */ +/* { dg-final { scan-tree-dump-not "if" "phiopt1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-not "if" "phiopt2" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-24.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-24.c new file mode 100644 index 0000000..eb89dec --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-24.c @@ -0,0 +1,44 @@ +/* { dg-options "-O2 -fno-signed-zeros -fdump-tree-phiopt" } */ + +float f0(float A) +{ +// A == 0? A : -A same as -A + if (A == 0) return A; + return -A; +} + +float f1(float A) +{ +// A != 0? A : -A same as A + if (A != 0) return A; + return -A; +} +float f2(float A) +{ +// A >= 0? A : -A same as abs (A) + if (A >= 0) return A; + return -A; +} +float f3(float A) +{ +// A > 0? A : -A same as abs (A) + if (A > 0) return A; + return -A; +} +float f4(float A) +{ +// A <= 0? A : -A same as -abs (A) + if (A <= 0) return A; + return -A; +} +float f5(float A) +{ +// A < 0? A : -A same as -abs (A) + if (A < 0) return A; + return -A; +} + +/* These should be optimized in phiopt1 but is confused by predicts. */ +/* { dg-final { scan-tree-dump-not "if" "phiopt1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-not "if" "phiopt2" } } */ + diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index f8d7ae1..ab63bf6 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -63,8 +63,6 @@ static int value_replacement (basic_block, basic_block, edge, edge, gphi *, tree, tree); static bool minmax_replacement (basic_block, basic_block, edge, edge, gphi *, tree, tree); -static bool abs_replacement (basic_block, basic_block, - edge, edge, gphi *, tree, tree); static bool spaceship_replacement (basic_block, basic_block, edge, edge, gphi *, tree, tree); static bool cond_removal_in_popcount_clz_ctz_pattern (basic_block, basic_block, @@ -350,8 +348,6 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p) arg0, arg1, early_p)) cfgchanged = true; - else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) - cfgchanged = true; else if (!early_p && cond_removal_in_popcount_clz_ctz_pattern (bb, bb1, e1, e2, phi, arg0, @@ -2606,134 +2602,6 @@ cond_removal_in_popcount_clz_ctz_pattern (basic_block cond_bb, return true; } -/* The function absolute_replacement does the main work of doing the absolute - replacement. Return true if the replacement is done. Otherwise return - false. - bb is the basic block where the replacement is going to be done on. arg0 - is argument 0 from the phi. Likewise for arg1. */ - -static bool -abs_replacement (basic_block cond_bb, basic_block middle_bb, - edge e0 ATTRIBUTE_UNUSED, edge e1, - gphi *phi, tree arg0, tree arg1) -{ - tree result; - gassign *new_stmt; - gimple *cond; - gimple_stmt_iterator gsi; - edge true_edge, false_edge; - gimple *assign; - edge e; - tree rhs, lhs; - bool negate; - enum tree_code cond_code; - - /* If the type says honor signed zeros we cannot do this - optimization. */ - if (HONOR_SIGNED_ZEROS (arg1)) - return false; - - /* OTHER_BLOCK must have only one executable statement which must have the - form arg0 = -arg1 or arg1 = -arg0. */ - - assign = last_and_only_stmt (middle_bb); - /* If we did not find the proper negation assignment, then we cannot - optimize. */ - if (assign == NULL) - return false; - - /* If we got here, then we have found the only executable statement - in OTHER_BLOCK. If it is anything other than arg = -arg1 or - arg1 = -arg0, then we cannot optimize. */ - if (gimple_code (assign) != GIMPLE_ASSIGN) - return false; - - lhs = gimple_assign_lhs (assign); - - if (gimple_assign_rhs_code (assign) != NEGATE_EXPR) - return false; - - rhs = gimple_assign_rhs1 (assign); - - /* The assignment has to be arg0 = -arg1 or arg1 = -arg0. */ - if (!(lhs == arg0 && rhs == arg1) - && !(lhs == arg1 && rhs == arg0)) - return false; - - cond = last_stmt (cond_bb); - result = PHI_RESULT (phi); - - /* Only relationals comparing arg[01] against zero are interesting. */ - cond_code = gimple_cond_code (cond); - if (cond_code != GT_EXPR && cond_code != GE_EXPR - && cond_code != LT_EXPR && cond_code != LE_EXPR) - return false; - - /* Make sure the conditional is arg[01] OP y. */ - if (gimple_cond_lhs (cond) != rhs) - return false; - - if (FLOAT_TYPE_P (TREE_TYPE (gimple_cond_rhs (cond))) - ? real_zerop (gimple_cond_rhs (cond)) - : integer_zerop (gimple_cond_rhs (cond))) - ; - else - return false; - - /* We need to know which is the true edge and which is the false - edge so that we know if have abs or negative abs. */ - extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge); - - /* For GT_EXPR/GE_EXPR, if the true edge goes to OTHER_BLOCK, then we - will need to negate the result. Similarly for LT_EXPR/LE_EXPR if - the false edge goes to OTHER_BLOCK. */ - if (cond_code == GT_EXPR || cond_code == GE_EXPR) - e = true_edge; - else - e = false_edge; - - if (e->dest == middle_bb) - negate = true; - else - negate = false; - - /* If the code negates only iff positive then make sure to not - introduce undefined behavior when negating or computing the absolute. - ??? We could use range info if present to check for arg1 == INT_MIN. */ - if (negate - && (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg1)) - && ! TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg1)))) - return false; - - result = duplicate_ssa_name (result, NULL); - - if (negate) - lhs = make_ssa_name (TREE_TYPE (result)); - else - lhs = result; - - /* Build the modify expression with abs expression. */ - new_stmt = gimple_build_assign (lhs, ABS_EXPR, rhs); - - gsi = gsi_last_bb (cond_bb); - gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT); - - if (negate) - { - /* Get the right GSI. We want to insert after the recently - added ABS_EXPR statement (which we know is the first statement - in the block. */ - new_stmt = gimple_build_assign (result, NEGATE_EXPR, lhs); - - gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT); - } - - replace_phi_edge_with_variable (cond_bb, e1, phi, result); - - /* Note that we optimized this PHI. */ - return true; -} - /* Auxiliary functions to determine the set of memory accesses which can't trap because they are preceded by accesses to the same memory portion. We do that for MEM_REFs, so we only need to track @@ -3670,7 +3538,7 @@ gate_hoist_loads (void) ABS Replacement --------------- - This transformation, implemented in abs_replacement, replaces + This transformation, implemented in match_simplify_replacement, replaces bb0: if (a >= 0) goto bb2; else goto bb1; -- cgit v1.1 From 1562c7987be115311a75b1074c3768a1b006adb6 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Mon, 5 Jul 2021 17:23:43 -0400 Subject: Remove redundant compare in shift loop on H8 gcc/ChangeLog * config/h8300/shiftrotate.md (shift-by-variable patterns): Update to generate condition code aware RTL directly. --- gcc/config/h8300/shiftrotate.md | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/config/h8300/shiftrotate.md b/gcc/config/h8300/shiftrotate.md index 0476324..485303c 100644 --- a/gcc/config/h8300/shiftrotate.md +++ b/gcc/config/h8300/shiftrotate.md @@ -385,10 +385,15 @@ (parallel [(set (match_dup 0) (match_op_dup 2 [(match_dup 0) (const_int 1)])) - (clobber (scratch:QI))]) - (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1))) + (clobber (reg:CC CC_REG))]) + (parallel + [(set (reg:CCZN CC_REG) + (compare:CCZN + (plus:QI (match_dup 1) (const_int -1)) + (const_int 0))) + (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1)))]) (set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) + (if_then_else (ne (reg:CCZN CC_REG) (const_int 0)) (label_ref (match_dup 4)) (pc))) (match_dup 5)] @@ -416,10 +421,15 @@ (parallel [(set (match_dup 0) (match_op_dup 2 [(match_dup 0) (const_int 1)])) - (clobber (scratch:QI))]) - (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1))) + (clobber (reg:CC CC_REG))]) + (parallel + [(set (reg:CCZN CC_REG) + (compare:CCZN + (plus:QI (match_dup 3) (const_int -1)) + (const_int 0))) + (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1)))]) (set (pc) - (if_then_else (ne (match_dup 3) (const_int 0)) + (if_then_else (ne (reg:CCZN CC_REG) (const_int 0)) (label_ref (match_dup 4)) (pc))) (match_dup 5)] -- cgit v1.1 From 6d53e6f9c7ab06510953b9881550b54a24137d4d Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Tue, 6 Jul 2021 00:16:44 +0000 Subject: Daily bump. --- gcc/ChangeLog | 90 ++++++++++++ gcc/DATESTAMP | 2 +- gcc/ada/ChangeLog | 365 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 22 +++ 4 files changed, 478 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 88620d1..4e6b874 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,93 @@ +2021-07-05 Jeff Law + + * config/h8300/shiftrotate.md (shift-by-variable patterns): Update to + generate condition code aware RTL directly. + +2021-07-05 Andrew Pinski + + PR tree-optimization/101039 + * match.pd (A CMP 0 ? A : -A): New patterns. + * tree-ssa-phiopt.c (abs_replacement): Delete function. + (tree_ssa_phiopt_worker): Don't call abs_replacement. + Update comment about abs_replacement. + +2021-07-05 Andrew Pinski + + * tree-ssa-phiopt.c (gimple_simplify_phiopt): + If "A ? B : C" fails to simplify, try "(!A) ? C : B". + +2021-07-05 Andrew Pinski + + * tree-ssa-phiopt.c (match_simplify_replacement): + Add early_p argument. Call gimple_simplify_phiopt + instead of gimple_simplify. + (tree_ssa_phiopt_worker): Update call to + match_simplify_replacement and allow unconditionally. + (phiopt_early_allow): New function. + (gimple_simplify_phiopt): New function. + +2021-07-05 Andrew Pinski + + PR middle-end/101237 + * fold-const.c (negate_expr_p): Remove call to element_mode + and TREE_MODE/TREE_TYPE when calling HONOR_SIGNED_ZEROS, + HONOR_SIGN_DEPENDENT_ROUNDING, and HONOR_SNANS. + (fold_negate_expr_1): Likewise. + (const_unop): Likewise. + (fold_cond_expr_with_comparison): Likewise. + (fold_binary_loc): Likewise. + (fold_ternary_loc): Likewise. + (tree_call_nonnegative_warnv_p): Likewise. + * match.pd (-(A + B) -> (-B) - A): Likewise. + +2021-07-05 Iain Sandoe + + * configure.ac: Handle --with-dsymutil in the same way as we + do for the assembler and linker. (DEFAULT_DSYMUTIL): New. + Extract the type and version for the dsymutil configured or + found by the default searches. + * config.in: Regenerated. + * configure: Regenerated. + * collect2.c (do_dsymutil): Handle locating dsymutil in the + same way as for the assembler and linker. + * config/darwin.h (DSYMUTIL): Delete. + * gcc.c: Report a configured dsymutil correctly. + * exec-tool.in: Allow for dsymutil. + +2021-07-05 Uroš Bizjak + + * config/i386/i386-expand.c (ix86_split_mmx_punpck): + Handle V4QI and V2HI modes. + (expand_vec_perm_blend): Allow 4-byte vector modes with TARGET_SSE4_1. + Handle V4QI mode. Emit mmx_pblendvb32 for 4-byte modes. + (expand_vec_perm_pshufb): Rewrite to use switch statemets. + Handle 4-byte dual operands with TARGET_XOP and single operands + with TARGET_SSSE3. Emit mmx_ppermv32 for TARGET_XOP and + mmx_pshufbv4qi3 for TARGET_SSSE3. + (expand_vec_perm_pblendv): Allow 4-byte vector modes with TARGET_SSE4_1. + (expand_vec_perm_interleave2): Allow 4-byte vector modes. + (expand_vec_perm_pshufb2): Allow 4-byte vector modes with TARGET_SSSE3. + (expand_vec_perm_even_odd_1): Handle V4QI mode. + (expand_vec_perm_broadcast_1): Handle V4QI mode. + (ix86_vectorize_vec_perm_const): Handle V4QI mode. + * config/i386/mmx.md (mmx_ppermv32): New insn pattern. + (mmx_pshufbv4qi3): Ditto. + (*mmx_pblendw32): Ditto. + (*mmx_pblendw64): Rename from *mmx_pblendw. + (mmx_punpckhbw_low): New insn_and_split pattern. + (mmx_punpcklbw_low): Ditto. + +2021-07-05 Richard Biener + + * tree-vect-loop-manip.c (vect_loop_versioning): Do not + set LOOP_C_INFINITE on the vectorized loop. + +2021-07-05 Richard Biener + + PR middle-end/101291 + * cfgloopmanip.c (loop_version): Set the loop copy of the + versioned loop to the new loop. + 2021-07-04 Iain Sandoe PR target/100269 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7596b54..740061a 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210705 +20210706 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 923c8a6..d1116c9 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,368 @@ +2021-07-05 Pierre-Marie de Rodat + + * gnat-style.texi, gnat_rm.texi, gnat_ugn.texi: Regenerate. + +2021-07-05 Piotr Trojanek + + * sem_prag.adb (Analyze_Depends_In_Decl_Part): Reject overlays + in Depends and Refined_Depends contracts. + (Analyze_Global_In_Decl_Part): Likewise for Global and + Refined_Global. + (Analyze_Initializes_In_Decl_Part): Likewise for Initializes + (when appearing both as a single item and as a initialization + clause). + * sem_util.ads (Ultimate_Overlaid_Entity): New routine. + * sem_util.adb (Report_Unused_Body_States): Ignore overlays. + (Ultimate_Overlaid_Entity): New routine. + +2021-07-05 Claire Dross + + * libgnat/a-cfdlli.ads, libgnat/a-cfdlli.adb + libgnat/a-cfinve.ads, libgnat/a-cfinve.adb, + libgnat/a-cofove.ads, libgnat/a-cofove.adb, + libgnat/a-coboho.ads, libgnat/a-coboho.adb (Constant_Reference): + Get a read-only access to an element of the container. + (At_End): Ghost functions used to express pledges in the + postcondition of Reference. + (Reference): Get a read-write access to an element of the + container. + * libgnat/a-cfhama.ads, libgnat/a-cfhama.adb, + libgnat/a-cforma.ads, libgnat/a-cforma.adb: The full view of the + Map type is no longer a tagged type, but a wrapper over this + tagged type. This is to avoid issues with dispatching result in + At_End functions. + (Constant_Reference): Get a read-only access to an element of + the container. + (At_End): Ghost functions used to express pledges in the + postcondition of Reference. + (Reference): Get a read-write access to an element of the + container. + * libgnat/a-cfhase.ads, libgnat/a-cfhase.adb, + libgnat/a-cforse.ads, libgnat/a-cforse.adb: The full view of the + Map type is no longer a tagged type, but a wrapper over this + tagged type. + (Constant_Reference): Get a read-only access to an element of + the container. + * libgnat/a-cofuse.ads, libgnat/a-cofuve.ads (Copy_Element): + Expression function used to cause SPARK to make sure + Element_Type is copiable. + * libgnat/a-cofuma.ads (Copy_Key): Expression function used to + cause SPARK to make sure Key_Type is copiable. + (Copy_Element): Expression function used to cause SPARK to make + sure Element_Type is copiable. + +2021-07-05 Yannick Moy + + * sem_prag.adb (Analyze_Global_Item): Adapt to update SPARK RM + rule. + +2021-07-05 Arnaud Charlet + + * Make-generated.in: Add -f switch to ensure cp will never fail. + +2021-07-05 Steve Baird + + * exp_ch3.adb (Build_Record_Init_Proc.Build_Assignment): When + building the assignment statement corresponding to the default + expression for a component, we make a copy of the expression. + When making that copy (and if we have seen a component that + requires late initialization), pass a Map parameter into the + call to New_Copy_Tree to redirect references to the type to + instead refer to the _Init formal parameter of the init proc. + This includes hoisting the declaration of Has_Late_Init_Comp out + one level so that it becomes available to Build_Assignment. + (Find_Current_Instance): Return True for other kinds of current + instance references, instead of just access-valued attribute + references such as T'Access. + * sem_util.adb (Is_Aliased_View): Return True for the _Init + formal parameter of an init procedure. The changes in + exp_ch3.adb can have the effect of replacing a "T'Access" + attribute reference in an init procedure with an "_Init'Access" + attribute reference. We want such an attribute reference to be + legal. However, we do not simply mark the formal parameter as + being aliased because that might impact callers. + (Is_Object_Image): Return True if Is_Current_Instance returns + True for the prefix of an Image (or related attribute) attribute + reference. + +2021-07-05 Piotr Trojanek + + * exp_ch3.adb (Stream_Operation_OK): Reuse + Is_Concurrent_Interface. + * sem_ch3.adb (Analyze_Interface_Declaration, + Build_Derived_Record_Type): Likewise. + * sem_ch6.adb (Check_Limited_Return): Likewise. + * sem_util.adb (Is_Concurrent_Interface): Don't call + Is_Interface because each of the Is_Protected_Interface, + Is_Synchronized_Interface and Is_Task_Interface calls it anyway. + +2021-07-05 Ghjuvan Lacambre + + * sem_ch6.adb (Check_Limited_Return): Replace Comes_From_Source + with Comes_From_Extended_Return_Statement. + +2021-07-05 Steve Baird + + * libgnat/a-stobbu.adb, libgnat/a-stobbu.ads, + libgnat/a-stobfi.adb, libgnat/a-stobfi.ads, + libgnat/a-stoubu.adb, libgnat/a-stoubu.ads, + libgnat/a-stoufi.adb, libgnat/a-stoufi.ads, + libgnat/a-stoufo.adb, libgnat/a-stoufo.ads, + libgnat/a-stouut.adb, libgnat/a-stouut.ads, + libgnat/a-stteou.ads: Delete files. + * Makefile.rtl, impunit.adb: Remove references to deleted files. + +2021-07-05 Piotr Trojanek + + * sem_util.adb (Has_Compatible_Alignment_Internal): If the + prefix of the Address expression is an entire object with a + known alignment, then skip checks related to its size. + +2021-07-05 Doug Rupp + + * libgnat/s-os_lib.ads: Import OS_Time comparison ops as + intrinsic. + * libgnat/s-os_lib.adb: Remove OS_TIme comparison ops + implementation. + +2021-07-05 Doug Rupp + + * libgnat/s-os_lib.ads: Add some comments about time_t. + * libgnat/s-os_lib.adb (GM_Split/To_GM_Time): Rename formal to + P_OS_Time. + (GM_Time_Of/To_OS_Time): Likewise. + +2021-07-05 Ghjuvan Lacambre + + * sem_res.adb (Resolve): Insert minus sign if needed. + +2021-07-05 Steve Baird + + * exp_put_image.adb: + (Enable_Put_Image, Preload_Root_Buffer_Type): Revert to querying + the -gnatd_z switch, as opposed to testing whether Ada_Version >= Ada_2022. + +2021-07-05 Justin Squirek + + * checks.adb (Accessibility_Checks_Suppressed): Add check + against restriction No_Dynamic_Accessibility_Checks. + (Apply_Accessibility_Check): Add assertion to check restriction + No_Dynamic_Accessibility_Checks is not active. + * debug.adb: Add documentation for new debugging switch to + control which accessibility model gets employed under + restriction No_Dynamic_Accessibility_Checks. + * exp_attr.adb (Expand_N_Attribute_Reference): Disable dynamic + accessibility check generation when + No_Dynamic_Accessibility_Checks is active. + * exp_ch4.adb (Apply_Accessibility_Check): Skip check generation + when restriction No_Dynamic_Accessibility_Checks is active. + (Expand_N_Allocator): Disable dynamic accessibility checks when + No_Dynamic_Accessibility_Checks is active. + (Expand_N_In): Disable dynamic accessibility checks when + No_Dynamic_Accessibility_Checks is active. + (Expand_N_Type_Conversion): Disable dynamic accessibility checks + when No_Dynamic_Accessibility_Checks is active. + * exp_ch5.adb (Expand_N_Assignment_Statement): Disable + alternative accessibility model calculations when computing a + dynamic level for a SAOAAT. + * exp_ch6.adb (Add_Call_By_Copy_Code): Disable dynamic + accessibility check generation when + No_Dynamic_Accessibility_Checks is active. + (Expand_Branch): Disable alternative accessibility model + calculations. + (Expand_Call_Helper): Disable alternative accessibility model + calculations. + * restrict.adb, restrict.ads: Add new restriction + No_Dynamic_Accessibility_Checks. + (No_Dynamic_Accessibility_Checks_Enabled): Created to test when + experimental features (which are generally incompatible with + standard Ada) can be enabled. + * sem_attr.adb (Safe_Value_Conversions): Add handling of new + accessibility model under the restriction + No_Dynamic_Accessibility_Checks. + * sem_prag.adb (Process_Restrictions_Or_Restriction_Warnings): + Disallow new restriction No_Dynamic_Accessibility_Checks from + being exclusively specified within a body or subunit without + being present in a specification. + * sem_res.adb (Check_Fully_Declared_Prefix): Minor comment + fixup. + (Valid_Conversion): Omit implicit conversion checks on anonymous + access types and perform static checking instead when + No_Dynamic_Accessibility_Checks is active. + * sem_util.adb, sem_util.ads (Accessibility_Level): Add special + handling of anonymous access objects, formal parameters, + anonymous access components, and function return objects. + (Deepest_Type_Access_Level): When + No_Dynamic_Accessibility_Checks is active employ an alternative + model. Add paramter Allow_Alt_Model to override the new behavior + in certain cases. + (Type_Access_Level): When No_Dynamic_Accessibility_Checks is + active employ an alternative model. Add parameter + Allow_Alt_Model to override the new behavior in certain cases. + (Typ_Access_Level): Created within Accessibility_Level for + convenience. + * libgnat/s-rident.ads, snames.ads-tmpl: Add handing for + No_Dynamic_Accessibility_Checks. + +2021-07-05 Doug Rupp + + * adaint.h (__gnat_set_file_time_name): Use OS_Time. + * adaint.c (__gnat_set_file_time_name): Likewise. + +2021-07-05 Doug Rupp + + * adaint.h (OS_Time): typedef as long long. + * osint.adb (Underlying_OS_Time): Declare as 64-bit signed type. + * libgnat/s-os_lib.adb ("<"): Compare OS_Time as + Long_Long_Integer. + ("<="): Likewise. + (">"): Likewise. + (">="): Likewise. + * libgnat/s-os_lib.ads (OS_Time): Declare as 64-bit signed type. + +2021-07-05 Ghjuvan Lacambre + + * sem_ch3.adb (Check_Abstract_Overriding): Post error message on + renaming node. + +2021-07-05 Yannick Moy + + * libgnat/a-uncdea.ads: Add Depends/Post to + Ada.Unchecked_Deallocation. + * sem_ch4.adb (Analyze_Allocator): Remove checking of allocator + placement. + * sem_res.adb (Flag_Object): Same. + +2021-07-05 Ghjuvan Lacambre + + * aspects.ads: Add GNAT_Annotate aspect. + * gnat1drv.adb (Adjust_Global_Switches): Stop defining + Name_Gnat_Annotate as an alias of Name_Annotate. + * snames.ads-tmpl: Define Gnat_Annotate. + * par-prag.adb, sem_prag.ads: Add Pragma_Gnat_Annotate to list + of pragmas. + * lib-writ.adb, sem_ch13.adb, sem_prag.adb: Handle Gnat_Annotate + like Aspect_Annotate. + +2021-07-05 Piotr Trojanek + + * ttypes.ads (Target_Strict_Alignment): Fix comment. + +2021-07-05 Piotr Trojanek + + * sem_util.adb (Has_Compatible_Alignment_Internal): Fix + indentation of ELSIF comments; remove explicit calls to + UI_To_Int; remove extra parens around the MOD operand. + +2021-07-05 Ed Schonberg + + * sem_aggr.adb (Resolve_Record_Aggregate, Step_5): Do not check + for the need to use an extension aggregate for a given component + when within an instance and the type of the component hss a + private ancestor: the instantiation is legal if the generic + compiles, and spurious errors may be generated otherwise. + +2021-07-05 Ghjuvan Lacambre + + * errout.adb (Output_JSON_Message): Recursively call + Output_JSON_Message for continuation messages instead of + appending their content to the initial message. + +2021-07-05 Steve Baird + + * debug.adb: Remove comments about -gnatd_z switch. + * exp_ch3.adb (Make_Predefined_Primitive_Specs): A one-line fix + for a subtle bug that took some effort to debug. Append a new + Put_Image procedure for a type extension even if it seems to + already have one, just as is done for (for example) the + streaming-related Read procedure. + * exp_put_image.adb: + (Build_Record_Put_Image_Procedure.Make_Component_Attributes): Do + not treat _Parent component like just another component, for two + reasons. 1. If the _parent component's type has a + user-specified Put_Image procedure, then we want to generate a + call to that procedure and then generate extension aggregate + syntax. 2. Otherwise, we still don't want to see any mention of + "_parent" in the generated image text. + (Build_Record_Put_Image_Procedure.Make_Component_Name): Add + assertion that we are not generating a reference to an "_parent" + component. + (Build_Record_Put_Image_Procedure): Add special treatment for + null records. Add call to Duplicate_Subexpr for image attribute + prefix in order to help with expansion needed in the class-wide + case (where the prefix is also referenced in the call to + Wide_Wide_Expanded_Name) if evaluation of the prefix has side + effects. Add new local helper function, Put_String_Exp. Add + support for case where prefix type is class-wide. + (Enable_Put_Image, Preload_Root_Buffer_Type): Query Ada_Version + > Ada_2022 instead of (indirectly) querying -gnatd_z switch. + * freeze.adb (In_Expanded_Body): A one-line change to add + TSS_Put_Image to the list of subprograms that have + expander-created bodies. + * rtsfind.ads: Add support for accessing + Ada.Tags.Wide_Wide_Expanded_Name. + * sem_ch3.ads, sem_ch3.adb: Delete Is_Null_Extension function, + as part of moving it to Sem_Util. + * sem_ch13.adb + (Analyze_Put_Image_TSS_Definition.Has_Good_Profile): Improve + diagnostic messages in cases where the result is going to be + False and the Report parameter is True. Relax overly-restrictive + checks in order to implement mode conformance. + (Analyze_Stream_TSS_Definition.Has_Good_Profile): Add similar + relaxation of parameter subtype checking for the Stream + parameter of user-defined streaming subprograms. + * sem_disp.adb (Check_Dispatching_Operation): A one-line + change (and an accompanying comment change) to add TSS_Put_Image + to the list of compiler-generated dispatching primitive + operations. + * sem_util.ads, sem_util.adb: Add Ignore_Privacy Boolean + parameter to Is_Null_Record_Type function (typically the + parameter will be False when the function is being used in the + implementation of static semantics and True for dynamic + semantics; the parameter might make a difference in the case of, + for example, a private type that is implemented as a null record + type). Add related new routines Is_Null_Extension (formerly + declared in Sem_Ch3), Is_Null_Extension_Of, and + Is_Null_Record_Definition. + +2021-07-05 Justin Squirek + + * freeze.adb (Freeze_Profile): Use N's Sloc, F_type's chars. + +2021-07-05 Bob Duff + + * checks.adb, exp_aggr.adb, exp_ch5.adb, freeze.adb, + sem_util.adb, sem_util.ads: Change L and H to be First and Last, + to match the attributes in the RM. Change calls from procedure + to function where appropriate. + +2021-07-05 Bob Duff + + * sem_util.ads, sem_util.adb (Compute_Returns_By_Ref): New + procedure to compute Returns_By_Ref, to avoid some code + duplication. This will likely change soon, so it's good to have + the code in one place. + (CW_Or_Has_Controlled_Part): Move here from Exp_Ch7, because + it's called by Compute_Returns_By_Ref, and this is a better + place for it anyway. + (Needs_Finalization): Fix comment to be vague instead of wrong. + * exp_ch6.adb (Expand_N_Subprogram_Body, Freeze_Subprogram): + Call Compute_Returns_By_Ref. + * sem_ch6.adb (Check_Delayed_Subprogram): Call + Compute_Returns_By_Ref. + * exp_ch7.ads, exp_ch7.adb (CW_Or_Has_Controlled_Part): Move to + Sem_Util. + (Has_New_Controlled_Component): Remove unused function. + +2021-07-05 Ghjuvan Lacambre + + * sem_ch3.adb (Check_Abstract_Overriding): Check for renamings. + +2021-07-05 Boris Yakobowski + + * exp_ch4.adb (Expand_N_Op_Rem): Remove special case for rem -1 + in CodePeer_Mode. + 2021-07-01 Eric Botcazou PR ada/101094 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 187a6ef..87cd3ed7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,25 @@ +2021-07-05 Andrew Pinski + + PR tree-optimization/101039 + * gcc.dg/tree-ssa/phi-opt-15.c: Update test to expect + ABSU and still not expect ABS_EXPR. + * gcc.dg/tree-ssa/phi-opt-23.c: New test. + * gcc.dg/tree-ssa/phi-opt-24.c: New test. + +2021-07-05 Christophe Lyon + + PR debug/101321 + * gcc.dg/debug/btf/btf-bitfields-3.c: Add -fno-short-enums. + +2021-07-05 Richard Biener + + PR testsuite/101299 + * gcc.dg/vect/bb-slp-74.c: Add vect_double requires. + +2021-07-05 liuhongt + + * gcc.target/i386/pr92658-avx512vl.c: Refine testcase. + 2021-07-03 David Edelsohn * gcc.dg/debug/btf/btf.exp: Skip on AIX. -- cgit v1.1 From a3543b5e8002c033b2304d7ac1d1e58218eebb51 Mon Sep 17 00:00:00 2001 From: Indu Bhagat Date: Mon, 5 Jul 2021 17:28:24 -0700 Subject: CTF,BTF testsuite: Use -gdwarf-4 for restrict type qualifier [PR101283] DWARF DIEs do not contain DW_TAG_restrict_type when DWARF version is 2. CTF/BTF generation feeds off DWARF DIEs, and as such, CTF records of kind CTF_K_RESTRICT cease to be generated when DWARF version is 2. This patch fixes the failure of these testcases on Darwin by using an explicit -gdwarf-4 in the dg-options. This keeps the CTF record generation for restrict type qualifier tested. PR debug/101283 - Several tests fail on Darwin with -gctf/gbtf 2021-07-05 Indu Bhagat gcc/testsuite/ChangeLog: PR debug/101283 * gcc.dg/debug/btf/btf-cvr-quals-1.c: Use -gdwarf-4 on Darwin targets. * gcc.dg/debug/ctf/ctf-cvr-quals-1.c: Likewise. --- gcc/testsuite/gcc.dg/debug/btf/btf-cvr-quals-1.c | 1 + gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c | 1 + 2 files changed, 2 insertions(+) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-cvr-quals-1.c b/gcc/testsuite/gcc.dg/debug/btf/btf-cvr-quals-1.c index 79e9f52..33e2f64 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf-cvr-quals-1.c +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-cvr-quals-1.c @@ -23,6 +23,7 @@ /* { dg-do compile } */ /* { dg-options "-O0 -gbtf -dA" } */ +/* { dg-options "-O0 -gbtf -gdwarf-4 -dA" { target { *-*-darwin* } } } */ /* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*btf_string" 1 } } */ diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c index 9368d47..0137e9d 100644 --- a/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c @@ -31,6 +31,7 @@ /* { dg-do compile ) */ /* { dg-options "-O0 -gctf -dA" } */ +/* { dg-options "-O0 -gctf -gdwarf-4 -dA" { target { *-*-darwin* } } } */ /* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ /* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctt_name" 7 } } */ -- cgit v1.1 From 8ffe25eefae57fb3a228a2d31a57af5bdab8911f Mon Sep 17 00:00:00 2001 From: Kewen Lin Date: Mon, 5 Jul 2021 20:53:19 -0500 Subject: ira: Support more matching constraint forms with param [PR100328] This patch is to make IRA consider matching constraint heavily, even if there is at least one other alternative with non-NO_REG register class constraint, it will continue and check matching constraint in all available alternatives and respect the matching constraint with preferred register class. One typical case is destructive FMA style instruction on rs6000. Without this patch, for the mentioned FMA instruction, IRA won't respect the matching constraint on VSX_REG since there are some alternative with FLOAT_REG which doesn't have matching constraint. It can cause extra register copies since later reload has to make code to respect the constraint. This patch make IRA respect this matching constraint on VSX_REG which is the preferred regclass, but it excludes some cases where for one preferred register class there can be two or more alternatives, one of them has the matching constraint, while another doesn't have. It also considers the possibility of free register copy. With option Ofast unroll, this patch can help to improve SPEC2017 bmk 508.namd_r +2.42% and 519.lbm_r +2.43% on Power8 while 508.namd_r +3.02% and 519.lbm_r +3.85% on Power9 without any remarkable degradations. It also improved something on SVE as testcase changes showed and Richard's confirmation. Bootstrapped & regtested on powerpc64le-linux-gnu P9, x86_64-redhat-linux and aarch64-linux-gnu. gcc/ChangeLog: PR rtl-optimization/100328 * doc/invoke.texi (ira-consider-dup-in-all-alts): Document new parameter. * ira.c (ira_get_dup_out_num): Adjust as parameter param_ira_consider_dup_in_all_alts. * params.opt (ira-consider-dup-in-all-alts): New. * ira-conflicts.c (process_regs_for_copy): Add one parameter single_input_op_has_cstr_p. (get_freq_for_shuffle_copy): New function. (add_insn_allocno_copies): Adjust as single_input_op_has_cstr_p. * ira-int.h (ira_get_dup_out_num): Add one bool parameter. gcc/testsuite/ChangeLog: PR rtl-optimization/100328 * gcc.target/aarch64/sve/acle/asm/div_f16.c: Remove one xfail. * gcc.target/aarch64/sve/acle/asm/div_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/div_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/divr_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/divr_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/divr_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mad_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mad_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mad_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mla_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mla_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mla_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mls_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mls_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mls_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/msb_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/msb_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/msb_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mulx_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mulx_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/mulx_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmad_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmad_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmad_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmla_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmla_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmla_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmls_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmls_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmls_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmsb_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmsb_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/nmsb_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/sub_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/sub_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/sub_f64.c: Likewise. * gcc.target/aarch64/sve/acle/asm/subr_f16.c: Likewise. * gcc.target/aarch64/sve/acle/asm/subr_f32.c: Likewise. * gcc.target/aarch64/sve/acle/asm/subr_f64.c: Likewise. --- gcc/doc/invoke.texi | 10 ++ gcc/ira-conflicts.c | 93 ++++++++++++--- gcc/ira-int.h | 2 +- gcc/ira.c | 128 +++++++++++++++++++-- gcc/params.opt | 4 + .../gcc.target/aarch64/sve/acle/asm/div_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/div_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/div_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/divr_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/divr_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/divr_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mad_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mad_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mad_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mla_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mla_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mla_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mls_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mls_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mls_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/msb_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/msb_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/msb_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mulx_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mulx_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/mulx_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmad_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmad_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmad_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmla_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmla_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmla_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmls_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmls_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmls_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmsb_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmsb_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/nmsb_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/sub_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/sub_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/sub_f64.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/subr_f16.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/subr_f32.c | 2 +- .../gcc.target/aarch64/sve/acle/asm/subr_f64.c | 2 +- 44 files changed, 248 insertions(+), 67 deletions(-) (limited to 'gcc') diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index a9fd5fd..f470fc6 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -13917,6 +13917,16 @@ of available registers reserved for some other purposes is given by this parameter. Default of the parameter is the best found from numerous experiments. +@item ira-consider-dup-in-all-alts +Make IRA to consider matching constraint (duplicated operand number) +heavily in all available alternatives for preferred register class. +If it is set as zero, it means IRA only respects the matching +constraint when it's in the only available alternative with an +appropriate register class. Otherwise, it means IRA will check all +available alternatives for preferred register class even if it has +found some choice with an appropriate register class and respect the +found qualified matching constraint. + @item lra-inheritance-ebb-probability-cutoff LRA tries to reuse values reloaded in registers in subsequent insns. This optimization is called inheritance. EBB is used as a region to diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c index d83cfc1..86c6f24 100644 --- a/gcc/ira-conflicts.c +++ b/gcc/ira-conflicts.c @@ -233,19 +233,30 @@ go_through_subreg (rtx x, int *offset) return reg; } +/* Return the recomputed frequency for this shuffle copy or its similar + case, since it's not for a real move insn, make it smaller. */ + +static int +get_freq_for_shuffle_copy (int freq) +{ + return freq < 8 ? 1 : freq / 8; +} + /* Process registers REG1 and REG2 in move INSN with execution frequency FREQ. The function also processes the registers in a potential move insn (INSN == NULL in this case) with frequency FREQ. The function can modify hard register costs of the corresponding allocnos or create a copy involving the corresponding allocnos. The function does nothing if the both registers are hard - registers. When nothing is changed, the function returns - FALSE. */ + registers. When nothing is changed, the function returns FALSE. + SINGLE_INPUT_OP_HAS_CSTR_P is only meaningful when constraint_p + is true, see function ira_get_dup_out_num for its meaning. */ static bool -process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p, - rtx_insn *insn, int freq) +process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p, rtx_insn *insn, + int freq, bool single_input_op_has_cstr_p = true) { - int allocno_preferenced_hard_regno, cost, index, offset1, offset2; + int allocno_preferenced_hard_regno, index, offset1, offset2; + int cost, conflict_cost, move_cost; bool only_regs_p; ira_allocno_t a; reg_class_t rclass, aclass; @@ -306,9 +317,52 @@ process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p, return false; ira_init_register_move_cost_if_necessary (mode); if (HARD_REGISTER_P (reg1)) - cost = ira_register_move_cost[mode][aclass][rclass] * freq; + move_cost = ira_register_move_cost[mode][aclass][rclass]; + else + move_cost = ira_register_move_cost[mode][rclass][aclass]; + + if (!single_input_op_has_cstr_p) + { + /* When this is a constraint copy and the matching constraint + doesn't only exist for this given operand but also for some + other operand(s), it means saving the possible move cost does + NOT need to require reg1 and reg2 to use the same hardware + register, so this hardware preference isn't required to be + fixed. To avoid it to over prefer this hardware register, + and over disparage this hardware register on conflicted + objects, we need some cost tweaking here, similar to what + we do for shuffle copy. */ + gcc_assert (constraint_p); + int reduced_freq = get_freq_for_shuffle_copy (freq); + if (HARD_REGISTER_P (reg1)) + /* For reg2 = opcode(reg1, reg3 ...), assume that reg3 is a + pseudo register which has matching constraint on reg2, + even if reg2 isn't assigned by reg1, it's still possible + not to have register moves if reg2 and reg3 use the same + hardware register. So to avoid the allocation to over + prefer reg1, we can just take it as a shuffle copy. */ + cost = conflict_cost = move_cost * reduced_freq; + else + { + /* For reg1 = opcode(reg2, reg3 ...), assume that reg3 is a + pseudo register which has matching constraint on reg2, + to save the register move, it's better to assign reg1 + to either of reg2 and reg3 (or one of other pseudos like + reg3), it's reasonable to use freq for the cost. But + for conflict_cost, since reg2 and reg3 conflicts with + each other, both of them has the chance to be assigned + by reg1, assume reg3 has one copy which also conflicts + with reg2, we shouldn't make it less preferred on reg1 + since reg3 has the same chance to be assigned by reg1. + So it adjusts the conflic_cost to make it same as what + we use for shuffle copy. */ + cost = move_cost * freq; + conflict_cost = move_cost * reduced_freq; + } + } else - cost = ira_register_move_cost[mode][rclass][aclass] * freq; + cost = conflict_cost = move_cost * freq; + do { ira_allocate_and_set_costs @@ -317,7 +371,7 @@ process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p, ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), aclass, 0); ALLOCNO_HARD_REG_COSTS (a)[index] -= cost; - ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost; + ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= conflict_cost; if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_CLASS_COST (a)) ALLOCNO_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index]; ira_add_allocno_pref (a, allocno_preferenced_hard_regno, freq); @@ -420,7 +474,8 @@ add_insn_allocno_copies (rtx_insn *insn) operand = recog_data.operand[i]; if (! REG_SUBREG_P (operand)) continue; - if ((n = ira_get_dup_out_num (i, alts)) >= 0) + bool single_input_op_has_cstr_p; + if ((n = ira_get_dup_out_num (i, alts, single_input_op_has_cstr_p)) >= 0) { bound_p[n] = true; dup = recog_data.operand[n]; @@ -429,8 +484,8 @@ add_insn_allocno_copies (rtx_insn *insn) REG_P (operand) ? operand : SUBREG_REG (operand)) != NULL_RTX) - process_regs_for_copy (operand, dup, true, NULL, - freq); + process_regs_for_copy (operand, dup, true, NULL, freq, + single_input_op_has_cstr_p); } } for (i = 0; i < recog_data.n_operands; i++) @@ -440,13 +495,15 @@ add_insn_allocno_copies (rtx_insn *insn) && find_reg_note (insn, REG_DEAD, REG_P (operand) ? operand : SUBREG_REG (operand)) != NULL_RTX) - /* If an operand dies, prefer its hard register for the output - operands by decreasing the hard register cost or creating - the corresponding allocno copies. The cost will not - correspond to a real move insn cost, so make the frequency - smaller. */ - process_reg_shuffles (insn, operand, i, freq < 8 ? 1 : freq / 8, - bound_p); + { + /* If an operand dies, prefer its hard register for the output + operands by decreasing the hard register cost or creating + the corresponding allocno copies. The cost will not + correspond to a real move insn cost, so make the frequency + smaller. */ + int new_freq = get_freq_for_shuffle_copy (freq); + process_reg_shuffles (insn, operand, i, new_freq, bound_p); + } } } diff --git a/gcc/ira-int.h b/gcc/ira-int.h index 31e013b..da74862 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -971,7 +971,7 @@ extern void ira_debug_disposition (void); extern void ira_debug_allocno_classes (void); extern void ira_init_register_move_cost (machine_mode); extern alternative_mask ira_setup_alts (rtx_insn *); -extern int ira_get_dup_out_num (int, alternative_mask); +extern int ira_get_dup_out_num (int, alternative_mask, bool &); /* ira-build.c */ diff --git a/gcc/ira.c b/gcc/ira.c index 638ef4e..866fb98 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -1922,9 +1922,25 @@ ira_setup_alts (rtx_insn *insn) /* Return the number of the output non-early clobber operand which should be the same in any case as operand with number OP_NUM (or negative value if there is no such operand). ALTS is the mask - of alternatives that we should consider. */ + of alternatives that we should consider. SINGLE_INPUT_OP_HAS_CSTR_P + should be set in this function, it indicates whether there is only + a single input operand which has the matching constraint on the + output operand at the position specified in return value. If the + pattern allows any one of several input operands holds the matching + constraint, it's set as false, one typical case is destructive FMA + instruction on target rs6000. Note that for a non-NO_REG preferred + register class with no free register move copy, if the parameter + PARAM_IRA_CONSIDER_DUP_IN_ALL_ALTS is set to one, this function + will check all available alternatives for matching constraints, + even if it has found or will find one alternative with non-NO_REG + regclass, it can respect more cases with matching constraints. If + PARAM_IRA_CONSIDER_DUP_IN_ALL_ALTS is set to zero, + SINGLE_INPUT_OP_HAS_CSTR_P is always true, it will stop to find + matching constraint relationship once it hits some alternative with + some non-NO_REG regclass. */ int -ira_get_dup_out_num (int op_num, alternative_mask alts) +ira_get_dup_out_num (int op_num, alternative_mask alts, + bool &single_input_op_has_cstr_p) { int curr_alt, c, original; bool ignore_p, use_commut_op_p; @@ -1937,10 +1953,42 @@ ira_get_dup_out_num (int op_num, alternative_mask alts) return -1; str = recog_data.constraints[op_num]; use_commut_op_p = false; + single_input_op_has_cstr_p = true; + + rtx op = recog_data.operand[op_num]; + int op_regno = reg_or_subregno (op); + enum reg_class op_pref_cl = reg_preferred_class (op_regno); + machine_mode op_mode = GET_MODE (op); + + ira_init_register_move_cost_if_necessary (op_mode); + /* If the preferred regclass isn't NO_REG, continue to find the matching + constraint in all available alternatives with preferred regclass, even + if we have found or will find one alternative whose constraint stands + for a REG (non-NO_REG) regclass. Note that it would be fine not to + respect matching constraint if the register copy is free, so exclude + it. */ + bool respect_dup_despite_reg_cstr + = param_ira_consider_dup_in_all_alts + && op_pref_cl != NO_REGS + && ira_register_move_cost[op_mode][op_pref_cl][op_pref_cl] > 0; + + /* Record the alternative whose constraint uses the same regclass as the + preferred regclass, later if we find one matching constraint for this + operand with preferred reclass, we will visit these recorded + alternatives to check whether if there is one alternative in which no + any INPUT operands have one matching constraint same as our candidate. + If yes, it means there is one alternative which is perfectly fine + without satisfying this matching constraint. If no, it means in any + alternatives there is one other INPUT operand holding this matching + constraint, it's fine to respect this matching constraint and further + create this constraint copy since it would become harmless once some + other takes preference and it's interfered. */ + alternative_mask pref_cl_alts; + for (;;) { - rtx op = recog_data.operand[op_num]; - + pref_cl_alts = 0; + for (curr_alt = 0, ignore_p = !TEST_BIT (alts, curr_alt), original = -1;;) { @@ -1963,9 +2011,25 @@ ira_get_dup_out_num (int op_num, alternative_mask alts) { enum constraint_num cn = lookup_constraint (str); enum reg_class cl = reg_class_for_constraint (cn); - if (cl != NO_REGS - && !targetm.class_likely_spilled_p (cl)) - goto fail; + if (cl != NO_REGS && !targetm.class_likely_spilled_p (cl)) + { + if (respect_dup_despite_reg_cstr) + { + /* If it's free to move from one preferred class to + the one without matching constraint, it doesn't + have to respect this constraint with costs. */ + if (cl != op_pref_cl + && (ira_reg_class_intersect[cl][op_pref_cl] + != NO_REGS) + && (ira_may_move_in_cost[op_mode][op_pref_cl][cl] + == 0)) + goto fail; + else if (cl == op_pref_cl) + pref_cl_alts |= ALTERNATIVE_BIT (curr_alt); + } + else + goto fail; + } if (constraint_satisfied_p (op, cn)) goto fail; break; @@ -1979,7 +2043,21 @@ ira_get_dup_out_num (int op_num, alternative_mask alts) str = end; if (original != -1 && original != n) goto fail; - original = n; + gcc_assert (n < recog_data.n_operands); + if (respect_dup_despite_reg_cstr) + { + const operand_alternative *op_alt + = &recog_op_alt[curr_alt * recog_data.n_operands]; + /* Only respect the one with preferred rclass, without + respect_dup_despite_reg_cstr it's possible to get + one whose regclass isn't preferred first before, + but it would fail since there should be other + alternatives with preferred regclass. */ + if (op_alt[n].cl == op_pref_cl) + original = n; + } + else + original = n; continue; } } @@ -1988,7 +2066,39 @@ ira_get_dup_out_num (int op_num, alternative_mask alts) if (original == -1) goto fail; if (recog_data.operand_type[original] == OP_OUT) - return original; + { + if (pref_cl_alts == 0) + return original; + /* Visit these recorded alternatives to check whether + there is one alternative in which no any INPUT operands + have one matching constraint same as our candidate. + Give up this candidate if so. */ + int nop, nalt; + for (nalt = 0; nalt < recog_data.n_alternatives; nalt++) + { + if (!TEST_BIT (pref_cl_alts, nalt)) + continue; + const operand_alternative *op_alt + = &recog_op_alt[nalt * recog_data.n_operands]; + bool dup_in_other = false; + for (nop = 0; nop < recog_data.n_operands; nop++) + { + if (recog_data.operand_type[nop] != OP_IN) + continue; + if (nop == op_num) + continue; + if (op_alt[nop].matches == original) + { + dup_in_other = true; + break; + } + } + if (!dup_in_other) + return -1; + } + single_input_op_has_cstr_p = false; + return original; + } fail: if (use_commut_op_p) break; diff --git a/gcc/params.opt b/gcc/params.opt index 18e6036..577cd42 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -330,6 +330,10 @@ Max size of conflict table in MB. Common Joined UInteger Var(param_ira_max_loops_num) Init(100) Param Optimization Max loops number for regional RA. +-param=ira-consider-dup-in-all-alts= +Common Joined UInteger Var(param_ira_consider_dup_in_all_alts) Init(1) IntegerRange(0, 1) Param Optimization +Control ira to consider matching constraint (duplicated operand number) heavily in all available alternatives for preferred register class. If it is set as zero, it means ira only respects the matching constraint when it's in the only available alternative with an appropriate register class. Otherwise, it means ira will check all available alternatives for preferred register class even if it has found some choice with an appropriate register class and respect the found qualified matching constraint. + -param=iv-always-prune-cand-set-bound= Common Joined UInteger Var(param_iv_always_prune_cand_set_bound) Init(10) Param Optimization If number of candidates in the set is smaller, we always try to remove unused ivs during its optimization. diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f16.c index 35f5c15..8bcd094 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f16.c @@ -218,7 +218,7 @@ TEST_UNIFORM_ZD (div_h4_f16_x_tied1, svfloat16_t, __fp16, z0 = svdiv_x (p0, z0, d4)) /* -** div_h4_f16_x_untied: { xfail *-*-* } +** div_h4_f16_x_untied: ** mov z0\.h, h4 ** fdivr z0\.h, p0/m, z0\.h, z1\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f32.c index 40cc203..546c61d 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f32.c @@ -218,7 +218,7 @@ TEST_UNIFORM_ZD (div_s4_f32_x_tied1, svfloat32_t, float, z0 = svdiv_x (p0, z0, d4)) /* -** div_s4_f32_x_untied: { xfail *-*-* } +** div_s4_f32_x_untied: ** mov z0\.s, s4 ** fdivr z0\.s, p0/m, z0\.s, z1\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f64.c index 56acbbe..1e24bc26 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/div_f64.c @@ -218,7 +218,7 @@ TEST_UNIFORM_ZD (div_d4_f64_x_tied1, svfloat64_t, double, z0 = svdiv_x (p0, z0, d4)) /* -** div_d4_f64_x_untied: { xfail *-*-* } +** div_d4_f64_x_untied: ** mov z0\.d, d4 ** fdivr z0\.d, p0/m, z0\.d, z1\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f16.c index 03cc034..e293be6 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f16.c @@ -239,7 +239,7 @@ TEST_UNIFORM_ZD (divr_h4_f16_x_tied1, svfloat16_t, __fp16, z0 = svdivr_x (p0, z0, d4)) /* -** divr_h4_f16_x_untied: { xfail *-*-* } +** divr_h4_f16_x_untied: ** mov z0\.h, h4 ** fdiv z0\.h, p0/m, z0\.h, z1\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f32.c index c2b65fc..04a7ac4 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f32.c @@ -239,7 +239,7 @@ TEST_UNIFORM_ZD (divr_s4_f32_x_tied1, svfloat32_t, float, z0 = svdivr_x (p0, z0, d4)) /* -** divr_s4_f32_x_untied: { xfail *-*-* } +** divr_s4_f32_x_untied: ** mov z0\.s, s4 ** fdiv z0\.s, p0/m, z0\.s, z1\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f64.c index 0a72a37..bef1a9b 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/divr_f64.c @@ -239,7 +239,7 @@ TEST_UNIFORM_ZD (divr_d4_f64_x_tied1, svfloat64_t, double, z0 = svdivr_x (p0, z0, d4)) /* -** divr_d4_f64_x_untied: { xfail *-*-* } +** divr_d4_f64_x_untied: ** mov z0\.d, d4 ** fdiv z0\.d, p0/m, z0\.d, z1\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f16.c index 7656f9e..4b31484 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f16.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (mad_h4_f16_x_tied2, svfloat16_t, __fp16, z0 = svmad_x (p0, z1, z0, d4)) /* -** mad_h4_f16_x_untied: { xfail *-*-* } +** mad_h4_f16_x_untied: ** mov z0\.h, h4 ** fmla z0\.h, p0/m, z1\.h, z2\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f32.c index dbdd2b9..d5dbc85 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f32.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (mad_s4_f32_x_tied2, svfloat32_t, float, z0 = svmad_x (p0, z1, z0, d4)) /* -** mad_s4_f32_x_untied: { xfail *-*-* } +** mad_s4_f32_x_untied: ** mov z0\.s, s4 ** fmla z0\.s, p0/m, z1\.s, z2\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f64.c index 9782812..7b5dc22 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mad_f64.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (mad_d4_f64_x_tied2, svfloat64_t, double, z0 = svmad_x (p0, z1, z0, d4)) /* -** mad_d4_f64_x_untied: { xfail *-*-* } +** mad_d4_f64_x_untied: ** mov z0\.d, d4 ** fmla z0\.d, p0/m, z1\.d, z2\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f16.c index f22a582..d32ce58 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f16.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (mla_h4_f16_x_tied2, svfloat16_t, __fp16, z0 = svmla_x (p0, z1, z0, d4)) /* -** mla_h4_f16_x_untied: { xfail *-*-* } +** mla_h4_f16_x_untied: ** mov z0\.h, h4 ** fmad z0\.h, p0/m, z2\.h, z1\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f32.c index 1d95eb0..d10ba69 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f32.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (mla_s4_f32_x_tied2, svfloat32_t, float, z0 = svmla_x (p0, z1, z0, d4)) /* -** mla_s4_f32_x_untied: { xfail *-*-* } +** mla_s4_f32_x_untied: ** mov z0\.s, s4 ** fmad z0\.s, p0/m, z2\.s, z1\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f64.c index 74fd292..94c1e0b 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mla_f64.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (mla_d4_f64_x_tied2, svfloat64_t, double, z0 = svmla_x (p0, z1, z0, d4)) /* -** mla_d4_f64_x_untied: { xfail *-*-* } +** mla_d4_f64_x_untied: ** mov z0\.d, d4 ** fmad z0\.d, p0/m, z2\.d, z1\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f16.c index 87fba3d..b58104d 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f16.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (mls_h4_f16_x_tied2, svfloat16_t, __fp16, z0 = svmls_x (p0, z1, z0, d4)) /* -** mls_h4_f16_x_untied: { xfail *-*-* } +** mls_h4_f16_x_untied: ** mov z0\.h, h4 ** fmsb z0\.h, p0/m, z2\.h, z1\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f32.c index 04ce1ec..7d6e605 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f32.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (mls_s4_f32_x_tied2, svfloat32_t, float, z0 = svmls_x (p0, z1, z0, d4)) /* -** mls_s4_f32_x_untied: { xfail *-*-* } +** mls_s4_f32_x_untied: ** mov z0\.s, s4 ** fmsb z0\.s, p0/m, z2\.s, z1\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f64.c index 1e2108a..a6ed28e 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mls_f64.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (mls_d4_f64_x_tied2, svfloat64_t, double, z0 = svmls_x (p0, z1, z0, d4)) /* -** mls_d4_f64_x_untied: { xfail *-*-* } +** mls_d4_f64_x_untied: ** mov z0\.d, d4 ** fmsb z0\.d, p0/m, z2\.d, z1\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f16.c index fe11457..894961a 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f16.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (msb_h4_f16_x_tied2, svfloat16_t, __fp16, z0 = svmsb_x (p0, z1, z0, d4)) /* -** msb_h4_f16_x_untied: { xfail *-*-* } +** msb_h4_f16_x_untied: ** mov z0\.h, h4 ** fmls z0\.h, p0/m, z1\.h, z2\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f32.c index f7a9f27..0d09159 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f32.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (msb_s4_f32_x_tied2, svfloat32_t, float, z0 = svmsb_x (p0, z1, z0, d4)) /* -** msb_s4_f32_x_untied: { xfail *-*-* } +** msb_s4_f32_x_untied: ** mov z0\.s, s4 ** fmls z0\.s, p0/m, z1\.s, z2\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f64.c index e3ff414..52dc396 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/msb_f64.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (msb_d4_f64_x_tied2, svfloat64_t, double, z0 = svmsb_x (p0, z1, z0, d4)) /* -** msb_d4_f64_x_untied: { xfail *-*-* } +** msb_d4_f64_x_untied: ** mov z0\.d, d4 ** fmls z0\.d, p0/m, z1\.d, z2\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f16.c index ce02c3c..b8d6bf5 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f16.c @@ -303,7 +303,7 @@ TEST_UNIFORM_ZD (mulx_h4_f16_x_tied1, svfloat16_t, __fp16, z0 = svmulx_x (p0, z0, d4)) /* -** mulx_h4_f16_x_untied: { xfail *-*-* } +** mulx_h4_f16_x_untied: ** mov z0\.h, h4 ** fmulx z0\.h, p0/m, z0\.h, z1\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f32.c index e0d3695..b8f5c13 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f32.c @@ -303,7 +303,7 @@ TEST_UNIFORM_ZD (mulx_s4_f32_x_tied1, svfloat32_t, float, z0 = svmulx_x (p0, z0, d4)) /* -** mulx_s4_f32_x_untied: { xfail *-*-* } +** mulx_s4_f32_x_untied: ** mov z0\.s, s4 ** fmulx z0\.s, p0/m, z0\.s, z1\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f64.c index 6af5703..746cc94 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mulx_f64.c @@ -303,7 +303,7 @@ TEST_UNIFORM_ZD (mulx_d4_f64_x_tied1, svfloat64_t, double, z0 = svmulx_x (p0, z0, d4)) /* -** mulx_d4_f64_x_untied: { xfail *-*-* } +** mulx_d4_f64_x_untied: ** mov z0\.d, d4 ** fmulx z0\.d, p0/m, z0\.d, z1\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f16.c index abfe0a0..92e0664 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f16.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmad_h4_f16_x_tied2, svfloat16_t, __fp16, z0 = svnmad_x (p0, z1, z0, d4)) /* -** nmad_h4_f16_x_untied: { xfail *-*-* } +** nmad_h4_f16_x_untied: ** mov z0\.h, h4 ** fnmla z0\.h, p0/m, z1\.h, z2\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f32.c index ab86385..cef731e 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f32.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmad_s4_f32_x_tied2, svfloat32_t, float, z0 = svnmad_x (p0, z1, z0, d4)) /* -** nmad_s4_f32_x_untied: { xfail *-*-* } +** nmad_s4_f32_x_untied: ** mov z0\.s, s4 ** fnmla z0\.s, p0/m, z1\.s, z2\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f64.c index c236ff5..43b97c0 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmad_f64.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmad_d4_f64_x_tied2, svfloat64_t, double, z0 = svnmad_x (p0, z1, z0, d4)) /* -** nmad_d4_f64_x_untied: { xfail *-*-* } +** nmad_d4_f64_x_untied: ** mov z0\.d, d4 ** fnmla z0\.d, p0/m, z1\.d, z2\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f16.c index f7ac377..75d0ec7 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f16.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmla_h4_f16_x_tied2, svfloat16_t, __fp16, z0 = svnmla_x (p0, z1, z0, d4)) /* -** nmla_h4_f16_x_untied: { xfail *-*-* } +** nmla_h4_f16_x_untied: ** mov z0\.h, h4 ** fnmad z0\.h, p0/m, z2\.h, z1\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f32.c index ef9542d..da594d3 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f32.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmla_s4_f32_x_tied2, svfloat32_t, float, z0 = svnmla_x (p0, z1, z0, d4)) /* -** nmla_s4_f32_x_untied: { xfail *-*-* } +** nmla_s4_f32_x_untied: ** mov z0\.s, s4 ** fnmad z0\.s, p0/m, z2\.s, z1\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f64.c index 441821f..73f15f4 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmla_f64.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmla_d4_f64_x_tied2, svfloat64_t, double, z0 = svnmla_x (p0, z1, z0, d4)) /* -** nmla_d4_f64_x_untied: { xfail *-*-* } +** nmla_d4_f64_x_untied: ** mov z0\.d, d4 ** fnmad z0\.d, p0/m, z2\.d, z1\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f16.c index 8aa6c75..ccf7e51 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f16.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmls_h4_f16_x_tied2, svfloat16_t, __fp16, z0 = svnmls_x (p0, z1, z0, d4)) /* -** nmls_h4_f16_x_untied: { xfail *-*-* } +** nmls_h4_f16_x_untied: ** mov z0\.h, h4 ** fnmsb z0\.h, p0/m, z2\.h, z1\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f32.c index 42ea13f..10d3450 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f32.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmls_s4_f32_x_tied2, svfloat32_t, float, z0 = svnmls_x (p0, z1, z0, d4)) /* -** nmls_s4_f32_x_untied: { xfail *-*-* } +** nmls_s4_f32_x_untied: ** mov z0\.s, s4 ** fnmsb z0\.s, p0/m, z2\.s, z1\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f64.c index 994c2a7..bf2a441 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmls_f64.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmls_d4_f64_x_tied2, svfloat64_t, double, z0 = svnmls_x (p0, z1, z0, d4)) /* -** nmls_d4_f64_x_untied: { xfail *-*-* } +** nmls_d4_f64_x_untied: ** mov z0\.d, d4 ** fnmsb z0\.d, p0/m, z2\.d, z1\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f16.c index c114014..5311ceb 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f16.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmsb_h4_f16_x_tied2, svfloat16_t, __fp16, z0 = svnmsb_x (p0, z1, z0, d4)) /* -** nmsb_h4_f16_x_untied: { xfail *-*-* } +** nmsb_h4_f16_x_untied: ** mov z0\.h, h4 ** fnmls z0\.h, p0/m, z1\.h, z2\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f32.c index c2204e0..6f1407a 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f32.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmsb_s4_f32_x_tied2, svfloat32_t, float, z0 = svnmsb_x (p0, z1, z0, d4)) /* -** nmsb_s4_f32_x_untied: { xfail *-*-* } +** nmsb_s4_f32_x_untied: ** mov z0\.s, s4 ** fnmls z0\.s, p0/m, z1\.s, z2\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f64.c index 56592d3..5e4e1dd 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/nmsb_f64.c @@ -281,7 +281,7 @@ TEST_UNIFORM_ZD (nmsb_d4_f64_x_tied2, svfloat64_t, double, z0 = svnmsb_x (p0, z1, z0, d4)) /* -** nmsb_d4_f64_x_untied: { xfail *-*-* } +** nmsb_d4_f64_x_untied: ** mov z0\.d, d4 ** fnmls z0\.d, p0/m, z1\.d, z2\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f16.c index bf4a0ab..48a5746 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f16.c @@ -336,7 +336,7 @@ TEST_UNIFORM_ZD (sub_h4_f16_x_tied1, svfloat16_t, __fp16, z0 = svsub_x (p0, z0, d4)) /* -** sub_h4_f16_x_untied: { xfail *-*-* } +** sub_h4_f16_x_untied: ** mov z0\.h, h4 ** fsubr z0\.h, p0/m, z0\.h, z1\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f32.c index 05be52b..32d57be 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f32.c @@ -336,7 +336,7 @@ TEST_UNIFORM_ZD (sub_s4_f32_x_tied1, svfloat32_t, float, z0 = svsub_x (p0, z0, d4)) /* -** sub_s4_f32_x_untied: { xfail *-*-* } +** sub_s4_f32_x_untied: ** mov z0\.s, s4 ** fsubr z0\.s, p0/m, z0\.s, z1\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f64.c index 2179382..cdc2558 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sub_f64.c @@ -336,7 +336,7 @@ TEST_UNIFORM_ZD (sub_d4_f64_x_tied1, svfloat64_t, double, z0 = svsub_x (p0, z0, d4)) /* -** sub_d4_f64_x_untied: { xfail *-*-* } +** sub_d4_f64_x_untied: ** mov z0\.d, d4 ** fsubr z0\.d, p0/m, z0\.d, z1\.d ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f16.c index e14357d..6929b28 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f16.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f16.c @@ -285,7 +285,7 @@ TEST_UNIFORM_ZD (subr_h4_f16_x_tied1, svfloat16_t, __fp16, z0 = svsubr_x (p0, z0, d4)) /* -** subr_h4_f16_x_untied: { xfail *-*-* } +** subr_h4_f16_x_untied: ** mov z0\.h, h4 ** fsub z0\.h, p0/m, z0\.h, z1\.h ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f32.c index 98dc7ad..5bf90a3 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f32.c @@ -285,7 +285,7 @@ TEST_UNIFORM_ZD (subr_s4_f32_x_tied1, svfloat32_t, float, z0 = svsubr_x (p0, z0, d4)) /* -** subr_s4_f32_x_untied: { xfail *-*-* } +** subr_s4_f32_x_untied: ** mov z0\.s, s4 ** fsub z0\.s, p0/m, z0\.s, z1\.s ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f64.c index 81f1112..7091c40 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_f64.c @@ -285,7 +285,7 @@ TEST_UNIFORM_ZD (subr_d4_f64_x_tied1, svfloat64_t, double, z0 = svsubr_x (p0, z0, d4)) /* -** subr_d4_f64_x_untied: { xfail *-*-* } +** subr_d4_f64_x_untied: ** mov z0\.d, d4 ** fsub z0\.d, p0/m, z0\.d, z1\.d ** ret -- cgit v1.1 From c64d15224c6dc4dc3b6b3c2c6b6fd5c7e0e9c072 Mon Sep 17 00:00:00 2001 From: Kewen Lin Date: Mon, 5 Jul 2021 20:54:16 -0500 Subject: i386: Disable param ira-consider-dup-in-all-alts [PR100328] With Hongtao's SPEC2017 performance evaluation result here: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573986.html this new parameter ira-consider-dup-in-all-alts has negative effects on i386, this patch is to disable it explicitly on i386. Bootstrapped & regtested on x86_64-redhat-linux. gcc/ChangeLog: PR rtl-optimization/100328 * config/i386/i386-options.c (ix86_option_override_internal): Set param_ira_consider_dup_in_all_alts to 0. --- gcc/config/i386/i386-options.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gcc') diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c index 0eccb54..7a35c46 100644 --- a/gcc/config/i386/i386-options.c +++ b/gcc/config/i386/i386-options.c @@ -2831,6 +2831,8 @@ ix86_option_override_internal (bool main_args_p, if (ix86_indirect_branch != indirect_branch_keep) SET_OPTION_IF_UNSET (opts, opts_set, flag_jump_tables, 0); + SET_OPTION_IF_UNSET (opts, opts_set, param_ira_consider_dup_in_all_alts, 0); + return true; } -- cgit v1.1 From d7e3855d5dd8c001bb65dc7da1cda0249bfc2986 Mon Sep 17 00:00:00 2001 From: Thomas Koenig Date: Tue, 6 Jul 2021 07:04:09 +0200 Subject: Do not replace variable op variable in I/O implied DO loop replacement. This PR came about because index expressions of the form k+k in implied DO loops in I/O statements were considered for replacement by array slices. Fixed by only doing the transformation if the expression is of the type expr OP contastant. gcc/fortran/ChangeLog: PR fortran/100227 * frontend-passes.c (traverse_io_block): Adjust test for when a variable is eligible for the transformation to array slice. gcc/testsuite/ChangeLog: PR fortran/100227 * gfortran.dg/implied_do_io_7.f90: New test. --- gcc/fortran/frontend-passes.c | 4 ++-- gcc/testsuite/gfortran.dg/implied_do_io_7.f90 | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/implied_do_io_7.f90 (limited to 'gcc') diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c index 72a4e04..996dcc2 100644 --- a/gcc/fortran/frontend-passes.c +++ b/gcc/fortran/frontend-passes.c @@ -1299,8 +1299,8 @@ traverse_io_block (gfc_code *code, bool *has_reached, gfc_code *prev) std::swap (start->value.op.op1, start->value.op.op2); gcc_fallthrough (); case INTRINSIC_MINUS: - if ((start->value.op.op1->expr_type!= EXPR_VARIABLE - && start->value.op.op2->expr_type != EXPR_CONSTANT) + if (start->value.op.op1->expr_type!= EXPR_VARIABLE + || start->value.op.op2->expr_type != EXPR_CONSTANT || start->value.op.op1->ref) return false; if (!stack_top || !stack_top->iter diff --git a/gcc/testsuite/gfortran.dg/implied_do_io_7.f90 b/gcc/testsuite/gfortran.dg/implied_do_io_7.f90 new file mode 100644 index 0000000..63927aa --- /dev/null +++ b/gcc/testsuite/gfortran.dg/implied_do_io_7.f90 @@ -0,0 +1,16 @@ +! { dg-do run } +! PR 100227 - this was falsely optimized, leading to nonsense results. +! Original test case by "Mathieu". + +program p + implicit none + integer, parameter :: nbmode = 3 + integer :: k + real :: mass(nbmode*2) + character (len=80) :: line + do k = 1, nbmode*2 + mass(k) = k + end do + write (unit=line,fmt='(*(F6.2))') (mass(k+k), k=1,nbmode) + if (line /= ' 2.00 4.00 6.00') stop 1 +end program -- cgit v1.1 From 51abfb6a893c87dbf84a33009b6cd6dbd25d66f1 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Tue, 29 Jun 2021 14:30:34 -0700 Subject: Fix 101256: Wrong code due to range incorrect from PHI-OPT So the problem here is that replace_phi_edge_with_variable will copy range information to a already (not newly) defined ssa name. This causes wrong code later on. This fixes the problem by require the new ssa name to be defined in the same bb as the conditional that is about to be deleted. OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions. Changes from v1: * this is a simplification of what was trying to be done before. gcc/ChangeLog: PR tree-optimization/101256 * dbgcnt.def (phiopt_edge_range): New counter. * tree-ssa-phiopt.c (replace_phi_edge_with_variable): Check to make sure the new name is defined in the same bb as the conditional before duplicating range info. Also add debug counter. gcc/testsuite/ChangeLog: PR tree-optimization/101256 * g++.dg/torture/pr101256.C: New test. --- gcc/dbgcnt.def | 1 + gcc/testsuite/g++.dg/torture/pr101256.C | 28 ++++++++++++++++++++++++++++ gcc/tree-ssa-phiopt.c | 16 ++++++++++------ 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr101256.C (limited to 'gcc') diff --git a/gcc/dbgcnt.def b/gcc/dbgcnt.def index 93e7b4f..2345899 100644 --- a/gcc/dbgcnt.def +++ b/gcc/dbgcnt.def @@ -183,6 +183,7 @@ DEBUG_COUNTER (lim) DEBUG_COUNTER (local_alloc_for_sched) DEBUG_COUNTER (match) DEBUG_COUNTER (merged_ipa_icf) +DEBUG_COUNTER (phiopt_edge_range) DEBUG_COUNTER (postreload_cse) DEBUG_COUNTER (pre) DEBUG_COUNTER (pre_insn) diff --git a/gcc/testsuite/g++.dg/torture/pr101256.C b/gcc/testsuite/g++.dg/torture/pr101256.C new file mode 100644 index 0000000..973a8b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr101256.C @@ -0,0 +1,28 @@ +// { dg-do run } + +template +const T& max(const T& a, const T& b) +{ + return (a < b) ? b : a; +} + +signed char var_5 = -128; +unsigned int var_11 = 2144479212U; +unsigned long long int arr [22]; + +void +__attribute__((noipa)) +test(signed char var_5, unsigned var_11) { + for (short i_61 = 0; i_61 < var_5 + 149; i_61 += 10000) + arr[i_61] = max((signed char)0, var_5) ? max((signed char)1, var_5) : var_11; +} + +int main() { + for (int i_0 = 0; i_0 < 22; ++i_0) + arr [i_0] = 11834725929543695741ULL; + + test(var_5, var_11); + if (arr [0] != 2144479212ULL && arr [0] != 11834725929543695741ULL) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index ab63bf6..8b60ee8 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see #include "internal-fn.h" #include "gimple-range.h" #include "gimple-match.h" +#include "dbgcnt.h" static unsigned int tree_ssa_phiopt_worker (bool, bool, bool); static bool two_value_replacement (basic_block, basic_block, edge, gphi *, @@ -390,7 +391,7 @@ replace_phi_edge_with_variable (basic_block cond_block, gimple_stmt_iterator gsi; tree phi_result = PHI_RESULT (phi); - /* Duplicate range info if we're the only things setting the target PHI. + /* Duplicate range info if they are the only things setting the target PHI. This is needed as later on, the new_tree will be replacing The assignement of the PHI. For an example: @@ -398,19 +399,22 @@ replace_phi_edge_with_variable (basic_block cond_block, _4 = min goto bb2 - range<-INF,255> + # RANGE [-INF, 255] a_3 = PHI<_4(1)> bb3: use(a_3) - And _4 gets prograted into the use of a_3 and losing the range info. - This can't be done for more than 2 incoming edges as the progration - won't happen. */ + And _4 gets propagated into the use of a_3 and losing the range info. + This can't be done for more than 2 incoming edges as the propagation + won't happen. + The new_tree needs to be defined in the same basic block as the conditional. */ if (TREE_CODE (new_tree) == SSA_NAME && EDGE_COUNT (gimple_bb (phi)->preds) == 2 && INTEGRAL_TYPE_P (TREE_TYPE (phi_result)) && !SSA_NAME_RANGE_INFO (new_tree) - && SSA_NAME_RANGE_INFO (phi_result)) + && SSA_NAME_RANGE_INFO (phi_result) + && gimple_bb (SSA_NAME_DEF_STMT (new_tree)) == cond_block + && dbg_cnt (phiopt_edge_range)) duplicate_ssa_name_range_info (new_tree, SSA_NAME_RANGE_TYPE (phi_result), SSA_NAME_RANGE_INFO (phi_result)); -- cgit v1.1 From b019b28ebd65462a092c96d95e9e356c8bb39b78 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Tue, 6 Jul 2021 09:19:30 +0100 Subject: Documentation : Describe --with-dsymutil configure option. This adds documentation for the dsymutil configuration option introduced with commit r12-2037-g3b5e8ee4f1ec. Signed-off-by: Iain Sandoe gcc/ChangeLog: * doc/install.texi: Document --with-dsymutil. --- gcc/doc/install.texi | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gcc') diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 94b167a..6eee1bb 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -1084,6 +1084,10 @@ but for the linker. Same as @uref{#with-as,,@option{--with-as}} but for the linker. +@item --with-dsymutil=@var{pathname} +Same as @uref{#with-as,,@option{--with-as}} +but for the debug linker (only used on Darwin platforms so far). + @item --with-stabs Specify that stabs debugging information should be used instead of whatever format the host normally -- cgit v1.1 From 9f489a5731f12b8e6b49994e8f61acb5d26f508e Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 2 Jul 2021 13:48:07 +0200 Subject: add -fmove-loop-stores option to control GIMPLE loop store-motion This adds the -fmove-loop-stores option, mainly as a way to disable the store-motion part of GIMPLE invariant motion (-ftree-loop-im) which is enabled by default. It might be sensible to turn off -fmove-loop-stores at -O1 since it can result in compile-time as well as memory usage issues but this patch tries to preserve existing behavior besides introducing the new option with the exception of -Og where I've disabled it. Controlling store-motion has been made easy by earlier refactoring for the invariant motion only use after loop interchange. 2021-07-02 Richard Biener * doc/invoke.texi (fmove-loop-stores): Document. * common.opt (fmove-loop-stores): New option. * opts.c (default_options_table): Enable -fmove-loop-stores at -O1 but not -Og. * tree-ssa-loop-im.c (pass_lim::execute): Pass flag_move_loop_stores instead of true to loop_invariant_motion_in_fun. --- gcc/common.opt | 4 ++++ gcc/doc/invoke.texi | 14 ++++++++++++-- gcc/opts.c | 1 + gcc/tree-ssa-loop-im.c | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/common.opt b/gcc/common.opt index 5b03bbc..d9da113 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2084,6 +2084,10 @@ fmove-loop-invariants Common Var(flag_move_loop_invariants) Optimization Move loop invariant computations out of loops. +fmove-loop-stores +Common Var(flag_move_loop_stores) Optimization +Move stores out of loops. + fdce Common Var(flag_dce) Init(1) Optimization Use the RTL dead code elimination pass. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index f470fc6..e67d47a 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -528,7 +528,7 @@ Objective-C and Objective-C++ Dialects}. -floop-parallelize-all -flra-remat -flto -flto-compression-level @gol -flto-partition=@var{alg} -fmerge-all-constants @gol -fmerge-constants -fmodulo-sched -fmodulo-sched-allow-regmoves @gol --fmove-loop-invariants -fno-branch-count-reg @gol +-fmove-loop-invariants -fmove-loop-stores -fno-branch-count-reg @gol -fno-defer-pop -fno-fp-int-builtin-inexact -fno-function-cse @gol -fno-guess-branch-probability -fno-inline -fno-math-errno -fno-peephole @gol -fno-peephole2 -fno-printf-return-value -fno-sched-interblock @gol @@ -10260,6 +10260,7 @@ compilation time. -fipa-reference-addressable @gol -fmerge-constants @gol -fmove-loop-invariants @gol +-fmove-loop-stores@gol -fomit-frame-pointer @gol -freorder-blocks @gol -fshrink-wrap @gol @@ -10403,7 +10404,7 @@ optimization flags except for those that may interfere with debugging: @gccoptlist{-fbranch-count-reg -fdelayed-branch @gol -fdse -fif-conversion -fif-conversion2 @gol -finline-functions-called-once @gol --fmove-loop-invariants -fssa-phiopt @gol +-fmove-loop-invariants -fmove-loop-stores -fssa-phiopt @gol -ftree-bit-ccp -ftree-dse -ftree-pta -ftree-sra} @end table @@ -13011,6 +13012,15 @@ Enabled by @option{-O3}, @option{-fprofile-use}, and @option{-fauto-profile}. Enables the loop invariant motion pass in the RTL loop optimizer. Enabled at level @option{-O1} and higher, except for @option{-Og}. +@item -fmove-loop-stores +@opindex fmove-loop-stores +Enables the loop store motion pass in the GIMPLE loop optimizer. This +moves invariant stores to after the end of the loop in exchange for +carrying the stored value in a register across the iteration. +Note for this option to have an effect @option{-ftree-loop-im} has to +be enabled as well. Enabled at level @option{-O1} and higher, except +for @option{-Og}. + @item -fsplit-loops @opindex fsplit-loops Split a loop into two if it contains a condition that's always true diff --git a/gcc/opts.c b/gcc/opts.c index f159bb3..25282f7 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -575,6 +575,7 @@ static const struct default_options default_options_table[] = { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion2, NULL, 1 }, { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_finline_functions_called_once, NULL, 1 }, { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fmove_loop_invariants, NULL, 1 }, + { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fmove_loop_stores, NULL, 1 }, { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fssa_phiopt, NULL, 1 }, { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fipa_modref, NULL, 1 }, { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_bit_ccp, NULL, 1 }, diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index e7a3050..9ac390b 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -3258,7 +3258,7 @@ pass_lim::execute (function *fun) if (number_of_loops (fun) <= 1) return 0; - unsigned int todo = loop_invariant_motion_in_fun (fun, true); + unsigned int todo = loop_invariant_motion_in_fun (fun, flag_move_loop_stores); if (!in_loop_pipeline) loop_optimizer_finalize (); -- cgit v1.1 From 7d810646d421f6975300c0d06f4e9af27a48f26d Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 5 Jul 2021 15:51:49 +0200 Subject: Add FMADDSUB and FMSUBADD SLP vectorization patterns and optabs This adds named expanders for vec_fmaddsub4 and vec_fmsubadd4 which map to x86 vfmaddsubXXXp{ds} and vfmsubaddXXXp{ds} instructions. This complements the previous addition of ADDSUB support. x86 lacks SUBADD and the negate variants of FMA with mixed plus minus so I did not add optabs or patterns for those but it would not be difficult if there's a target that has them. 2021-07-05 Richard Biener * doc/md.texi (vec_fmaddsub4): Document. (vec_fmsubadd4): Likewise. * optabs.def (vec_fmaddsub$a4): Add. (vec_fmsubadd$a4): Likewise. * internal-fn.def (IFN_VEC_FMADDSUB): Add. (IFN_VEC_FMSUBADD): Likewise. * tree-vect-slp-patterns.c (addsub_pattern::recognize): Refactor to handle IFN_VEC_FMADDSUB and IFN_VEC_FMSUBADD. (addsub_pattern::build): Likewise. * tree-vect-slp.c (vect_optimize_slp): CFN_VEC_FMADDSUB and CFN_VEC_FMSUBADD are not transparent for permutes. * config/i386/sse.md (vec_fmaddsub4): New expander. (vec_fmsubadd4): Likewise. * gcc.target/i386/vect-fmaddsubXXXpd.c: New testcase. * gcc.target/i386/vect-fmaddsubXXXps.c: Likewise. * gcc.target/i386/vect-fmsubaddXXXpd.c: Likewise. * gcc.target/i386/vect-fmsubaddXXXps.c: Likewise. --- gcc/config/i386/sse.md | 19 ++ gcc/doc/md.texi | 14 ++ gcc/internal-fn.def | 3 +- gcc/optabs.def | 2 + gcc/testsuite/gcc.target/i386/vect-fmaddsubXXXpd.c | 34 ++++ gcc/testsuite/gcc.target/i386/vect-fmaddsubXXXps.c | 34 ++++ gcc/testsuite/gcc.target/i386/vect-fmsubaddXXXpd.c | 34 ++++ gcc/testsuite/gcc.target/i386/vect-fmsubaddXXXps.c | 34 ++++ gcc/tree-vect-slp-patterns.c | 192 +++++++++++++++------ gcc/tree-vect-slp.c | 2 + 10 files changed, 311 insertions(+), 57 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/vect-fmaddsubXXXpd.c create mode 100644 gcc/testsuite/gcc.target/i386/vect-fmaddsubXXXps.c create mode 100644 gcc/testsuite/gcc.target/i386/vect-fmsubaddXXXpd.c create mode 100644 gcc/testsuite/gcc.target/i386/vect-fmsubaddXXXps.c (limited to 'gcc') diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index bcf1605..17c9e57 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -4644,6 +4644,25 @@ ;; ;; But this doesn't seem useful in practice. +(define_expand "vec_fmaddsub4" + [(set (match_operand:VF 0 "register_operand") + (unspec:VF + [(match_operand:VF 1 "nonimmediate_operand") + (match_operand:VF 2 "nonimmediate_operand") + (match_operand:VF 3 "nonimmediate_operand")] + UNSPEC_FMADDSUB))] + "TARGET_FMA || TARGET_FMA4 || ( == 64 || TARGET_AVX512VL)") + +(define_expand "vec_fmsubadd4" + [(set (match_operand:VF 0 "register_operand") + (unspec:VF + [(match_operand:VF 1 "nonimmediate_operand") + (match_operand:VF 2 "nonimmediate_operand") + (neg:VF + (match_operand:VF 3 "nonimmediate_operand"))] + UNSPEC_FMADDSUB))] + "TARGET_FMA || TARGET_FMA4 || ( == 64 || TARGET_AVX512VL)") + (define_expand "fmaddsub_" [(set (match_operand:VF 0 "register_operand") (unspec:VF diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 1b91814..cc92ebd 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -5688,6 +5688,20 @@ Alternating subtract, add with even lanes doing subtract and odd lanes doing addition. Operands 1 and 2 and the outout operand are vectors with mode @var{m}. +@cindex @code{vec_fmaddsub@var{m}4} instruction pattern +@item @samp{vec_fmaddsub@var{m}4} +Alternating multiply subtract, add with even lanes doing subtract and odd +lanes doing addition of the third operand to the multiplication result +of the first two operands. Operands 1, 2 and 3 and the outout operand are vectors +with mode @var{m}. + +@cindex @code{vec_fmsubadd@var{m}4} instruction pattern +@item @samp{vec_fmsubadd@var{m}4} +Alternating multiply add, subtract with even lanes doing addition and odd +lanes doing subtraction of the third operand to the multiplication result +of the first two operands. Operands 1, 2 and 3 and the outout operand are vectors +with mode @var{m}. + These instructions are not allowed to @code{FAIL}. @cindex @code{mulhisi3} instruction pattern diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index c3b8e73..a7003d5 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -282,7 +282,8 @@ DEF_INTERNAL_OPTAB_FN (COMPLEX_ADD_ROT270, ECF_CONST, cadd270, binary) DEF_INTERNAL_OPTAB_FN (COMPLEX_MUL, ECF_CONST, cmul, binary) DEF_INTERNAL_OPTAB_FN (COMPLEX_MUL_CONJ, ECF_CONST, cmul_conj, binary) DEF_INTERNAL_OPTAB_FN (VEC_ADDSUB, ECF_CONST, vec_addsub, binary) - +DEF_INTERNAL_OPTAB_FN (VEC_FMADDSUB, ECF_CONST, vec_fmaddsub, ternary) +DEF_INTERNAL_OPTAB_FN (VEC_FMSUBADD, ECF_CONST, vec_fmsubadd, ternary) /* FP scales. */ DEF_INTERNAL_FLT_FN (LDEXP, ECF_CONST, ldexp, binary) diff --git a/gcc/optabs.def b/gcc/optabs.def index 41ab259..51acc1b 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -408,6 +408,8 @@ OPTAB_D (vec_widen_usubl_lo_optab, "vec_widen_usubl_lo_$a") OPTAB_D (vec_widen_uaddl_hi_optab, "vec_widen_uaddl_hi_$a") OPTAB_D (vec_widen_uaddl_lo_optab, "vec_widen_uaddl_lo_$a") OPTAB_D (vec_addsub_optab, "vec_addsub$a3") +OPTAB_D (vec_fmaddsub_optab, "vec_fmaddsub$a4") +OPTAB_D (vec_fmsubadd_optab, "vec_fmsubadd$a4") OPTAB_D (sync_add_optab, "sync_add$I$a") OPTAB_D (sync_and_optab, "sync_and$I$a") diff --git a/gcc/testsuite/gcc.target/i386/vect-fmaddsubXXXpd.c b/gcc/testsuite/gcc.target/i386/vect-fmaddsubXXXpd.c new file mode 100644 index 0000000..b30d107 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-fmaddsubXXXpd.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-require-effective-target fma } */ +/* { dg-options "-O3 -mfma -save-temps" } */ + +#include "fma-check.h" + +void __attribute__((noipa)) +check_fmaddsub (double * __restrict a, double *b, double *c, int n) +{ + for (int i = 0; i < n; ++i) + { + a[2*i + 0] = b[2*i + 0] * c[2*i + 0] - a[2*i + 0]; + a[2*i + 1] = b[2*i + 1] * c[2*i + 1] + a[2*i + 1]; + } +} + +static void +fma_test (void) +{ + double a[4], b[4], c[4]; + for (int i = 0; i < 4; ++i) + { + a[i] = i; + b[i] = 3*i; + c[i] = 7*i; + } + check_fmaddsub (a, b, c, 2); + const double d[4] = { 0., 22., 82., 192. }; + for (int i = 0; i < 4; ++i) + if (a[i] != d[i]) + __builtin_abort (); +} + +/* { dg-final { scan-assembler "fmaddsub...pd" } } */ diff --git a/gcc/testsuite/gcc.target/i386/vect-fmaddsubXXXps.c b/gcc/testsuite/gcc.target/i386/vect-fmaddsubXXXps.c new file mode 100644 index 0000000..cd2af87 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-fmaddsubXXXps.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-require-effective-target fma } */ +/* { dg-options "-O3 -mfma -save-temps" } */ + +#include "fma-check.h" + +void __attribute__((noipa)) +check_fmaddsub (float * __restrict a, float *b, float *c, int n) +{ + for (int i = 0; i < n; ++i) + { + a[2*i + 0] = b[2*i + 0] * c[2*i + 0] - a[2*i + 0]; + a[2*i + 1] = b[2*i + 1] * c[2*i + 1] + a[2*i + 1]; + } +} + +static void +fma_test (void) +{ + float a[4], b[4], c[4]; + for (int i = 0; i < 4; ++i) + { + a[i] = i; + b[i] = 3*i; + c[i] = 7*i; + } + check_fmaddsub (a, b, c, 2); + const float d[4] = { 0., 22., 82., 192. }; + for (int i = 0; i < 4; ++i) + if (a[i] != d[i]) + __builtin_abort (); +} + +/* { dg-final { scan-assembler "fmaddsub...ps" } } */ diff --git a/gcc/testsuite/gcc.target/i386/vect-fmsubaddXXXpd.c b/gcc/testsuite/gcc.target/i386/vect-fmsubaddXXXpd.c new file mode 100644 index 0000000..7ca2a27 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-fmsubaddXXXpd.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-require-effective-target fma } */ +/* { dg-options "-O3 -mfma -save-temps" } */ + +#include "fma-check.h" + +void __attribute__((noipa)) +check_fmsubadd (double * __restrict a, double *b, double *c, int n) +{ + for (int i = 0; i < n; ++i) + { + a[2*i + 0] = b[2*i + 0] * c[2*i + 0] + a[2*i + 0]; + a[2*i + 1] = b[2*i + 1] * c[2*i + 1] - a[2*i + 1]; + } +} + +static void +fma_test (void) +{ + double a[4], b[4], c[4]; + for (int i = 0; i < 4; ++i) + { + a[i] = i; + b[i] = 3*i; + c[i] = 7*i; + } + check_fmsubadd (a, b, c, 2); + const double d[4] = { 0., 20., 86., 186. }; + for (int i = 0; i < 4; ++i) + if (a[i] != d[i]) + __builtin_abort (); +} + +/* { dg-final { scan-assembler "fmsubadd...pd" } } */ diff --git a/gcc/testsuite/gcc.target/i386/vect-fmsubaddXXXps.c b/gcc/testsuite/gcc.target/i386/vect-fmsubaddXXXps.c new file mode 100644 index 0000000..9ddd0e4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-fmsubaddXXXps.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-require-effective-target fma } */ +/* { dg-options "-O3 -mfma -save-temps" } */ + +#include "fma-check.h" + +void __attribute__((noipa)) +check_fmsubadd (float * __restrict a, float *b, float *c, int n) +{ + for (int i = 0; i < n; ++i) + { + a[2*i + 0] = b[2*i + 0] * c[2*i + 0] + a[2*i + 0]; + a[2*i + 1] = b[2*i + 1] * c[2*i + 1] - a[2*i + 1]; + } +} + +static void +fma_test (void) +{ + float a[4], b[4], c[4]; + for (int i = 0; i < 4; ++i) + { + a[i] = i; + b[i] = 3*i; + c[i] = 7*i; + } + check_fmsubadd (a, b, c, 2); + const float d[4] = { 0., 20., 86., 186. }; + for (int i = 0; i < 4; ++i) + if (a[i] != d[i]) + __builtin_abort (); +} + +/* { dg-final { scan-assembler "fmsubadd...ps" } } */ diff --git a/gcc/tree-vect-slp-patterns.c b/gcc/tree-vect-slp-patterns.c index 2671f91..f774cac 100644 --- a/gcc/tree-vect-slp-patterns.c +++ b/gcc/tree-vect-slp-patterns.c @@ -1496,8 +1496,8 @@ complex_operations_pattern::build (vec_info * /* vinfo */) class addsub_pattern : public vect_pattern { public: - addsub_pattern (slp_tree *node) - : vect_pattern (node, NULL, IFN_VEC_ADDSUB) {}; + addsub_pattern (slp_tree *node, internal_fn ifn) + : vect_pattern (node, NULL, ifn) {}; void build (vec_info *); @@ -1510,46 +1510,68 @@ addsub_pattern::recognize (slp_tree_to_load_perm_map_t *, slp_tree *node_) { slp_tree node = *node_; if (SLP_TREE_CODE (node) != VEC_PERM_EXPR - || SLP_TREE_CHILDREN (node).length () != 2) + || SLP_TREE_CHILDREN (node).length () != 2 + || SLP_TREE_LANE_PERMUTATION (node).length () % 2) return NULL; /* Match a blend of a plus and a minus op with the same number of plus and minus lanes on the same operands. */ - slp_tree sub = SLP_TREE_CHILDREN (node)[0]; - slp_tree add = SLP_TREE_CHILDREN (node)[1]; - bool swapped_p = false; - if (vect_match_expression_p (sub, PLUS_EXPR)) - { - std::swap (add, sub); - swapped_p = true; - } - if (!(vect_match_expression_p (add, PLUS_EXPR) - && vect_match_expression_p (sub, MINUS_EXPR))) + unsigned l0 = SLP_TREE_LANE_PERMUTATION (node)[0].first; + unsigned l1 = SLP_TREE_LANE_PERMUTATION (node)[1].first; + if (l0 == l1) + return NULL; + bool l0add_p = vect_match_expression_p (SLP_TREE_CHILDREN (node)[l0], + PLUS_EXPR); + if (!l0add_p + && !vect_match_expression_p (SLP_TREE_CHILDREN (node)[l0], MINUS_EXPR)) + return NULL; + bool l1add_p = vect_match_expression_p (SLP_TREE_CHILDREN (node)[l1], + PLUS_EXPR); + if (!l1add_p + && !vect_match_expression_p (SLP_TREE_CHILDREN (node)[l1], MINUS_EXPR)) return NULL; - if (!((SLP_TREE_CHILDREN (sub)[0] == SLP_TREE_CHILDREN (add)[0] - && SLP_TREE_CHILDREN (sub)[1] == SLP_TREE_CHILDREN (add)[1]) - || (SLP_TREE_CHILDREN (sub)[0] == SLP_TREE_CHILDREN (add)[1] - && SLP_TREE_CHILDREN (sub)[1] == SLP_TREE_CHILDREN (add)[0]))) + + slp_tree l0node = SLP_TREE_CHILDREN (node)[l0]; + slp_tree l1node = SLP_TREE_CHILDREN (node)[l1]; + if (!((SLP_TREE_CHILDREN (l0node)[0] == SLP_TREE_CHILDREN (l1node)[0] + && SLP_TREE_CHILDREN (l0node)[1] == SLP_TREE_CHILDREN (l1node)[1]) + || (SLP_TREE_CHILDREN (l0node)[0] == SLP_TREE_CHILDREN (l1node)[1] + && SLP_TREE_CHILDREN (l0node)[1] == SLP_TREE_CHILDREN (l1node)[0]))) return NULL; for (unsigned i = 0; i < SLP_TREE_LANE_PERMUTATION (node).length (); ++i) { std::pair perm = SLP_TREE_LANE_PERMUTATION (node)[i]; - if (swapped_p) - perm.first = perm.first == 0 ? 1 : 0; - /* It has to be alternating -, +, -, ... + /* It has to be alternating -, +, -, While we could permute the .ADDSUB inputs and the .ADDSUB output that's only profitable over the add + sub + blend if at least one of the permute is optimized which we can't determine here. */ - if (perm.first != (i & 1) + if (perm.first != ((i & 1) ? l1 : l0) || perm.second != i) return NULL; } - if (!vect_pattern_validate_optab (IFN_VEC_ADDSUB, node)) - return NULL; + /* Now we have either { -, +, -, + ... } (!l0add_p) or { +, -, +, - ... } + (l0add_p), see whether we have FMA variants. */ + if (!l0add_p + && vect_match_expression_p (SLP_TREE_CHILDREN (l0node)[0], MULT_EXPR)) + { + /* (c * d) -+ a */ + if (vect_pattern_validate_optab (IFN_VEC_FMADDSUB, node)) + return new addsub_pattern (node_, IFN_VEC_FMADDSUB); + } + else if (l0add_p + && vect_match_expression_p (SLP_TREE_CHILDREN (l1node)[0], MULT_EXPR)) + { + /* (c * d) +- a */ + if (vect_pattern_validate_optab (IFN_VEC_FMSUBADD, node)) + return new addsub_pattern (node_, IFN_VEC_FMSUBADD); + } - return new addsub_pattern (node_); + if (!l0add_p && vect_pattern_validate_optab (IFN_VEC_ADDSUB, node)) + return new addsub_pattern (node_, IFN_VEC_ADDSUB); + + return NULL; } void @@ -1557,38 +1579,96 @@ addsub_pattern::build (vec_info *vinfo) { slp_tree node = *m_node; - slp_tree sub = SLP_TREE_CHILDREN (node)[0]; - slp_tree add = SLP_TREE_CHILDREN (node)[1]; - if (vect_match_expression_p (sub, PLUS_EXPR)) - std::swap (add, sub); - - /* Modify the blend node in-place. */ - SLP_TREE_CHILDREN (node)[0] = SLP_TREE_CHILDREN (sub)[0]; - SLP_TREE_CHILDREN (node)[1] = SLP_TREE_CHILDREN (sub)[1]; - SLP_TREE_REF_COUNT (SLP_TREE_CHILDREN (node)[0])++; - SLP_TREE_REF_COUNT (SLP_TREE_CHILDREN (node)[1])++; - - /* Build IFN_VEC_ADDSUB from the sub representative operands. */ - stmt_vec_info rep = SLP_TREE_REPRESENTATIVE (sub); - gcall *call = gimple_build_call_internal (IFN_VEC_ADDSUB, 2, - gimple_assign_rhs1 (rep->stmt), - gimple_assign_rhs2 (rep->stmt)); - gimple_call_set_lhs (call, make_ssa_name - (TREE_TYPE (gimple_assign_lhs (rep->stmt)))); - gimple_call_set_nothrow (call, true); - gimple_set_bb (call, gimple_bb (rep->stmt)); - stmt_vec_info new_rep = vinfo->add_pattern_stmt (call, rep); - SLP_TREE_REPRESENTATIVE (node) = new_rep; - STMT_VINFO_RELEVANT (new_rep) = vect_used_in_scope; - STMT_SLP_TYPE (new_rep) = pure_slp; - STMT_VINFO_VECTYPE (new_rep) = SLP_TREE_VECTYPE (node); - STMT_VINFO_SLP_VECT_ONLY_PATTERN (new_rep) = true; - STMT_VINFO_REDUC_DEF (new_rep) = STMT_VINFO_REDUC_DEF (vect_orig_stmt (rep)); - SLP_TREE_CODE (node) = ERROR_MARK; - SLP_TREE_LANE_PERMUTATION (node).release (); - - vect_free_slp_tree (sub); - vect_free_slp_tree (add); + unsigned l0 = SLP_TREE_LANE_PERMUTATION (node)[0].first; + unsigned l1 = SLP_TREE_LANE_PERMUTATION (node)[1].first; + + switch (m_ifn) + { + case IFN_VEC_ADDSUB: + { + slp_tree sub = SLP_TREE_CHILDREN (node)[l0]; + slp_tree add = SLP_TREE_CHILDREN (node)[l1]; + + /* Modify the blend node in-place. */ + SLP_TREE_CHILDREN (node)[0] = SLP_TREE_CHILDREN (sub)[0]; + SLP_TREE_CHILDREN (node)[1] = SLP_TREE_CHILDREN (sub)[1]; + SLP_TREE_REF_COUNT (SLP_TREE_CHILDREN (node)[0])++; + SLP_TREE_REF_COUNT (SLP_TREE_CHILDREN (node)[1])++; + + /* Build IFN_VEC_ADDSUB from the sub representative operands. */ + stmt_vec_info rep = SLP_TREE_REPRESENTATIVE (sub); + gcall *call = gimple_build_call_internal (IFN_VEC_ADDSUB, 2, + gimple_assign_rhs1 (rep->stmt), + gimple_assign_rhs2 (rep->stmt)); + gimple_call_set_lhs (call, make_ssa_name + (TREE_TYPE (gimple_assign_lhs (rep->stmt)))); + gimple_call_set_nothrow (call, true); + gimple_set_bb (call, gimple_bb (rep->stmt)); + stmt_vec_info new_rep = vinfo->add_pattern_stmt (call, rep); + SLP_TREE_REPRESENTATIVE (node) = new_rep; + STMT_VINFO_RELEVANT (new_rep) = vect_used_in_scope; + STMT_SLP_TYPE (new_rep) = pure_slp; + STMT_VINFO_VECTYPE (new_rep) = SLP_TREE_VECTYPE (node); + STMT_VINFO_SLP_VECT_ONLY_PATTERN (new_rep) = true; + STMT_VINFO_REDUC_DEF (new_rep) = STMT_VINFO_REDUC_DEF (vect_orig_stmt (rep)); + SLP_TREE_CODE (node) = ERROR_MARK; + SLP_TREE_LANE_PERMUTATION (node).release (); + + vect_free_slp_tree (sub); + vect_free_slp_tree (add); + break; + } + case IFN_VEC_FMADDSUB: + case IFN_VEC_FMSUBADD: + { + slp_tree sub, add; + if (m_ifn == IFN_VEC_FMADDSUB) + { + sub = SLP_TREE_CHILDREN (node)[l0]; + add = SLP_TREE_CHILDREN (node)[l1]; + } + else /* m_ifn == IFN_VEC_FMSUBADD */ + { + sub = SLP_TREE_CHILDREN (node)[l1]; + add = SLP_TREE_CHILDREN (node)[l0]; + } + slp_tree mul = SLP_TREE_CHILDREN (sub)[0]; + /* Modify the blend node in-place. */ + SLP_TREE_CHILDREN (node).safe_grow (3, true); + SLP_TREE_CHILDREN (node)[0] = SLP_TREE_CHILDREN (mul)[0]; + SLP_TREE_CHILDREN (node)[1] = SLP_TREE_CHILDREN (mul)[1]; + SLP_TREE_CHILDREN (node)[2] = SLP_TREE_CHILDREN (sub)[1]; + SLP_TREE_REF_COUNT (SLP_TREE_CHILDREN (node)[0])++; + SLP_TREE_REF_COUNT (SLP_TREE_CHILDREN (node)[1])++; + SLP_TREE_REF_COUNT (SLP_TREE_CHILDREN (node)[2])++; + + /* Build IFN_VEC_FMADDSUB from the mul/sub representative operands. */ + stmt_vec_info srep = SLP_TREE_REPRESENTATIVE (sub); + stmt_vec_info mrep = SLP_TREE_REPRESENTATIVE (mul); + gcall *call = gimple_build_call_internal (m_ifn, 3, + gimple_assign_rhs1 (mrep->stmt), + gimple_assign_rhs2 (mrep->stmt), + gimple_assign_rhs2 (srep->stmt)); + gimple_call_set_lhs (call, make_ssa_name + (TREE_TYPE (gimple_assign_lhs (srep->stmt)))); + gimple_call_set_nothrow (call, true); + gimple_set_bb (call, gimple_bb (srep->stmt)); + stmt_vec_info new_rep = vinfo->add_pattern_stmt (call, srep); + SLP_TREE_REPRESENTATIVE (node) = new_rep; + STMT_VINFO_RELEVANT (new_rep) = vect_used_in_scope; + STMT_SLP_TYPE (new_rep) = pure_slp; + STMT_VINFO_VECTYPE (new_rep) = SLP_TREE_VECTYPE (node); + STMT_VINFO_SLP_VECT_ONLY_PATTERN (new_rep) = true; + STMT_VINFO_REDUC_DEF (new_rep) = STMT_VINFO_REDUC_DEF (vect_orig_stmt (srep)); + SLP_TREE_CODE (node) = ERROR_MARK; + SLP_TREE_LANE_PERMUTATION (node).release (); + + vect_free_slp_tree (sub); + vect_free_slp_tree (add); + break; + } + default:; + } } /******************************************************************************* diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index f08797c..5357cd0 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -3728,6 +3728,8 @@ vect_optimize_slp (vec_info *vinfo) case CFN_COMPLEX_MUL: case CFN_COMPLEX_MUL_CONJ: case CFN_VEC_ADDSUB: + case CFN_VEC_FMADDSUB: + case CFN_VEC_FMSUBADD: vertices[idx].perm_in = 0; vertices[idx].perm_out = 0; default:; -- cgit v1.1 From f99f6eb58e1f894dae024f63cc2fe30fa7605e59 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Sat, 3 Jul 2021 19:47:48 +0100 Subject: X86: Provide a CTOR for stringop_algs [PR100246]. Several older compilers fail to build modern GCC because of missing or incomplete C++11 support. Signed-off-by: Iain Sandoe PR bootstrap/100246 - [11/12 Regression] GCC will not bootstrap with clang 3.4/3.5 [xcode 5/6, Darwin 12/13] PR bootstrap/100246 gcc/ChangeLog: * config/i386/i386.h (struct stringop_algs): Define a CTOR for this type. --- gcc/config/i386/i386.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'gcc') diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 6e0340a..03d1761 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -73,6 +73,15 @@ struct stringop_algs { const enum stringop_alg unknown_size; const struct stringop_strategy { + /* Several older compilers delete the default constructor because of the + const entries (see PR100246). Manually specifying a CTOR works around + this issue. Since this header is used by code compiled with the C + compiler we must guard the addition. */ +#ifdef __cplusplus + stringop_strategy(int _max = -1, enum stringop_alg _alg = libcall, + int _noalign = false) + : max (_max), alg (_alg), noalign (_noalign) {} +#endif const int max; const enum stringop_alg alg; int noalign; -- cgit v1.1 From 0b2e9514880c304488da80776c77d25e17ef1622 Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Thu, 29 Apr 2021 15:29:16 -0700 Subject: [Ada] Add GNAT RM text regarding Ada 2022 default Put_Image implementation gcc/ada/ * doc/gnat_rm/implementation_of_specific_ada_features.rst: Add a warning indicating that the details of the default (i.e., selected by the compiler) implementation of T'Put_Image for a nonscalar type T are subject to change. * gnat_rm.texi: Regenerate. --- .../implementation_of_specific_ada_features.rst | 20 ++++++ gcc/ada/gnat_rm.texi | 80 ++++++++++++++-------- 2 files changed, 71 insertions(+), 29 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/doc/gnat_rm/implementation_of_specific_ada_features.rst b/gcc/ada/doc/gnat_rm/implementation_of_specific_ada_features.rst index e818ab5..9f419a7 100644 --- a/gcc/ada/doc/gnat_rm/implementation_of_specific_ada_features.rst +++ b/gcc/ada/doc/gnat_rm/implementation_of_specific_ada_features.rst @@ -672,6 +672,26 @@ aliasing all views of the object (which may be manipulated by different tasks, say) must be consistent, so it is imperative that the object, once created, remain invariant. +.. _Image_Values_For_Nonscalar_Types: + +Image Values For Nonscalar Types +================================ + +Ada 2022 defines the Image, Wide_Image, and Wide_Wide image attributes +for nonscalar types; earlier Ada versions defined these attributes only +for scalar types. Ada RM 4.10 provides some general guidance regarding +the default implementation of these attributes and the GNAT compiler +follows that guidance. However, beyond that the precise details of the +image text generated in these cases are deliberately not documented and are +subject to change. In particular, users should not rely on formatting details +(such as spaces or line breaking), record field order, image values for access +types, image values for types that have ancestor or subcomponent types +declared in non-Ada2022 code, image values for predefined types, or the +compiler's choices regarding the implementation permissions described in +Ada RM 4.10. This list is not intended to be exhaustive. If more precise +control of image text is required for some type T, then T'Put_Image should be +explicitly specified. + .. _Strict_Conformance_to_the_Ada_Reference_Manual: Strict Conformance to the Ada Reference Manual diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 14b03c4..771e6aa 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -860,6 +860,7 @@ Implementation of Specific Ada Features * GNAT Implementation of Shared Passive Packages:: * Code Generation for Array Aggregates:: * The Size of Discriminated Records with Default Discriminants:: +* Image Values For Nonscalar Types:: * Strict Conformance to the Ada Reference Manual:: GNAT Implementation of Tasking @@ -25601,6 +25602,7 @@ facilities. * GNAT Implementation of Shared Passive Packages:: * Code Generation for Array Aggregates:: * The Size of Discriminated Records with Default Discriminants:: +* Image Values For Nonscalar Types:: * Strict Conformance to the Ada Reference Manual:: @end menu @@ -26215,7 +26217,7 @@ If any of these conditions are violated, the aggregate will be built in a temporary (created either by the front-end or the code generator) and then that temporary will be copied onto the target. -@node The Size of Discriminated Records with Default Discriminants,Strict Conformance to the Ada Reference Manual,Code Generation for Array Aggregates,Implementation of Specific Ada Features +@node The Size of Discriminated Records with Default Discriminants,Image Values For Nonscalar Types,Code Generation for Array Aggregates,Implementation of Specific Ada Features @anchor{gnat_rm/implementation_of_specific_ada_features id13}@anchor{431}@anchor{gnat_rm/implementation_of_specific_ada_features the-size-of-discriminated-records-with-default-discriminants}@anchor{432} @section The Size of Discriminated Records with Default Discriminants @@ -26295,8 +26297,28 @@ aliasing all views of the object (which may be manipulated by different tasks, say) must be consistent, so it is imperative that the object, once created, remain invariant. -@node Strict Conformance to the Ada Reference Manual,,The Size of Discriminated Records with Default Discriminants,Implementation of Specific Ada Features -@anchor{gnat_rm/implementation_of_specific_ada_features id14}@anchor{433}@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{434} +@node Image Values For Nonscalar Types,Strict Conformance to the Ada Reference Manual,The Size of Discriminated Records with Default Discriminants,Implementation of Specific Ada Features +@anchor{gnat_rm/implementation_of_specific_ada_features id14}@anchor{433}@anchor{gnat_rm/implementation_of_specific_ada_features image-values-for-nonscalar-types}@anchor{434} +@section Image Values For Nonscalar Types + + +Ada 2022 defines the Image, Wide_Image, and Wide_Wide image attributes +for nonscalar types; earlier Ada versions defined these attributes only +for scalar types. Ada RM 4.10 provides some general guidance regarding +the default implementation of these attributes and the GNAT compiler +follows that guidance. However, beyond that the precise details of the +image text generated in these cases are deliberately not documented and are +subject to change. In particular, users should not rely on formatting details +(such as spaces or line breaking), record field order, image values for access +types, image values for types that have ancestor or subcomponent types +declared in non-Ada2022 code, image values for predefined types, or the +compiler’s choices regarding the implementation permissions described in +Ada RM 4.10. This list is not intended to be exhaustive. If more precise +control of image text is required for some type T, then T’Put_Image should be +explicitly specified. + +@node Strict Conformance to the Ada Reference Manual,,Image Values For Nonscalar Types,Implementation of Specific Ada Features +@anchor{gnat_rm/implementation_of_specific_ada_features id15}@anchor{435}@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{436} @section Strict Conformance to the Ada Reference Manual @@ -26323,7 +26345,7 @@ behavior (although at the cost of a significant performance penalty), so infinite and NaN values are properly generated. @node Implementation of Ada 2012 Features,Obsolescent Features,Implementation of Specific Ada Features,Top -@anchor{gnat_rm/implementation_of_ada_2012_features doc}@anchor{435}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{436}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14} +@anchor{gnat_rm/implementation_of_ada_2012_features doc}@anchor{437}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{438}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14} @chapter Implementation of Ada 2012 Features @@ -28489,7 +28511,7 @@ RM References: H.04 (8/1) @end itemize @node Obsolescent Features,Compatibility and Porting Guide,Implementation of Ada 2012 Features,Top -@anchor{gnat_rm/obsolescent_features doc}@anchor{437}@anchor{gnat_rm/obsolescent_features id1}@anchor{438}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{15} +@anchor{gnat_rm/obsolescent_features doc}@anchor{439}@anchor{gnat_rm/obsolescent_features id1}@anchor{43a}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{15} @chapter Obsolescent Features @@ -28508,7 +28530,7 @@ compatibility purposes. @end menu @node pragma No_Run_Time,pragma Ravenscar,,Obsolescent Features -@anchor{gnat_rm/obsolescent_features id2}@anchor{439}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{43a} +@anchor{gnat_rm/obsolescent_features id2}@anchor{43b}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{43c} @section pragma No_Run_Time @@ -28521,7 +28543,7 @@ preferred usage is to use an appropriately configured run-time that includes just those features that are to be made accessible. @node pragma Ravenscar,pragma Restricted_Run_Time,pragma No_Run_Time,Obsolescent Features -@anchor{gnat_rm/obsolescent_features id3}@anchor{43b}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{43c} +@anchor{gnat_rm/obsolescent_features id3}@anchor{43d}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{43e} @section pragma Ravenscar @@ -28530,7 +28552,7 @@ The pragma @code{Ravenscar} has exactly the same effect as pragma is part of the new Ada 2005 standard. @node pragma Restricted_Run_Time,pragma Task_Info,pragma Ravenscar,Obsolescent Features -@anchor{gnat_rm/obsolescent_features id4}@anchor{43d}@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{43e} +@anchor{gnat_rm/obsolescent_features id4}@anchor{43f}@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{440} @section pragma Restricted_Run_Time @@ -28540,7 +28562,7 @@ preferred since the Ada 2005 pragma @code{Profile} is intended for this kind of implementation dependent addition. @node pragma Task_Info,package System Task_Info s-tasinf ads,pragma Restricted_Run_Time,Obsolescent Features -@anchor{gnat_rm/obsolescent_features id5}@anchor{43f}@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{440} +@anchor{gnat_rm/obsolescent_features id5}@anchor{441}@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{442} @section pragma Task_Info @@ -28566,7 +28588,7 @@ in the spec of package System.Task_Info in the runtime library. @node package System Task_Info s-tasinf ads,,pragma Task_Info,Obsolescent Features -@anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{441}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{442} +@anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{443}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{444} @section package System.Task_Info (@code{s-tasinf.ads}) @@ -28576,7 +28598,7 @@ to support the @code{Task_Info} pragma. The predefined Ada package standard replacement for GNAT’s @code{Task_Info} functionality. @node Compatibility and Porting Guide,GNU Free Documentation License,Obsolescent Features,Top -@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{443}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{16}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{444} +@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{445}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{16}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{446} @chapter Compatibility and Porting Guide @@ -28598,7 +28620,7 @@ applications developed in other Ada environments. @end menu @node Writing Portable Fixed-Point Declarations,Compatibility with Ada 83,,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{445}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{446} +@anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{447}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{448} @section Writing Portable Fixed-Point Declarations @@ -28720,7 +28742,7 @@ If you follow this scheme you will be guaranteed that your fixed-point types will be portable. @node Compatibility with Ada 83,Compatibility between Ada 95 and Ada 2005,Writing Portable Fixed-Point Declarations,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{447}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{448} +@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{449}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{44a} @section Compatibility with Ada 83 @@ -28748,7 +28770,7 @@ following subsections treat the most likely issues to be encountered. @end menu @node Legal Ada 83 programs that are illegal in Ada 95,More deterministic semantics,,Compatibility with Ada 83 -@anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{449}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{44a} +@anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{44b}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{44c} @subsection Legal Ada 83 programs that are illegal in Ada 95 @@ -28848,7 +28870,7 @@ the fix is usually simply to add the @code{(<>)} to the generic declaration. @end itemize @node More deterministic semantics,Changed semantics,Legal Ada 83 programs that are illegal in Ada 95,Compatibility with Ada 83 -@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{44b}@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{44c} +@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{44d}@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{44e} @subsection More deterministic semantics @@ -28876,7 +28898,7 @@ which open select branches are executed. @end itemize @node Changed semantics,Other language compatibility issues,More deterministic semantics,Compatibility with Ada 83 -@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{44d}@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{44e} +@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{44f}@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{450} @subsection Changed semantics @@ -28918,7 +28940,7 @@ covers only the restricted range. @end itemize @node Other language compatibility issues,,Changed semantics,Compatibility with Ada 83 -@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{44f}@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{450} +@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{451}@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{452} @subsection Other language compatibility issues @@ -28951,7 +28973,7 @@ include @code{pragma Interface} and the floating point type attributes @end itemize @node Compatibility between Ada 95 and Ada 2005,Implementation-dependent characteristics,Compatibility with Ada 83,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{451}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{452} +@anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{453}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{454} @section Compatibility between Ada 95 and Ada 2005 @@ -29023,7 +29045,7 @@ can declare a function returning a value from an anonymous access type. @end itemize @node Implementation-dependent characteristics,Compatibility with Other Ada Systems,Compatibility between Ada 95 and Ada 2005,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{453}@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{454} +@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{455}@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{456} @section Implementation-dependent characteristics @@ -29046,7 +29068,7 @@ transition from certain Ada 83 compilers. @end menu @node Implementation-defined pragmas,Implementation-defined attributes,,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{455}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{456} +@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{457}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{458} @subsection Implementation-defined pragmas @@ -29068,7 +29090,7 @@ avoiding compiler rejection of units that contain such pragmas; they are not relevant in a GNAT context and hence are not otherwise implemented. @node Implementation-defined attributes,Libraries,Implementation-defined pragmas,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{457}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{458} +@anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{459}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{45a} @subsection Implementation-defined attributes @@ -29082,7 +29104,7 @@ Ada 83, GNAT supplies the attributes @code{Bit}, @code{Machine_Size} and @code{Type_Class}. @node Libraries,Elaboration order,Implementation-defined attributes,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{459}@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{45a} +@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{45b}@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{45c} @subsection Libraries @@ -29111,7 +29133,7 @@ be preferable to retrofit the application using modular types. @end itemize @node Elaboration order,Target-specific aspects,Libraries,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{45b}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{45c} +@anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{45d}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{45e} @subsection Elaboration order @@ -29147,7 +29169,7 @@ pragmas either globally (as an effect of the @emph{-gnatE} switch) or locally @end itemize @node Target-specific aspects,,Elaboration order,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{45d}@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{45e} +@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{45f}@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{460} @subsection Target-specific aspects @@ -29160,10 +29182,10 @@ on the robustness of the original design. Moreover, Ada 95 (and thus Ada 2005 and Ada 2012) are sometimes incompatible with typical Ada 83 compiler practices regarding implicit packing, the meaning of the Size attribute, and the size of access values. -GNAT’s approach to these issues is described in @ref{45f,,Representation Clauses}. +GNAT’s approach to these issues is described in @ref{461,,Representation Clauses}. @node Compatibility with Other Ada Systems,Representation Clauses,Implementation-dependent characteristics,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{460}@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{461} +@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{462}@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{463} @section Compatibility with Other Ada Systems @@ -29206,7 +29228,7 @@ far beyond this minimal set, as described in the next section. @end itemize @node Representation Clauses,Compatibility with HP Ada 83,Compatibility with Other Ada Systems,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{462}@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{45f} +@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{464}@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{461} @section Representation Clauses @@ -29299,7 +29321,7 @@ with thin pointers. @end itemize @node Compatibility with HP Ada 83,,Representation Clauses,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{463}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{464} +@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{465}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{466} @section Compatibility with HP Ada 83 @@ -29329,7 +29351,7 @@ extension of package System. @end itemize @node GNU Free Documentation License,Index,Compatibility and Porting Guide,Top -@anchor{share/gnu_free_documentation_license doc}@anchor{465}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{466} +@anchor{share/gnu_free_documentation_license doc}@anchor{467}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{468} @chapter GNU Free Documentation License -- cgit v1.1 From daf9bc6aeab822da203c01beb47d2c9e11ab3635 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Sat, 1 May 2021 19:55:36 -0400 Subject: [Ada] Spurious conformance error on expression function gcc/ada/ * sem_ch6.adb (Analyze_Subprogram_Body_Helper): Do not perform conformance check when the subprogram body has been created for an expression function that is not a completion of a previous specification, because the profile of the constructed body is copied from the expression function itself. --- gcc/ada/sem_ch6.adb | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 4b58d59..c7d4b96 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -4585,6 +4585,17 @@ package body Sem_Ch6 is then Conformant := True; + -- Finally, a body generated for an expression function copies + -- the profile of the function and no check is needed either. + -- If the body is the completion of a previous function + -- declared elsewhere, the conformance check is required. + + elsif Nkind (N) = N_Subprogram_Body + and then Was_Expression_Function (N) + and then Sloc (Spec_Id) = Sloc (Body_Id) + then + Conformant := True; + else Check_Conformance (Body_Id, Spec_Id, -- cgit v1.1 From 2e1f3a5e3e76aa1149b9061304a4ef0ea40483b3 Mon Sep 17 00:00:00 2001 From: Gary Dismukes Date: Mon, 3 May 2021 01:56:38 -0400 Subject: [Ada] Support for Object.Op subprogram-call notation for untagged types gcc/ada/ * doc/gnat_rm/implementation_defined_pragmas.rst: Add a description of the feature of prefixed-view calls for untagged types to the section on pragma Extensions_Allowed. * gnat_rm.texi: Regenerate. * einfo.ads: Update specification for Direct_Primitive_Operations to reflect its use for untagged types when Extensions_Allowed is True. * gen_il-gen-gen_entities.adb: Allow Direct_Primitive_Operations as a field of untagged classes of types by removing the "Pre" test of "Is_Tagged_Type (N)", and making that field generally available for all types and subtypes by defining it for Type_Kind and removing its specification for individual classes of types. * sem_ch3.adb (Analyze_Full_Type_Declaration): Initialize the Direct_Primitive_Operations list when not already set for the new (sub)type and its base type (except when Ekind of the type is E_Void, which can happen due to errors in cases where Derived_Type_Declaration is called and perhaps in other situations). (Analyze_Subtype_Declaration): Inherit Direct_Primitive_Operations list from the base type, for record and private cases. (Build_Derived_Record_Type): Initialize the Direct_Primitive_Operations list for derived record and private types. (Build_Derived_Type): Initialize the Direct_Primitive_Operations list for derived types (and also for their associated base types when needed). (Process_Full_View): For full types that are untagged record and private types, copy the primitive operations of the partial view to the primitives list of the full view. * sem_ch4.adb (Analyze_Selected_Component): Allow prefixed notation for subprogram calls in the case of untagged types (when Extensions_Allowed is True). In the case where Is_Private_Type (Prefix_Type) is True, call Try_Object_Operation when a discriminant selector wasn't found. Also call Try_Object_Operation in other type kind cases (when Extensions_Allowed is True). (Try_Object_Operation.Try_One_Prefixed_Interpretation): Prevent early return in the untagged case (when Extensions_Allowed is True). Condition main call to Try_Primitive_Operation on the type having primitives, and after that, if Prim_Result is False, test for case where the prefix type is a named access type with primitive operations and in that case call Try_Primitive_Operation after temporarily resetting Obj_Type to denote the access type (and restore it to the designated type after the call) (Try_Object_Operation.Valid_First_Argument_Of): Do matching type comparison by testing Base_Type (Obj_Type) against Base_Type (Typ), rather than against just Typ, to properly handle cases where the object prefix has a constrained subtype. (Fixes a bug discovered while working on this feature.) * sem_ch6.adb (New_Overloaded_Entity.Check_For_Primitive_Subprogram): Add a primitive of an untagged type to the type's list of primitive operations, for both explicit and implicit (derived, so Comes_From_Source is False) subprogram declarations. In the case where the new primitive overrides an inherited subprogram, locate the primitives Elist that references the overridden subprogram, and replace that element of the list with the new subprogram (done by calling the new procedure Add_Or_Replace_Untagged_Primitive on the result type and each formal atype). (Check_For_Primitive_Subprogram.Add_Or_Replace_Untagged_Primitive): New nested procedure to either add or replace an untagged primitive subprogram in a given type's list of primitive operations (replacement happens in case where the new subprogram overrides a primitive of the type). * sem_ch7.adb (New_Private_Type): When Extensions_Allowed is True, initialize the Direct_Primitive_Operations list of a private type to New_Elmt_List in the case of untagged types. * sem_ch8.adb (Find_Selected_Component): In the case where the prefix is an entity name, relax condition that tests Has_Components so that Analyze_Selected_Component will also be called when Extensions_Allowed is True and the prefix type is any type. --- .../doc/gnat_rm/implementation_defined_pragmas.rst | 17 +++ gcc/ada/einfo.ads | 17 ++- gcc/ada/gen_il-gen-gen_entities.adb | 35 +---- gcc/ada/gnat_rm.texi | 18 +++ gcc/ada/sem_ch3.adb | 162 ++++++++++++++++----- gcc/ada/sem_ch4.adb | 60 +++++++- gcc/ada/sem_ch6.adb | 98 ++++++++++++- gcc/ada/sem_ch7.adb | 9 ++ gcc/ada/sem_ch8.adb | 14 +- 9 files changed, 346 insertions(+), 84 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst index d86a2fd..c82658d 100644 --- a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst +++ b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst @@ -2362,6 +2362,23 @@ of GNAT specific extensions are recognized as follows: knows the lower bound of unconstrained array formals when the formal's subtype has index ranges with static fixed lower bounds. +* Prefixed-view notation for calls to primitive subprograms of untagged types + + Since Ada 2005, calls to primitive subprograms of a tagged type that + have a "prefixed view" (see RM 4.1.3(9.2)) have been allowed to be + written using the form of a selected_component, with the first actual + parameter given as the prefix and the name of the subprogram as a + selector. This prefixed-view notation for calls is extended so as to + also allow such syntax for calls to primitive subprograms of untagged + types. The primitives of an untagged type T that have a prefixed view + are those where the first formal parameter of the subprogram either + is of type T or is an anonymous access parameter whose designated type + is T. For a type that has a component that happens to have the same + simple name as one of the type's primitive subprograms, where the + component is visible at the point of a selected_component using that + name, preference is given to the component in a selected_component + (as is currently the case for tagged types with such component names). + .. _Pragma-Extensions_Visible: Pragma Extensions_Visible diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index 70b93b3..59588bb 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -933,14 +933,15 @@ package Einfo is -- Direct_Primitive_Operations -- Defined in tagged types and subtypes (including synchronized types), --- in tagged private types and in tagged incomplete types. Element list --- of entities for primitive operations of the tagged type. Not defined --- in untagged types. In order to follow the C++ ABI, entities of --- primitives that come from source must be stored in this list in the --- order of their occurrence in the sources. For incomplete types the --- list is always empty. --- When expansion is disabled the corresponding record type of a --- synchronized type is not constructed. In that case, such types +-- in tagged private types, and in tagged incomplete types. However, when +-- Extensions_Allowed is True (-gnatX), also defined for untagged types +-- (for support of the extension feature of prefixed calls for untagged +-- types). This field is an element list of entities for primitive +-- operations of the type. For incomplete types the list is always empty. +-- In order to follow the C++ ABI, entities of primitives that come from +-- source must be stored in this list in the order of their occurrence in +-- the sources. When expansion is disabled, the corresponding record type +-- of a synchronized type is not constructed. In that case, such types -- carry this attribute directly. -- Directly_Designated_Type diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb index f5040b2..9538a74 100644 --- a/gcc/ada/gen_il-gen-gen_entities.adb +++ b/gcc/ada/gen_il-gen-gen_entities.adb @@ -461,6 +461,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Contract, Node_Id), Sm (Current_Use_Clause, Node_Id), Sm (Derived_Type_Link, Node_Id), + Sm (Direct_Primitive_Operations, Elist_Id), Sm (Predicates_Ignored, Flag), Sm (Esize, Uint), Sm (Finalize_Storage_Only, Flag, Base_Type_Only), @@ -560,11 +561,9 @@ begin -- Gen_IL.Gen.Gen_Entities Ab (Signed_Integer_Kind, Integer_Kind, (Sm (First_Entity, Node_Id))); - Cc (E_Signed_Integer_Type, Signed_Integer_Kind, + Cc (E_Signed_Integer_Type, Signed_Integer_Kind); -- Signed integer type, used for the anonymous base type of the -- integer subtype created by an integer type declaration. - (Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"))); Cc (E_Signed_Integer_Subtype, Signed_Integer_Kind); -- Signed integer subtype, created by either an integer subtype or @@ -648,14 +647,12 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (No_Strict_Aliasing, Flag, Base_Type_Only), Sm (Storage_Size_Variable, Node_Id, Impl_Base_Type_Only))); - Cc (E_Access_Type, Access_Kind, + Cc (E_Access_Type, Access_Kind); -- An access type created by an access type declaration with no all -- keyword present. Note that the predefined type Any_Access, which -- has E_Access_Type Ekind, is used to label NULL in the upwards pass -- of type analysis, to be replaced by the true access type in the -- downwards resolution pass. - (Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"))); Cc (E_Access_Subtype, Access_Kind); -- An access subtype created by a subtype declaration for any access @@ -739,8 +736,6 @@ begin -- Gen_IL.Gen.Gen_Entities -- An array subtype, created by an explicit array subtype declaration, -- or the use of an anonymous array subtype. (Sm (Predicated_Parent, Node_Id), - Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"), Sm (First_Entity, Node_Id), Sm (Static_Real_Or_String_Predicate, Node_Id))); @@ -752,8 +747,6 @@ begin -- Gen_IL.Gen.Gen_Entities Ab (Class_Wide_Kind, Aggregate_Kind, (Sm (C_Pass_By_Copy, Flag, Impl_Base_Type_Only), - Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"), Sm (Equivalent_Type, Node_Id), Sm (First_Entity, Node_Id), Sm (Has_Complex_Representation, Flag, Impl_Base_Type_Only), @@ -785,8 +778,6 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (C_Pass_By_Copy, Flag, Impl_Base_Type_Only), Sm (Corresponding_Concurrent_Type, Node_Id), Sm (Corresponding_Remote_Type, Node_Id), - Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"), Sm (Dispatch_Table_Wrappers, Elist_Id, Impl_Base_Type_Only), Sm (First_Entity, Node_Id), Sm (Has_Complex_Representation, Flag, Impl_Base_Type_Only), @@ -807,8 +798,6 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Cloned_Subtype, Node_Id), Sm (Corresponding_Remote_Type, Node_Id), Sm (Predicated_Parent, Node_Id), - Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"), Sm (Dispatch_Table_Wrappers, Elist_Id, Impl_Base_Type_Only), Sm (First_Entity, Node_Id), Sm (Has_Complex_Representation, Flag, Impl_Base_Type_Only), @@ -841,8 +830,6 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (C_Pass_By_Copy, Flag, Impl_Base_Type_Only), Sm (Component_Alignment, Component_Alignment_Kind, Base_Type_Only), Sm (Corresponding_Remote_Type, Node_Id), - Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"), Sm (Has_Complex_Representation, Flag, Impl_Base_Type_Only), Sm (Has_Pragma_Pack, Flag, Impl_Base_Type_Only), Sm (Has_Record_Rep_Clause, Flag, Impl_Base_Type_Only), @@ -861,8 +848,6 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Component_Alignment, Component_Alignment_Kind, Base_Type_Only), Sm (Corresponding_Remote_Type, Node_Id), Sm (Predicated_Parent, Node_Id), - Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"), Sm (Has_Complex_Representation, Flag, Impl_Base_Type_Only), Sm (Has_Pragma_Pack, Flag, Impl_Base_Type_Only), Sm (Has_Record_Rep_Clause, Flag, Impl_Base_Type_Only), @@ -877,17 +862,13 @@ begin -- Gen_IL.Gen.Gen_Entities Cc (E_Private_Type, Private_Kind, -- A private type, created by a private type declaration that has -- neither the keyword limited nor the keyword tagged. - (Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"), - Sm (Scalar_Range, Node_Id), + (Sm (Scalar_Range, Node_Id), Sm (Scope_Depth_Value, Uint))); Cc (E_Private_Subtype, Private_Kind, -- A subtype of a private type, created by a subtype declaration used -- to declare a subtype of a private type. - (Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"), - Sm (Scope_Depth_Value, Uint))); + (Sm (Scope_Depth_Value, Uint))); Cc (E_Limited_Private_Type, Private_Kind, -- A limited private type, created by a private type declaration that @@ -901,9 +882,7 @@ begin -- Gen_IL.Gen.Gen_Entities (Sm (Scope_Depth_Value, Uint))); Ab (Incomplete_Kind, Incomplete_Or_Private_Kind, - (Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"), - Sm (Non_Limited_View, Node_Id))); + (Sm (Non_Limited_View, Node_Id))); Cc (E_Incomplete_Type, Incomplete_Kind, -- An incomplete type, created by an incomplete type declaration @@ -915,8 +894,6 @@ begin -- Gen_IL.Gen.Gen_Entities Ab (Concurrent_Kind, Composite_Kind, (Sm (Corresponding_Record_Type, Node_Id), - Sm (Direct_Primitive_Operations, Elist_Id, - Pre => "Is_Tagged_Type (N)"), Sm (First_Entity, Node_Id), Sm (First_Private_Entity, Node_Id), Sm (Last_Entity, Node_Id), diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 771e6aa..19d6f33 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -3793,6 +3793,24 @@ Use of this feature increases safety by simplifying code, and can also improve the efficiency of indexing operations, since the compiler statically knows the lower bound of unconstrained array formals when the formal’s subtype has index ranges with static fixed lower bounds. + +@item +Prefixed-view notation for calls to primitive subprograms of untagged types + +Since Ada 2005, calls to primitive subprograms of a tagged type that +have a “prefixed view” (see RM 4.1.3(9.2)) have been allowed to be +written using the form of a selected_component, with the first actual +parameter given as the prefix and the name of the subprogram as a +selector. This prefixed-view notation for calls is extended so as to +also allow such syntax for calls to primitive subprograms of untagged +types. The primitives of an untagged type T that have a prefixed view +are those where the first formal parameter of the subprogram either +is of type T or is an anonymous access parameter whose designated type +is T. For a type that has a component that happens to have the same +simple name as one of the type’s primitive subprograms, where the +component is visible at the point of a selected_component using that +name, preference is given to the component in a selected_component +(as is currently the case for tagged types with such component names). @end itemize @node Pragma Extensions_Visible,Pragma External,Pragma Extensions_Allowed,Implementation Defined Pragmas diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 95a27a2..936852c 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -3261,6 +3261,40 @@ package body Sem_Ch3 is return; end if; + -- Set the primitives list of the full type and its base type when + -- needed. T may be E_Void in cases of earlier errors, and in that + -- case we bypass this. + + if Ekind (T) /= E_Void + and then not Present (Direct_Primitive_Operations (T)) + then + if Etype (T) = T then + Set_Direct_Primitive_Operations (T, New_Elmt_List); + + -- If Etype of T is the base type (as opposed to a parent type) and + -- already has an associated list of primitive operations, then set + -- T's primitive list to the base type's list. Otherwise, create a + -- new empty primitives list and share the list between T and its + -- base type. The lists need to be shared in common between the two. + + elsif Etype (T) = Base_Type (T) then + + if not Present (Direct_Primitive_Operations (Base_Type (T))) then + Set_Direct_Primitive_Operations + (Base_Type (T), New_Elmt_List); + end if; + + Set_Direct_Primitive_Operations + (T, Direct_Primitive_Operations (Base_Type (T))); + + -- Case where the Etype is a parent type, so we need a new primitives + -- list for T. + + else + Set_Direct_Primitive_Operations (T, New_Elmt_List); + end if; + end if; + -- Some common processing for all types Set_Depends_On_Private (T, Has_Private_Component (T)); @@ -5706,6 +5740,14 @@ package body Sem_Ch3 is Inherit_Predicate_Flags (Id, T); end if; + -- When prefixed calls are enabled for untagged types, the subtype + -- shares the primitive operations of its base type. + + if Extensions_Allowed then + Set_Direct_Primitive_Operations + (Id, Direct_Primitive_Operations (Base_Type (T))); + end if; + if Etype (Id) = Any_Type then goto Leave; end if; @@ -9507,6 +9549,13 @@ package body Sem_Ch3 is end; end if; + -- When prefixed-call syntax is allowed for untagged types, initialize + -- the list of primitive operations to an empty list. + + if Extensions_Allowed and then not Is_Tagged then + Set_Direct_Primitive_Operations (Derived_Type, New_Elmt_List); + end if; + -- Set fields for tagged types if Is_Tagged then @@ -9985,6 +10034,28 @@ package body Sem_Ch3 is return; end if; + -- If not already set, initialize the derived type's list of primitive + -- operations to an empty element list. + + if not Present (Direct_Primitive_Operations (Derived_Type)) then + Set_Direct_Primitive_Operations (Derived_Type, New_Elmt_List); + + -- If Etype of the derived type is the base type (as opposed to + -- a parent type) and doesn't have an associated list of primitive + -- operations, then set the base type's primitive list to the + -- derived type's list. The lists need to be shared in common + -- between the two. + + if Etype (Derived_Type) = Base_Type (Derived_Type) + and then + not Present (Direct_Primitive_Operations (Etype (Derived_Type))) + then + Set_Direct_Primitive_Operations + (Etype (Derived_Type), + Direct_Primitive_Operations (Derived_Type)); + end if; + end if; + -- Set delayed freeze and then derive subprograms, we need to do this -- in this order so that derived subprograms inherit the derived freeze -- if necessary. @@ -21011,48 +21082,48 @@ package body Sem_Ch3 is end loop; end; - -- If the private view was tagged, copy the new primitive operations - -- from the private view to the full view. + declare + Disp_Typ : Entity_Id; + Full_List : Elist_Id; + Prim : Entity_Id; + Prim_Elmt : Elmt_Id; + Priv_List : Elist_Id; + + function Contains + (E : Entity_Id; + L : Elist_Id) return Boolean; + -- Determine whether list L contains element E + + -------------- + -- Contains -- + -------------- + + function Contains + (E : Entity_Id; + L : Elist_Id) return Boolean + is + List_Elmt : Elmt_Id; - if Is_Tagged_Type (Full_T) then - declare - Disp_Typ : Entity_Id; - Full_List : Elist_Id; - Prim : Entity_Id; - Prim_Elmt : Elmt_Id; - Priv_List : Elist_Id; - - function Contains - (E : Entity_Id; - L : Elist_Id) return Boolean; - -- Determine whether list L contains element E - - -------------- - -- Contains -- - -------------- - - function Contains - (E : Entity_Id; - L : Elist_Id) return Boolean - is - List_Elmt : Elmt_Id; + begin + List_Elmt := First_Elmt (L); + while Present (List_Elmt) loop + if Node (List_Elmt) = E then + return True; + end if; - begin - List_Elmt := First_Elmt (L); - while Present (List_Elmt) loop - if Node (List_Elmt) = E then - return True; - end if; + Next_Elmt (List_Elmt); + end loop; - Next_Elmt (List_Elmt); - end loop; + return False; + end Contains; - return False; - end Contains; + -- Start of processing - -- Start of processing + begin + -- If the private view was tagged, copy the new primitive operations + -- from the private view to the full view. - begin + if Is_Tagged_Type (Full_T) then if Is_Tagged_Type (Priv_T) then Priv_List := Primitive_Operations (Priv_T); Prim_Elmt := First_Elmt (Priv_List); @@ -21186,8 +21257,23 @@ package body Sem_Ch3 is Propagate_Concurrent_Flags (Class_Wide_Type (Priv_T), Full_T); end if; - end; - end if; + + -- For untagged types, copy the primitives across from the private + -- view to the full view (when extensions are allowed), for support + -- of prefixed calls (when extensions are enabled). + + elsif Extensions_Allowed then + Priv_List := Primitive_Operations (Priv_T); + Prim_Elmt := First_Elmt (Priv_List); + + Full_List := Primitive_Operations (Full_T); + while Present (Prim_Elmt) loop + Prim := Node (Prim_Elmt); + Append_Elmt (Prim, Full_List); + Next_Elmt (Prim_Elmt); + end loop; + end if; + end; -- Ada 2005 AI 161: Check preelaborable initialization consistency diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index d849834..eb1a556 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -5002,8 +5002,11 @@ package body Sem_Ch4 is -- Ada 2005 (AI05-0030): In the case of dispatching requeue, the -- selected component should resolve to a name. + -- Extension feature: Also support calls with prefixed views for + -- untagged record types. + if Ada_Version >= Ada_2005 - and then Is_Tagged_Type (Prefix_Type) + and then (Is_Tagged_Type (Prefix_Type) or else Extensions_Allowed) and then not Is_Concurrent_Type (Prefix_Type) then if Nkind (Parent (N)) = N_Generic_Association @@ -5076,6 +5079,15 @@ package body Sem_Ch4 is Next_Entity (Comp); end loop; + -- Extension feature: Also support calls with prefixed views for + -- untagged private types. + + if Extensions_Allowed then + if Try_Object_Operation (N) then + return; + end if; + end if; + elsif Is_Concurrent_Type (Prefix_Type) then -- Find visible operation with given name. For a protected type, @@ -5328,6 +5340,14 @@ package body Sem_Ch4 is Set_Is_Overloaded (N, Is_Overloaded (Sel)); + -- Extension feature: Also support calls with prefixed views for + -- untagged types. + + elsif Extensions_Allowed + and then Try_Object_Operation (N) + then + return; + else -- Invalid prefix @@ -9536,7 +9556,11 @@ package body Sem_Ch4 is -- type, this is not a prefixed call. Restore the previous type as -- the current one is not a legal candidate. - if not Is_Tagged_Type (Obj_Type) + -- Extension feature: Calls with prefixed views are also supported + -- for untagged types, so skip the early return when extensions are + -- enabled. + + if (not Is_Tagged_Type (Obj_Type) and then not Extensions_Allowed) or else Is_Incomplete_Type (Obj_Type) then Obj_Type := Prev_Obj_Type; @@ -9554,6 +9578,36 @@ package body Sem_Ch4 is Try_Primitive_Operation (Call_Node => New_Call_Node, Node_To_Replace => Node_To_Replace); + + -- Extension feature: In the case where the prefix is of an + -- access type, and a primitive wasn't found for the designated + -- type, then if the access type has primitives we attempt a + -- prefixed call using one of its primitives. (It seems that + -- this isn't quite right to give preference to the designated + -- type in the case where both the access and designated types + -- have homographic prefixed-view operations that could result + -- in an ambiguity, but handling properly may be tricky. ???) + + if Extensions_Allowed + and then not Prim_Result + and then Is_Named_Access_Type (Prev_Obj_Type) + and then Present (Direct_Primitive_Operations (Prev_Obj_Type)) + then + -- Temporarily reset Obj_Type to the original access type + + Obj_Type := Prev_Obj_Type; + + Prim_Result := + Try_Primitive_Operation + (Call_Node => New_Call_Node, + Node_To_Replace => Node_To_Replace); + + -- Restore Obj_Type to the designated type (is this really + -- necessary, or should it only be done when Prim_Result is + -- still False?). + + Obj_Type := Designated_Type (Obj_Type); + end if; end if; -- Check if there is a class-wide subprogram covering the @@ -9893,7 +9947,7 @@ package body Sem_Ch4 is -- be the corresponding record of a synchronized type. return Obj_Type = Typ - or else Base_Type (Obj_Type) = Typ + or else Base_Type (Obj_Type) = Base_Type (Typ) or else Corr_Type = Typ -- Object may be of a derived type whose parent has unknown diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index c7d4b96..abe8060 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -11022,6 +11022,12 @@ package body Sem_Ch6 is F_Typ : Entity_Id; B_Typ : Entity_Id; + procedure Add_Or_Replace_Untagged_Primitive (Typ : Entity_Id); + -- Either add the new subprogram to the list of primitives for + -- untagged type Typ, or if it overrides a primitive of Typ, then + -- replace the overridden primitive in Typ's primitives list with + -- the new subprogram. + function Visible_Part_Type (T : Entity_Id) return Boolean; -- Returns true if T is declared in the visible part of the current -- package scope; otherwise returns false. Assumes that T is declared @@ -11035,6 +11041,63 @@ package body Sem_Ch6 is -- in a private part, then it must override a function declared in -- the visible part. + --------------------------------------- + -- Add_Or_Replace_Untagged_Primitive -- + --------------------------------------- + + procedure Add_Or_Replace_Untagged_Primitive (Typ : Entity_Id) is + Replaced_Overridden_Subp : Boolean := False; + + begin + pragma Assert (not Is_Tagged_Type (Typ)); + + -- Anonymous access types don't have a primitives list. Normally + -- such types wouldn't make it here, but the case of anonymous + -- access-to-subprogram types can. + + if not Is_Anonymous_Access_Type (Typ) then + + -- If S overrides a subprogram that's a primitive of + -- the formal's type, then replace the overridden + -- subprogram with the new subprogram in the type's + -- list of primitives. + + if Is_Overriding then + pragma Assert (Present (Overridden_Subp) + and then Overridden_Subp = E); -- Added for now + + declare + Prim_Ops : constant Elist_Id := + Primitive_Operations (Typ); + Elmt : Elmt_Id; + begin + if Present (Prim_Ops) then + Elmt := First_Elmt (Prim_Ops); + + while Present (Elmt) + and then Node (Elmt) /= Overridden_Subp + loop + Next_Elmt (Elmt); + end loop; + + if Present (Elmt) then + Replace_Elmt (Elmt, S); + Replaced_Overridden_Subp := True; + end if; + end if; + end; + end if; + + -- If the new subprogram did not override an operation + -- of the formal's type, then add it to the primitives + -- list of the type. + + if not Replaced_Overridden_Subp then + Append_Unique_Elmt (S, Primitive_Operations (Typ)); + end if; + end if; + end Add_Or_Replace_Untagged_Primitive; + ------------------------------ -- Check_Private_Overriding -- ------------------------------ @@ -11213,7 +11276,17 @@ package body Sem_Ch6 is Is_Primitive := False; if not Comes_From_Source (S) then - null; + + -- Add an inherited primitive for an untagged derived type to + -- Derived_Type's list of primitives. Tagged primitives are dealt + -- with in Check_Dispatching_Operation. + + if Present (Derived_Type) + and then Extensions_Allowed + and then not Is_Tagged_Type (Derived_Type) + then + Append_Unique_Elmt (S, Primitive_Operations (Derived_Type)); + end if; -- If subprogram is at library level, it is not primitive operation @@ -11242,8 +11315,18 @@ package body Sem_Ch6 is Is_Primitive := True; Set_Has_Primitive_Operations (B_Typ); Set_Is_Primitive (S); - Check_Private_Overriding (B_Typ); + -- Add a primitive for an untagged type to B_Typ's list + -- of primitives. Tagged primitives are dealt with in + -- Check_Dispatching_Operation. + + if Extensions_Allowed + and then not Is_Tagged_Type (B_Typ) + then + Add_Or_Replace_Untagged_Primitive (B_Typ); + end if; + + Check_Private_Overriding (B_Typ); -- The Ghost policy in effect at the point of declaration -- or a tagged type and a primitive operation must match -- (SPARK RM 6.9(16)). @@ -11275,6 +11358,17 @@ package body Sem_Ch6 is Is_Primitive := True; Set_Is_Primitive (S); Set_Has_Primitive_Operations (B_Typ); + + -- Add a primitive for an untagged type to B_Typ's list + -- of primitives. Tagged primitives are dealt with in + -- Check_Dispatching_Operation. + + if Extensions_Allowed + and then not Is_Tagged_Type (B_Typ) + then + Add_Or_Replace_Untagged_Primitive (B_Typ); + end if; + Check_Private_Overriding (B_Typ); -- The Ghost policy in effect at the point of declaration diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb index 69ad184..f30a9aa 100644 --- a/gcc/ada/sem_ch7.adb +++ b/gcc/ada/sem_ch7.adb @@ -2612,6 +2612,15 @@ package body Sem_Ch7 is elsif Abstract_Present (Def) then Error_Msg_N ("only a tagged type can be abstract", N); + + -- When extensions are enabled, we initialize the primitive operations + -- list of an untagged private type to an empty element list. (Note: + -- This could be done for all private types and shared with the tagged + -- case above, but for now we do it separately when the feature of + -- prefixed calls for untagged types is enabled.) + + elsif Extensions_Allowed then + Set_Direct_Primitive_Operations (Id, New_Elmt_List); end if; end New_Private_Type; diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index aa33c50..d3bbfeb 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -7588,10 +7588,16 @@ package body Sem_Ch8 is P_Type := Implicitly_Designated_Type (P_Type); end if; - -- First check for components of a record object (not the - -- result of a call, which is handled below). - - if Has_Components (P_Type) + -- First check for components of a record object (not the result of + -- a call, which is handled below). This also covers the case where + -- where the extension feature that supports the prefixed form of + -- calls for primitives of untagged types is enabled (excluding + -- concurrent cases, which are handled further below). + + if Is_Type (P_Type) + and then (Has_Components (P_Type) + or else (Extensions_Allowed + and then not Is_Concurrent_Type (P_Type))) and then not Is_Overloadable (P_Name) and then not Is_Type (P_Name) then -- cgit v1.1 From e9559decc68753387914528e72b46db5be13226b Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Mon, 3 May 2021 21:05:59 -0400 Subject: [Ada] Add Void_Or_Type_Kind and Exception_Or_Object_Kind gcc/ada/ * gen_il-types.ads (Void_Or_Type_Kind, Exception_Or_Object_Kind): Declare. * gen_il-gen-gen_entities.adb: Likewise. --- gcc/ada/gen_il-gen-gen_entities.adb | 12 ++++++++---- gcc/ada/gen_il-types.ads | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb index 9538a74..1c6a518 100644 --- a/gcc/ada/gen_il-gen-gen_entities.adb +++ b/gcc/ada/gen_il-gen-gen_entities.adb @@ -238,7 +238,9 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Warnings_Off_Used_Unreferenced, Flag), Sm (Was_Hidden, Flag))); - Cc (E_Void, Entity_Kind, + Ab (Void_Or_Type_Kind, Entity_Kind); + + Cc (E_Void, Void_Or_Type_Kind, -- The initial Ekind value for a newly created entity. Also used as the -- Ekind for Standard_Void_Type, a type entity in Standard used as a -- dummy type for the return type of a procedure (the reason we create @@ -300,7 +302,9 @@ begin -- Gen_IL.Gen.Gen_Entities -- but not getters; the Ekind is modified before any such getters are -- called. - Ab (Object_Kind, Entity_Kind, + Ab (Exception_Or_Object_Kind, Entity_Kind); + + Ab (Object_Kind, Exception_Or_Object_Kind, (Sm (Current_Value, Node_Id), Sm (Renamed_Or_Alias, Node_Id))); @@ -452,7 +456,7 @@ begin -- Gen_IL.Gen.Gen_Entities Cc (E_Named_Real, Named_Kind); -- Named numbers created by a number declaration with a real value - Ab (Type_Kind, Entity_Kind, + Ab (Type_Kind, Void_Or_Type_Kind, (Sm (Alignment, Uint), Sm (Associated_Node_For_Itype, Node_Id), Sm (Can_Use_Internal_Rep, Flag, Base_Type_Only, @@ -1177,7 +1181,7 @@ begin -- Gen_IL.Gen.Gen_Entities -- for the body of a protected entry family. (Sm (Entry_Index_Constant, Node_Id))); - Cc (E_Exception, Entity_Kind, + Cc (E_Exception, Exception_Or_Object_Kind, -- An exception created by an exception declaration. The exception -- itself uses E_Exception for the Ekind, the implicit type that is -- created to represent its type uses the Ekind E_Exception_Type. diff --git a/gcc/ada/gen_il-types.ads b/gcc/ada/gen_il-types.ads index 6850411..84eb63f 100644 --- a/gcc/ada/gen_il-types.ads +++ b/gcc/ada/gen_il-types.ads @@ -140,6 +140,7 @@ package Gen_IL.Types is Elementary_Kind, Enumeration_Kind, Entry_Kind, + Exception_Or_Object_Kind, Fixed_Point_Kind, Float_Kind, Formal_Kind, @@ -166,6 +167,7 @@ package Gen_IL.Types is Signed_Integer_Kind, Task_Kind, Type_Kind, + Void_Or_Type_Kind, -- End of abstract entity types. -- cgit v1.1 From 885efc5e70f46c8fe38855815bb37fecc5783046 Mon Sep 17 00:00:00 2001 From: Doug Rupp Date: Mon, 3 May 2021 15:22:26 -0700 Subject: [Ada] Unix Epochalypse (s-osprim.adb) gcc/ada/ * Makefile.rtl (LIBGNAT_TARGET_PAIRS): Use s-osprim__posix.adb vice s-osprim__vxworks.adb for all vxworks7r2 targets. --- gcc/ada/Makefile.rtl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index d712ab5..e421c7c 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -1088,7 +1088,7 @@ ifeq ($(strip $(filter-out powerpc% wrs vxworks vxworksspe vxworks7% vxworks7spe s-intman.adb Date: Tue, 4 May 2021 10:13:36 -0400 Subject: [Ada] Add assertions on tampering counts gcc/ada/ * libgnat/a-conhel.adb: Assert that tampering counts remain between 0 and 2**31-1. This makes debugging of finalization-related bugs easier. --- gcc/ada/libgnat/a-conhel.adb | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/libgnat/a-conhel.adb b/gcc/ada/libgnat/a-conhel.adb index e7d82ac..316c866 100644 --- a/gcc/ada/libgnat/a-conhel.adb +++ b/gcc/ada/libgnat/a-conhel.adb @@ -27,6 +27,13 @@ package body Ada.Containers.Helpers is + Max_Count : constant := 2**31 - 1; + -- Used in assertions below, to make sure the counts don't wrap around. + -- This can help detect bugs in which Adjust and Finalize calls are + -- improperly generated. An extra Decrement could otherwise cause + -- wraparound from 0 to 2**32-1. The highest count seen so far is + -- around 25, so this should be plenty. + package body Generic_Implementation is use type SAC.Atomic_Unsigned; @@ -50,6 +57,7 @@ package body Ada.Containers.Helpers is begin if T_Check then SAC.Increment (T_Counts.Busy); + pragma Assert (T_Counts.Busy <= Max_Count); end if; end Busy; @@ -112,7 +120,9 @@ package body Ada.Containers.Helpers is begin if T_Check then SAC.Increment (T_Counts.Lock); + pragma Assert (T_Counts.Lock <= Max_Count); SAC.Increment (T_Counts.Busy); + pragma Assert (T_Counts.Busy <= Max_Count); end if; end Lock; @@ -158,6 +168,7 @@ package body Ada.Containers.Helpers is begin if T_Check then SAC.Decrement (T_Counts.Busy); + pragma Assert (T_Counts.Busy <= Max_Count); end if; end Unbusy; @@ -169,7 +180,9 @@ package body Ada.Containers.Helpers is begin if T_Check then SAC.Decrement (T_Counts.Lock); + pragma Assert (T_Counts.Lock <= Max_Count); SAC.Decrement (T_Counts.Busy); + pragma Assert (T_Counts.Busy <= Max_Count); end if; end Unlock; -- cgit v1.1 From f55784f8adc6033639840c609329d7b1facb2e71 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Wed, 5 May 2021 08:50:23 -0400 Subject: [Ada] Improper predicate check on view conversion gcc/ada/ * exp_ch4.adb (Expand_N_Type_Conversion): If the conversion is the name of an assignment operation do not apply predicate check to it prior to the assignment. --- gcc/ada/exp_ch4.adb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index d608a30..21b2c22 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -12748,7 +12748,16 @@ package body Exp_Ch4 is -- guard is necessary to prevent infinite recursions when we generate -- internal conversions for the purpose of checking predicates. - if Predicate_Enabled (Target_Type) + -- A view conversion of a tagged object is an object and can appear + -- in an assignment context, in which case no predicate check applies + -- to the now-dead value. + + if Nkind (Parent (N)) = N_Assignment_Statement + and then N = Name (Parent (N)) + then + null; + + elsif Predicate_Enabled (Target_Type) and then Target_Type /= Operand_Type and then Comes_From_Source (N) then -- cgit v1.1 From f5063691c19a20cd3abb1c3f686ca44bea04d889 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Wed, 5 May 2021 18:29:28 -0400 Subject: [Ada] Make parent of N_Exception_Declaration be N_Declaration gcc/ada/ * gen_il-gen-gen_nodes.adb: Change the parent of N_Exception_Declaration to be N_Declaration. Minor comment fix. --- gcc/ada/gen_il-gen-gen_nodes.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb index 26fc069..e6defb1 100644 --- a/gcc/ada/gen_il-gen-gen_nodes.adb +++ b/gcc/ada/gen_il-gen-gen_nodes.adb @@ -573,7 +573,7 @@ begin -- Gen_IL.Gen.Gen_Nodes Ab (N_Declaration, Node_Kind); -- Note: this includes all constructs normally thought of as declarations - -- except those which are separately grouped as later declarations. + -- except those that are separately grouped in N_Later_Decl_Item. Cc (N_Component_Declaration, N_Declaration, (Sy (Defining_Identifier, Node_Id), @@ -1342,7 +1342,7 @@ begin -- Gen_IL.Gen.Gen_Nodes (Sy (Defining_Identifier, Node_Id), Sy (Discrete_Subtype_Definition, Node_Id, Default_Empty))); - Cc (N_Exception_Declaration, Node_Kind, + Cc (N_Exception_Declaration, N_Declaration, (Sy (Defining_Identifier, Node_Id), Sm (Expression, Node_Id), Sm (More_Ids, Flag), -- cgit v1.1 From f037632e655c8348b06ffa797c9b1041a5a823ec Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Fri, 7 May 2021 10:41:03 -0400 Subject: [Ada] Transient scope cleanup gcc/ada/ * sem.ads (Node_To_Be_Wrapped): Minor comment fix. * exp_ch7.adb (Establish_Transient_Scope): Misc cleanups and comment improvements. (Set_Node_To_Be_Wrapped): Remove -- not worth putting this code in a separate procedure, called only once. * sem_util.adb (Requires_Transient_Scope): Assert that our parameter has the right Kind. It probably shouldn't be E_Void, but that is passed in in some cases. (Ensure_Minimum_Decoration): Move the call later, so we know Typ is Present, and remove "if Present (Typ)" from this procedure. * exp_aggr.adb (Convert_To_Assignments): Use membership test, and avoid the "if False" idiom. (Expand_Array_Aggregate): Remove a ??? comment. * sem_ch8.adb (Push_Scope): Take advantage of the full coverage rules for aggregates. * sem_res.adb (Resolve_Declare_Expression): Remove test for Is_Type -- that's all it can be. Use named notation in call to Establish_Transient_Scope. * libgnat/a-cdlili.adb (Adjust): Remove redundant code. (Clear): Remove "pragma Warnings (Off);", which wasn't actually suppressing any warnings. --- gcc/ada/exp_aggr.adb | 12 +- gcc/ada/exp_ch7.adb | 474 +++++++++++++++++++++---------------------- gcc/ada/libgnat/a-cdlili.adb | 7 - gcc/ada/sem.ads | 2 +- gcc/ada/sem_ch8.adb | 86 ++++---- gcc/ada/sem_res.adb | 3 +- gcc/ada/sem_util.adb | 12 +- 7 files changed, 287 insertions(+), 309 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 7978b1c..1b08436 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -4919,13 +4919,11 @@ package body Exp_Aggr is -- Just set the Delay flag in the cases where the transformation will be -- done top down from above. - if False - + if -- Internal aggregate (transformed when expanding the parent) - or else Parent_Kind = N_Aggregate - or else Parent_Kind = N_Extension_Aggregate - or else Parent_Kind = N_Component_Association + Parent_Kind in + N_Aggregate | N_Extension_Aggregate | N_Component_Association -- Allocator (see Convert_Aggr_In_Allocator) @@ -6601,8 +6599,8 @@ package body Exp_Aggr is -- For assignments we do the assignment in place if all the component -- associations have compile-time known values, or are default- -- initialized limited components, e.g. tasks. For other cases we - -- create a temporary. The analysis for safety of on-line assignment - -- is delicate, i.e. we don't know how to do it fully yet ??? + -- create a temporary. A full analysis for safety of in-place assignment + -- is delicate. -- For allocators we assign to the designated object in place if the -- aggregate meets the same conditions as other in-place assignments. diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 469c9fb..4c1e16d 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -131,11 +131,6 @@ package body Exp_Ch7 is -- Transient Blocks and Finalization Management -- -------------------------------------------------- - function Find_Transient_Context (N : Node_Id) return Node_Id; - -- Locate a suitable context for arbitrary node N which may need to be - -- serviced by a transient scope. Return Empty if no suitable context is - -- available. - procedure Insert_Actions_In_Scope_Around (N : Node_Id; Clean : Boolean; @@ -155,9 +150,6 @@ package body Exp_Ch7 is -- involves controlled objects or secondary stack usage, the corresponding -- cleanup actions are performed at the end of the block. - procedure Set_Node_To_Be_Wrapped (N : Node_Id); - -- Set the field Node_To_Be_Wrapped of the current scope - procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id); -- Shared processing for Store_xxx_Actions_In_Scope @@ -5151,37 +5143,47 @@ package body Exp_Ch7 is (N : Node_Id; Manage_Sec_Stack : Boolean) is - procedure Create_Transient_Scope (Constr : Node_Id); - -- Place a new scope on the scope stack in order to service construct - -- Constr. The new scope may also manage the secondary stack. + function Is_Package_Or_Subprogram (Id : Entity_Id) return Boolean; + -- Determine whether arbitrary Id denotes a package or subprogram [body] + + function Find_Enclosing_Transient_Scope return Entity_Id; + -- Examine the scope stack looking for the nearest enclosing transient + -- scope within the innermost enclosing package or subprogram. Return + -- Empty if no such scope exists. + + function Find_Transient_Context (N : Node_Id) return Node_Id; + -- Locate a suitable context for arbitrary node N which may need to be + -- serviced by a transient scope. Return Empty if no suitable context + -- is available. procedure Delegate_Sec_Stack_Management; -- Move the management of the secondary stack to the nearest enclosing -- suitable scope. - function Find_Enclosing_Transient_Scope return Entity_Id; - -- Examine the scope stack looking for the nearest enclosing transient - -- scope. Return Empty if no such scope exists. - - function Is_Package_Or_Subprogram (Id : Entity_Id) return Boolean; - -- Determine whether arbitrary Id denotes a package or subprogram [body] + procedure Create_Transient_Scope (Context : Node_Id); + -- Place a new scope on the scope stack in order to service construct + -- Context. Context is the node found by Find_Transient_Context. The + -- new scope may also manage the secondary stack. ---------------------------- -- Create_Transient_Scope -- ---------------------------- - procedure Create_Transient_Scope (Constr : Node_Id) is + procedure Create_Transient_Scope (Context : Node_Id) is Loc : constant Source_Ptr := Sloc (N); Iter_Loop : Entity_Id; - Trans_Scop : Entity_Id; + Trans_Scop : constant Entity_Id := + New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'); begin - Trans_Scop := New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'); Set_Etype (Trans_Scop, Standard_Void_Type); + -- Push a new scope, and set its Node_To_Be_Wrapped and Is_Transient + -- fields. + Push_Scope (Trans_Scop); - Set_Node_To_Be_Wrapped (Constr); + Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := Context; Set_Scope_Is_Transient; -- The transient scope must also manage the secondary stack @@ -5232,37 +5234,34 @@ package body Exp_Ch7 is ----------------------------------- procedure Delegate_Sec_Stack_Management is - Scop_Id : Entity_Id; - Scop_Rec : Scope_Stack_Entry; - begin for Index in reverse Scope_Stack.First .. Scope_Stack.Last loop - Scop_Rec := Scope_Stack.Table (Index); - Scop_Id := Scop_Rec.Entity; - - -- Prevent the search from going too far or within the scope space - -- of another unit. + declare + Scope : Scope_Stack_Entry renames Scope_Stack.Table (Index); + begin + -- Prevent the search from going too far or within the scope + -- space of another unit. - if Scop_Id = Standard_Standard then - return; + if Scope.Entity = Standard_Standard then + return; - -- No transient scope should be encountered during the traversal - -- because Establish_Transient_Scope should have already handled - -- this case. + -- No transient scope should be encountered during the + -- traversal because Establish_Transient_Scope should have + -- already handled this case. - elsif Scop_Rec.Is_Transient then - pragma Assert (False); - return; + elsif Scope.Is_Transient then + raise Program_Error; - -- The construct which requires secondary stack management is - -- always enclosed by a package or subprogram scope. + -- The construct that requires secondary stack management is + -- always enclosed by a package or subprogram scope. - elsif Is_Package_Or_Subprogram (Scop_Id) then - Set_Uses_Sec_Stack (Scop_Id); - Check_Restriction (No_Secondary_Stack, N); + elsif Is_Package_Or_Subprogram (Scope.Entity) then + Set_Uses_Sec_Stack (Scope.Entity); + Check_Restriction (No_Secondary_Stack, N); - return; - end if; + return; + end if; + end; end loop; -- At this point no suitable scope was found. This should never occur @@ -5277,30 +5276,198 @@ package body Exp_Ch7 is ------------------------------------ function Find_Enclosing_Transient_Scope return Entity_Id is - Scop_Id : Entity_Id; - Scop_Rec : Scope_Stack_Entry; - begin for Index in reverse Scope_Stack.First .. Scope_Stack.Last loop - Scop_Rec := Scope_Stack.Table (Index); - Scop_Id := Scop_Rec.Entity; - - -- Prevent the search from going too far or within the scope space - -- of another unit. + declare + Scope : Scope_Stack_Entry renames Scope_Stack.Table (Index); + begin + -- Prevent the search from going too far or within the scope + -- space of another unit. - if Scop_Id = Standard_Standard - or else Is_Package_Or_Subprogram (Scop_Id) - then - exit; + if Scope.Entity = Standard_Standard + or else Is_Package_Or_Subprogram (Scope.Entity) + then + exit; - elsif Scop_Rec.Is_Transient then - return Scop_Id; - end if; + elsif Scope.Is_Transient then + return Scope.Entity; + end if; + end; end loop; return Empty; end Find_Enclosing_Transient_Scope; + ---------------------------- + -- Find_Transient_Context -- + ---------------------------- + + function Find_Transient_Context (N : Node_Id) return Node_Id is + Curr : Node_Id := N; + Prev : Node_Id := Empty; + + begin + while Present (Curr) loop + case Nkind (Curr) is + + -- Declarations + + -- Declarations act as a boundary for a transient scope even if + -- they are not wrapped, see Wrap_Transient_Declaration. + + when N_Object_Declaration + | N_Object_Renaming_Declaration + | N_Subtype_Declaration + => + return Curr; + + -- Statements + + -- Statements and statement-like constructs act as a boundary + -- for a transient scope. + + when N_Accept_Alternative + | N_Attribute_Definition_Clause + | N_Case_Statement + | N_Case_Statement_Alternative + | N_Code_Statement + | N_Delay_Alternative + | N_Delay_Until_Statement + | N_Delay_Relative_Statement + | N_Discriminant_Association + | N_Elsif_Part + | N_Entry_Body_Formal_Part + | N_Exit_Statement + | N_If_Statement + | N_Iteration_Scheme + | N_Terminate_Alternative + => + pragma Assert (Present (Prev)); + return Prev; + + when N_Assignment_Statement => + return Curr; + + when N_Entry_Call_Statement + | N_Procedure_Call_Statement + => + -- When an entry or procedure call acts as the alternative + -- of a conditional or timed entry call, the proper context + -- is that of the alternative. + + if Nkind (Parent (Curr)) = N_Entry_Call_Alternative + and then Nkind (Parent (Parent (Curr))) in + N_Conditional_Entry_Call | N_Timed_Entry_Call + then + return Parent (Parent (Curr)); + + -- General case for entry or procedure calls + + else + return Curr; + end if; + + when N_Pragma => + + -- Pragma Check is not a valid transient context in + -- GNATprove mode because the pragma must remain unchanged. + + if GNATprove_Mode + and then Get_Pragma_Id (Curr) = Pragma_Check + then + return Empty; + + -- General case for pragmas + + else + return Curr; + end if; + + when N_Raise_Statement => + return Curr; + + when N_Simple_Return_Statement => + + -- A return statement is not a valid transient context when + -- the function itself requires transient scope management + -- because the result will be reclaimed too early. + + if Requires_Transient_Scope (Etype + (Return_Applies_To (Return_Statement_Entity (Curr)))) + then + return Empty; + + -- General case for return statements + + else + return Curr; + end if; + + -- Special + + when N_Attribute_Reference => + if Is_Procedure_Attribute_Name (Attribute_Name (Curr)) then + return Curr; + end if; + + -- An Ada 2012 iterator specification is not a valid context + -- because Analyze_Iterator_Specification already employs + -- special processing for it. + + when N_Iterator_Specification => + return Empty; + + when N_Loop_Parameter_Specification => + + -- An iteration scheme is not a valid context because + -- routine Analyze_Iteration_Scheme already employs + -- special processing. + + if Nkind (Parent (Curr)) = N_Iteration_Scheme then + return Empty; + else + return Parent (Curr); + end if; + + -- Termination + + -- The following nodes represent "dummy contexts" which do not + -- need to be wrapped. + + when N_Component_Declaration + | N_Discriminant_Specification + | N_Parameter_Specification + => + return Empty; + + -- If the traversal leaves a scope without having been able to + -- find a construct to wrap, something is going wrong, but this + -- can happen in error situations that are not detected yet + -- (such as a dynamic string in a pragma Export). + + when N_Block_Statement + | N_Entry_Body + | N_Package_Body + | N_Package_Declaration + | N_Protected_Body + | N_Subprogram_Body + | N_Task_Body + => + return Empty; + + -- Default + + when others => + null; + end case; + + Prev := Curr; + Curr := Parent (Curr); + end loop; + + return Empty; + end Find_Transient_Context; + ------------------------------ -- Is_Package_Or_Subprogram -- ------------------------------ @@ -5323,8 +5490,8 @@ package body Exp_Ch7 is -- Start of processing for Establish_Transient_Scope begin - -- Do not create a new transient scope if there is an existing transient - -- scope on the stack. + -- Do not create a new transient scope if there is already an enclosing + -- transient scope within the innermost enclosing package or subprogram. if Present (Trans_Id) then @@ -5338,9 +5505,8 @@ package body Exp_Ch7 is return; end if; - -- At this point it is known that the scope stack is free of transient - -- scopes. Locate the proper construct which must be serviced by a new - -- transient scope. + -- Find the construct that must be serviced by a new transient scope, if + -- it exists. Context := Find_Transient_Context (N); @@ -5950,177 +6116,6 @@ package body Exp_Ch7 is end if; end Expand_N_Package_Declaration; - ---------------------------- - -- Find_Transient_Context -- - ---------------------------- - - function Find_Transient_Context (N : Node_Id) return Node_Id is - Curr : Node_Id; - Prev : Node_Id; - - begin - Curr := N; - Prev := Empty; - while Present (Curr) loop - case Nkind (Curr) is - - -- Declarations - - -- Declarations act as a boundary for a transient scope even if - -- they are not wrapped, see Wrap_Transient_Declaration. - - when N_Object_Declaration - | N_Object_Renaming_Declaration - | N_Subtype_Declaration - => - return Curr; - - -- Statements - - -- Statements and statement-like constructs act as a boundary for - -- a transient scope. - - when N_Accept_Alternative - | N_Attribute_Definition_Clause - | N_Case_Statement - | N_Case_Statement_Alternative - | N_Code_Statement - | N_Delay_Alternative - | N_Delay_Until_Statement - | N_Delay_Relative_Statement - | N_Discriminant_Association - | N_Elsif_Part - | N_Entry_Body_Formal_Part - | N_Exit_Statement - | N_If_Statement - | N_Iteration_Scheme - | N_Terminate_Alternative - => - pragma Assert (Present (Prev)); - return Prev; - - when N_Assignment_Statement => - return Curr; - - when N_Entry_Call_Statement - | N_Procedure_Call_Statement - => - -- When an entry or procedure call acts as the alternative of a - -- conditional or timed entry call, the proper context is that - -- of the alternative. - - if Nkind (Parent (Curr)) = N_Entry_Call_Alternative - and then Nkind (Parent (Parent (Curr))) in - N_Conditional_Entry_Call | N_Timed_Entry_Call - then - return Parent (Parent (Curr)); - - -- General case for entry or procedure calls - - else - return Curr; - end if; - - when N_Pragma => - - -- Pragma Check is not a valid transient context in GNATprove - -- mode because the pragma must remain unchanged. - - if GNATprove_Mode - and then Get_Pragma_Id (Curr) = Pragma_Check - then - return Empty; - - -- General case for pragmas - - else - return Curr; - end if; - - when N_Raise_Statement => - return Curr; - - when N_Simple_Return_Statement => - - -- A return statement is not a valid transient context when the - -- function itself requires transient scope management because - -- the result will be reclaimed too early. - - if Requires_Transient_Scope (Etype - (Return_Applies_To (Return_Statement_Entity (Curr)))) - then - return Empty; - - -- General case for return statements - - else - return Curr; - end if; - - -- Special - - when N_Attribute_Reference => - if Is_Procedure_Attribute_Name (Attribute_Name (Curr)) then - return Curr; - end if; - - -- An Ada 2012 iterator specification is not a valid context - -- because Analyze_Iterator_Specification already employs special - -- processing for it. - - when N_Iterator_Specification => - return Empty; - - when N_Loop_Parameter_Specification => - - -- An iteration scheme is not a valid context because routine - -- Analyze_Iteration_Scheme already employs special processing. - - if Nkind (Parent (Curr)) = N_Iteration_Scheme then - return Empty; - else - return Parent (Curr); - end if; - - -- Termination - - -- The following nodes represent "dummy contexts" which do not - -- need to be wrapped. - - when N_Component_Declaration - | N_Discriminant_Specification - | N_Parameter_Specification - => - return Empty; - - -- If the traversal leaves a scope without having been able to - -- find a construct to wrap, something is going wrong, but this - -- can happen in error situations that are not detected yet (such - -- as a dynamic string in a pragma Export). - - when N_Block_Statement - | N_Entry_Body - | N_Package_Body - | N_Package_Declaration - | N_Protected_Body - | N_Subprogram_Body - | N_Task_Body - => - return Empty; - - -- Default - - when others => - null; - end case; - - Prev := Curr; - Curr := Parent (Curr); - end loop; - - return Empty; - end Find_Transient_Context; - --------------------------------- -- Has_Simple_Protected_Object -- --------------------------------- @@ -9891,15 +9886,6 @@ package body Exp_Ch7 is end Node_To_Be_Wrapped; ---------------------------- - -- Set_Node_To_Be_Wrapped -- - ---------------------------- - - procedure Set_Node_To_Be_Wrapped (N : Node_Id) is - begin - Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := N; - end Set_Node_To_Be_Wrapped; - - ---------------------------- -- Store_Actions_In_Scope -- ---------------------------- diff --git a/gcc/ada/libgnat/a-cdlili.adb b/gcc/ada/libgnat/a-cdlili.adb index 73c1e6d..75961a2 100644 --- a/gcc/ada/libgnat/a-cdlili.adb +++ b/gcc/ada/libgnat/a-cdlili.adb @@ -130,11 +130,6 @@ is pragma Assert (Container.Last.Next = null); pragma Assert (Container.Length > 0); - Container.First := null; - Container.Last := null; - Container.Length := 0; - Zero_Counts (Container.TC); - Container.First := new Node_Type'(Src.Element, null, null); Container.Last := Container.First; Container.Length := 1; @@ -232,9 +227,7 @@ is Container.Last := null; Container.Length := 0; - pragma Warnings (Off); Free (X); - pragma Warnings (On); end Clear; ------------------------ diff --git a/gcc/ada/sem.ads b/gcc/ada/sem.ads index a56ce937..2fdccf7 100644 --- a/gcc/ada/sem.ads +++ b/gcc/ada/sem.ads @@ -533,7 +533,7 @@ package Sem is -- See Sem_Ch10 (Install_Parents, Remove_Parents). Node_To_Be_Wrapped : Node_Id; - -- Only used in transient scopes. Records the node which will be wrapped + -- Only used in transient scopes. Records the node that will be wrapped -- by the transient block. Actions_To_Be_Wrapped : Scope_Actions; diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index d3bbfeb..f056a18 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -8995,6 +8995,28 @@ package body Sem_Ch8 is procedure Push_Scope (S : Entity_Id) is E : constant Entity_Id := Scope (S); + function Component_Alignment_Default return Component_Alignment_Kind; + -- Return Component_Alignment_Kind for the newly-pushed scope. + + function Component_Alignment_Default return Component_Alignment_Kind is + begin + -- Each new scope pushed onto the scope stack inherits the component + -- alignment of the previous scope. This emulates the "visibility" + -- semantics of pragma Component_Alignment. + + if Scope_Stack.Last > Scope_Stack.First then + return Scope_Stack.Table + (Scope_Stack.Last - 1).Component_Alignment_Default; + + -- Otherwise, this is the first scope being pushed on the scope + -- stack. Inherit the component alignment from the configuration + -- form of pragma Component_Alignment (if any). + + else + return Configuration_Component_Alignment; + end if; + end Component_Alignment_Default; + begin if Ekind (S) = E_Void then null; @@ -9023,49 +9045,27 @@ package body Sem_Ch8 is Scope_Stack.Increment_Last; - declare - SST : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last); - - begin - SST.Entity := S; - SST.Save_Scope_Suppress := Scope_Suppress; - SST.Save_Local_Suppress_Stack_Top := Local_Suppress_Stack_Top; - SST.Save_Check_Policy_List := Check_Policy_List; - SST.Save_Default_Storage_Pool := Default_Pool; - SST.Save_No_Tagged_Streams := No_Tagged_Streams; - SST.Save_SPARK_Mode := SPARK_Mode; - SST.Save_SPARK_Mode_Pragma := SPARK_Mode_Pragma; - SST.Save_Default_SSO := Default_SSO; - SST.Save_Uneval_Old := Uneval_Old; - - -- Each new scope pushed onto the scope stack inherits the component - -- alignment of the previous scope. This emulates the "visibility" - -- semantics of pragma Component_Alignment. - - if Scope_Stack.Last > Scope_Stack.First then - SST.Component_Alignment_Default := - Scope_Stack.Table - (Scope_Stack.Last - 1).Component_Alignment_Default; - - -- Otherwise, this is the first scope being pushed on the scope - -- stack. Inherit the component alignment from the configuration - -- form of pragma Component_Alignment (if any). - - else - SST.Component_Alignment_Default := - Configuration_Component_Alignment; - end if; - - SST.Last_Subprogram_Name := null; - SST.Is_Transient := False; - SST.Node_To_Be_Wrapped := Empty; - SST.Pending_Freeze_Actions := No_List; - SST.Actions_To_Be_Wrapped := (others => No_List); - SST.First_Use_Clause := Empty; - SST.Is_Active_Stack_Base := False; - SST.Previous_Visibility := False; - SST.Locked_Shared_Objects := No_Elist; - end; + Scope_Stack.Table (Scope_Stack.Last) := + (Entity => S, + Save_Scope_Suppress => Scope_Suppress, + Save_Local_Suppress_Stack_Top => Local_Suppress_Stack_Top, + Save_Check_Policy_List => Check_Policy_List, + Save_Default_Storage_Pool => Default_Pool, + Save_No_Tagged_Streams => No_Tagged_Streams, + Save_SPARK_Mode => SPARK_Mode, + Save_SPARK_Mode_Pragma => SPARK_Mode_Pragma, + Save_Default_SSO => Default_SSO, + Save_Uneval_Old => Uneval_Old, + Component_Alignment_Default => Component_Alignment_Default, + Last_Subprogram_Name => null, + Is_Transient => False, + Node_To_Be_Wrapped => Empty, + Pending_Freeze_Actions => No_List, + Actions_To_Be_Wrapped => (others => No_List), + First_Use_Clause => Empty, + Is_Active_Stack_Base => False, + Previous_Visibility => False, + Locked_Shared_Objects => No_Elist); if Debug_Flag_W then Write_Str ("--> new scope: "); diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 494904f..3ebf93a 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -7521,7 +7521,6 @@ package body Sem_Res is Node := First (Actions (N)); while Present (Node) loop if Nkind (Node) = N_Object_Declaration - and then Is_Type (Etype (Defining_Identifier (Node))) and then Requires_Transient_Scope (Etype (Defining_Identifier (Node))) then @@ -7534,7 +7533,7 @@ package body Sem_Res is end; if Need_Transient_Scope then - Establish_Transient_Scope (Decl, True); + Establish_Transient_Scope (Decl, Manage_Sec_Stack => True); else Push_Scope (Scope (Defining_Identifier (Decl))); end if; diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 038c1ee..5c6a7013 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -26956,6 +26956,8 @@ package body Sem_Util is -- generated before the next instruction. function Requires_Transient_Scope (Id : Entity_Id) return Boolean is + pragma Assert (if Present (Id) then Ekind (Id) in E_Void | Type_Kind); + function Caller_Known_Size_Record (Typ : Entity_Id) return Boolean; -- This is called for untagged records and protected types, with -- nondefaulted discriminants. Returns True if the size of function @@ -27036,8 +27038,7 @@ package body Sem_Util is -- Do not set Has_Controlled_Component on a class-wide equivalent -- type. See Make_CW_Equivalent_Type. - if Present (Typ) - and then not Is_Frozen (Typ) + if not Is_Frozen (Typ) and then Is_Base_Type (Typ) and then (Is_Record_Type (Typ) or else Is_Concurrent_Type (Typ) @@ -27154,19 +27155,20 @@ package body Sem_Util is -- Start of processing for Requires_Transient_Scope begin - Ensure_Minimum_Decoration (Id); - -- This is a private type which is not completed yet. This can only -- happen in a default expression (of a formal parameter or of a -- record component). Do not expand transient scope in this case. if No (Typ) then return False; + end if; + + Ensure_Minimum_Decoration (Id); -- Do not expand transient scope for non-existent procedure return or -- string literal types. - elsif Typ = Standard_Void_Type + if Typ = Standard_Void_Type or else Ekind (Typ) = E_String_Literal_Subtype then return False; -- cgit v1.1 From c7959e489dd324fb6c4266c01c2dd6afd1fabb34 Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Fri, 7 May 2021 12:26:09 -0400 Subject: [Ada] Return when not working for procedures gcc/ada/ * par-ch6.adb (Get_Return_Kind): Properly handle the case of a "return when" statement in the procedure case. --- gcc/ada/par-ch6.adb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb index 45a4214..2337175 100644 --- a/gcc/ada/par-ch6.adb +++ b/gcc/ada/par-ch6.adb @@ -1903,6 +1903,11 @@ package body Ch6 is end if; Restore_Scan_State (Scan_State); -- to identifier + + elsif Token = Tok_When then + Error_Msg_GNAT_Extension ("return when statement"); + + Result := Return_When; end if; return Result; -- cgit v1.1 From 06a5fb60eb53ef297454f58db61d3374d538f515 Mon Sep 17 00:00:00 2001 From: Gary Dismukes Date: Sat, 8 May 2021 17:49:04 -0400 Subject: [Ada] Removal of various ??? comments plus related code changes gcc/ada/ * checks.adb: Remove calls of Set_Do_Tag_Check (N, False). * einfo.ads: Remove hanging unneeded ??? comment ("this real description was clobbered"). * exp_util.ads (Insert_Actions_After): Remove ??? from spec comment. * gen_il-fields.ads (Opt_Field_Enum): Remove literals Do_Accessibility_Check and Do_Tag_Check. * gen_il-gen-gen_nodes.adb: Remove all calls to Sm for Do_Accessibility_Check and Do_Tag_Check. * sem_type.ads (Is_Subtype_Of): Remove obsolete ??? comment (function is not limited to scalar subtypes). * sem_util.ads (Is_Local_Variable_Reference): Revise comment to mention out-mode parameters as well, and remove ???. (Propagate_Concurrent_Flags): Minor reformatting. (Propagate_Invariant_Attributes): Typo fix. (Propagate_Predicate_Attributes): Indicate what is propagated and remove ??? comment. * sem_util.adb (Cannot_Raise_Constraint_Error): Remove unneeded test of Do_Tag_Check. (Is_Local_Variable_Reference): Extend function to testing for formals of mode out as well. * sinfo.ads: Remove ??? comment about flag Convert_To_Return_False indicating that the flag is obsolete (in fact it's used). Remove references to Do_Accessibility_Check and Do_Tag_Check (and the two associated ??? comments), as these flags are unneeded. * sinfo-cn.adb (Change_Conversion_To_Unchecked): Remove call of Set_Do_Tag_Check (N, False). * targparm.ads (Support_Atomic_Primitives_On_Target): Remove ??? comment, plus minor reformatting. --- gcc/ada/checks.adb | 4 ---- gcc/ada/einfo.ads | 2 -- gcc/ada/exp_util.ads | 2 +- gcc/ada/gen_il-fields.ads | 2 -- gcc/ada/gen_il-gen-gen_nodes.adb | 6 ------ gcc/ada/sem_type.ads | 3 +-- gcc/ada/sem_util.adb | 5 +++-- gcc/ada/sem_util.ads | 17 ++++++++--------- gcc/ada/sinfo-cn.adb | 1 - gcc/ada/sinfo.ads | 23 +---------------------- gcc/ada/targparm.ads | 10 +++++----- 11 files changed, 19 insertions(+), 56 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 96a2a3f..d3d7852 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -9766,9 +9766,6 @@ package body Checks is when N_Attribute_Reference => Set_Do_Overflow_Check (N, False); - when N_Function_Call => - Set_Do_Tag_Check (N, False); - when N_Op => Set_Do_Overflow_Check (N, False); @@ -9804,7 +9801,6 @@ package body Checks is when N_Type_Conversion => Set_Do_Length_Check (N, False); - Set_Do_Tag_Check (N, False); Set_Do_Overflow_Check (N, False); when others => diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index 59588bb..2feef7a 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -1931,8 +1931,6 @@ package Einfo is -- that clients should generally not test this flag directly, but instead -- use function Has_Unreferenced. --- ??? this real description was clobbered - -- Has_Pragma_Unreferenced_Objects -- Defined in all entities. Set if a valid pragma Unused applies to an -- entity, indicating that warnings should be given if the entity is diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads index 2b3147d..3be0166 100644 --- a/gcc/ada/exp_util.ads +++ b/gcc/ada/exp_util.ads @@ -162,7 +162,7 @@ package Exp_Util is -- -- Implementation limitation: Assoc_Node must be a statement. We can -- generalize to expressions if there is a need but this is tricky to - -- implement because of short-circuits (among other things).??? + -- implement because of short-circuits (among other things). procedure Insert_Declaration (N : Node_Id; Decl : Node_Id); -- N must be a subexpression (Nkind in N_Subexpr). This is similar to diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads index 603f08a..e2592ee 100644 --- a/gcc/ada/gen_il-fields.ads +++ b/gcc/ada/gen_il-fields.ads @@ -150,14 +150,12 @@ package Gen_IL.Fields is Discrete_Subtype_Definitions, Discriminant_Specifications, Discriminant_Type, - Do_Accessibility_Check, Do_Discriminant_Check, Do_Division_Check, Do_Length_Check, Do_Overflow_Check, Do_Range_Check, Do_Storage_Check, - Do_Tag_Check, Elaborate_All_Desirable, Elaborate_All_Present, Elaborate_Desirable, diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb index e6defb1..ef7dfa4 100644 --- a/gcc/ada/gen_il-gen-gen_nodes.adb +++ b/gcc/ada/gen_il-gen-gen_nodes.adb @@ -390,7 +390,6 @@ begin -- Gen_IL.Gen.Gen_Nodes Ab (N_Subprogram_Call, N_Subexpr, (Sm (Controlling_Argument, Node_Id), - Sm (Do_Tag_Check, Flag), Sm (First_Named_Actual, Node_Id), Sm (Is_Elaboration_Checks_OK_Node, Flag), Sm (Is_Elaboration_Warnings_OK_Node, Flag), @@ -553,7 +552,6 @@ begin -- Gen_IL.Gen.Gen_Nodes Sm (Do_Discriminant_Check, Flag), Sm (Do_Length_Check, Flag), Sm (Do_Overflow_Check, Flag), - Sm (Do_Tag_Check, Flag), Sm (Float_Truncate, Flag), Sm (Rounded_Result, Flag))); @@ -949,7 +947,6 @@ begin -- Gen_IL.Gen.Gen_Nodes Sm (Componentwise_Assignment, Flag), Sm (Do_Discriminant_Check, Flag), Sm (Do_Length_Check, Flag), - Sm (Do_Tag_Check, Flag), Sm (Forwards_OK, Flag), Sm (Has_Target_Names, Flag), Sm (Is_Elaboration_Checks_OK_Node, Flag), @@ -1056,7 +1053,6 @@ begin -- Gen_IL.Gen.Gen_Nodes (Sy (Expression, Node_Id, Default_Empty), Sm (By_Ref, Flag), Sm (Comes_From_Extended_Return_Statement, Flag), - Sm (Do_Tag_Check, Flag), Sm (Procedure_To_Call, Node_Id), Sm (Return_Statement_Entity, Node_Id), Sm (Storage_Pool, Node_Id))); @@ -1065,7 +1061,6 @@ begin -- Gen_IL.Gen.Gen_Nodes (Sy (Return_Object_Declarations, List_Id), Sy (Handled_Statement_Sequence, Node_Id, Default_Empty), Sm (By_Ref, Flag), - Sm (Do_Tag_Check, Flag), Sm (Procedure_To_Call, Node_Id), Sm (Return_Statement_Entity, Node_Id), Sm (Storage_Pool, Node_Id))); @@ -1487,7 +1482,6 @@ begin -- Gen_IL.Gen.Gen_Nodes Sy (Parameter_Type, Node_Id), Sy (Expression, Node_Id, Default_Empty), Sm (Default_Expression, Node_Id), - Sm (Do_Accessibility_Check, Flag), Sm (More_Ids, Flag), Sm (Prev_Ids, Flag))); diff --git a/gcc/ada/sem_type.ads b/gcc/ada/sem_type.ads index 89fd617..018c283 100644 --- a/gcc/ada/sem_type.ads +++ b/gcc/ada/sem_type.ads @@ -243,8 +243,7 @@ package Sem_Type is -- in the signature of an inherited operation must carry the derived type. function Is_Subtype_Of (T1 : Entity_Id; T2 : Entity_Id) return Boolean; - -- Checks whether T1 is any subtype of T2 directly or indirectly. Applies - -- only to scalar subtypes??? + -- Checks whether T1 is any subtype of T2 directly or indirectly function Operator_Matches_Spec (Op, New_S : Entity_Id) return Boolean; -- Used to resolve subprograms renaming operators, and calls to user diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 5c6a7013..cfb3293 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -3087,7 +3087,6 @@ package body Sem_Util is when N_Type_Conversion => if Do_Overflow_Check (Expr) or else Do_Length_Check (Expr) - or else Do_Tag_Check (Expr) then return False; else @@ -18097,7 +18096,9 @@ package body Sem_Util is Ent : constant Entity_Id := Entity (Expr); Sub : constant Entity_Id := Enclosing_Subprogram (Ent); begin - if Ekind (Ent) not in E_Variable | E_In_Out_Parameter then + if Ekind (Ent) + not in E_Variable | E_In_Out_Parameter | E_Out_Parameter + then return False; else return Present (Sub) and then Sub = Current_Subprogram; diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index 7cacae2..bacf8b4 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -2113,9 +2113,8 @@ package Sem_Util is -- limited view must be treated in the same way. function Is_Local_Variable_Reference (Expr : Node_Id) return Boolean; - -- Determines whether Expr is a reference to a variable or IN OUT mode - -- parameter of the current enclosing subprogram. - -- Why are OUT parameters not considered here ??? + -- Determines whether Expr is a reference to a variable or formal parameter + -- of mode OUT or IN OUT of the current enclosing subprogram. function Is_Master (N : Node_Id) return Boolean; -- Determine if the given node N constitutes a finalization master @@ -2902,9 +2901,9 @@ package Sem_Util is procedure Propagate_Concurrent_Flags (Typ : Entity_Id; Comp_Typ : Entity_Id); - -- Set Has_Task, Has_Protected and Has_Timing_Event on Typ when the flags - -- are set on Comp_Typ. This follows the definition of these flags which - -- are set (recursively) on any composite type which has a component marked + -- Set Has_Task, Has_Protected, and Has_Timing_Event on Typ when the flags + -- are set on Comp_Typ. This follows the definition of these flags, which + -- are set (recursively) on any composite type that has a component marked -- by one of these flags. This procedure can only set flags for Typ, and -- never clear them. Comp_Typ is the type of a component or a parent. @@ -2917,14 +2916,14 @@ package Sem_Util is procedure Propagate_Invariant_Attributes (Typ : Entity_Id; From_Typ : Entity_Id); - -- Inherit all invariant-related attributes form type From_Typ. Typ is the + -- Inherit all invariant-related attributes from type From_Typ. Typ is the -- destination type. procedure Propagate_Predicate_Attributes (Typ : Entity_Id; From_Typ : Entity_Id); - -- Inherit some predicate-related attributes form type From_Typ. Typ is the - -- destination type. Probably to be completed with more attributes??? + -- Inherit predicate functions and Has_Predicates flag from type From_Typ. + -- Typ is the destination type. procedure Record_Possible_Part_Of_Reference (Var_Id : Entity_Id; diff --git a/gcc/ada/sinfo-cn.adb b/gcc/ada/sinfo-cn.adb index 9a9af9b..c676d47 100644 --- a/gcc/ada/sinfo-cn.adb +++ b/gcc/ada/sinfo-cn.adb @@ -56,7 +56,6 @@ package body Sinfo.CN is procedure Change_Conversion_To_Unchecked (N : Node_Id) is begin Set_Do_Overflow_Check (N, False); - Set_Do_Tag_Check (N, False); Set_Do_Length_Check (N, False); Mutate_Nkind (N, N_Unchecked_Type_Conversion); end Change_Conversion_To_Unchecked; diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index fe4f4e1..8f23f7d 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -689,11 +689,9 @@ package Sinfo is -- The following flag fields appear in various nodes: - -- Do_Accessibility_Check -- Do_Discriminant_Check -- Do_Length_Check -- Do_Storage_Check - -- Do_Tag_Check -- These flags are used in some specific cases by the front end, either -- during semantic analysis or during expansion, and cannot be expected @@ -1012,7 +1010,7 @@ package Sinfo is -- Present in N_Raise_Expression nodes that appear in the body of the -- special predicateM function used to test a predicate in the context -- of a membership test, where raise expression results in returning a - -- value of False rather than raising an exception.???obsolete flag + -- value of False rather than raising an exception. -- Corresponding_Aspect -- Present in N_Pragma node. Used to point back to the source aspect from @@ -1096,11 +1094,6 @@ package Sinfo is -- discriminant checking functions are constructed. The purpose is to -- avoid attempting to set these functions more than once. - -- Do_Accessibility_Check - -- This flag is set on N_Parameter_Specification nodes to indicate - -- that an accessibility check is required for the parameter. It is - -- not yet decided who takes care of this check???. - -- Do_Discriminant_Check -- This flag is set on N_Selected_Component nodes to indicate that a -- discriminant check is required using the discriminant check routine @@ -1185,13 +1178,6 @@ package Sinfo is -- to the runtime routine. The N_Subprogram_Body case is handled by the -- backend, and all the semantics does is set the flag. - -- Do_Tag_Check - -- This flag is set on an N_Assignment_Statement, N_Function_Call, - -- N_Procedure_Call_Statement, N_Type_Conversion, - -- N_Simple_Return_Statement, or N_Extended_Return_Statement - -- node to indicate that the tag check can be suppressed. It is not - -- yet decided how this flag is used???. - -- Elaborate_Present -- This flag is set in the N_With_Clause node to indicate that pragma -- Elaborate pragma appears for the with'ed units. @@ -4740,7 +4726,6 @@ package Sinfo is -- Do_Discriminant_Check -- Do_Length_Check -- Float_Truncate - -- Do_Tag_Check -- Conversion_OK -- Do_Overflow_Check -- Rounded_Result @@ -4913,7 +4898,6 @@ package Sinfo is -- No_Ctrl_Actions -- Has_Target_Names -- Is_Elaboration_Code - -- Do_Tag_Check -- Componentwise_Assignment -- Suppress_Assignment_Checks @@ -5436,7 +5420,6 @@ package Sinfo is -- Null_Exclusion_Present -- Parameter_Type subtype mark or access definition -- Expression (set to Empty if no default expression present) - -- Do_Accessibility_Check -- More_Ids (set to False if no more identifiers in list) -- Prev_Ids (set to False if no previous identifiers in list) -- Default_Expression @@ -5505,7 +5488,6 @@ package Sinfo is -- Is_SPARK_Mode_On_Node -- Is_Elaboration_Warnings_OK_Node -- No_Elaboration_Check - -- Do_Tag_Check -- Is_Known_Guaranteed_ABE -- plus fields for expression @@ -5539,7 +5521,6 @@ package Sinfo is -- Is_Elaboration_Warnings_OK_Node -- No_Elaboration_Check -- Is_Expanded_Build_In_Place_Call - -- Do_Tag_Check -- No_Side_Effect_Removal -- Is_Known_Guaranteed_ABE -- plus fields for expression @@ -5602,7 +5583,6 @@ package Sinfo is -- Expression (set to Empty if no expression present) -- Storage_Pool -- Procedure_To_Call - -- Do_Tag_Check -- By_Ref -- Comes_From_Extended_Return_Statement @@ -5618,7 +5598,6 @@ package Sinfo is -- Handled_Statement_Sequence (set to Empty if not present) -- Storage_Pool -- Procedure_To_Call - -- Do_Tag_Check -- By_Ref -- Note: Return_Statement_Entity points to an E_Return_Statement. diff --git a/gcc/ada/targparm.ads b/gcc/ada/targparm.ads index 28465ea..302247f 100644 --- a/gcc/ada/targparm.ads +++ b/gcc/ada/targparm.ads @@ -365,12 +365,12 @@ package Targparm is -- this flag is False, and the use of aggregates is not permitted. Support_Atomic_Primitives_On_Target : Boolean := False; - -- If this flag is True, then the back-end support GCC built-in atomic - -- operations for memory model such as atomic load or atomic compare + -- If this flag is True, then the back end supports GCC built-in atomic + -- operations for memory model, such as atomic load or atomic compare -- exchange (see the GCC manual for more information). If the flag is - -- False, then the back-end doesn't provide this support. Note this flag is - -- set to True only if the target supports all atomic primitives up to 64 - -- bits. ??? To be modified. + -- False, then the back end doesn't provide this support. Note that this + -- flag is set to True only if the target supports all atomic primitives + -- up to 64 bits. Support_Composite_Assign_On_Target : Boolean := True; -- The assignment of composite objects other than small records and -- cgit v1.1 From 82a794419a00ea98b68d69b64363ae6746710de9 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Sat, 8 May 2021 11:39:52 -0400 Subject: [Ada] Tbuild cleanup gcc/ada/ * tbuild.adb (Convert_To): Add assert, along with a comment. (Make_DT_Access): Remove this function, which is not used. It was incorrect anyway (the call to New_Occurrence_Of should not be there). (Unchecked_Convert_To): Add assert. The previous version's test for unchecked conversion to the same type was redundant and could never be true, because the previous 'if' already checked for ANY expression of the same type. Remove that, and replace with a test for unchecked conversion to a related type. Otherwise, we somethings get things like "finalize(some_type!(some_type!(x)))" in the generated code, where x is already of type some_type, but we're converting it to the private type and then to the full type or vice versa (so the types aren't equal, so the previous 'if' doesn't catch it). Avoid updating the Parent. This is not necessary; the Parent will be updated if/when the node is attached to the tree. * tbuild.ads: Fix comments. No need to say "this is safe" when we just explained that a few lines earlier. Remove Make_DT_Access. * sinfo.ads: Add comments. * exp_ch7.adb (Make_Finalize_Address_Stmts): Minor comment fix. * gen_il-gen.adb, gen_il-gen.ads, gen_il-gen-gen_nodes.adb, gen_il-internals.ads: Implement a feature where you can put: Nmake_Assert => "expr" where expr is a boolean expression in a call to Create_Concrete_Node_Type. It is added in a pragma Assert in the Nmake.Make_... function for that type. --- gcc/ada/exp_ch7.adb | 2 +- gcc/ada/gen_il-gen-gen_nodes.adb | 10 +++++-- gcc/ada/gen_il-gen.adb | 40 +++++++++++++++++---------- gcc/ada/gen_il-gen.ads | 18 +++++++----- gcc/ada/gen_il-internals.ads | 2 ++ gcc/ada/sinfo.ads | 7 +++-- gcc/ada/tbuild.adb | 59 +++++++++++----------------------------- gcc/ada/tbuild.ads | 31 ++++++++------------- 8 files changed, 79 insertions(+), 90 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 4c1e16d..b0374a3 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -9344,7 +9344,7 @@ package body Exp_Ch7 is Dope_Id : Entity_Id; begin - -- Ensure that Ptr_Typ a thin pointer, generate: + -- Ensure that Ptr_Typ is a thin pointer; generate: -- for Ptr_Typ'Size use System.Address'Size; Append_To (Decls, diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb index ef7dfa4..2427a1e 100644 --- a/gcc/ada/gen_il-gen-gen_nodes.adb +++ b/gcc/ada/gen_il-gen-gen_nodes.adb @@ -31,7 +31,8 @@ procedure Gen_IL.Gen.Gen_Nodes is renames Create_Abstract_Node_Type; procedure Cc -- Short for "ConCrete" (T : Concrete_Node; Parent : Abstract_Type; - Fields : Field_Sequence := No_Fields) + Fields : Field_Sequence := No_Fields; + Nmake_Assert : String := "") renames Create_Concrete_Node_Type; function Sy -- Short for "Syntactic" @@ -562,7 +563,12 @@ begin -- Gen_IL.Gen.Gen_Nodes (Sy (Subtype_Mark, Node_Id, Default_Empty), Sy (Expression, Node_Id, Default_Empty), Sm (Kill_Range_Check, Flag), - Sm (No_Truncation, Flag))); + Sm (No_Truncation, Flag)), + Nmake_Assert => "True or else Nkind (Expression) /= N_Unchecked_Type_Conversion"); +-- Nmake_Assert => "Nkind (Expression) /= N_Unchecked_Type_Conversion"); + -- Assert that we don't have unchecked conversions of unchecked + -- conversions; if Expression might be an unchecked conversion, + -- then Tbuild.Unchecked_Convert_To should be used. Cc (N_Subtype_Indication, N_Has_Etype, (Sy (Subtype_Mark, Node_Id, Default_Empty), diff --git a/gcc/ada/gen_il-gen.adb b/gcc/ada/gen_il-gen.adb index 0f3698e..94f7c9c 100644 --- a/gcc/ada/gen_il-gen.adb +++ b/gcc/ada/gen_il-gen.adb @@ -47,9 +47,10 @@ package body Gen_IL.Gen is All_Entities : constant Type_Vector := To_Vector (Entity_Kind, Length => 1); procedure Create_Type - (T : Node_Or_Entity_Type; - Parent : Opt_Abstract_Type; - Fields : Field_Sequence); + (T : Node_Or_Entity_Type; + Parent : Opt_Abstract_Type; + Fields : Field_Sequence; + Nmake_Assert : String); -- Called by the Create_..._Type procedures exported by this package to -- create an entry in the Types_Table. @@ -107,9 +108,10 @@ package body Gen_IL.Gen is ----------------- procedure Create_Type - (T : Node_Or_Entity_Type; - Parent : Opt_Abstract_Type; - Fields : Field_Sequence) + (T : Node_Or_Entity_Type; + Parent : Opt_Abstract_Type; + Fields : Field_Sequence; + Nmake_Assert : String) is begin Check_Type (T); @@ -132,7 +134,8 @@ package body Gen_IL.Gen is new Type_Info' (Is_Union => False, Parent => Parent, Children | Concrete_Descendants => Type_Vectors.Empty_Vector, - First | Last | Fields => <>); -- filled in later + First | Last | Fields => <>, -- filled in later + Nmake_Assert => new String'(Nmake_Assert)); if Parent /= No_Type then Append (Type_Table (Parent).Children, T); @@ -215,7 +218,7 @@ package body Gen_IL.Gen is (T : Abstract_Node; Fields : Field_Sequence := No_Fields) is begin - Create_Type (T, Parent => No_Type, Fields => Fields); + Create_Type (T, Parent => No_Type, Fields => Fields, Nmake_Assert => ""); end Create_Root_Node_Type; ------------------------------- @@ -227,7 +230,7 @@ package body Gen_IL.Gen is Fields : Field_Sequence := No_Fields) is begin - Create_Type (T, Parent, Fields); + Create_Type (T, Parent, Fields, Nmake_Assert => ""); end Create_Abstract_Node_Type; ------------------------------- @@ -236,10 +239,11 @@ package body Gen_IL.Gen is procedure Create_Concrete_Node_Type (T : Concrete_Node; Parent : Abstract_Type; - Fields : Field_Sequence := No_Fields) + Fields : Field_Sequence := No_Fields; + Nmake_Assert : String := "") is begin - Create_Type (T, Parent, Fields); + Create_Type (T, Parent, Fields, Nmake_Assert); end Create_Concrete_Node_Type; ----------------------------- @@ -250,7 +254,7 @@ package body Gen_IL.Gen is (T : Abstract_Entity; Fields : Field_Sequence := No_Fields) is begin - Create_Type (T, Parent => No_Type, Fields => Fields); + Create_Type (T, Parent => No_Type, Fields => Fields, Nmake_Assert => ""); end Create_Root_Entity_Type; --------------------------------- @@ -262,7 +266,7 @@ package body Gen_IL.Gen is Fields : Field_Sequence := No_Fields) is begin - Create_Type (T, Parent, Fields); + Create_Type (T, Parent, Fields, Nmake_Assert => ""); end Create_Abstract_Entity_Type; --------------------------------- @@ -274,7 +278,7 @@ package body Gen_IL.Gen is Fields : Field_Sequence := No_Fields) is begin - Create_Type (T, Parent, Fields); + Create_Type (T, Parent, Fields, Nmake_Assert => ""); end Create_Concrete_Entity_Type; ------------------ @@ -352,7 +356,7 @@ package body Gen_IL.Gen is Image (Field); end if; - if Pre /= Field_Table (Field).Pre.all then + if Pre_Set /= Field_Table (Field).Pre_Set.all then raise Illegal with "mismatched extra setter-only preconditions for " & Image (Field); @@ -2561,6 +2565,11 @@ package body Gen_IL.Gen is end; end if; + if Type_Table (T).Nmake_Assert.all /= "" then + Put (S, "pragma Assert (" & + Type_Table (T).Nmake_Assert.all & ");" & LF); + end if; + Put (S, "return N;" & LF); Decrease_Indent (S, 3); @@ -2628,6 +2637,7 @@ package body Gen_IL.Gen is Increase_Indent (B, 3); Put (B, "-- This package is automatically generated." & LF & LF); + Put (B, "pragma Style_Checks (""M200"");" & LF); Put_Make_Bodies (B, Node_Kind); diff --git a/gcc/ada/gen_il-gen.ads b/gcc/ada/gen_il-gen.ads index 34ce2d6..1d24ebf 100644 --- a/gcc/ada/gen_il-gen.ads +++ b/gcc/ada/gen_il-gen.ads @@ -102,9 +102,12 @@ package Gen_IL.Gen is procedure Create_Concrete_Node_Type (T : Concrete_Node; Parent : Abstract_Type; - Fields : Field_Sequence := No_Fields); + Fields : Field_Sequence := No_Fields; + Nmake_Assert : String := ""); -- Create a concrete node type. Every node is an instance of a concrete - -- node type. + -- node type. Nmake_Assert is an assertion to put in the Make_... function + -- in the generated Nmake package. It should be a String that represents a + -- Boolean expression. procedure Create_Root_Entity_Type (T : Abstract_Entity; @@ -151,13 +154,14 @@ package Gen_IL.Gen is -- only for syntactic fields. Flag fields of syntactic nodes always have a -- default value, which is False unless specified as Default_True. Pre is -- an additional precondition for the field getter and setter, in addition - -- to the precondition that asserts that the type has that field. Pre_Get - -- and Pre_Set are similar to Pre, but for the getter or setter only, - -- respectively. + -- to the precondition that asserts that the type has that field. It should + -- be a String that represents a Boolean expression. Pre_Get and Pre_Set + -- are similar to Pre, but for the getter or setter only, respectively. -- -- If multiple calls to these occur for the same Field but different types, - -- the Field_Type and Pre must match. Default_Value should match for - -- syntactic fields. See the declaration of Type_Only_Enum for Type_Only. + -- the Field_Type, Pre, Pre_Get, and Pre_Set must match. Default_Value + -- should match for syntactic fields. See the declaration of Type_Only_Enum + -- for Type_Only. -- -- (The matching Default_Value requirement is a simplification from the -- earlier hand-written version.) diff --git a/gcc/ada/gen_il-internals.ads b/gcc/ada/gen_il-internals.ads index 9c5779b..b8911ec 100644 --- a/gcc/ada/gen_il-internals.ads +++ b/gcc/ada/gen_il-internals.ads @@ -104,6 +104,8 @@ package Gen_IL.Internals is -- includes two or more types. Fields : Field_Vector; + + Nmake_Assert : String_Access; -- only for concrete node types end case; end record; diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index 8f23f7d..f6c5e0d 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -8420,8 +8420,11 @@ package Sinfo is -- An unchecked type conversion node represents the semantic action -- corresponding to a call to an instantiation of Unchecked_Conversion. -- It is generated as a result of actual use of Unchecked_Conversion - -- and also the expander generates unchecked type conversion nodes - -- directly for expansion of complex semantic actions. + -- and also by the expander. + + -- Unchecked type conversion nodes should normally be created by calling + -- Tbuild.Unchecked_Convert_To, rather than by directly calling + -- Nmake.Make_Unchecked_Type_Conversion. -- Note: an unchecked type conversion is a variable as far as the -- semantics are concerned, which is convenient for the expander. diff --git a/gcc/ada/tbuild.adb b/gcc/ada/tbuild.adb index 4c53cdb..e718644 100644 --- a/gcc/ada/tbuild.adb +++ b/gcc/ada/tbuild.adb @@ -29,14 +29,12 @@ with Csets; use Csets; with Einfo; use Einfo; with Einfo.Entities; use Einfo.Entities; with Einfo.Utils; use Einfo.Utils; -with Elists; use Elists; with Lib; use Lib; with Nlists; use Nlists; with Nmake; use Nmake; with Opt; use Opt; with Restrict; use Restrict; with Rident; use Rident; -with Sem_Aux; use Sem_Aux; with Sinfo.Utils; use Sinfo.Utils; with Sem_Util; use Sem_Util; with Snames; use Snames; @@ -117,6 +115,7 @@ package body Tbuild is ---------------- function Convert_To (Typ : Entity_Id; Expr : Node_Id) return Node_Id is + pragma Assert (Is_Type (Typ)); Result : Node_Id; begin @@ -185,32 +184,6 @@ package body Tbuild is return N; end Make_Byte_Aligned_Attribute_Reference; - -------------------- - -- Make_DT_Access -- - -------------------- - - function Make_DT_Access - (Loc : Source_Ptr; - Rec : Node_Id; - Typ : Entity_Id) return Node_Id - is - Full_Type : Entity_Id := Typ; - - begin - if Is_Private_Type (Typ) then - Full_Type := Underlying_Type (Typ); - end if; - - return - Unchecked_Convert_To ( - New_Occurrence_Of - (Etype (Node (First_Elmt (Access_Disp_Table (Full_Type)))), Loc), - Make_Selected_Component (Loc, - Prefix => New_Copy (Rec), - Selector_Name => - New_Occurrence_Of (First_Tag_Component (Full_Type), Loc))); - end Make_DT_Access; - ------------------------ -- Make_Float_Literal -- ------------------------ @@ -906,26 +879,34 @@ package body Tbuild is (Typ : Entity_Id; Expr : Node_Id) return Node_Id is + pragma Assert (Ekind (Typ) in E_Void | Type_Kind); + -- We don't really want to allow E_Void here, but existing code passes + -- it. + Loc : constant Source_Ptr := Sloc (Expr); Result : Node_Id; - Expr_Parent : Node_Id; begin -- If the expression is already of the correct type, then nothing - -- to do, except for relocating the node in case this is required. + -- to do, except for relocating the node if Present (Etype (Expr)) - and then (Base_Type (Etype (Expr)) = Typ - or else Etype (Expr) = Typ) + and then (Base_Type (Etype (Expr)) = Typ or else Etype (Expr) = Typ) then return Relocate_Node (Expr); - -- Case where the expression is itself an unchecked conversion to - -- the same type, and we can thus eliminate the outer conversion. + -- Case where the expression is already an unchecked conversion. We + -- replace the type being converted to, to avoid creating an unchecked + -- conversion of an unchecked conversion. Extra unchecked conversions + -- make the .dg output less readable. We can't do this in cases + -- involving bitfields, because the sizes might not match. The + -- Is_Composite_Type checks avoid such cases. elsif Nkind (Expr) = N_Unchecked_Type_Conversion - and then Entity (Subtype_Mark (Expr)) = Typ + and then Is_Composite_Type (Etype (Expr)) + and then Is_Composite_Type (Typ) then + Set_Subtype_Mark (Expr, New_Occurrence_Of (Typ, Loc)); Result := Relocate_Node (Expr); elsif Nkind (Expr) = N_Null @@ -938,18 +919,10 @@ package body Tbuild is -- All other cases else - -- Capture the parent of the expression before relocating it and - -- creating the conversion, so the conversion's parent can be set - -- to the original parent below. - - Expr_Parent := Parent (Expr); - Result := Make_Unchecked_Type_Conversion (Loc, Subtype_Mark => New_Occurrence_Of (Typ, Loc), Expression => Relocate_Node (Expr)); - - Set_Parent (Result, Expr_Parent); end if; Set_Etype (Result, Typ); diff --git a/gcc/ada/tbuild.ads b/gcc/ada/tbuild.ads index 07cd7a7..f2f9809 100644 --- a/gcc/ada/tbuild.ads +++ b/gcc/ada/tbuild.ads @@ -41,19 +41,16 @@ package Tbuild is -- except that it will be analyzed and resolved with checks off. function Convert_To (Typ : Entity_Id; Expr : Node_Id) return Node_Id; - -- Returns an expression that represents the result of a checked convert - -- of expression Exp to type T. If the base type of Exp is T, then no - -- conversion is required, and Exp is returned unchanged. Otherwise an - -- N_Type_Conversion node is constructed to convert the expression. - -- If an N_Type_Conversion node is required, Relocate_Node is used on - -- Exp. This means that it is safe to replace a node by a Convert_To - -- of itself to some other type. + -- Returns an expression that is a type conversion of expression Expr to + -- type Typ. If the type of Expr is Typ, then no conversion is required. + -- Otherwise an N_Type_Conversion node is constructed to convert the + -- expression. Relocate_Node is applied to Expr, so that it is safe to + -- replace a node by a Convert_To of itself to some other type. procedure Convert_To_And_Rewrite (Typ : Entity_Id; Expr : Node_Id); pragma Inline (Convert_To_And_Rewrite); -- Like the function, except that there is an extra step of calling -- Rewrite on the Expr node and replacing it with the converted result. - -- As noted above, this is safe, because Relocate_Node is called. procedure Discard_Node (N : Node_Or_Entity_Id); pragma Inline (Discard_Node); @@ -78,11 +75,6 @@ package Tbuild is -- Must_Be_Byte_Aligned is set in the attribute reference node. The -- Attribute_Name must be Name_Address or Name_Unrestricted_Access. - function Make_DT_Access - (Loc : Source_Ptr; Rec : Node_Id; Typ : Entity_Id) return Node_Id; - -- Create an access to the Dispatch Table by using the Tag field of a - -- tagged record : Acc_Dt (Rec.tag).all - function Make_Float_Literal (Loc : Source_Ptr; Radix : Uint; @@ -319,13 +311,12 @@ package Tbuild is function New_Occurrence_Of (Def_Id : Entity_Id; Loc : Source_Ptr) return Node_Id; - -- New_Occurrence_Of creates an N_Identifier node which is an occurrence - -- of the defining identifier which is passed as its argument. The Entity - -- and Etype of the result are set from the given defining identifier as - -- follows: Entity is simply a copy of Def_Id. Etype is a copy of Def_Id - -- for types, and a copy of the Etype of Def_Id for other entities. Note - -- that Is_Static_Expression is set if this call creates an occurrence of - -- an enumeration literal. + -- New_Occurrence_Of creates an N_Identifier node that is an occurrence of + -- the defining identifier Def_Id. The Entity and Etype of the result are + -- set from the given defining identifier as follows: Entity is a copy of + -- Def_Id. Etype is a copy of Def_Id for types, and a copy of the Etype of + -- Def_Id for other entities. Note that Is_Static_Expression is set if this + -- call creates an occurrence of an enumeration literal. function New_Suffixed_Name (Related_Id : Name_Id; -- cgit v1.1 From cb338455b39c13cc2385b653dc9bb89edca24b62 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Mon, 10 May 2021 14:36:25 +0200 Subject: [Ada] Missing space in error message for pattern matching gcc/ada/ * sem_case.adb: Fix error message. --- gcc/ada/sem_case.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_case.adb b/gcc/ada/sem_case.adb index 36db9a7..9ff2564 100644 --- a/gcc/ada/sem_case.adb +++ b/gcc/ada/sem_case.adb @@ -2908,7 +2908,7 @@ package body Sem_Case is begin if Has_Predicates (Subtyp) then Error_Msg_N - ("subtype of case selector (or subcomponent thereof)" & + ("subtype of case selector (or subcomponent thereof) " & "has predicate", N); elsif Is_Discrete_Type (Subtyp) then if not Is_Static_Subtype (Subtyp) then @@ -2938,7 +2938,7 @@ package body Sem_Case is elsif Is_Record_Type (Subtyp) then if Has_Discriminants (Subtyp) then Error_Msg_N - ("type of case selector (or subcomponent thereof)" & + ("type of case selector (or subcomponent thereof) " & "is discriminated", N); else declare -- cgit v1.1 From 3a7961c89914cf544018e731693418f18b5cc984 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 10 May 2021 09:40:22 -0400 Subject: [Ada] Crash on use of 'Img on record type in expression gcc/ada/ * exp_ch4.adb (Process_Transient_In_Expression): Ensure that Fin_Context, used to insert finalization code for the expression, is a list member: the value returned by Find_Hook_Context may be an expression node when the transient is part of a larger expression and it has a non-boolean type. --- gcc/ada/exp_ch4.adb | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 21b2c22..738d651 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -14952,7 +14952,17 @@ package body Exp_Ch4 is -- Hook := null; -- end if; + -- Note that the value returned by Find_Hook_Context may be an + -- operator node, which is not a list member. We must locate in the + -- tree the proper node after which to inwert the finaliation code. + else + while not Is_List_Member (Fin_Context) loop + Fin_Context := Parent (Fin_Context); + end loop; + + pragma Assert (Present (Fin_Context)); + Insert_Action_After (Fin_Context, Make_Implicit_If_Statement (Obj_Decl, Condition => -- cgit v1.1 From 160a6c31074afde0bfc835591a95653c5e65cc45 Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Sat, 8 May 2021 00:28:55 -0400 Subject: [Ada] Spurious initialization of element iterators in "for of" loops gcc/ada/ * exp_ch5.adb (Expand_Formal_Container_Element_Loop): Remove legacy expansion of element iterators, and use expansion form used by unconstrained element types in the general case. --- gcc/ada/exp_ch5.adb | 68 ++++++++++++----------------------------------------- 1 file changed, 15 insertions(+), 53 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 2cc8b64..3e65084 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -4077,7 +4077,6 @@ package body Exp_Ch5 is Make_Defining_Identifier (Loc, Chars => New_External_Name (Chars (Element), 'C')); Elmt_Decl : Node_Id; - Elmt_Ref : Node_Id; Element_Op : constant Entity_Id := Get_Iterable_Type_Primitive (Container_Typ, Name_Element); @@ -4088,19 +4087,10 @@ package body Exp_Ch5 is begin -- For an element iterator, the Element aspect must be present, - -- (this is checked during analysis) and the expansion takes the form: + -- (this is checked during analysis). - -- Cursor : Cursor_Type := First (Container); - -- Elmt : Element_Type; - -- while Has_Element (Cursor, Container) loop - -- Elmt := Element (Container, Cursor); - -- - -- Cursor := Next (Container, Cursor); - -- end loop; - - -- However this expansion is not legal if the element is indefinite. - -- In that case we create a block to hold a variable declaration - -- initialized with a call to Element, and generate: + -- We create a block to hold a variable declaration initialized with + -- a call to Element, and generate: -- Cursor : Cursor_Type := First (Container); -- while Has_Element (Cursor, Container) loop @@ -4132,48 +4122,20 @@ package body Exp_Ch5 is Defining_Identifier => Element, Object_Definition => New_Occurrence_Of (Etype (Element_Op), Loc)); - if not Is_Constrained (Etype (Element_Op)) then - Set_Expression (Elmt_Decl, - Make_Function_Call (Loc, - Name => New_Occurrence_Of (Element_Op, Loc), - Parameter_Associations => New_List ( - Convert_To_Iterable_Type (Container, Loc), - New_Occurrence_Of (Cursor, Loc)))); - - Set_Statements (New_Loop, - New_List - (Make_Block_Statement (Loc, - Declarations => New_List (Elmt_Decl), - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => Stats)))); - - else - Elmt_Ref := - Make_Assignment_Statement (Loc, - Name => New_Occurrence_Of (Element, Loc), - Expression => - Make_Function_Call (Loc, - Name => New_Occurrence_Of (Element_Op, Loc), - Parameter_Associations => New_List ( - Convert_To_Iterable_Type (Container, Loc), - New_Occurrence_Of (Cursor, Loc)))); - - Prepend (Elmt_Ref, Stats); - - -- The element is assignable in the expanded code - - Set_Assignment_OK (Name (Elmt_Ref)); - - -- The loop is rewritten as a block, to hold the element declaration - - New_Loop := - Make_Block_Statement (Loc, - Declarations => New_List (Elmt_Decl), + Set_Expression (Elmt_Decl, + Make_Function_Call (Loc, + Name => New_Occurrence_Of (Element_Op, Loc), + Parameter_Associations => New_List ( + Convert_To_Iterable_Type (Container, Loc), + New_Occurrence_Of (Cursor, Loc)))); + + Set_Statements (New_Loop, + New_List + (Make_Block_Statement (Loc, + Declarations => New_List (Elmt_Decl), Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List (New_Loop))); - end if; + Statements => Stats)))); -- The element is only modified in expanded code, so it appears as -- unassigned to the warning machinery. We must suppress this spurious -- cgit v1.1 From 0547a12f6ae617009ecb264674aa3ebb0c8fe462 Mon Sep 17 00:00:00 2001 From: Gary Dismukes Date: Mon, 10 May 2021 15:14:38 -0400 Subject: [Ada] Reformatting, typo corrections, and minor rewording of a comment. gcc/ada/ * exp_ch4.adb (Process_Transient_In_Expression): In one comment, fix two typos and reorder wording of one sentence, plus minor reformatting. --- gcc/ada/exp_ch4.adb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 738d651..7e8a741 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -14952,9 +14952,9 @@ package body Exp_Ch4 is -- Hook := null; -- end if; - -- Note that the value returned by Find_Hook_Context may be an - -- operator node, which is not a list member. We must locate in the - -- tree the proper node after which to inwert the finaliation code. + -- Note that the value returned by Find_Hook_Context may be an operator + -- node, which is not a list member. We must locate the proper node in + -- in the tree after which to insert the finalization code. else while not Is_List_Member (Fin_Context) loop -- cgit v1.1 From e11a24513632e2b2a3842bfd3ef226565f523778 Mon Sep 17 00:00:00 2001 From: Gary Dismukes Date: Tue, 11 May 2021 14:49:46 -0400 Subject: [Ada] Regression on overloaded prefixed calls related to prefixed-call extension gcc/ada/ * sem_ch4.adb (Try_One_Prefix_Interpretation): Augment test of "not Extensions_Allowed" with test for absence of Obj_Type's primitive operations Elist, as an additional condition for early return from this procedure. --- gcc/ada/sem_ch4.adb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index eb1a556..1bfd222 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -9558,9 +9558,13 @@ package body Sem_Ch4 is -- Extension feature: Calls with prefixed views are also supported -- for untagged types, so skip the early return when extensions are - -- enabled. + -- enabled, unless the type doesn't have a primitive operations list + -- (such as in the case of predefined types). - if (not Is_Tagged_Type (Obj_Type) and then not Extensions_Allowed) + if (not Is_Tagged_Type (Obj_Type) + and then + (not Extensions_Allowed + or else not Present (Primitive_Operations (Obj_Type)))) or else Is_Incomplete_Type (Obj_Type) then Obj_Type := Prev_Obj_Type; -- cgit v1.1 From 6dff0d21e56d15dafc683dd69c6a9fbf3f1e7dfc Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Fri, 7 May 2021 14:49:57 -0400 Subject: [Ada] Return_when_statement not working for non identifier return values gcc/ada/ * par-ch6.adb (Get_Return_Kind): Removed. (Is_Extended): Created to identify simple and "when" return statements from extended return statements. (P_Return_Statement): Merged simple and "when" return statement processing. --- gcc/ada/par-ch6.adb | 134 ++++++++++++++++++++++++---------------------------- 1 file changed, 61 insertions(+), 73 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb index 2337175..e3b3155 100644 --- a/gcc/ada/par-ch6.adb +++ b/gcc/ada/par-ch6.adb @@ -1874,48 +1874,38 @@ package body Ch6 is function P_Return_Statement return Node_Id is -- The caller has checked that the initial token is RETURN - type Return_Kind is (Simple_Return, Extended_Return, Return_When); - - function Get_Return_Kind return Return_Kind; + function Is_Extended return Boolean; -- Scan state is just after RETURN (and is left that way). Determine -- whether this is a simple or extended return statement by looking -- ahead for "identifier :", which implies extended. - --------------------- - -- Get_Return_Kind -- - --------------------- + ----------------- + -- Is_Extended -- + ----------------- - function Get_Return_Kind return Return_Kind is - Scan_State : Saved_Scan_State; - Result : Return_Kind := Simple_Return; + function Is_Extended return Boolean is + Scan_State : Saved_Scan_State; + Is_Extended : Boolean := False; begin + if Token = Tok_Identifier then Save_Scan_State (Scan_State); -- at identifier Scan; -- past identifier if Token = Tok_Colon then - Result := Extended_Return; -- It's an extended_return_statement - elsif Token = Tok_When then - Error_Msg_GNAT_Extension ("return when statement"); - - Result := Return_When; + Is_Extended := True; end if; Restore_Scan_State (Scan_State); -- to identifier - - elsif Token = Tok_When then - Error_Msg_GNAT_Extension ("return when statement"); - - Result := Return_When; end if; - return Result; - end Get_Return_Kind; + return Is_Extended; + end Is_Extended; Ret_Sloc : constant Source_Ptr := Token_Ptr; Ret_Strt : constant Column_Number := Start_Column; - Ret_Node : Node_Id := New_Node (N_Simple_Return_Statement, Ret_Sloc); + Ret_Node : Node_Id; Decl : Node_Id; -- Start of processing for P_Return_Statement @@ -1928,75 +1918,73 @@ package body Ch6 is if Token = Tok_Semicolon then Scan; -- past ; + Ret_Node := New_Node (N_Simple_Return_Statement, Ret_Sloc); -- Nontrivial case else - -- Simple_return_statement with expression + -- Extended_return_statement (Ada 2005 only -- AI-318): - -- We avoid trying to scan an expression if we are at an - -- expression terminator since in that case the best error - -- message is probably that we have a missing semicolon. + if Is_Extended then + Error_Msg_Ada_2005_Extension ("extended return statement"); - case Get_Return_Kind is - -- Return_when_statement (Experimental only) + Ret_Node := New_Node (N_Extended_Return_Statement, Ret_Sloc); + Decl := P_Return_Object_Declaration; + Set_Return_Object_Declarations (Ret_Node, New_List (Decl)); - when Return_When => - Ret_Node := New_Node (N_Return_When_Statement, Ret_Sloc); - - if Token not in Token_Class_Eterm then - Set_Expression (Ret_Node, P_Expression_No_Right_Paren); - end if; - - if Token = Tok_When and then not Missing_Semicolon_On_When then - Scan; -- past WHEN - Set_Condition (Ret_Node, P_Condition); - - -- Allow IF instead of WHEN, giving error message + if Token = Tok_With then + P_Aspect_Specifications (Decl, False); + end if; - elsif Token = Tok_If then - T_When; - Scan; -- past IF used in place of WHEN - Set_Condition (Ret_Node, P_Expression_No_Right_Paren); - end if; + if Token = Tok_Do then + Push_Scope_Stack; + Scopes (Scope.Last).Ecol := Ret_Strt; + Scopes (Scope.Last).Etyp := E_Return; + Scopes (Scope.Last).Labl := Error; + Scopes (Scope.Last).Sloc := Ret_Sloc; + Scan; -- past DO + Set_Handled_Statement_Sequence + (Ret_Node, P_Handled_Sequence_Of_Statements); + End_Statements; + + -- Do we need to handle Error_Resync here??? + end if; - -- Simple_return_statement + -- Simple_return_statement or Return_when_Statement + -- with expression. - when Simple_Return => - Ret_Node := New_Node (N_Simple_Return_Statement, Ret_Sloc); + -- We avoid trying to scan an expression if we are at an + -- expression terminator since in that case the best error + -- message is probably that we have a missing semicolon. - if Token not in Token_Class_Eterm then - Set_Expression (Ret_Node, P_Expression_No_Right_Paren); - end if; + else + Ret_Node := New_Node (N_Simple_Return_Statement, Ret_Sloc); - -- Extended_return_statement (Ada 2005 only -- AI-318): + if Token not in Token_Class_Eterm then + Set_Expression (Ret_Node, P_Expression_No_Right_Paren); + end if; - when Extended_Return => - Error_Msg_Ada_2005_Extension ("extended return statement"); + -- When the next token is WHEN or IF we know that we are looking + -- at a Return_when_statement - Ret_Node := New_Node (N_Extended_Return_Statement, Ret_Sloc); - Decl := P_Return_Object_Declaration; - Set_Return_Object_Declarations (Ret_Node, New_List (Decl)); + if Token = Tok_When and then not Missing_Semicolon_On_When then + Error_Msg_GNAT_Extension ("return when statement"); + Mutate_Nkind (Ret_Node, N_Return_When_Statement); - if Token = Tok_With then - P_Aspect_Specifications (Decl, False); - end if; + Scan; -- past WHEN + Set_Condition (Ret_Node, P_Condition); - if Token = Tok_Do then - Push_Scope_Stack; - Scopes (Scope.Last).Ecol := Ret_Strt; - Scopes (Scope.Last).Etyp := E_Return; - Scopes (Scope.Last).Labl := Error; - Scopes (Scope.Last).Sloc := Ret_Sloc; + -- Allow IF instead of WHEN, giving error message - Scan; -- past DO - Set_Handled_Statement_Sequence - (Ret_Node, P_Handled_Sequence_Of_Statements); - End_Statements; + elsif Token = Tok_If then + Error_Msg_GNAT_Extension ("return when statement"); + Mutate_Nkind (Ret_Node, N_Return_When_Statement); - -- Do we need to handle Error_Resync here??? - end if; - end case; + T_When; + Scan; -- past IF used in place of WHEN + Set_Condition (Ret_Node, P_Condition); + end if; + end if; TF_Semicolon; end if; -- cgit v1.1 From c6d8890c7d1e717c2f8ed5f2b04ca5a9b26cdfc1 Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Tue, 11 May 2021 14:27:09 -0700 Subject: [Ada] Fix bug in casing on composite values with -gnatX gcc/ada/ * exp_ch5.adb (Expand_N_Case_Statement.Expand_General_Case_Statement.Pattern_Match): When generating an equality test for a statically known discrete value, only generate the numeric value if the discrete type is not an enumeration type. If it is an enumeration type, then call Get_Enum_Lit_From_Pos instead. --- gcc/ada/exp_ch5.adb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 3e65084..2559e56 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -3384,9 +3384,17 @@ package body Exp_Ch5 is and then Is_Discrete_Type (Etype (Pattern)) and then Compile_Time_Known_Value (Pattern) then - return Make_Op_Eq (Loc, - Object, - Make_Integer_Literal (Loc, Expr_Value (Pattern))); + declare + Val : Node_Id; + begin + if Is_Enumeration_Type (Etype (Pattern)) then + Val := Get_Enum_Lit_From_Pos + (Etype (Pattern), Expr_Value (Pattern), Loc); + else + Val := Make_Integer_Literal (Loc, Expr_Value (Pattern)); + end if; + return Make_Op_Eq (Loc, Object, Val); + end; end if; case Nkind (Pattern) is -- cgit v1.1 From 3751af1e7ba5173f35f0e0a5adc62e4455f7a963 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Mon, 10 May 2021 18:55:37 +0200 Subject: [Ada] Simplify dependency on System gcc/ada/ * lib-writ.adb (Ensure_System_Dependency): Simplify by reusing a constant name. --- gcc/ada/lib-writ.adb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb index 16993dd..1b02b1c 100644 --- a/gcc/ada/lib-writ.adb +++ b/gcc/ada/lib-writ.adb @@ -158,9 +158,7 @@ package body Lib.Writ is -- on system as a result of Targparm scanning the system.ads file to -- determine the target dependent parameters for the compilation. - Name_Len := 6; - Name_Buffer (1 .. 6) := "system"; - System_Uname := Name_To_Unit_Name (Name_Enter); + System_Uname := Name_To_Unit_Name (Name_System); System_Fname := File_Name (System_Source_File_Index); Units.Increment_Last; -- cgit v1.1 From ca290f108a62e041ea3ca7c981d8225f34cefdbd Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Mon, 10 May 2021 18:00:46 +0200 Subject: [Ada] Simplify unit loading with membership tests gcc/ada/ * lib-load.adb (Load_Unit): Remove excessive whitespace. * lib.adb (Is_Internal_Unit, Is_Predefined_Unit): Likewise. * par-ch10.adb (P_Compilation_Unit): Simplify with membership test. * par-load.adb (Load): Likewise. * uname.adb (Get_Unit_Name): Likewise. --- gcc/ada/lib-load.adb | 16 ++++++++-------- gcc/ada/lib.adb | 14 ++++---------- gcc/ada/par-ch10.adb | 2 +- gcc/ada/par-load.adb | 22 +++++++--------------- gcc/ada/uname.adb | 4 ++-- 5 files changed, 22 insertions(+), 36 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/lib-load.adb b/gcc/ada/lib-load.adb index 330faa7..75b52e2 100644 --- a/gcc/ada/lib-load.adb +++ b/gcc/ada/lib-load.adb @@ -396,14 +396,14 @@ package body Lib.Load is --------------- function Load_Unit - (Load_Name : Unit_Name_Type; - Required : Boolean; - Error_Node : Node_Id; - Subunit : Boolean; - Corr_Body : Unit_Number_Type := No_Unit; - Renamings : Boolean := False; - With_Node : Node_Id := Empty; - PMES : Boolean := False) return Unit_Number_Type + (Load_Name : Unit_Name_Type; + Required : Boolean; + Error_Node : Node_Id; + Subunit : Boolean; + Corr_Body : Unit_Number_Type := No_Unit; + Renamings : Boolean := False; + With_Node : Node_Id := Empty; + PMES : Boolean := False) return Unit_Number_Type is Calling_Unit : Unit_Number_Type; Uname_Actual : Unit_Name_Type; diff --git a/gcc/ada/lib.adb b/gcc/ada/lib.adb index 31a6b8c..44aa5c6 100644 --- a/gcc/ada/lib.adb +++ b/gcc/ada/lib.adb @@ -128,12 +128,12 @@ package body Lib is return Units.Table (U).Is_Predefined_Renaming; end Is_Predefined_Renaming; - function Is_Internal_Unit (U : Unit_Number_Type) return Boolean is + function Is_Internal_Unit (U : Unit_Number_Type) return Boolean is begin return Units.Table (U).Is_Internal_Unit; end Is_Internal_Unit; - function Is_Predefined_Unit (U : Unit_Number_Type) return Boolean is + function Is_Predefined_Unit (U : Unit_Number_Type) return Boolean is begin return Units.Table (U).Is_Predefined_Unit; end Is_Predefined_Unit; @@ -482,18 +482,12 @@ package body Lib is -- body of the same unit. The location in the spec is considered -- earlier. - if Nkind (Unit1) = N_Subprogram_Body - or else - Nkind (Unit1) = N_Package_Body - then + if Nkind (Unit1) in N_Subprogram_Body | N_Package_Body then if Library_Unit (Cunit (Unum1)) = Cunit (Unum2) then return Yes_After; end if; - elsif Nkind (Unit2) = N_Subprogram_Body - or else - Nkind (Unit2) = N_Package_Body - then + elsif Nkind (Unit2) in N_Subprogram_Body | N_Package_Body then if Library_Unit (Cunit (Unum2)) = Cunit (Unum1) then return Yes_Before; end if; diff --git a/gcc/ada/par-ch10.adb b/gcc/ada/par-ch10.adb index e140626..9a49d45 100644 --- a/gcc/ada/par-ch10.adb +++ b/gcc/ada/par-ch10.adb @@ -555,7 +555,7 @@ package body Ch10 is | N_Generic_Function_Renaming_Declaration | N_Generic_Package_Renaming_Declaration | N_Generic_Procedure_Renaming_Declaration - or else Nkind (Unit_Node) in N_Package_Body + | N_Package_Body | N_Package_Instantiation | N_Package_Renaming_Declaration | N_Package_Specification diff --git a/gcc/ada/par-load.adb b/gcc/ada/par-load.adb index 05e9f9e..fe8fede 100644 --- a/gcc/ada/par-load.adb +++ b/gcc/ada/par-load.adb @@ -182,14 +182,8 @@ begin -- Check for predefined file case if Name_Len > 1 + and then Name_Buffer (1) in 'a' | 's' | 'i' | 'g' and then Name_Buffer (2) = '-' - and then (Name_Buffer (1) = 'a' - or else - Name_Buffer (1) = 's' - or else - Name_Buffer (1) = 'i' - or else - Name_Buffer (1) = 'g') then declare Expect_Name : constant Unit_Name_Type := Expected_Unit (Cur_Unum); @@ -248,9 +242,7 @@ begin -- If current unit is a body, load its corresponding spec - if Nkind (Unit (Curunit)) = N_Package_Body - or else Nkind (Unit (Curunit)) = N_Subprogram_Body - then + if Nkind (Unit (Curunit)) in N_Package_Body | N_Subprogram_Body then Spec_Name := Get_Spec_Name (Unit_Name (Cur_Unum)); Unum := Load_Unit @@ -304,11 +296,11 @@ begin -- If current unit is a child unit spec, load its parent. If the child unit -- is loaded through a limited with, the parent must be as well. - elsif Nkind (Unit (Curunit)) = N_Package_Declaration - or else Nkind (Unit (Curunit)) = N_Subprogram_Declaration - or else Nkind (Unit (Curunit)) in N_Generic_Declaration - or else Nkind (Unit (Curunit)) in N_Generic_Instantiation - or else Nkind (Unit (Curunit)) in N_Renaming_Declaration + elsif Nkind (Unit (Curunit)) in N_Package_Declaration + | N_Subprogram_Declaration + | N_Generic_Declaration + | N_Generic_Instantiation + | N_Renaming_Declaration then -- Turn style checks off for parent unit diff --git a/gcc/ada/uname.adb b/gcc/ada/uname.adb index ca937ef..3192c3d 100644 --- a/gcc/ada/uname.adb +++ b/gcc/ada/uname.adb @@ -367,8 +367,8 @@ package body Uname is Node := Declaration_Node (Entity (Node)); end if; - if Nkind (Node) = N_Package_Specification - or else Nkind (Node) in N_Subprogram_Specification + if Nkind (Node) in N_Package_Specification + | N_Subprogram_Specification then Node := Parent (Node); end if; -- cgit v1.1 From ddbe7338f1ea50db4d39a925c6c530052ed288a4 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 11 May 2021 13:01:35 +0200 Subject: [Ada] Simplify returning from Enclosing_Comp_Unit_Node gcc/ada/ * sem_util.adb (Enclosing_Comp_Unit_Node): When the loop exits the Current_Node is either an N_Compilation_Unit node or Empty, so simply return it without redundant checks. --- gcc/ada/sem_util.adb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index cfb3293..9d54309 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -8037,11 +8037,7 @@ package body Sem_Util is Current_Node := Parent (Current_Node); end loop; - if Nkind (Current_Node) /= N_Compilation_Unit then - return Empty; - else - return Current_Node; - end if; + return Current_Node; end Enclosing_Comp_Unit_Node; -------------------------- -- cgit v1.1 From b1c4989d174cb22297a88f8873be95430ad62bcd Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 11 May 2021 14:11:12 +0200 Subject: [Ada] Replace a question mark comment with assertion gcc/ada/ * lib.adb (Remove_Unit): Replace defensive code with an assertion. * par-load.adb (Load): Address a question mark in the comment. --- gcc/ada/lib.adb | 7 +++---- gcc/ada/par-load.adb | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/lib.adb b/gcc/ada/lib.adb index 44aa5c6..44a4af0 100644 --- a/gcc/ada/lib.adb +++ b/gcc/ada/lib.adb @@ -1174,10 +1174,9 @@ package body Lib is procedure Remove_Unit (U : Unit_Number_Type) is begin - if U = Units.Last then - Unit_Names.Set (Unit_Name (U), No_Unit); - Units.Decrement_Last; - end if; + pragma Assert (U = Units.Last); + Unit_Names.Set (Unit_Name (U), No_Unit); + Units.Decrement_Last; end Remove_Unit; ---------------------------------- diff --git a/gcc/ada/par-load.adb b/gcc/ada/par-load.adb index fe8fede..39c445e 100644 --- a/gcc/ada/par-load.adb +++ b/gcc/ada/par-load.adb @@ -234,8 +234,7 @@ begin Error_Msg ("\\found unit $!", Loc); end if; - -- In both cases, remove the unit if it is the last unit (which it - -- normally (always?) will be) so that it is out of the way later. + -- In both cases, remove the unit so that it is out of the way later Remove_Unit (Cur_Unum); end if; -- cgit v1.1 From 435e79cbe51e8f7e587b9dc7da794e82fba55932 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 11 May 2021 16:53:36 +0200 Subject: [Ada] Simplify code by removing local constant gcc/ada/ * uname.adb (Add_Node_Name): Replace local constant whose initial expression was evaluated even when unnecessary with just that expression that is evaluated at most once and only when needed. --- gcc/ada/uname.adb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/uname.adb b/gcc/ada/uname.adb index 3192c3d..5dc8ac6 100644 --- a/gcc/ada/uname.adb +++ b/gcc/ada/uname.adb @@ -223,8 +223,6 @@ package body Uname is ------------------- procedure Add_Node_Name (Node : Node_Id) is - Kind : constant Node_Kind := Nkind (Node); - begin -- Just ignore an error node (someone else will give a message) @@ -234,7 +232,7 @@ package body Uname is -- Otherwise see what kind of node we have else - case Kind is + case Nkind (Node) is when N_Defining_Identifier | N_Defining_Operator_Symbol | N_Identifier -- cgit v1.1 From d8870b1f64ae927e9469082490760b760ef5616f Mon Sep 17 00:00:00 2001 From: Nicolas Roche Date: Tue, 11 May 2021 07:58:42 +0200 Subject: [Ada] Handle malformed command line on Win32 gcc/ada/ * rtinit.c (skip_quoted_string): Handle malformed command line with no closing double quote. (skip_argument): Handle case in which a null character is encountered by skip_quote_string. --- gcc/ada/rtinit.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/rtinit.c b/gcc/ada/rtinit.c index 391c7e9..83a63c8 100644 --- a/gcc/ada/rtinit.c +++ b/gcc/ada/rtinit.c @@ -147,6 +147,19 @@ static void skip_quoted_string (const WCHAR **current_in, } ci++; } + + /* Handle the case in which a nul character was found instead of a closing + double quote. In that case consider all the backslashes as literal + characters. */ + if (*ci == '\0') + { + for (int i=0; i Date: Wed, 12 May 2021 14:43:06 +0200 Subject: [Ada] Warn on statically known empty loop caused by constraint gcc/ada/ * sem_ch5.adb (Analyze_Loop_Parameter_Specification): Check for empty loops caused by constraints. --- gcc/ada/sem_ch5.adb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb index 3c98d73..ccd5a37 100644 --- a/gcc/ada/sem_ch5.adb +++ b/gcc/ada/sem_ch5.adb @@ -3377,6 +3377,32 @@ package body Sem_Ch5 is ("\loop executes zero times or raises " & "Constraint_Error??", Bad_Bound); end if; + + if Compile_Time_Compare (LLo, LHi, Assume_Valid => False) + = GT + then + Error_Msg_N ("??constrained range is null", + Constraint (DS)); + + -- Additional constraints on modular types can be + -- confusing, add more information. + + if Ekind (Etype (DS)) = E_Modular_Integer_Subtype then + Error_Msg_Uint_1 := Intval (LLo); + Error_Msg_Uint_2 := Intval (LHi); + Error_Msg_NE ("\iterator has modular type &, " & + "so the loop has bounds ^ ..^", + Constraint (DS), + Subtype_Mark (DS)); + end if; + + Set_Is_Null_Loop (Loop_Nod); + Null_Range := True; + + -- Suppress other warnigns about the body of the loop, as + -- it will never execute. + Set_Suppress_Loop_Warnings (Loop_Nod); + end if; end; end if; -- cgit v1.1 From fb632ef567d8af061e7f73fcf7bb2b75796cdfb4 Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Tue, 11 May 2021 11:43:31 -0700 Subject: [Ada] Implement missing constraint checks for default streaming operations gcc/ada/ * sem_ch5.adb (Analyze_Assignment): Add new nested function, Omit_Range_Check_For_Streaming, and make call to Apply_Scalar_Range_Check conditional on the result of this new function. * exp_attr.adb (Compile_Stream_Body_In_Scope): Eliminate Check parameter, update callers. The new Omit_Range_Check_For_Streaming parameter takes the place of the old use of calling Insert_Action with Suppress => All_Checks, which was insufficiently precise (it did not allow suppressing checks for one component but not for another). (Expand_N_Attribute_Reference): Eliminate another "Suppress => All_Checks" from an Insert_Action call, this one in generating the expansion of a T'Read attribute reference for a composite type T. --- gcc/ada/exp_attr.adb | 26 +++++----------- gcc/ada/sem_ch5.adb | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 19 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 067e7ed..e33a36e 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -117,8 +117,7 @@ package body Exp_Attr is procedure Compile_Stream_Body_In_Scope (N : Node_Id; Decl : Node_Id; - Arr : Entity_Id; - Check : Boolean); + Arr : Entity_Id); -- The body for a stream subprogram may be generated outside of the scope -- of the type. If the type is fully private, it may depend on the full -- view of other types (e.g. indexes) that are currently private as well. @@ -867,8 +866,7 @@ package body Exp_Attr is procedure Compile_Stream_Body_In_Scope (N : Node_Id; Decl : Node_Id; - Arr : Entity_Id; - Check : Boolean) + Arr : Entity_Id) is C_Type : constant Entity_Id := Base_Type (Component_Type (Arr)); Curr : constant Entity_Id := Current_Scope; @@ -922,11 +920,7 @@ package body Exp_Attr is Install := False; end if; - if Check then - Insert_Action (N, Decl); - else - Insert_Action (N, Decl, Suppress => All_Checks); - end if; + Insert_Action (N, Decl); if Install then @@ -4128,7 +4122,7 @@ package body Exp_Attr is elsif Is_Array_Type (U_Type) then Build_Array_Input_Function (Loc, U_Type, Decl, Fname); - Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False); + Compile_Stream_Body_In_Scope (N, Decl, U_Type); -- Dispatching case with class-wide type @@ -5238,7 +5232,7 @@ package body Exp_Attr is elsif Is_Array_Type (U_Type) then Build_Array_Output_Procedure (Loc, U_Type, Decl, Pname); - Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False); + Compile_Stream_Body_In_Scope (N, Decl, U_Type); -- Class-wide case, first output external tag, then dispatch -- to the appropriate primitive Output function (RM 13.13.2(31)). @@ -6090,7 +6084,7 @@ package body Exp_Attr is elsif Is_Array_Type (U_Type) then Build_Array_Read_Procedure (N, U_Type, Decl, Pname); - Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False); + Compile_Stream_Body_In_Scope (N, Decl, U_Type); -- Tagged type case, use the primitive Read function. Note that -- this will dispatch in the class-wide case which is what we want @@ -6129,11 +6123,7 @@ package body Exp_Attr is (Loc, Full_Base (U_Type), Decl, Pname); end if; - -- Suppress checks, uninitialized or otherwise invalid - -- data does not cause constraint errors to be raised for - -- a complete record read. - - Insert_Action (N, Decl, All_Checks); + Insert_Action (N, Decl); end if; end if; @@ -7718,7 +7708,7 @@ package body Exp_Attr is elsif Is_Array_Type (U_Type) then Build_Array_Write_Procedure (N, U_Type, Decl, Pname); - Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False); + Compile_Stream_Body_In_Scope (N, Decl, U_Type); -- Tagged type case, use the primitive Write function. Note that -- this will dispatch in the class-wide case which is what we want diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb index ccd5a37..fbb6904 100644 --- a/gcc/ada/sem_ch5.adb +++ b/gcc/ada/sem_ch5.adb @@ -33,6 +33,7 @@ with Einfo.Utils; use Einfo.Utils; with Errout; use Errout; with Expander; use Expander; with Exp_Ch6; use Exp_Ch6; +with Exp_Tss; use Exp_Tss; with Exp_Util; use Exp_Util; with Freeze; use Freeze; with Ghost; use Ghost; @@ -979,7 +980,92 @@ package body Sem_Ch5 is end if; if Is_Scalar_Type (T1) then - Apply_Scalar_Range_Check (Rhs, Etype (Lhs)); + declare + + function Omit_Range_Check_For_Streaming return Boolean; + -- Return True if this assignment statement is the expansion of + -- a Some_Scalar_Type'Read procedure call such that all conditions + -- of 13.3.2(35)'s "no check is made" rule are met. + + ------------------------------------ + -- Omit_Range_Check_For_Streaming -- + ------------------------------------ + + function Omit_Range_Check_For_Streaming return Boolean is + begin + -- Have we got an implicitly generated assignment to a + -- component of a composite object? If not, return False. + + if Comes_From_Source (N) + or else Serious_Errors_Detected > 0 + or else Nkind (Lhs) + not in N_Selected_Component | N_Indexed_Component + then + return False; + end if; + + declare + Pref : constant Node_Id := Prefix (Lhs); + begin + -- Are we in the implicitly-defined Read subprogram + -- for a composite type, reading the value of a scalar + -- component from the stream? If not, return False. + + if Nkind (Pref) /= N_Identifier + or else not Is_TSS (Scope (Entity (Pref)), TSS_Stream_Read) + then + return False; + end if; + + -- Return False if Default_Value or Default_Component_Value + -- aspect applies. + + if Has_Default_Aspect (Etype (Lhs)) + or else Has_Default_Aspect (Etype (Pref)) + then + return False; + + -- Are we assigning to a record component (as opposed to + -- an array component)? + + elsif Nkind (Lhs) = N_Selected_Component then + + -- Are we assigning to a nondiscriminant component + -- that lacks a default initial value expression? + -- If so, return True. + + declare + Comp_Id : constant Entity_Id := + Original_Record_Component + (Entity (Selector_Name (Lhs))); + begin + if Ekind (Comp_Id) = E_Component + and then Nkind (Parent (Comp_Id)) + = N_Component_Declaration + and then + not Present (Expression (Parent (Comp_Id))) + then + return True; + end if; + return False; + end; + + -- We are assigning to a component of an array + -- (and we tested for both Default_Value and + -- Default_Component_Value above), so return True. + + else + pragma Assert (Nkind (Lhs) = N_Indexed_Component); + return True; + end if; + end; + end Omit_Range_Check_For_Streaming; + + begin + if not Omit_Range_Check_For_Streaming then + Apply_Scalar_Range_Check (Rhs, Etype (Lhs)); + end if; + end; -- For array types, verify that lengths match. If the right hand side -- is a function call that has been inlined, the assignment has been -- cgit v1.1 From 4206000ac40ef24704cf9bf936f8aac900cdbff5 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 12 May 2021 23:37:20 +0200 Subject: [Ada] Fix old typo in comment gcc/ada/ * repinfo-input.adb (JSON_Entity_Kind, Read_Variant_Part): Fix typo in comment. --- gcc/ada/repinfo-input.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/repinfo-input.adb b/gcc/ada/repinfo-input.adb index 106c43c..5d85040 100644 --- a/gcc/ada/repinfo-input.adb +++ b/gcc/ada/repinfo-input.adb @@ -38,7 +38,7 @@ package body Repinfo.Input is -- Value for Storage_Unit type JSON_Entity_Kind is (JE_Record_Type, JE_Array_Type, JE_Other); - -- Kind of an entiy + -- Kind of an entity type JSON_Entity_Node (Kind : JSON_Entity_Kind := JE_Other) is record Esize : Node_Ref_Or_Val; @@ -1219,7 +1219,7 @@ package body Repinfo.Input is Var : JSON_Variant_Node; begin - -- Read a non-empty array of components + -- Read a nonempty array of components Read_Token_And_Error (J_ARRAY, Token_Start, Token_End); -- cgit v1.1 From 09768159b3f4b5343848d12d6cd5e95b574d8cca Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Tue, 11 May 2021 11:45:06 -0700 Subject: [Ada] Enable Ada 2020 Put_Image and Image support for tagged types gcc/ada/ * exp_put_image.adb: Eliminate references to Debug_Flag_Underscore_Z. Change the meaning of the function Enable_Put_Image. Previously, a result of False for a tagged type would mean that the type does not get a Put_Image (PI) routine at all. Now, it means that the type gets a PI routine with very abbreviated functionality (just a call to Unknown_Put_Image). This resolves problems in mixing code compiled with and without the -gnat2022 switch. * exp_ch3.adb: Enable_Put_Image no longer participates in determining whether a tagged type gets a Put_Image procedure. A tagged type does not get a Put_Image procedure if the type Root_Buffer_Type is unavailable. This is needed to support cross targets where tagged types are supported but the type Root_Buffer_Type is not available. * exp_dist.adb: Add workarounds for some problems that arise when using the (obsolete?) Garlic implementation of the distributed systems annex with Ada 2022 constructs. * libgnat/a-sttebu.ads: Workaround a bootstrapping problem. Older compilers do not support raise expressions, so revise the the Pre'Class condition to meet this requirement without changing the condition's behavior at run time. --- gcc/ada/exp_ch3.adb | 14 +++++++-- gcc/ada/exp_dist.adb | 25 ++++++++++++++-- gcc/ada/exp_put_image.adb | 69 ++++++++++++++++++++++++-------------------- gcc/ada/libgnat/a-sttebu.ads | 3 +- 4 files changed, 74 insertions(+), 37 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 504410d..ad6c7a7 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -10334,7 +10334,14 @@ package body Exp_Ch3 is -- Spec of Put_Image - if Enable_Put_Image (Tag_Typ) then + if (not No_Run_Time_Mode) + and then RTE_Available (RE_Root_Buffer_Type) + then + -- No_Run_Time_Mode implies that the declaration of Tag_Typ + -- (like any tagged type) will be rejected. Given this, avoid + -- cascading errors associated with the Tag_Typ's TSS_Put_Image + -- procedure. + Append_To (Res, Predef_Spec_Or_Body (Loc, Tag_Typ => Tag_Typ, Name => Make_TSS_Name (Tag_Typ, TSS_Put_Image), @@ -10936,8 +10943,9 @@ package body Exp_Ch3 is -- Body of Put_Image - if Enable_Put_Image (Tag_Typ) - and then No (TSS (Tag_Typ, TSS_Put_Image)) + if No (TSS (Tag_Typ, TSS_Put_Image)) + and then (not No_Run_Time_Mode) + and then RTE_Available (RE_Root_Buffer_Type) then Build_Record_Put_Image_Procedure (Loc, Tag_Typ, Decl, Ent); Append_To (Res, Decl); diff --git a/gcc/ada/exp_dist.adb b/gcc/ada/exp_dist.adb index 9805457..35ccf9d 100644 --- a/gcc/ada/exp_dist.adb +++ b/gcc/ada/exp_dist.adb @@ -4211,6 +4211,14 @@ package body Exp_Dist is -- Used only for the PolyORB case begin + -- workaround for later failures in Exp_Util.Find_Prim_Op + if Is_TSS (Defining_Unit_Name (Spec), TSS_Put_Image) then + Append_To (Statements, + Make_Raise_Program_Error (Loc, + Reason => PE_Stream_Operation_Not_Allowed)); + return; + end if; + -- The general form of a calling stub for a given subprogram is: -- procedure X (...) is P : constant Partition_ID := @@ -4726,11 +4734,11 @@ package body Exp_Dist is -- Formal parameter for receiving stubs: a descriptor for an incoming -- request. - Decls : constant List_Id := New_List; + Decls : List_Id := New_List; -- All the parameters will get declared before calling the real -- subprograms. Also the out parameters will be declared. - Statements : constant List_Id := New_List; + Statements : List_Id := New_List; Extra_Formal_Statements : constant List_Id := New_List; -- Statements concerning extra formal parameters @@ -5165,6 +5173,19 @@ package body Exp_Dist is Parameter_Type => New_Occurrence_Of (RTE (RE_Request_Access), Loc)))); + -- workaround for later failures in Exp_Util.Find_Prim_Op + if Is_TSS (Defining_Unit_Name (Specification (Vis_Decl)), + TSS_Put_Image) + then + -- drop everything on the floor + Decls := New_List; + Statements := New_List; + Excep_Handlers := New_List; + Append_To (Statements, + Make_Raise_Program_Error (Loc, + Reason => PE_Stream_Operation_Not_Allowed)); + end if; + return Make_Subprogram_Body (Loc, Specification => Subp_Spec, diff --git a/gcc/ada/exp_put_image.adb b/gcc/ada/exp_put_image.adb index 0cf38ac..082e08b 100644 --- a/gcc/ada/exp_put_image.adb +++ b/gcc/ada/exp_put_image.adb @@ -26,7 +26,6 @@ with Aspects; use Aspects; with Atree; use Atree; with Csets; use Csets; -with Debug; use Debug; with Einfo; use Einfo; with Einfo.Entities; use Einfo.Entities; with Einfo.Utils; use Einfo.Utils; @@ -45,15 +44,13 @@ with Sinfo.Nodes; use Sinfo.Nodes; with Sinfo.Utils; use Sinfo.Utils; with Snames; use Snames; with Stand; +with Stringt; use Stringt; with Tbuild; use Tbuild; with Ttypes; use Ttypes; with Uintp; use Uintp; package body Exp_Put_Image is - Tagged_Put_Image_Enabled : Boolean renames Debug_Flag_Underscore_Z; - -- Temporary until we resolve mixing Ada 2012 and 2022 code - ----------------------- -- Local Subprograms -- ----------------------- @@ -531,6 +528,7 @@ package body Exp_Put_Image is Pnam : out Entity_Id) is Btyp : constant Entity_Id := Base_Type (Typ); + pragma Assert (not Is_Class_Wide_Type (Btyp)); pragma Assert (not Is_Unchecked_Union (Btyp)); First_Time : Boolean := True; @@ -789,7 +787,31 @@ package body Exp_Put_Image is -- Start of processing for Build_Record_Put_Image_Procedure begin - if Is_Null_Record_Type (Btyp, Ignore_Privacy => True) then + if (Ada_Version < Ada_2022) + or else not Enable_Put_Image (Btyp) + then + -- generate a very simple Put_Image implementation + + if Is_RTE (Typ, RE_Root_Buffer_Type) then + -- Avoid introducing a cyclic dependency between + -- Ada.Strings.Text_Buffers and System.Put_Images. + + Append_To (Stms, + Make_Raise_Program_Error (Loc, + Reason => PE_Explicit_Raise)); + else + Append_To (Stms, + Make_Procedure_Call_Statement (Loc, + Name => New_Occurrence_Of (RTE (RE_Put_Image_Unknown), Loc), + Parameter_Associations => New_List + (Make_Identifier (Loc, Name_S), + Make_String_Literal (Loc, + To_String (Fully_Qualified_Name_String (Btyp)))))); + end if; + elsif Is_Null_Record_Type (Btyp, Ignore_Privacy => True) then + + -- Interface types take this path. + Append_To (Stms, Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (RTE (RE_Put_UTF_8), Loc), @@ -908,42 +930,29 @@ package body Exp_Put_Image is function Enable_Put_Image (Typ : Entity_Id) return Boolean is begin + -- If this function returns False for a non-scalar type Typ, then + -- a) calls to Typ'Image will result in calls to + -- System.Put_Images.Put_Image_Unknown to generate the image. + -- b) If Typ is a tagged type, then similarly the implementation + -- of Typ's Put_Image procedure will call Put_Image_Unknown + -- and will ignore its formal parameter of type Typ. + -- Note that Typ will still have a Put_Image procedure + -- in this case, albeit one with a simplified implementation. + -- -- The name "Sink" here is a short nickname for -- "Ada.Strings.Text_Buffers.Root_Buffer_Type". - - -- There's a bit of a chicken&egg problem. The compiler is likely to - -- have trouble if we refer to the Put_Image of Sink itself, because - -- Sink is part of the parameter profile: - -- - -- function Sink'Put_Image (S : in out Sink'Class; V : T); - -- - -- Likewise, the Ada.Strings.Buffer package, where Sink is - -- declared, depends on various other packages, so if we refer to - -- Put_Image of types declared in those other packages, we could create - -- cyclic dependencies. Therefore, we disable Put_Image for some - -- types. It's not clear exactly what types should be disabled. Scalar - -- types are OK, even if predefined, because calls to Put_Image of - -- scalar types are expanded inline. We certainly want to be able to use - -- Integer'Put_Image, for example. - - -- ???Temporarily disable to work around bugs: -- -- Put_Image does not work for Remote_Types. We check the containing -- package, rather than the type itself, because we want to include -- types in the private part of a Remote_Types package. - -- - -- Put_Image on tagged types triggers some bugs. - if Ada_Version < Ada_2022 - or else Is_Remote_Types (Scope (Typ)) + if Is_Remote_Types (Scope (Typ)) + or else Is_Remote_Call_Interface (Typ) or else (Is_Tagged_Type (Typ) and then In_Predefined_Unit (Typ)) - or else (Is_Tagged_Type (Typ) and then not Tagged_Put_Image_Enabled) then return False; end if; - -- End of workarounds. - -- No sense in generating code for Put_Image if there are errors. This -- avoids certain cascade errors. @@ -1192,8 +1201,6 @@ package body Exp_Put_Image is -- Don't do it if type Root_Buffer_Type is unavailable in the runtime. if not In_Predefined_Unit (Compilation_Unit) - and then Ada_Version >= Ada_2022 - and then Tagged_Put_Image_Enabled and then Tagged_Seen and then not No_Run_Time_Mode and then RTE_Available (RE_Root_Buffer_Type) diff --git a/gcc/ada/libgnat/a-sttebu.ads b/gcc/ada/libgnat/a-sttebu.ads index 4f6fafc..39144a6 100644 --- a/gcc/ada/libgnat/a-sttebu.ads +++ b/gcc/ada/libgnat/a-sttebu.ads @@ -59,7 +59,8 @@ is (Buffer : in out Root_Buffer_Type; Amount : Text_Buffer_Count := Standard_Indent) with Pre'Class => Current_Indent (Buffer) >= Amount - or else raise Constraint_Error, + -- or else raise Constraint_Error, + or else Boolean'Val (Current_Indent (Buffer) - Amount), Post'Class => Current_Indent (Buffer) = Current_Indent (Buffer)'Old - Amount; -- cgit v1.1 From 5db3ea9d748f00e55ddcb72d0720526824eeb4a9 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Mon, 17 May 2021 06:28:18 -0400 Subject: [Ada] Initialize Current_Error_Node gcc/ada/ * atree.ads (Current_Error_Node): Initialize to Empty. --- gcc/ada/atree.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/atree.ads b/gcc/ada/atree.ads index 0995b94..42df950 100644 --- a/gcc/ada/atree.ads +++ b/gcc/ada/atree.ads @@ -130,7 +130,7 @@ package Atree is -- Current_Error_Node is also used for other purposes. See, for example, -- Rtsfind. - Current_Error_Node : Node_Id; + Current_Error_Node : Node_Id := Empty; -- Node to place compiler abort messages ------------------ -- cgit v1.1 From 73c49ff53235d92aba4ee748fcb06b06e83e0b8f Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Tue, 6 Jul 2021 10:55:53 -0400 Subject: Use H8 nop moves as tst insns gcc * config/h8300/jumpcall.md (*branch): When possible, generate the comparison in CCZN mode. * config/h8300/predicates.md (simple_memory_operand): Reject all auto-increment addressing modes. --- gcc/config/h8300/jumpcall.md | 27 +++++++++++++++++++++++---- gcc/config/h8300/predicates.md | 2 ++ 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/config/h8300/jumpcall.md b/gcc/config/h8300/jumpcall.md index 7b6a66a..e1f0418 100644 --- a/gcc/config/h8300/jumpcall.md +++ b/gcc/config/h8300/jumpcall.md @@ -23,13 +23,32 @@ "" "#" "&& reload_completed" - [(set (reg:H8cc CC_REG) - (compare:H8cc (match_dup 1) (match_dup 2))) + [(set (match_dup 4) + (match_dup 5)) (set (pc) (if_then_else (match_op_dup 0 - [(reg:H8cc CC_REG) (const_int 0)]) + [(match_dup 4) (const_int 0)]) (label_ref (match_dup 3)) (pc)))] - "") + " +{ + machine_mode mode; + + if (REG_P (operands[1]) + && operands[2] == const0_rtx + && (GET_CODE (operands[0]) == EQ + || GET_CODE (operands[0]) == NE + || GET_CODE (operands[0]) == LT + || GET_CODE (operands[0]) == GE + /* Our tstxx insns will set ZN and clear V, so we can handle + a couple additional cases. */ + || GET_CODE (operands[0]) == LE + || GET_CODE (operands[0]) == GT)) + mode = E_CCZNmode; + else + mode = E_CCmode; + operands[4] = gen_rtx_REG (mode, CC_REG); + operands[5] = gen_rtx_COMPARE (mode, operands[1], operands[2]); +}") (define_insn "*branch_1" [(set (pc) diff --git a/gcc/config/h8300/predicates.md b/gcc/config/h8300/predicates.md index f4e3ed4..bed23e9 100644 --- a/gcc/config/h8300/predicates.md +++ b/gcc/config/h8300/predicates.md @@ -506,6 +506,8 @@ { if (GET_MODE (op) == mode && (GET_CODE (XEXP (op, 0)) != PRE_DEC + && GET_CODE (XEXP (op, 0)) != PRE_INC + && GET_CODE (XEXP (op, 0)) != POST_DEC && GET_CODE (XEXP (op, 0)) != POST_INC)) return 1; return 0; -- cgit v1.1 From f65878178ab05180a5937f11f8fdb755678a82ce Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Tue, 6 Jul 2021 19:27:34 +0200 Subject: i386: Add variable vec_set for 32bit vectors [PR97194] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To generate sane code a SSE4.1 variable PBLENDV instruction is needed. Also enable variable vec_set through vec_setm_operand predicate for TARGET_SSE4_1 instead of TARGET_AVX2. ix86_expand_vector_init_duplicate is able to emulate vpbroadcast{b,w} with pxor/pshufb. 2021-07-06 Uroš Bizjak gcc/ PR target/97194 * config/i386/predicates.md (vec_setm_operand): Enable register_operand for TARGET_SSE4_1. * config/i386/mmx.md (vec_setv2hi): Use vec_setm_operand as operand 2 predicate. Call ix86_expand_vector_set_var for non-constant index operand. (vec_setv4qi): Use vec_setm_mmx_operand as operand 2 predicate. Call ix86_expand_vector_set_var for non-constant index operand. gcc/testsuite/ PR target/97194 * gcc.target/i386/sse4_1-vec-set-1a.c: New test. * gcc.target/i386/sse4_1-vec-set-2a.c: Ditto. --- gcc/config/i386/mmx.md | 18 ++++++---- gcc/config/i386/predicates.md | 2 +- gcc/testsuite/gcc.target/i386/sse4_1-vec-set-1a.c | 20 +++++++++++ gcc/testsuite/gcc.target/i386/sse4_1-vec-set-2a.c | 44 +++++++++++++++++++++++ 4 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/sse4_1-vec-set-1a.c create mode 100644 gcc/testsuite/gcc.target/i386/sse4_1-vec-set-2a.c (limited to 'gcc') diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index 4ead8be..7e83b64 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -3534,11 +3534,14 @@ (define_expand "vec_setv2hi" [(match_operand:V2HI 0 "register_operand") (match_operand:HI 1 "register_operand") - (match_operand 2 "const_int_operand")] + (match_operand 2 "vec_setm_operand")] "TARGET_SSE2" { - ix86_expand_vector_set (false, operands[0], operands[1], - INTVAL (operands[2])); + if (CONST_INT_P (operands[2])) + ix86_expand_vector_set (false, operands[0], operands[1], + INTVAL (operands[2])); + else + ix86_expand_vector_set_var (operands[0], operands[1], operands[2]); DONE; }) @@ -3556,11 +3559,14 @@ (define_expand "vec_setv4qi" [(match_operand:V4QI 0 "register_operand") (match_operand:QI 1 "register_operand") - (match_operand 2 "const_int_operand")] + (match_operand 2 "vec_setm_mmx_operand")] "TARGET_SSE4_1" { - ix86_expand_vector_set (false, operands[0], operands[1], - INTVAL (operands[2])); + if (CONST_INT_P (operands[2])) + ix86_expand_vector_set (false, operands[0], operands[1], + INTVAL (operands[2])); + else + ix86_expand_vector_set_var (operands[0], operands[1], operands[2]); DONE; }) diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index c4b35c8..9488632 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1023,7 +1023,7 @@ ;; True for registers, or const_int_operand, used to vec_setm expander. (define_predicate "vec_setm_operand" (ior (and (match_operand 0 "register_operand") - (match_test "TARGET_AVX2")) + (match_test "TARGET_SSE4_1")) (match_code "const_int"))) (define_predicate "vec_setm_mmx_operand" diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-vec-set-1a.c b/gcc/testsuite/gcc.target/i386/sse4_1-vec-set-1a.c new file mode 100644 index 0000000..e2a67a6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse4_1-vec-set-1a.c @@ -0,0 +1,20 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-msse4.1 -O2" } */ +/* { dg-final { scan-assembler-times {(?n)v?pcmpeq[bwd]} 2 } } */ +/* { dg-final { scan-assembler-times {(?n)v?p?blendv} 2 } } */ + +typedef char v4qi __attribute__ ((vector_size (4))); +typedef short v2hi __attribute__ ((vector_size (4))); + +#define FOO(VTYPE, TYPE) \ + VTYPE \ + __attribute__ ((noipa)) \ + foo_##VTYPE (VTYPE a, TYPE b, unsigned int c) \ + { \ + a[c] = b; \ + return a; \ + } \ + +FOO (v4qi, char); + +FOO (v2hi, short); diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-vec-set-2a.c b/gcc/testsuite/gcc.target/i386/sse4_1-vec-set-2a.c new file mode 100644 index 0000000..5a945be --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse4_1-vec-set-2a.c @@ -0,0 +1,44 @@ +/* { dg-do run { target { ! ia32 } } } */ +/* { dg-require-effective-target sse4 } */ +/* { dg-options "-O2 -msse4.1" } */ + + +#ifndef CHECK +#define CHECK "sse4_1-check.h" +#endif + +#ifndef TEST +#define TEST sse4_1_test +#endif + +#include CHECK + +#include "sse4_1-vec-set-1a.c" + +#define CALC_TEST(vtype, type, N, idx) \ +do \ + { \ + int i,val = idx * idx - idx * 3 + 16; \ + type res[N],exp[N]; \ + vtype resv; \ + for (i = 0; i < N; i++) \ + { \ + res[i] = i * i - i * 3 + 15; \ + exp[i] = res[i]; \ + } \ + exp[idx] = val; \ + resv = foo_##vtype (*(vtype *)&res[0], val, idx); \ + for (i = 0; i < N; i++) \ + { \ + if (resv[i] != exp[i]) \ + abort (); \ + } \ + } \ +while (0) + +static void +TEST (void) +{ + CALC_TEST (v4qi, char, 4, 2); + CALC_TEST (v2hi, short, 2, 1); +} -- cgit v1.1 From 6d3bab5d5adb3e28ddb16c97b0831efdea23cf7d Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 6 Jul 2021 13:41:02 -0600 Subject: Improve warning suppression for inlined functions. Resolves: PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute gcc/ChangeLog: * builtins.c (warn_string_no_nul): Remove %G. (maybe_warn_for_bound): Same. (warn_for_access): Same. (check_access): Same. (check_strncat_sizes): Same. (expand_builtin_strncat): Same. (expand_builtin_strncmp): Same. (expand_builtin): Same. (expand_builtin_object_size): Same. (warn_dealloc_offset): Same. (maybe_emit_free_warning): Same. * calls.c (maybe_warn_alloc_args_overflow): Same. (maybe_warn_nonstring_arg): Same. (maybe_warn_rdwr_sizes): Same. * expr.c (expand_expr_real_1): Remove %K. * gimple-fold.c (gimple_fold_builtin_strncpy): Remove %G. (gimple_fold_builtin_strncat): Same. * gimple-ssa-sprintf.c (format_directive): Same. (handle_printf_call): Same. * gimple-ssa-warn-alloca.c (pass_walloca::execute): Same. * gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same. (maybe_diag_access_bounds): Same. Call gimple_location. (check_bounds_or_overlap): Same. * trans-mem.c (ipa_tm_scan_irr_block): Remove %K. Simplify. * tree-ssa-ccp.c (pass_post_ipa_warn::execute): Remove %G. * tree-ssa-strlen.c (maybe_warn_overflow): Same. (maybe_diag_stxncpy_trunc): Same. (handle_builtin_stxncpy_strncat): Same. (maybe_warn_pointless_strcmp): Same. * tree-ssa-uninit.c (maybe_warn_operand): Same. gcc/testsuite/ChangeLog: * gcc.dg/Wobjsize-1.c: Prune expected output. * gcc.dg/Warray-bounds-71.c: New test. * gcc.dg/Warray-bounds-71.h: New test header. * gcc.dg/Warray-bounds-72.c: New test. * gcc.dg/Warray-bounds-73.c: New test. * gcc.dg/Warray-bounds-74.c: New test. * gcc.dg/Warray-bounds-75.c: New test. * gcc.dg/Wfree-nonheap-object-4.c: Adjust expected output. * gcc.dg/Wfree-nonheap-object-5.c: New test. * gcc.dg/Wfree-nonheap-object-6.c: New test. * gcc.dg/pragma-diag-10.c: New test. * gcc.dg/pragma-diag-9.c: New test. * gcc.dg/uninit-suppress_3.c: New test. * gcc.dg/pr79214.c: Xfail tests. * gcc.dg/tree-ssa/builtin-sprintf-warn-27.c: New test. * gcc.dg/format/c90-printf-1.c: Adjust expected output. --- gcc/builtins.c | 342 ++++++++++----------- gcc/calls.c | 58 ++-- gcc/expr.c | 10 +- gcc/gimple-fold.c | 18 +- gcc/gimple-ssa-sprintf.c | 11 +- gcc/gimple-ssa-warn-alloca.c | 26 +- gcc/gimple-ssa-warn-restrict.c | 152 ++++----- gcc/testsuite/gcc.dg/Warray-bounds-71.c | 7 + gcc/testsuite/gcc.dg/Warray-bounds-71.h | 46 +++ gcc/testsuite/gcc.dg/Warray-bounds-72.c | 7 + gcc/testsuite/gcc.dg/Warray-bounds-73.c | 7 + gcc/testsuite/gcc.dg/Warray-bounds-74.c | 7 + gcc/testsuite/gcc.dg/Warray-bounds-75.c | 12 + gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c | 24 +- gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c | 46 +++ gcc/testsuite/gcc.dg/Wfree-nonheap-object-6.c | 49 +++ gcc/testsuite/gcc.dg/Wobjsize-1.c | 12 +- gcc/testsuite/gcc.dg/format/c90-printf-1.c | 2 +- gcc/testsuite/gcc.dg/pr79214.c | 22 +- gcc/testsuite/gcc.dg/pragma-diag-10.c | 20 ++ gcc/testsuite/gcc.dg/pragma-diag-9.c | 141 +++++++++ .../gcc.dg/tree-ssa/builtin-sprintf-warn-27.c | 20 ++ gcc/testsuite/gcc.dg/uninit-suppress_3.c | 98 ++++++ gcc/trans-mem.c | 8 +- gcc/tree-ssa-ccp.c | 6 +- gcc/tree-ssa-strlen.c | 105 ++++--- gcc/tree-ssa-uninit.c | 4 +- 27 files changed, 852 insertions(+), 408 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-71.c create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-71.h create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-72.c create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-73.c create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-74.c create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-75.c create mode 100644 gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c create mode 100644 gcc/testsuite/gcc.dg/Wfree-nonheap-object-6.c create mode 100644 gcc/testsuite/gcc.dg/pragma-diag-10.c create mode 100644 gcc/testsuite/gcc.dg/pragma-diag-9.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-27.c create mode 100644 gcc/testsuite/gcc.dg/uninit-suppress_3.c (limited to 'gcc') diff --git a/gcc/builtins.c b/gcc/builtins.c index e5e3938..e52fe42 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1126,30 +1126,30 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname, { if (wi::ltu_p (maxsiz, bndrng[0])) warned = warning_at (loc, opt, - "%K%qD specified bound %s exceeds " + "%qD specified bound %s exceeds " "maximum object size %E", - expr, func, bndstr, maxobjsize); + func, bndstr, maxobjsize); else { bool maybe = wi::to_wide (size) == bndrng[0]; warned = warning_at (loc, opt, exact - ? G_("%K%qD specified bound %s exceeds " + ? G_("%qD specified bound %s exceeds " "the size %E of unterminated array") : (maybe - ? G_("%K%qD specified bound %s may " + ? G_("%qD specified bound %s may " "exceed the size of at most %E " "of unterminated array") - : G_("%K%qD specified bound %s exceeds " + : G_("%qD specified bound %s exceeds " "the size of at most %E " "of unterminated array")), - expr, func, bndstr, size); + func, bndstr, size); } } else warned = warning_at (loc, opt, - "%K%qD argument missing terminating nul", - expr, func); + "%qD argument missing terminating nul", + func); } else { @@ -3969,35 +3969,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func, warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD specified bound %E may " + ? G_("%qD specified bound %E may " "exceed maximum object size %E") - : G_("%K%qD specified bound %E " + : G_("%qD specified bound %E " "exceeds maximum object size %E")), - exp, func, bndrng[0], maxobjsize) + func, bndrng[0], maxobjsize) : warning_at (loc, opt, (maybe - ? G_("%Kspecified bound %E may " + ? G_("specified bound %E may " "exceed maximum object size %E") - : G_("%Kspecified bound %E " + : G_("specified bound %E " "exceeds maximum object size %E")), - exp, bndrng[0], maxobjsize)); + bndrng[0], maxobjsize)); else warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD specified bound [%E, %E] may " + ? G_("%qD specified bound [%E, %E] may " "exceed maximum object size %E") - : G_("%K%qD specified bound [%E, %E] " + : G_("%qD specified bound [%E, %E] " "exceeds maximum object size %E")), - exp, func, - bndrng[0], bndrng[1], maxobjsize) + func, bndrng[0], bndrng[1], maxobjsize) : warning_at (loc, opt, (maybe - ? G_("%Kspecified bound [%E, %E] may " + ? G_("specified bound [%E, %E] may " "exceed maximum object size %E") - : G_("%Kspecified bound [%E, %E] " + : G_("specified bound [%E, %E] " "exceeds maximum object size %E")), - exp, bndrng[0], bndrng[1], maxobjsize)); + bndrng[0], bndrng[1], maxobjsize)); } else if (!size || tree_int_cst_le (bndrng[0], size)) return false; @@ -4005,34 +4004,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func, warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD specified bound %E may exceed " + ? G_("%qD specified bound %E may exceed " "source size %E") - : G_("%K%qD specified bound %E exceeds " + : G_("%qD specified bound %E exceeds " "source size %E")), - exp, func, bndrng[0], size) + func, bndrng[0], size) : warning_at (loc, opt, (maybe - ? G_("%Kspecified bound %E may exceed " + ? G_("specified bound %E may exceed " "source size %E") - : G_("%Kspecified bound %E exceeds " + : G_("specified bound %E exceeds " "source size %E")), - exp, bndrng[0], size)); + bndrng[0], size)); else warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD specified bound [%E, %E] may " + ? G_("%qD specified bound [%E, %E] may " "exceed source size %E") - : G_("%K%qD specified bound [%E, %E] exceeds " + : G_("%qD specified bound [%E, %E] exceeds " "source size %E")), - exp, func, bndrng[0], bndrng[1], size) + func, bndrng[0], bndrng[1], size) : warning_at (loc, opt, (maybe - ? G_("%Kspecified bound [%E, %E] may exceed " + ? G_("specified bound [%E, %E] may exceed " "source size %E") - : G_("%Kspecified bound [%E, %E] exceeds " + : G_("specified bound [%E, %E] exceeds " "source size %E")), - exp, bndrng[0], bndrng[1], size)); + bndrng[0], bndrng[1], size)); if (warned) { if (pad && pad->src.ref) @@ -4057,35 +4056,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func, warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD specified size %E may " + ? G_("%qD specified size %E may " "exceed maximum object size %E") - : G_("%K%qD specified size %E " + : G_("%qD specified size %E " "exceeds maximum object size %E")), - exp, func, bndrng[0], maxobjsize) + func, bndrng[0], maxobjsize) : warning_at (loc, opt, (maybe - ? G_("%Kspecified size %E may exceed " + ? G_("specified size %E may exceed " "maximum object size %E") - : G_("%Kspecified size %E exceeds " + : G_("specified size %E exceeds " "maximum object size %E")), - exp, bndrng[0], maxobjsize)); + bndrng[0], maxobjsize)); else warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD specified size between %E and %E " + ? G_("%qD specified size between %E and %E " "may exceed maximum object size %E") - : G_("%K%qD specified size between %E and %E " + : G_("%qD specified size between %E and %E " "exceeds maximum object size %E")), - exp, func, - bndrng[0], bndrng[1], maxobjsize) + func, bndrng[0], bndrng[1], maxobjsize) : warning_at (loc, opt, (maybe - ? G_("%Kspecified size between %E and %E " + ? G_("specified size between %E and %E " "may exceed maximum object size %E") - : G_("%Kspecified size between %E and %E " + : G_("specified size between %E and %E " "exceeds maximum object size %E")), - exp, bndrng[0], bndrng[1], maxobjsize)); + bndrng[0], bndrng[1], maxobjsize)); } else if (!size || tree_int_cst_le (bndrng[0], size)) return false; @@ -4093,34 +4091,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func, warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD specified bound %E may exceed " + ? G_("%qD specified bound %E may exceed " "destination size %E") - : G_("%K%qD specified bound %E exceeds " + : G_("%qD specified bound %E exceeds " "destination size %E")), - exp, func, bndrng[0], size) + func, bndrng[0], size) : warning_at (loc, opt, (maybe - ? G_("%Kspecified bound %E may exceed " + ? G_("specified bound %E may exceed " "destination size %E") - : G_("%Kspecified bound %E exceeds " + : G_("specified bound %E exceeds " "destination size %E")), - exp, bndrng[0], size)); + bndrng[0], size)); else warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD specified bound [%E, %E] may exceed " + ? G_("%qD specified bound [%E, %E] may exceed " "destination size %E") - : G_("%K%qD specified bound [%E, %E] exceeds " + : G_("%qD specified bound [%E, %E] exceeds " "destination size %E")), - exp, func, bndrng[0], bndrng[1], size) + func, bndrng[0], bndrng[1], size) : warning_at (loc, opt, (maybe - ? G_("%Kspecified bound [%E, %E] exceeds " + ? G_("specified bound [%E, %E] exceeds " "destination size %E") - : G_("%Kspecified bound [%E, %E] exceeds " + : G_("specified bound [%E, %E] exceeds " "destination size %E")), - exp, bndrng[0], bndrng[1], size)); + bndrng[0], bndrng[1], size)); if (warned) { @@ -4158,65 +4156,63 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2], warned = (func ? warning_n (loc, opt, tree_to_uhwi (range[0]), (maybe - ? G_("%K%qD may access %E byte in a region " + ? G_("%qD may access %E byte in a region " "of size %E") - : G_("%K%qD accessing %E byte in a region " + : G_("%qD accessing %E byte in a region " "of size %E")), (maybe - ? G_ ("%K%qD may access %E bytes in a region " + ? G_ ("%qD may access %E bytes in a region " "of size %E") - : G_ ("%K%qD accessing %E bytes in a region " + : G_ ("%qD accessing %E bytes in a region " "of size %E")), - exp, func, range[0], size) + func, range[0], size) : warning_n (loc, opt, tree_to_uhwi (range[0]), (maybe - ? G_("%Kmay access %E byte in a region " + ? G_("may access %E byte in a region " "of size %E") - : G_("%Kaccessing %E byte in a region " + : G_("accessing %E byte in a region " "of size %E")), (maybe - ? G_("%Kmay access %E bytes in a region " + ? G_("may access %E bytes in a region " "of size %E") - : G_("%Kaccessing %E bytes in a region " + : G_("accessing %E bytes in a region " "of size %E")), - exp, range[0], size)); + range[0], size)); else if (tree_int_cst_sign_bit (range[1])) { /* Avoid printing the upper bound if it's invalid. */ warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD may access %E or more bytes " + ? G_("%qD may access %E or more bytes " "in a region of size %E") - : G_("%K%qD accessing %E or more bytes " + : G_("%qD accessing %E or more bytes " "in a region of size %E")), - exp, func, range[0], size) + func, range[0], size) : warning_at (loc, opt, (maybe - ? G_("%Kmay access %E or more bytes " + ? G_("may access %E or more bytes " "in a region of size %E") - : G_("%Kaccessing %E or more bytes " + : G_("accessing %E or more bytes " "in a region of size %E")), - exp, range[0], size)); + range[0], size)); } else warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD may access between %E and %E " + ? G_("%qD may access between %E and %E " "bytes in a region of size %E") - : G_("%K%qD accessing between %E and %E " + : G_("%qD accessing between %E and %E " "bytes in a region of size %E")), - exp, func, range[0], range[1], - size) + func, range[0], range[1], size) : warning_at (loc, opt, (maybe - ? G_("%Kmay access between %E and %E bytes " + ? G_("may access between %E and %E bytes " "in a region of size %E") - : G_("%Kaccessing between %E and %E bytes " + : G_("accessing between %E and %E bytes " "in a region of size %E")), - exp, range[0], range[1], - size)); + range[0], range[1], size)); return warned; } @@ -4226,69 +4222,67 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2], warned = (func ? warning_n (loc, opt, tree_to_uhwi (range[0]), (maybe - ? G_("%K%qD may write %E byte into a region " + ? G_("%qD may write %E byte into a region " "of size %E") - : G_("%K%qD writing %E byte into a region " + : G_("%qD writing %E byte into a region " "of size %E overflows the destination")), (maybe - ? G_("%K%qD may write %E bytes into a region " + ? G_("%qD may write %E bytes into a region " "of size %E") - : G_("%K%qD writing %E bytes into a region " + : G_("%qD writing %E bytes into a region " "of size %E overflows the destination")), - exp, func, range[0], size) + func, range[0], size) : warning_n (loc, opt, tree_to_uhwi (range[0]), (maybe - ? G_("%Kmay write %E byte into a region " + ? G_("may write %E byte into a region " "of size %E") - : G_("%Kwriting %E byte into a region " + : G_("writing %E byte into a region " "of size %E overflows the destination")), (maybe - ? G_("%Kmay write %E bytes into a region " + ? G_("may write %E bytes into a region " "of size %E") - : G_("%Kwriting %E bytes into a region " + : G_("writing %E bytes into a region " "of size %E overflows the destination")), - exp, range[0], size)); + range[0], size)); else if (tree_int_cst_sign_bit (range[1])) { /* Avoid printing the upper bound if it's invalid. */ warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD may write %E or more bytes " + ? G_("%qD may write %E or more bytes " "into a region of size %E") - : G_("%K%qD writing %E or more bytes " + : G_("%qD writing %E or more bytes " "into a region of size %E overflows " "the destination")), - exp, func, range[0], size) + func, range[0], size) : warning_at (loc, opt, (maybe - ? G_("%Kmay write %E or more bytes into " + ? G_("may write %E or more bytes into " "a region of size %E") - : G_("%Kwriting %E or more bytes into " + : G_("writing %E or more bytes into " "a region of size %E overflows " "the destination")), - exp, range[0], size)); + range[0], size)); } else warned = (func ? warning_at (loc, opt, (maybe - ? G_("%K%qD may write between %E and %E bytes " + ? G_("%qD may write between %E and %E bytes " "into a region of size %E") - : G_("%K%qD writing between %E and %E bytes " + : G_("%qD writing between %E and %E bytes " "into a region of size %E overflows " "the destination")), - exp, func, range[0], range[1], - size) + func, range[0], range[1], size) : warning_at (loc, opt, (maybe - ? G_("%Kmay write between %E and %E bytes " + ? G_("may write between %E and %E bytes " "into a region of size %E") - : G_("%Kwriting between %E and %E bytes " + : G_("writing between %E and %E bytes " "into a region of size %E overflows " "the destination")), - exp, range[0], range[1], - size)); + range[0], range[1], size)); return warned; } @@ -4299,64 +4293,64 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2], ? warning_n (loc, OPT_Wstringop_overread, tree_to_uhwi (range[0]), (maybe - ? G_("%K%qD may read %E byte from a region " + ? G_("%qD may read %E byte from a region " "of size %E") - : G_("%K%qD reading %E byte from a region " + : G_("%qD reading %E byte from a region " "of size %E")), (maybe - ? G_("%K%qD may read %E bytes from a region " + ? G_("%qD may read %E bytes from a region " "of size %E") - : G_("%K%qD reading %E bytes from a region " + : G_("%qD reading %E bytes from a region " "of size %E")), - exp, func, range[0], size) + func, range[0], size) : warning_n (loc, OPT_Wstringop_overread, tree_to_uhwi (range[0]), (maybe - ? G_("%Kmay read %E byte from a region " + ? G_("may read %E byte from a region " "of size %E") - : G_("%Kreading %E byte from a region " + : G_("reading %E byte from a region " "of size %E")), (maybe - ? G_("%Kmay read %E bytes from a region " + ? G_("may read %E bytes from a region " "of size %E") - : G_("%Kreading %E bytes from a region " + : G_("reading %E bytes from a region " "of size %E")), - exp, range[0], size)); + range[0], size)); else if (tree_int_cst_sign_bit (range[1])) { /* Avoid printing the upper bound if it's invalid. */ warned = (func ? warning_at (loc, OPT_Wstringop_overread, (maybe - ? G_("%K%qD may read %E or more bytes " + ? G_("%qD may read %E or more bytes " "from a region of size %E") - : G_("%K%qD reading %E or more bytes " + : G_("%qD reading %E or more bytes " "from a region of size %E")), - exp, func, range[0], size) + func, range[0], size) : warning_at (loc, OPT_Wstringop_overread, (maybe - ? G_("%Kmay read %E or more bytes " + ? G_("may read %E or more bytes " "from a region of size %E") - : G_("%Kreading %E or more bytes " + : G_("reading %E or more bytes " "from a region of size %E")), - exp, range[0], size)); + range[0], size)); } else warned = (func ? warning_at (loc, OPT_Wstringop_overread, (maybe - ? G_("%K%qD may read between %E and %E bytes " + ? G_("%qD may read between %E and %E bytes " "from a region of size %E") - : G_("%K%qD reading between %E and %E bytes " + : G_("%qD reading between %E and %E bytes " "from a region of size %E")), - exp, func, range[0], range[1], size) + func, range[0], range[1], size) : warning_at (loc, opt, (maybe - ? G_("%Kmay read between %E and %E bytes " + ? G_("may read between %E and %E bytes " "from a region of size %E") - : G_("%Kreading between %E and %E bytes " + : G_("reading between %E and %E bytes " "from a region of size %E")), - exp, range[0], range[1], size)); + range[0], range[1], size)); if (warned) suppress_warning (exp, OPT_Wstringop_overread); @@ -4369,37 +4363,37 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2], warned = (func ? warning_n (loc, OPT_Wstringop_overread, tree_to_uhwi (range[0]), - "%K%qD expecting %E byte in a region of size %E", - "%K%qD expecting %E bytes in a region of size %E", - exp, func, range[0], size) + "%qD expecting %E byte in a region of size %E", + "%qD expecting %E bytes in a region of size %E", + func, range[0], size) : warning_n (loc, OPT_Wstringop_overread, tree_to_uhwi (range[0]), - "%Kexpecting %E byte in a region of size %E", - "%Kexpecting %E bytes in a region of size %E", - exp, range[0], size)); + "expecting %E byte in a region of size %E", + "expecting %E bytes in a region of size %E", + range[0], size)); else if (tree_int_cst_sign_bit (range[1])) { /* Avoid printing the upper bound if it's invalid. */ warned = (func ? warning_at (loc, OPT_Wstringop_overread, - "%K%qD expecting %E or more bytes in a region " + "%qD expecting %E or more bytes in a region " "of size %E", - exp, func, range[0], size) + func, range[0], size) : warning_at (loc, OPT_Wstringop_overread, - "%Kexpecting %E or more bytes in a region " + "expecting %E or more bytes in a region " "of size %E", - exp, range[0], size)); + range[0], size)); } else warned = (func ? warning_at (loc, OPT_Wstringop_overread, - "%K%qD expecting between %E and %E bytes in " + "%qD expecting between %E and %E bytes in " "a region of size %E", - exp, func, range[0], range[1], size) + func, range[0], range[1], size) : warning_at (loc, OPT_Wstringop_overread, - "%Kexpecting between %E and %E bytes in " + "expecting between %E and %E bytes in " "a region of size %E", - exp, range[0], range[1], size)); + range[0], range[1], size)); if (warned) suppress_warning (exp, OPT_Wstringop_overread); @@ -4759,7 +4753,7 @@ check_access (tree exp, tree dstwrite, && TREE_CODE (range[0]) == INTEGER_CST && tree_int_cst_lt (maxobjsize, range[0])) { - location_t loc = tree_inlined_location (exp); + location_t loc = EXPR_LOCATION (exp); maybe_warn_for_bound (OPT_Wstringop_overflow_, loc, exp, func, range, NULL_TREE, pad); return false; @@ -4787,7 +4781,7 @@ check_access (tree exp, tree dstwrite, && warning_suppressed_p (pad->dst.ref, opt))) return false; - location_t loc = tree_inlined_location (exp); + location_t loc = EXPR_LOCATION (exp); bool warned = false; if (dstwrite == slen && at_least_one) { @@ -4796,15 +4790,15 @@ check_access (tree exp, tree dstwrite, at least one byte past the end of the destination. */ warned = (func ? warning_at (loc, opt, - "%K%qD writing %E or more bytes into " + "%qD writing %E or more bytes into " "a region of size %E overflows " "the destination", - exp, func, range[0], dstsize) + func, range[0], dstsize) : warning_at (loc, opt, - "%Kwriting %E or more bytes into " + "writing %E or more bytes into " "a region of size %E overflows " "the destination", - exp, range[0], dstsize)); + range[0], dstsize)); } else { @@ -4840,7 +4834,7 @@ check_access (tree exp, tree dstwrite, PAD is nonnull and BNDRNG is valid. */ get_size_range (maxread, range, pad ? pad->src.bndrng : NULL); - location_t loc = tree_inlined_location (exp); + location_t loc = EXPR_LOCATION (exp); tree size = dstsize; if (pad && pad->mode == access_read_only) size = wide_int_to_tree (sizetype, pad->src.sizrng[1]); @@ -4901,7 +4895,7 @@ check_access (tree exp, tree dstwrite, && warning_suppressed_p (pad->src.ref, opt))) return false; - location_t loc = tree_inlined_location (exp); + location_t loc = EXPR_LOCATION (exp); const bool read = mode == access_read_only || mode == access_read_write; const bool maybe = pad && pad->dst.parmarray; @@ -6481,10 +6475,10 @@ check_strncat_sizes (tree exp, tree objsize) if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize) && tree_int_cst_equal (objsize, maxread)) { - location_t loc = tree_inlined_location (exp); + location_t loc = EXPR_LOCATION (exp); warning_at (loc, OPT_Wstringop_overflow_, - "%K%qD specified bound %E equals destination size", - exp, get_callee_fndecl (exp), maxread); + "%qD specified bound %E equals destination size", + get_callee_fndecl (exp), maxread); return false; } @@ -6554,10 +6548,10 @@ expand_builtin_strncat (tree exp, rtx) if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (destsize) && tree_int_cst_equal (destsize, maxread)) { - location_t loc = tree_inlined_location (exp); + location_t loc = EXPR_LOCATION (exp); warning_at (loc, OPT_Wstringop_overflow_, - "%K%qD specified bound %E equals destination size", - exp, get_callee_fndecl (exp), maxread); + "%qD specified bound %E equals destination size", + get_callee_fndecl (exp), maxread); return NULL_RTX; } @@ -7330,7 +7324,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, || !check_nul_terminated_array (exp, arg2, arg3)) return NULL_RTX; - location_t loc = tree_inlined_location (exp); + location_t loc = EXPR_LOCATION (exp); tree len1 = c_strlen (arg1, 1); tree len2 = c_strlen (arg2, 1); @@ -10006,13 +10000,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, case BUILT_IN_VA_ARG_PACK: /* All valid uses of __builtin_va_arg_pack () are removed during inlining. */ - error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp); + error ("invalid use of %<__builtin_va_arg_pack ()%>"); return const0_rtx; case BUILT_IN_VA_ARG_PACK_LEN: /* All valid uses of __builtin_va_arg_pack_len () are removed during inlining. */ - error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp); + error ("invalid use of %<__builtin_va_arg_pack_len ()%>"); return const0_rtx; /* Return the address of the first anonymous stack arg. */ @@ -12961,8 +12955,8 @@ expand_builtin_object_size (tree exp) if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) { - error ("%Kfirst argument of %qD must be a pointer, second integer constant", - exp, fndecl); + error ("first argument of %qD must be a pointer, second integer constant", + fndecl); expand_builtin_trap (); return const0_rtx; } @@ -12974,8 +12968,8 @@ expand_builtin_object_size (tree exp) || tree_int_cst_sgn (ost) < 0 || compare_tree_int (ost, 3) > 0) { - error ("%Klast argument of %qD is not integer constant between 0 and 3", - exp, fndecl); + error ("last argument of %qD is not integer constant between 0 and 3", + fndecl); expand_builtin_trap (); return const0_rtx; } @@ -13787,8 +13781,8 @@ warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref) } if (!warning_at (loc, OPT_Wfree_nonheap_object, - "%K%qD called on pointer %qE with nonzero offset%s", - exp, dealloc_decl, aref.ref, offstr)) + "%qD called on pointer %qE with nonzero offset%s", + dealloc_decl, aref.ref, offstr)) return false; if (DECL_P (aref.ref)) @@ -13843,15 +13837,15 @@ maybe_emit_free_warning (tree exp) return; tree dealloc_decl = get_callee_fndecl (exp); - location_t loc = tree_inlined_location (exp); + location_t loc = EXPR_LOCATION (exp); if (DECL_P (ref) || EXPR_P (ref)) { /* Diagnose freeing a declared object. */ if (aref.ref_declared () && warning_at (loc, OPT_Wfree_nonheap_object, - "%K%qD called on unallocated object %qD", - exp, dealloc_decl, ref)) + "%qD called on unallocated object %qD", + dealloc_decl, ref)) { loc = (DECL_P (ref) ? DECL_SOURCE_LOCATION (ref) @@ -13870,8 +13864,8 @@ maybe_emit_free_warning (tree exp) else if (CONSTANT_CLASS_P (ref)) { if (warning_at (loc, OPT_Wfree_nonheap_object, - "%K%qD called on a pointer to an unallocated " - "object %qE", exp, dealloc_decl, ref)) + "%qD called on a pointer to an unallocated " + "object %qE", dealloc_decl, ref)) { if (TREE_CODE (ptr) == SSA_NAME) { @@ -13909,18 +13903,18 @@ maybe_emit_free_warning (tree exp) ? OPT_Wmismatched_new_delete : OPT_Wmismatched_dealloc); warned = warning_at (loc, opt, - "%K%qD called on pointer returned " + "%qD called on pointer returned " "from a mismatched allocation " - "function", exp, dealloc_decl); + "function", dealloc_decl); } } else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA) || gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA_WITH_ALIGN)) warned = warning_at (loc, OPT_Wfree_nonheap_object, - "%K%qD called on pointer to " + "%qD called on pointer to " "an unallocated object", - exp, dealloc_decl); + dealloc_decl); else if (warn_dealloc_offset (loc, exp, aref)) return; diff --git a/gcc/calls.c b/gcc/calls.c index f8a4b79..d2413a2 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1435,8 +1435,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2]) if (tree_int_cst_lt (args[i], integer_zero_node)) { warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "%Kargument %i value %qE is negative", - exp, idx[i] + 1, args[i]); + "argument %i value %qE is negative", + idx[i] + 1, args[i]); } else if (integer_zerop (args[i])) { @@ -1452,8 +1452,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2]) : !lookup_attribute ("returns_nonnull", TYPE_ATTRIBUTES (fntype))) warned = warning_at (loc, OPT_Walloc_zero, - "%Kargument %i value is zero", - exp, idx[i] + 1); + "argument %i value is zero", + idx[i] + 1); } else if (tree_int_cst_lt (maxobjsize, args[i])) { @@ -1470,9 +1470,9 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2]) continue; warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "%Kargument %i value %qE exceeds " + "argument %i value %qE exceeds " "maximum object size %E", - exp, idx[i] + 1, args[i], maxobjsize); + idx[i] + 1, args[i], maxobjsize); } } else if (TREE_CODE (args[i]) == SSA_NAME @@ -1484,16 +1484,16 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2]) && tree_int_cst_le (argrange[i][1], integer_zero_node)) { warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "%Kargument %i range [%E, %E] is negative", - exp, idx[i] + 1, + "argument %i range [%E, %E] is negative", + idx[i] + 1, argrange[i][0], argrange[i][1]); } else if (tree_int_cst_lt (maxobjsize, argrange[i][0])) { warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "%Kargument %i range [%E, %E] exceeds " + "argument %i range [%E, %E] exceeds " "maximum object size %E", - exp, idx[i] + 1, + idx[i] + 1, argrange[i][0], argrange[i][1], maxobjsize); } @@ -1521,15 +1521,15 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2]) if (vflow) warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "%Kproduct %<%E * %E%> of arguments %i and %i " + "product %<%E * %E%> of arguments %i and %i " "exceeds %", - exp, argrange[0][0], argrange[1][0], + argrange[0][0], argrange[1][0], idx[0] + 1, idx[1] + 1); else if (wi::ltu_p (wi::to_wide (maxobjsize, szprec), prod)) warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "%Kproduct %<%E * %E%> of arguments %i and %i " + "product %<%E * %E%> of arguments %i and %i " "exceeds maximum object size %E", - exp, argrange[0][0], argrange[1][0], + argrange[0][0], argrange[1][0], idx[0] + 1, idx[1] + 1, maxobjsize); @@ -1729,14 +1729,14 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp) bool warned = false; if (tree_int_cst_equal (bndrng[0], bndrng[1])) warned = warning_at (loc, OPT_Wstringop_overread, - "%K%qD specified bound %E " + "%qD specified bound %E " "exceeds maximum object size %E", - exp, fndecl, bndrng[0], maxobjsize); + fndecl, bndrng[0], maxobjsize); else warned = warning_at (loc, OPT_Wstringop_overread, - "%K%qD specified bound [%E, %E] " + "%qD specified bound [%E, %E] " "exceeds maximum object size %E", - exp, fndecl, bndrng[0], bndrng[1], + fndecl, bndrng[0], bndrng[1], maxobjsize); if (warned) suppress_warning (exp, OPT_Wstringop_overread); @@ -2068,16 +2068,16 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp) = access.second.array_as_string (ptrtype); if (warning_at (loc, OPT_Wstringop_overflow_, - "%Kbound argument %i value %s is " + "bound argument %i value %s is " "negative for a variable length array " "argument %i of type %s", - exp, sizidx + 1, sizstr, + sizidx + 1, sizstr, ptridx + 1, argtypestr.c_str ())) arg_warned = OPT_Wstringop_overflow_; } else if (warning_at (loc, OPT_Wstringop_overflow_, - "%Kargument %i value %s is negative", - exp, sizidx + 1, sizstr)) + "argument %i value %s is negative", + sizidx + 1, sizstr)) arg_warned = OPT_Wstringop_overflow_; if (arg_warned != no_warning) @@ -2124,20 +2124,19 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp) = access.second.array_as_string (ptrtype); if (warning_at (loc, OPT_Wnonnull, - "%Kargument %i of variable length " + "argument %i of variable length " "array %s is null but " "the corresponding bound argument " "%i value is %s", - exp, sizidx + 1, argtypestr.c_str (), + sizidx + 1, argtypestr.c_str (), ptridx + 1, sizstr)) arg_warned = OPT_Wnonnull; } else if (warning_at (loc, OPT_Wnonnull, - "%Kargument %i is null but " + "argument %i is null but " "the corresponding size argument " "%i value is %s", - exp, ptridx + 1, sizidx + 1, - sizstr)) + ptridx + 1, sizidx + 1, sizstr)) arg_warned = OPT_Wnonnull; } else if (access_size && access.second.static_p) @@ -2145,10 +2144,9 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp) /* Warn about null pointers for [static N] array arguments but do not warn for ordinary (i.e., nonstatic) arrays. */ if (warning_at (loc, OPT_Wnonnull, - "%Kargument %i to %<%T[static %E]%> " + "argument %i to %<%T[static %E]%> " "is null where non-null expected", - exp, ptridx + 1, argtype, - access_size)) + ptridx + 1, argtype, access_size)) arg_warned = OPT_Wnonnull; } diff --git a/gcc/expr.c b/gcc/expr.c index bd85bbf..6a43681 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -11402,7 +11402,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, /* All valid uses of __builtin_va_arg_pack () are removed during inlining. */ if (CALL_EXPR_VA_ARG_PACK (exp)) - error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp); + error ("invalid use of %<__builtin_va_arg_pack ()%>"); { tree fndecl = get_callee_fndecl (exp), attr; @@ -11414,7 +11414,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, DECL_ATTRIBUTES (fndecl))) != NULL) { const char *ident = lang_hooks.decl_printable_name (fndecl, 1); - error ("%Kcall to %qs declared with attribute error: %s", exp, + error ("call to %qs declared with attribute error: %s", identifier_to_locale (ident), TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); } @@ -11426,10 +11426,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, DECL_ATTRIBUTES (fndecl))) != NULL) { const char *ident = lang_hooks.decl_printable_name (fndecl, 1); - warning_at (tree_nonartificial_location (exp), + warning_at (EXPR_LOCATION (exp), OPT_Wattribute_warning, - "%Kcall to %qs declared with attribute warning: %s", - exp, identifier_to_locale (ident), + "call to %qs declared with attribute warning: %s", + identifier_to_locale (ident), TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); } diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 6803153..1401092 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2115,13 +2115,13 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi, tree slen = get_maxval_strlen (src, SRK_STRLEN); if (slen && !integer_zerop (slen)) warning_at (loc, OPT_Wstringop_truncation, - "%G%qD destination unchanged after copying no bytes " + "%qD destination unchanged after copying no bytes " "from a string of length %E", - stmt, fndecl, slen); + fndecl, slen); else warning_at (loc, OPT_Wstringop_truncation, - "%G%qD destination unchanged after copying no bytes", - stmt, fndecl); + "%qD destination unchanged after copying no bytes", + fndecl); } replace_call_with_value (gsi, dest); @@ -2498,11 +2498,11 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi) location_t loc = gimple_location (stmt); nowarn = warning_at (loc, OPT_Wstringop_overflow_, cmpdst == 0 - ? G_("%G%qD specified bound %E equals " + ? G_("%qD specified bound %E equals " "destination size") - : G_("%G%qD specified bound %E exceeds " + : G_("%qD specified bound %E exceeds " "destination size %wu"), - stmt, fndecl, len, dstsize); + fndecl, len, dstsize); if (nowarn) suppress_warning (stmt, OPT_Wstringop_overflow_); } @@ -2518,8 +2518,8 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi) of the destination is unknown (it's not an uncommon mistake to specify as the bound to strncpy the length of the source). */ if (warning_at (loc, OPT_Wstringop_overflow_, - "%G%qD specified bound %E equals source length", - stmt, fndecl, len)) + "%qD specified bound %E equals source length", + fndecl, len)) suppress_warning (stmt, OPT_Wstringop_overflow_); } diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index 41e3be6..f38fb03 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -3115,9 +3115,8 @@ format_directive (const call_info &info, if (fmtres.nullp) { fmtwarn (dirloc, argloc, NULL, info.warnopt (), - "%G%<%.*s%> directive argument is null", - info.callstmt, dirlen, - target_to_host (hostdir, sizeof hostdir, dir.beg)); + "%<%.*s%> directive argument is null", + dirlen, target_to_host (hostdir, sizeof hostdir, dir.beg)); /* Don't bother processing the rest of the format string. */ res->warned = true; @@ -4620,8 +4619,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry) is not constant. */ location_t loc = gimple_location (info.callstmt); warning_at (EXPR_LOC_OR_LOC (dstptr, loc), - info.warnopt (), "%Gnull destination pointer", - info.callstmt); + info.warnopt (), "null destination pointer"); return false; } @@ -4650,8 +4648,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry) { location_t loc = gimple_location (info.callstmt); warning_at (EXPR_LOC_OR_LOC (info.format, loc), - info.warnopt (), "%Gnull format string", - info.callstmt); + info.warnopt (), "null format string"); return false; } diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c index 72480f1..4fc7125 100644 --- a/gcc/gimple-ssa-warn-alloca.c +++ b/gcc/gimple-ssa-warn-alloca.c @@ -283,7 +283,7 @@ pass_walloca::execute (function *fun) } else if (warn_alloca) { - warning_at (loc, OPT_Walloca, "%Guse of %", stmt); + warning_at (loc, OPT_Walloca, "use of %"); continue; } else if (warn_alloca_limit < 0) @@ -322,11 +322,10 @@ pass_walloca::execute (function *fun) auto_diagnostic_group d; if (warning_at (loc, wcode, (is_vla - ? G_("%Gargument to variable-length " + ? G_("argument to variable-length " "array may be too large") - : G_("%Gargument to % may be too " - "large")), - stmt) + : G_("argument to % may be too " + "large"))) && t.limit != 0) { print_decu (t.limit, buff); @@ -342,10 +341,9 @@ pass_walloca::execute (function *fun) auto_diagnostic_group d; if (warning_at (loc, wcode, (is_vla - ? G_("%Gargument to variable-length" + ? G_("argument to variable-length" " array is too large") - : G_("%Gargument to % is too large")), - stmt) + : G_("argument to % is too large"))) && t.limit != 0) { print_decu (t.limit, buff); @@ -361,22 +359,20 @@ pass_walloca::execute (function *fun) warning_at (loc, wcode, (is_vla - ? G_("%Gunbounded use of variable-length array") - : G_("%Gunbounded use of %")), - stmt); + ? G_("unbounded use of variable-length array") + : G_("unbounded use of %"))); break; case ALLOCA_IN_LOOP: gcc_assert (!is_vla); warning_at (loc, wcode, - "%Guse of % within a loop", stmt); + "use of % within a loop"); break; case ALLOCA_ARG_IS_ZERO: warning_at (loc, wcode, (is_vla - ? G_("%Gargument to variable-length array " + ? G_("argument to variable-length array " "is zero") - : G_("%Gargument to % is zero")), - stmt); + : G_("argument to % is zero"))); break; default: gcc_unreachable (); diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index 02771e4..efb8db9 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -1494,36 +1494,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) warning_at (loc, OPT_Wrestrict, sizrange[0] == 1 ? (ovlsiz[0] == 1 - ? G_("%G%qD accessing %wu byte at offsets %s " + ? G_("%qD accessing %wu byte at offsets %s " "and %s overlaps %wu byte at offset %s") - : G_("%G%qD accessing %wu byte at offsets %s " + : G_("%qD accessing %wu byte at offsets %s " "and %s overlaps %wu bytes at offset " "%s")) : (ovlsiz[0] == 1 - ? G_("%G%qD accessing %wu bytes at offsets %s " + ? G_("%qD accessing %wu bytes at offsets %s " "and %s overlaps %wu byte at offset %s") - : G_("%G%qD accessing %wu bytes at offsets %s " + : G_("%qD accessing %wu bytes at offsets %s " "and %s overlaps %wu bytes at offset " "%s")), - call, func, sizrange[0], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], offstr[2]); else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ()) warning_n (loc, OPT_Wrestrict, sizrange[0], - "%G%qD accessing %wu byte at offsets %s " + "%qD accessing %wu byte at offsets %s " "and %s overlaps between %wu and %wu bytes " "at offset %s", - "%G%qD accessing %wu bytes at offsets %s " + "%qD accessing %wu bytes at offsets %s " "and %s overlaps between %wu and %wu bytes " "at offset %s", - call, func, sizrange[0], offstr[0], offstr[1], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], ovlsiz[1], offstr[2]); else warning_n (loc, OPT_Wrestrict, sizrange[0], - "%G%qD accessing %wu byte at offsets %s and " + "%qD accessing %wu byte at offsets %s and " "%s overlaps %wu or more bytes at offset %s", - "%G%qD accessing %wu bytes at offsets %s and " + "%qD accessing %wu bytes at offsets %s and " "%s overlaps %wu or more bytes at offset %s", - call, func, sizrange[0], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], offstr[2]); return true; } @@ -1532,28 +1532,28 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) { if (ovlsiz[0] == ovlsiz[1]) warning_n (loc, OPT_Wrestrict, ovlsiz[0], - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "at offsets %s and %s overlaps %wu byte at " "offset %s", - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "at offsets %s and %s overlaps %wu bytes " "at offset %s", - call, func, sizrange[0], sizrange[1], + func, sizrange[0], sizrange[1], offstr[0], offstr[1], ovlsiz[0], offstr[2]); else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ()) warning_at (loc, OPT_Wrestrict, - "%G%qD accessing between %wu and %wu bytes at " + "%qD accessing between %wu and %wu bytes at " "offsets %s and %s overlaps between %wu and %wu " "bytes at offset %s", - call, func, sizrange[0], sizrange[1], + func, sizrange[0], sizrange[1], offstr[0], offstr[1], ovlsiz[0], ovlsiz[1], offstr[2]); else warning_at (loc, OPT_Wrestrict, - "%G%qD accessing between %wu and %wu bytes at " + "%qD accessing between %wu and %wu bytes at " "offsets %s and %s overlaps %wu or more bytes " "at offset %s", - call, func, sizrange[0], sizrange[1], + func, sizrange[0], sizrange[1], offstr[0], offstr[1], ovlsiz[0], offstr[2]); return true; } @@ -1563,24 +1563,24 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) if (ovlsiz[0] == ovlsiz[1]) warning_n (loc, OPT_Wrestrict, ovlsiz[0], - "%G%qD accessing %wu or more bytes at offsets " + "%qD accessing %wu or more bytes at offsets " "%s and %s overlaps %wu byte at offset %s", - "%G%qD accessing %wu or more bytes at offsets " + "%qD accessing %wu or more bytes at offsets " "%s and %s overlaps %wu bytes at offset %s", - call, func, sizrange[0], offstr[0], offstr[1], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], offstr[2]); else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ()) warning_at (loc, OPT_Wrestrict, - "%G%qD accessing %wu or more bytes at offsets %s " + "%qD accessing %wu or more bytes at offsets %s " "and %s overlaps between %wu and %wu bytes " "at offset %s", - call, func, sizrange[0], offstr[0], offstr[1], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], ovlsiz[1], offstr[2]); else warning_at (loc, OPT_Wrestrict, - "%G%qD accessing %wu or more bytes at offsets %s " + "%qD accessing %wu or more bytes at offsets %s " "and %s overlaps %wu or more bytes at offset %s", - call, func, sizrange[0], offstr[0], offstr[1], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], offstr[2]); return true; } @@ -1606,36 +1606,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) { if (open_range) warning_n (loc, OPT_Wrestrict, sizrange[1], - "%G%qD accessing %wu byte may overlap " + "%qD accessing %wu byte may overlap " "%wu byte", - "%G%qD accessing %wu bytes may overlap " + "%qD accessing %wu bytes may overlap " "%wu byte", - call, func, sizrange[1], ovlsiz[1]); + func, sizrange[1], ovlsiz[1]); else warning_n (loc, OPT_Wrestrict, sizrange[1], - "%G%qD accessing %wu byte at offsets %s " + "%qD accessing %wu byte at offsets %s " "and %s may overlap %wu byte at offset %s", - "%G%qD accessing %wu bytes at offsets %s " + "%qD accessing %wu bytes at offsets %s " "and %s may overlap %wu byte at offset %s", - call, func, sizrange[1], offstr[0], offstr[1], + func, sizrange[1], offstr[0], offstr[1], ovlsiz[1], offstr[2]); return true; } if (open_range) warning_n (loc, OPT_Wrestrict, sizrange[1], - "%G%qD accessing %wu byte may overlap " + "%qD accessing %wu byte may overlap " "up to %wu bytes", - "%G%qD accessing %wu bytes may overlap " + "%qD accessing %wu bytes may overlap " "up to %wu bytes", - call, func, sizrange[1], ovlsiz[1]); + func, sizrange[1], ovlsiz[1]); else warning_n (loc, OPT_Wrestrict, sizrange[1], - "%G%qD accessing %wu byte at offsets %s and " + "%qD accessing %wu byte at offsets %s and " "%s may overlap up to %wu bytes at offset %s", - "%G%qD accessing %wu bytes at offsets %s and " + "%qD accessing %wu bytes at offsets %s and " "%s may overlap up to %wu bytes at offset %s", - call, func, sizrange[1], offstr[0], offstr[1], + func, sizrange[1], offstr[0], offstr[1], ovlsiz[1], offstr[2]); return true; } @@ -1644,30 +1644,30 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) { if (open_range) warning_n (loc, OPT_Wrestrict, ovlsiz[1], - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "may overlap %wu byte", - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "may overlap up to %wu bytes", - call, func, sizrange[0], sizrange[1], ovlsiz[1]); + func, sizrange[0], sizrange[1], ovlsiz[1]); else warning_n (loc, OPT_Wrestrict, ovlsiz[1], - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "at offsets %s and %s may overlap %wu byte " "at offset %s", - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "at offsets %s and %s may overlap up to %wu " "bytes at offset %s", - call, func, sizrange[0], sizrange[1], + func, sizrange[0], sizrange[1], offstr[0], offstr[1], ovlsiz[1], offstr[2]); return true; } warning_n (loc, OPT_Wrestrict, ovlsiz[1], - "%G%qD accessing %wu or more bytes at offsets %s " + "%qD accessing %wu or more bytes at offsets %s " "and %s may overlap %wu byte at offset %s", - "%G%qD accessing %wu or more bytes at offsets %s " + "%qD accessing %wu or more bytes at offsets %s " "and %s may overlap up to %wu bytes at offset %s", - call, func, sizrange[0], offstr[0], offstr[1], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[1], offstr[2]); return true; @@ -1689,7 +1689,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, const builtin_memref &ref, offset_int wroff, bool do_warn) { - location_t loc = gimple_or_expr_nonartificial_location (call, ref.ptr); + location_t loc = gimple_location (call); const offset_int maxobjsize = ref.maxobjsize; /* Check for excessive size first and regardless of warning options @@ -1709,15 +1709,15 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, { if (ref.sizrange[0] == ref.sizrange[1]) warned = warning_at (loc, opt, - "%G%qD specified bound %wu " + "%qD specified bound %wu " "exceeds maximum object size %wu", - call, func, ref.sizrange[0].to_uhwi (), + func, ref.sizrange[0].to_uhwi (), maxobjsize.to_uhwi ()); else warned = warning_at (loc, opt, - "%G%qD specified bound between %wu and %wu " + "%qD specified bound between %wu and %wu " "exceeds maximum object size %wu", - call, func, ref.sizrange[0].to_uhwi (), + func, ref.sizrange[0].to_uhwi (), ref.sizrange[1].to_uhwi (), maxobjsize.to_uhwi ()); return warned ? opt : no_warning; @@ -1776,9 +1776,9 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, { auto_diagnostic_group d; if (warning_at (loc, opt, - "%G%qD pointer overflow between offset %s " + "%qD pointer overflow between offset %s " "and size %s accessing array %qD with type %qT", - call, func, rangestr[0], rangestr[1], ref.base, type)) + func, rangestr[0], rangestr[1], ref.base, type)) { inform (DECL_SOURCE_LOCATION (ref.base), "array %qD declared here", ref.base); @@ -1786,15 +1786,15 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, } else warned = warning_at (loc, opt, - "%G%qD pointer overflow between offset %s " + "%qD pointer overflow between offset %s " "and size %s", - call, func, rangestr[0], rangestr[1]); + func, rangestr[0], rangestr[1]); } else warned = warning_at (loc, opt, - "%G%qD pointer overflow between offset %s " + "%qD pointer overflow between offset %s " "and size %s", - call, func, rangestr[0], rangestr[1]); + func, rangestr[0], rangestr[1]); } else if (oobref == ref.base) { @@ -1809,20 +1809,20 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, if ((ref.basesize < maxobjsize && warning_at (loc, opt, form - ? G_("%G%qD forming offset %s is out of " + ? G_("%qD forming offset %s is out of " "the bounds [0, %wu] of object %qD with " "type %qT") - : G_("%G%qD offset %s is out of the bounds " + : G_("%qD offset %s is out of the bounds " "[0, %wu] of object %qD with type %qT"), - call, func, rangestr[0], ref.basesize.to_uhwi (), + func, rangestr[0], ref.basesize.to_uhwi (), ref.base, TREE_TYPE (ref.base))) || warning_at (loc, opt, form - ? G_("%G%qD forming offset %s is out of " + ? G_("%qD forming offset %s is out of " "the bounds of object %qD with type %qT") - : G_("%G%qD offset %s is out of the bounds " + : G_("%qD offset %s is out of the bounds " "of object %qD with type %qT"), - call, func, rangestr[0], + func, rangestr[0], ref.base, TREE_TYPE (ref.base))) { inform (DECL_SOURCE_LOCATION (ref.base), @@ -1833,17 +1833,17 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, else if (ref.basesize < maxobjsize) warned = warning_at (loc, opt, form - ? G_("%G%qD forming offset %s is out " + ? G_("%qD forming offset %s is out " "of the bounds [0, %wu]") - : G_("%G%qD offset %s is out " + : G_("%qD offset %s is out " "of the bounds [0, %wu]"), - call, func, rangestr[0], ref.basesize.to_uhwi ()); + func, rangestr[0], ref.basesize.to_uhwi ()); else warned = warning_at (loc, opt, form - ? G_("%G%qD forming offset %s is out of bounds") - : G_("%G%qD offset %s is out of bounds"), - call, func, rangestr[0]); + ? G_("%qD forming offset %s is out of bounds") + : G_("%qD offset %s is out of bounds"), + func, rangestr[0]); } else if (TREE_CODE (ref.ref) == MEM_REF) { @@ -1854,9 +1854,9 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, type = TYPE_MAIN_VARIANT (type); if (warning_at (loc, opt, - "%G%qD offset %s from the object at %qE is out " + "%qD offset %s from the object at %qE is out " "of the bounds of %qT", - call, func, rangestr[0], ref.base, type)) + func, rangestr[0], ref.base, type)) { if (TREE_CODE (ref.ref) == COMPONENT_REF) refop = TREE_OPERAND (ref.ref, 1); @@ -1872,10 +1872,10 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref)); if (warning_at (loc, opt, - "%G%qD offset %s from the object at %qE is out " + "%qD offset %s from the object at %qE is out " "of the bounds of referenced subobject %qD with " "type %qT at offset %wi", - call, func, rangestr[0], ref.base, + func, rangestr[0], ref.base, TREE_OPERAND (ref.ref, 1), type, ref.refoff.to_shwi ())) { @@ -2065,7 +2065,7 @@ check_bounds_or_overlap (range_query *query, } } - location_t loc = gimple_or_expr_nonartificial_location (call, dst); + location_t loc = gimple_location (call); if (operand_equal_p (dst, src, 0)) { /* Issue -Wrestrict unless the pointers are null (those do @@ -2075,8 +2075,8 @@ check_bounds_or_overlap (range_query *query, if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict)) { warning_at (loc, OPT_Wrestrict, - "%G%qD source argument is the same as destination", - call, func); + "%qD source argument is the same as destination", + func); suppress_warning (call, OPT_Wrestrict); return OPT_Wrestrict; } diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-71.c b/gcc/testsuite/gcc.dg/Warray-bounds-71.c new file mode 100644 index 0000000..425bb12 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-71.c @@ -0,0 +1,7 @@ +/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic + works at any call site in an inlining stack + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +#define IGNORE '1' +#include "Warray-bounds-71.h" diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-71.h b/gcc/testsuite/gcc.dg/Warray-bounds-71.h new file mode 100644 index 0000000..89d1068 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-71.h @@ -0,0 +1,46 @@ +/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic + works at any call site in an inlining stack + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +int a[4]; + +void f1 (int *p, int i) +{ +#pragma GCC diagnostic push +#if IGNORE == '1' +# pragma GCC diagnostic ignored "-Warray-bounds" +#endif + p[i + 1] = 0; +#pragma GCC diagnostic pop +} + +void f2 (int *p, int i) +{ +#pragma GCC diagnostic push +#if IGNORE == '2' +# pragma GCC diagnostic ignored "-Warray-bounds" +#endif + f1 (p + 1, i + 1); +#pragma GCC diagnostic pop +} + +void f3 (int *p, int i) +{ +#pragma GCC diagnostic push +#if IGNORE == '3' +# pragma GCC diagnostic ignored "-Warray-bounds" +#endif + f2 (p + 1, i + 1); +#pragma GCC diagnostic pop +} + +void f4 (void) +{ +#pragma GCC diagnostic push +#if IGNORE == '4' +# pragma GCC diagnostic ignored "-Warray-bounds" +#endif + f3 (a, 1); +#pragma GCC diagnostic pop +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-72.c b/gcc/testsuite/gcc.dg/Warray-bounds-72.c new file mode 100644 index 0000000..eb3f664 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-72.c @@ -0,0 +1,7 @@ +/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic + works at any call site in an inlining stack + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +#define IGNORE '2' +#include "Warray-bounds-71.h" diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-73.c b/gcc/testsuite/gcc.dg/Warray-bounds-73.c new file mode 100644 index 0000000..50e2083 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-73.c @@ -0,0 +1,7 @@ +/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic + works at any call site in an inlining stack + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +#define IGNORE '3' +#include "Warray-bounds-71.h" diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-74.c b/gcc/testsuite/gcc.dg/Warray-bounds-74.c new file mode 100644 index 0000000..c59a876 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-74.c @@ -0,0 +1,7 @@ +/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic + works at any call site in an inlining stack + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +#define IGNORE '4' +#include "Warray-bounds-71.h" diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-75.c b/gcc/testsuite/gcc.dg/Warray-bounds-75.c new file mode 100644 index 0000000..306b176 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-75.c @@ -0,0 +1,12 @@ +/* Sanity test for Warray-bounds-7[1-4].c. Also verify the expected + inlining stack. + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +#include "Warray-bounds-71.h" + +// { dg-regexp "In function 'f1'," "In function f1" { target *-*-* } 0 } +// { dg-regexp "inlined from 'f2' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f2" { target *-*-* } 0 } +// { dg-regexp "inlined from 'f3' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f3" { target *-*-* } 0 } +// { dg-regexp "inlined from 'f4' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f4" { target *-*-* } 0 } +// { dg-message "Warray-bounds-71.h:\\d+:\\d+: warning: array subscript 6 is outside array bounds of 'int\\\[4]'" "warning" { target *-*-* } 0 } diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c index a7d9212..e459b24 100644 --- a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c +++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c @@ -10,23 +10,23 @@ struct A void *p; }; -void f0 (struct A *p, void *q) { p->p = q; } -void f1 (struct A *p, void *q) { f0 (p, q); } -void f2 (struct A *p, void *q) { f1 (p, q); } +static void f0 (struct A *p, void *q) { p->p = q; } +static void f1 (struct A *p, void *q) { f0 (p, q); } +static void f2 (struct A *p, void *q) { f1 (p, q); } -void g0 (struct A *p) +static void g0 (struct A *p) { __builtin_free (p->p); // { dg-warning "\\\[-Wfree-nonheap-object" } } -void g1 (struct A *p) { g0 (p); } -void g2 (struct A *p) { g1 (p); } +static void g1 (struct A *p) { g0 (p); } +static void g2 (struct A *p) { g1 (p); } # 26 "Wfree-nonheap-object-4.c" #define NOIPA __attribute__ ((noipa)) -extern int array[]; +extern int array[]; // { dg-message "declared here" "note on line 29" } /* Verify the warning is issued even for calls in a system header inlined into a function outside the header. */ @@ -39,7 +39,7 @@ NOIPA void warn_g0 (struct A *p) g0 (p); } -// { dg-message "inlined from 'warn_g0'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'warn_g0'" "note on line 42" { target *-*-* } 0 } /* Also verify the warning can be suppressed. */ @@ -65,8 +65,8 @@ NOIPA void warn_g1 (struct A *p) g1 (p); } -// { dg-message "inlined from 'g1'" "" { target *-*-* } 0 } -// { dg-message "inlined from 'warn_g1'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'g1'" "note on line 68" { target *-*-* } 0 } +// { dg-message "inlined from 'warn_g1'" "note on line 69" { target *-*-* } 0 } NOIPA void nowarn_g1 (struct A *p) @@ -90,8 +90,8 @@ NOIPA void warn_g2 (struct A *p) g2 (p); } -// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 } -// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'g2'" "note on line 93" { target *-*-* } 0 } +// { dg-message "inlined from 'warn_g2'" "note on line 94" { target *-*-* } 0 } NOIPA void nowarn_g2 (struct A *p) diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c new file mode 100644 index 0000000..026cd45 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c @@ -0,0 +1,46 @@ +/* Similar to Wfree-nonheap-object-4.c but without system headers: + verify that warnings for the same call site from distinct callers + include the correct function names in the inlining stack. + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +struct A +{ + void *p; +}; + +static void f0 (struct A *p) +{ + __builtin_free (p->p); // { dg-warning "\\\[-Wfree-nonheap-object" } +} + +// Expect two instances of the text below: +// { dg-regexp "In function 'f0'," "first f0 prefix" { target *-*-* } 0 } +// { dg-regexp "In function 'f0'," "second f0 prefix" { target *-*-* } 0 } + +static void f1 (struct A *p) { f0 (p); } +static void f2 (struct A *p) { f1 (p); } + +extern int array[]; +// Also expect two instances of the note: +// { dg-regexp "declared here" "first note on line 24" { target *-*-* } .-2 } +// { dg-regexp "declared here" "second note on line 24" { target *-*-* } .-3 } + +void foo (struct A *p) +{ + p->p = array + 1; + f0 (p); +} + +// { dg-regexp " +inlined from 'foo' at \[^:\]+Wfree-nonheap-object-5.c:32:\\d+:" "note on line 32" } + + +void bar (struct A *p) +{ + p->p = array + 2; + f2 (p); +} + +// { dg-regexp " +inlined from 'f1' at \[^:\]+Wfree-nonheap-object-5.c:21:\\d+," "inlined from f1" } +// { dg-regexp " +inlined from 'f2' at \[^:\]+Wfree-nonheap-object-5.c:22:\\d+," "inlined from f2" } +// { dg-regexp " +inlined from 'bar' at \[^:\]+Wfree-nonheap-object-5.c:41:\\d+:" "inlined from bar" } diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-6.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-6.c new file mode 100644 index 0000000..c109558 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-6.c @@ -0,0 +1,49 @@ +/* Similar to Wfree-nonheap-object-5.c but with attribute artificial: + verify that warnings for the same call site from distinct callers + include the correct function names in the inlining stack. + { dg-do compile } + { dg-options "-O1 -Wall" } */ + +struct A +{ + void *p; +}; + +__attribute__ ((always_inline, artificial)) +inline void f0 (struct A *p) +{ + __builtin_free (p->p); // { dg-warning "\\\[-Wfree-nonheap-object" } +} + +// Expect two instances of the text below: +// { dg-regexp "In function 'f0'," "first f0 prefix" { target *-*-* } 0 } +// { dg-regexp "In function 'f0'," "second f0 prefix" { target *-*-* } 0 } + +__attribute__ ((always_inline, artificial)) +inline void f1 (struct A *p) { f0 (p); } +__attribute__ ((always_inline, artificial)) +inline void f2 (struct A *p) { f1 (p); } + +extern int array[]; +// Also expect two instances of the note: +// { dg-regexp "declared here" "first note for array" { target *-*-* } .-2 } +// { dg-regexp "declared here" "second note for array" { target *-*-* } .-3 } + +void foo (struct A *p) +{ + p->p = array + 1; + f0 (p); +} + +// { dg-regexp " +inlined from 'foo' at \[^:\]+Wfree-nonheap-object-6.c:35:\\d+:" "inlined from foo" } + + +void bar (struct A *p) +{ + p->p = array + 2; + f2 (p); +} + +// { dg-regexp " +inlined from 'f1' at \[^:\]+Wfree-nonheap-object-6.c:23:\\d+," "inlined from f1" } +// { dg-regexp " +inlined from 'f2' at \[^:\]+Wfree-nonheap-object-6.c:25:\\d+," "inlined from f2" } +// { dg-regexp " +inlined from 'bar' at \[^:\]+Wfree-nonheap-object-6.c:44:\\d+:" "inlined from bar" } diff --git a/gcc/testsuite/gcc.dg/Wobjsize-1.c b/gcc/testsuite/gcc.dg/Wobjsize-1.c index e80c8ad..2bd2f93 100644 --- a/gcc/testsuite/gcc.dg/Wobjsize-1.c +++ b/gcc/testsuite/gcc.dg/Wobjsize-1.c @@ -4,13 +4,17 @@ #include "Wobjsize-1.h" char buf[6]; -/* { dg-warning "writing" "" { target *-*-* } .-1 } */ int main(int argc, char **argv) { - strcpy (buf,"hello "); + strcpy (buf,"hello "); /* { dg-warning "\\\[-Wstringop-overflow" } */ return 0; } -/* { dg-message "file included" "included" { target *-*-* } 0 } */ -/* { dg-message "inlined from" "inlined" { target *-*-* } 0 } */ +/* { dg-message "file included" "included" { target *-*-* } 0 } + { dg-message "inlined from" "inlined" { target *-*-* } 0 } + + The test might emit two warnings, one for the strcpy call and + another for the inlined call to __builtin___strcpy_chk() called + from strcpy(). + { dg-prune-output "writing 7 bytes into a region of size 6" } */ diff --git a/gcc/testsuite/gcc.dg/format/c90-printf-1.c b/gcc/testsuite/gcc.dg/format/c90-printf-1.c index c8652fc..8ffd63f 100644 --- a/gcc/testsuite/gcc.dg/format/c90-printf-1.c +++ b/gcc/testsuite/gcc.dg/format/c90-printf-1.c @@ -240,7 +240,7 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p, printf ("%n", cn); /* { dg-warning "3:constant" "%n with const" } */ printf ((const char *)L"foo"); /* { dg-warning "25:wide" "wide string" } */ printf ("%n", (int *)0); /* { dg-warning "3:null" "%n with NULL" } */ - printf ("%s", (char *)0); /* { dg-warning "3:null" "%s with NULL" } */ + printf ("%s", (char *)0); /* { dg-warning "12:'%s' directive argument is null" "%s with NULL" } */ /* Test for correct column locations within strings with embedded escape sequences. */ printf ("\\\a\n \"\t%5n\n", n); /* { dg-warning "25:width" "width with %n" } */ diff --git a/gcc/testsuite/gcc.dg/pr79214.c b/gcc/testsuite/gcc.dg/pr79214.c index 3f5d935..2f93eed 100644 --- a/gcc/testsuite/gcc.dg/pr79214.c +++ b/gcc/testsuite/gcc.dg/pr79214.c @@ -22,67 +22,67 @@ static size_t range (void) void test_bzero (void) { - bzero (d, range ()); /* { dg-warning ".__builtin_(bzero|memset). writing 4 or more bytes into a region of size 3 overflows the destination" } */ + bzero (d, range ()); /* { dg-warning ".__builtin_(bzero|memset). writing 4 or more bytes into a region of size 3 overflows the destination" "pr?????" { xfail { *-*-* } } } */ } void test_memcpy (void) { - memcpy (d, s, range ()); /* { dg-warning ".__builtin_memcpy. writing 4 or more bytes into a region of size 3 overflows the destination" } */ + memcpy (d, s, range ()); /* { dg-warning ".__builtin_memcpy. writing 4 or more bytes into a region of size 3 overflows the destination" "pr?????" { xfail { *-*-* } } } */ } void test_memmove (void) { - memmove (d, d + 1, range ()); /* { dg-warning ".__builtin_memmove. writing 4 or more bytes into a region of size 3 overflows the destination" } */ + memmove (d, d + 1, range ()); /* { dg-warning ".__builtin_memmove. writing 4 or more bytes into a region of size 3 overflows the destination" "pr?????" { xfail { *-*-* } } } */ } void test_mempcpy (void) { - mempcpy (d, s, range ()); /* { dg-warning ".__builtin_mempcpy. writing 4 or more bytes into a region of size 3 overflows the destination" } */ + mempcpy (d, s, range ()); /* { dg-warning ".__builtin_mempcpy. writing 4 or more bytes into a region of size 3 overflows the destination" "pr?????" { xfail { *-*-* } } } */ } void test_memset (int n) { - memset (d, n, range ()); /* { dg-warning ".__builtin_memset. writing 4 or more bytes into a region of size 3 overflows the destination" } */ + memset (d, n, range ()); /* { dg-warning ".__builtin_memset. writing 4 or more bytes into a region of size 3 overflows the destination" "pr?????" { xfail { *-*-* } } } */ } void test_strcat (int i) { const char *s = i < 0 ? "123" : "4567"; - strcat (d, s); /* { dg-warning ".__builtin_strcat. writing between 4 and 5 bytes into a region of size 3 overflows the destination" } */ + strcat (d, s); /* { dg-warning ".__builtin_strcat. writing between 4 and 5 bytes into a region of size 3 overflows the destination" "pr?????" { xfail { *-*-* } } } */ } char* test_stpcpy (int i) { const char *s = i < 0 ? "123" : "4567"; - return stpcpy (d, s); /* { dg-warning ".__builtin_stpcpy. writing between 4 and 5 bytes into a region of size 3 overflows the destination" } */ + return stpcpy (d, s); /* { dg-warning ".__builtin_stpcpy. writing between 4 and 5 bytes into a region of size 3 overflows the destination" "pr?????" { xfail { *-*-* } } } */ } char* test_stpncpy (int i) { const char *s = i < 0 ? "123" : "4567"; - return stpncpy (d, s, range ()); /* { dg-warning ".__builtin_stpncpy. writing 4 or more bytes into a region of size 3 overflows the destination" } */ + return stpncpy (d, s, range ()); /* { dg-warning ".__builtin_stpncpy. writing 4 or more bytes into a region of size 3 overflows the destination" "pr?????" { xfail { *-*-* } } } */ } char* test_strcpy (int i) { const char *s = i < 0 ? "123" : "4567"; - return strcpy (d, s); /* { dg-warning ".__builtin_strcpy. writing between 4 and 5 bytes into a region of size 3 overflows the destination" } */ + return strcpy (d, s); /* { dg-warning ".__builtin_strcpy. writing between 4 and 5 bytes into a region of size 3 overflows the destination" "pr?????" { xfail { *-*-* } } } */ } char* test_strncpy (int i) { const char *s = i < 0 ? "123" : "4567"; - return strncpy (d, s, range ()); /* { dg-warning ".__builtin_strncpy. writing 4 or more bytes into a region of size 3 overflows the destination" } */ + return strncpy (d, s, range ()); /* { dg-warning ".__builtin_strncpy. writing 4 or more bytes into a region of size 3 overflows the destination" "pr?????" { xfail { *-*-* } } } */ } char* test_strncat (int i) { const char *s = i < 0 ? "123" : "4567"; - return strncat (d, s, range ()); /* { dg-warning ".__builtin_strncat. specified bound \\\[4, \[0-9\]+] exceeds destination size 3" } */ + return strncat (d, s, range ()); /* { dg-warning ".__builtin_strncat. specified bound \\\[4, \[0-9\]+] exceeds destination size 3" "pr?????" { xfail { *-*-* } } } */ } diff --git a/gcc/testsuite/gcc.dg/pragma-diag-10.c b/gcc/testsuite/gcc.dg/pragma-diag-10.c new file mode 100644 index 0000000..127b299 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pragma-diag-10.c @@ -0,0 +1,20 @@ +/* PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective + in conjunction with alias attribute + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +void * +__rawmemchr_ppc (const void *s, int c) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#pragma GCC diagnostic ignored "-Wstringop-overread" + if (c != 0) + return __builtin_memchr (s, c, (unsigned long)-1); // { dg-bogus "specified bound \\d+ exceeds maximum object size" } +#pragma GCC diagnostic pop + + return (char *)s + __builtin_strlen (s); +} + +extern __typeof (__rawmemchr_ppc) __EI___rawmemchr_ppc + __attribute__((alias ("__rawmemchr_ppc"))); diff --git a/gcc/testsuite/gcc.dg/pragma-diag-9.c b/gcc/testsuite/gcc.dg/pragma-diag-9.c new file mode 100644 index 0000000..9aac379 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pragma-diag-9.c @@ -0,0 +1,141 @@ +/* Verify that #pragma GCC diagnostic down the inlining stack suppresses + a warning that would otherwise be issued for inlined calls higher up + the inlining stack. + { dg-do compile } + { dg-options "-O2 -Wall -Wno-array-bounds" } */ + +extern void* memset (void*, int, __SIZE_TYPE__); + +static void warn0 (int *p) +{ + memset (p, __LINE__, 3); // { dg-warning "\\\[-Wstringop-overflow" } +} + +static void warn1 (int *p) +{ + warn0 (p + 1); +} + +static void warn2 (int *p) +{ + warn1 (p + 1); +} + +int a2[2]; // { dg-message "at offset 12 into destination object 'a2' of size 8" } + +void warn3 (void) +{ + warn2 (a2 + 1); +} + + +// Verify suppression at the innermost frame of the inlining stack. + +static void ignore0 (int *p) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" + memset (p, __LINE__, 3); +#pragma GCC diagnostic pop +} + +static void nowarn1_ignore0 (int *p) +{ + ignore0 (p + 1); +} + +static void nowarn2_ignore0 (int *p) +{ + nowarn1_ignore0 (p + 1); +} + +int b2[2]; + +void nowarn3_ignore0 (void) +{ + nowarn2_ignore0 (b2 + 1); +} + + +// Verify suppression at the second innermost frame of the inlining stack. + +static void nowarn0_ignore1 (int *p) +{ + memset (p, __LINE__, 3); +} + +static void ignore1 (int *p) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" + nowarn0_ignore1 (p + 1); +#pragma GCC diagnostic pop +} + +void nowarn2_ignore1 (int *p) +{ + ignore1 (p + 1); +} + +int c2[2]; + +void nowarn3_ignore1 (void) +{ + nowarn2_ignore1 (c2 + 1); +} + + +// Verify suppression at the third innermost frame of the inlining stack. + +static void nowarn0_ignore2 (int *p) +{ + memset (p, __LINE__, 3); +} + +static void nowarn1_ignore2 (int *p) +{ + nowarn0_ignore2 (p + 1); +} + +static void ignore2 (int *p) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" + nowarn1_ignore2 (p + 1); +#pragma GCC diagnostic pop +} + +int d2[2]; + +void nowarn3_ignore2 (void) +{ + ignore2 (c2 + 1); +} + + +// Verify suppression at the outermost frame of the inlining stack. + +static void nowarn0_ignore3 (int *p) +{ + memset (p, __LINE__, 3); +} + +static void nowarn1_ignore3 (int *p) +{ + nowarn0_ignore3 (p + 1); +} + +static void nowarn2_ignore3 (int *p) +{ + nowarn1_ignore3 (p + 1); +} + +int e2[2]; + +void ignore3 (void) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" + nowarn2_ignore3 (e2 + 1); +#pragma GCC diagnostic pop +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-27.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-27.c new file mode 100644 index 0000000..8188dd8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-27.c @@ -0,0 +1,20 @@ +/* PR middle-end/100325 - missing warning with -O0 on sprintf overflow with + pointer plus offset + { dg-do compile } + { dg-options "-O0 -Wall" } */ + +#define S(n) (&"0123456789"[10 - n]) + +extern int sprintf (char*, const char*, ...); + +char d[10]; + +void nowarn_d10_s9 () +{ + sprintf (d, "%s", S (9)); // { dg-bogus "-Wformat-overflow" } +} + +void warn_d10_s10 () +{ + sprintf (d, "%s", S (10)); // { dg-warning "-Wformat-overflow" } +} diff --git a/gcc/testsuite/gcc.dg/uninit-suppress_3.c b/gcc/testsuite/gcc.dg/uninit-suppress_3.c new file mode 100644 index 0000000..7bbe9ed --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-suppress_3.c @@ -0,0 +1,98 @@ +/* PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration + site + { dg-do compile } + { dg-options "-O1 -Wall" } */ + +struct A +{ + int x; +}; + +// Verify that suppression works at every inlining level. + +static int f0 (int *x) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + + return ++*x; + +#pragma GCC diagnostic pop +} + +static int f1 (int *p, int n) +{ + struct A a; + for (int i = 0; i < n; ++i) { + if (p[i] > 1) { + a = (struct A){p[i]}; + } + } + + return f0 (&a.x); +} + +int f2 (void) +{ + int a[] = { 1, 2, 3, 4 }; + return f1 (a, 4); +} + + +static int g0 (int *x) +{ + return ++*x; +} + +static int g1 (int *p, int n) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + + struct A a; + for (int i = 0; i < n; ++i) { + if (p[i] > 1) { + a = (struct A){p[i]}; + } + } + + return g0 (&a.x); + +#pragma GCC diagnostic pop +} + +int g2 (void) +{ + int a[] = { 1, 2, 3, 4, 5 }; + return g1 (a, 5); +} + + +static int h0 (int *x) +{ + return ++*x; +} + +static int h1 (int *p, int n) +{ + struct A a; + for (int i = 0; i < n; ++i) { + if (p[i] > 1) { + a = (struct A){p[i]}; + } + } + + return h0 (&a.x); +} + +int h2 (void) +{ + int a[] = { 1, 2, 3, 4, 5, 6 }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + + return h1 (a, 6); + +#pragma GCC diagnostic pop +} diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c index e74bd1f..c270d03 100644 --- a/gcc/trans-mem.c +++ b/gcc/trans-mem.c @@ -4413,12 +4413,8 @@ ipa_tm_scan_irr_block (basic_block bb) is to wrap it in a __tm_waiver block. This is not yet implemented, so we can't check for it. */ if (is_tm_safe (current_function_decl)) - { - tree t = build1 (NOP_EXPR, void_type_node, size_zero_node); - SET_EXPR_LOCATION (t, gimple_location (stmt)); - error ("%K% not allowed in % function", - t); - } + error_at (gimple_location (stmt), + "% not allowed in % function"); return true; default: diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 4258541..9ce6214 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -3563,7 +3563,7 @@ pass_post_ipa_warn::execute (function *fun) if (argno == 0) { if (warning_at (loc, OPT_Wnonnull, - "%G%qs pointer is null", stmt, "this") + "%qs pointer is null", "this") && fndecl) inform (DECL_SOURCE_LOCATION (fndecl), "in a call to non-static member function %qD", @@ -3572,8 +3572,8 @@ pass_post_ipa_warn::execute (function *fun) } if (!warning_at (loc, OPT_Wnonnull, - "%Gargument %u null where non-null " - "expected", stmt, argno)) + "argument %u null where non-null " + "expected", argno)) continue; tree fndecl = gimple_call_fndecl (stmt); diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 13ea107..94257df 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -2022,13 +2022,12 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry, warned = (writefn ? warning_at (loc, OPT_Wstringop_overflow_, - "%G%qD writing one too many bytes into a region " + "%qD writing one too many bytes into a region " "of a size that depends on %", - stmt, writefn) + writefn) : warning_at (loc, OPT_Wstringop_overflow_, - "%Gwriting one too many bytes into a region " - "of a size that depends on %", - stmt)); + "writing one too many bytes into a region " + "of a size that depends on %")); } else if (lenrng[0] == lenrng[1]) { @@ -2036,65 +2035,65 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry, warned = (writefn ? warning_n (loc, OPT_Wstringop_overflow_, lenrng[0].to_uhwi (), - "%G%qD writing %wu byte into a region " + "%qD writing %wu byte into a region " "of size %wu", - "%G%qD writing %wu bytes into a region " + "%qD writing %wu bytes into a region " "of size %wu", - stmt, writefn, lenrng[0].to_uhwi (), + writefn, lenrng[0].to_uhwi (), spcrng[0].to_uhwi ()) : warning_n (loc, OPT_Wstringop_overflow_, lenrng[0].to_uhwi (), - "%Gwriting %wu byte into a region " + "writing %wu byte into a region " "of size %wu", - "%Gwriting %wu bytes into a region " + "writing %wu bytes into a region " "of size %wu", - stmt, lenrng[0].to_uhwi (), + lenrng[0].to_uhwi (), spcrng[0].to_uhwi ())); else warned = (writefn ? warning_n (loc, OPT_Wstringop_overflow_, lenrng[0].to_uhwi (), - "%G%qD writing %wu byte into a region " + "%qD writing %wu byte into a region " "of size between %wu and %wu", - "%G%qD writing %wu bytes into a region " + "%qD writing %wu bytes into a region " "of size between %wu and %wu", - stmt, writefn, lenrng[0].to_uhwi (), + writefn, lenrng[0].to_uhwi (), spcrng[0].to_uhwi (), spcrng[1].to_uhwi ()) : warning_n (loc, OPT_Wstringop_overflow_, lenrng[0].to_uhwi (), - "%Gwriting %wu byte into a region " + "writing %wu byte into a region " "of size between %wu and %wu", - "%Gwriting %wu bytes into a region " + "writing %wu bytes into a region " "of size between %wu and %wu", - stmt, lenrng[0].to_uhwi (), + lenrng[0].to_uhwi (), spcrng[0].to_uhwi (), spcrng[1].to_uhwi ())); } else if (spcrng[0] == spcrng[1]) warned = (writefn ? warning_at (loc, OPT_Wstringop_overflow_, - "%G%qD writing between %wu and %wu bytes " + "%qD writing between %wu and %wu bytes " "into a region of size %wu", - stmt, writefn, lenrng[0].to_uhwi (), + writefn, lenrng[0].to_uhwi (), lenrng[1].to_uhwi (), spcrng[0].to_uhwi ()) : warning_at (loc, OPT_Wstringop_overflow_, - "%Gwriting between %wu and %wu bytes " + "writing between %wu and %wu bytes " "into a region of size %wu", - stmt, lenrng[0].to_uhwi (), + lenrng[0].to_uhwi (), lenrng[1].to_uhwi (), spcrng[0].to_uhwi ())); else warned = (writefn ? warning_at (loc, OPT_Wstringop_overflow_, - "%G%qD writing between %wu and %wu bytes " + "%qD writing between %wu and %wu bytes " "into a region of size between %wu and %wu", - stmt, writefn, lenrng[0].to_uhwi (), + writefn, lenrng[0].to_uhwi (), lenrng[1].to_uhwi (), spcrng[0].to_uhwi (), spcrng[1].to_uhwi ()) : warning_at (loc, OPT_Wstringop_overflow_, - "%Gwriting between %wu and %wu bytes " + "writing between %wu and %wu bytes " "into a region of size between %wu and %wu", - stmt, lenrng[0].to_uhwi (), + lenrng[0].to_uhwi (), lenrng[1].to_uhwi (), spcrng[0].to_uhwi (), spcrng[1].to_uhwi ())); @@ -2985,13 +2984,13 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt, if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1]) return warning_n (callloc, OPT_Wstringop_truncation, cntrange[0].to_uhwi (), - "%G%qD output truncated before terminating " + "%qD output truncated before terminating " "nul copying %E byte from a string of the " "same length", - "%G%qD output truncated before terminating nul " + "%qD output truncated before terminating nul " "copying %E bytes from a string of the same " "length", - stmt, func, cnt); + func, cnt); else if (!cat_dstlen_bounded) { if (wi::geu_p (lenrange[0], cntrange[1])) @@ -3001,16 +3000,16 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt, if (cntrange[0] == cntrange[1]) return warning_n (callloc, OPT_Wstringop_truncation, cntrange[0].to_uhwi (), - "%G%qD output truncated copying %E byte " + "%qD output truncated copying %E byte " "from a string of length %wu", - "%G%qD output truncated copying %E bytes " + "%qD output truncated copying %E bytes " "from a string of length %wu", - stmt, func, cnt, lenrange[0].to_uhwi ()); + func, cnt, lenrange[0].to_uhwi ()); return warning_at (callloc, OPT_Wstringop_truncation, - "%G%qD output truncated copying between %wu " + "%qD output truncated copying between %wu " "and %wu bytes from a string of length %wu", - stmt, func, cntrange[0].to_uhwi (), + func, cntrange[0].to_uhwi (), cntrange[1].to_uhwi (), lenrange[0].to_uhwi ()); } else if (wi::geu_p (lenrange[1], cntrange[1])) @@ -3020,16 +3019,16 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt, if (cntrange[0] == cntrange[1]) return warning_n (callloc, OPT_Wstringop_truncation, cntrange[0].to_uhwi (), - "%G%qD output may be truncated copying %E " + "%qD output may be truncated copying %E " "byte from a string of length %wu", - "%G%qD output may be truncated copying %E " + "%qD output may be truncated copying %E " "bytes from a string of length %wu", - stmt, func, cnt, lenrange[1].to_uhwi ()); + func, cnt, lenrange[1].to_uhwi ()); return warning_at (callloc, OPT_Wstringop_truncation, - "%G%qD output may be truncated copying between " + "%qD output may be truncated copying between " "%wu and %wu bytes from a string of length %wu", - stmt, func, cntrange[0].to_uhwi (), + func, cntrange[0].to_uhwi (), cntrange[1].to_uhwi (), lenrange[1].to_uhwi ()); } } @@ -3043,9 +3042,9 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt, the lower bound of the specified count but shorter than the upper bound the copy may (but need not) be truncated. */ return warning_at (callloc, OPT_Wstringop_truncation, - "%G%qD output may be truncated copying between " + "%qD output may be truncated copying between " "%wu and %wu bytes from a string of length %wu", - stmt, func, cntrange[0].to_uhwi (), + func, cntrange[0].to_uhwi (), cntrange[1].to_uhwi (), lenrange[0].to_uhwi ()); } } @@ -3072,8 +3071,8 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt, if (cntrange[0] == cntrange[1]) return warning_at (callloc, OPT_Wstringop_truncation, - "%G%qD specified bound %E equals destination size", - stmt, func, cnt); + "%qD specified bound %E equals destination size", + func, cnt); } return false; @@ -3197,9 +3196,9 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi) && sisrc == silen && is_strlen_related_p (src, len) && warning_at (callloc, OPT_Wstringop_truncation, - "%G%qD output truncated before terminating nul " + "%qD output truncated before terminating nul " "copying as many bytes from a string as its length", - stmt, func)) + func)) warned = true; else if ((append_p || !dstsize || len == dstlenp1) && silen && is_strlen_related_p (src, silen->ptr)) @@ -3210,9 +3209,9 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi) opt_code opt = (append_p || dstsize ? OPT_Wstringop_overflow_ : OPT_Wstringop_truncation); warned = warning_at (callloc, opt, - "%G%qD specified bound depends on the length " + "%qD specified bound depends on the length " "of the source argument", - stmt, func); + func); } if (warned) { @@ -4141,24 +4140,24 @@ maybe_warn_pointless_strcmp (gimple *stmt, HOST_WIDE_INT bound, if (siz <= minlen && bound == -1) warned = warning_at (stmt_loc, OPT_Wstring_compare, (at_least - ? G_("%G%qD of a string of length %wu or more and " + ? G_("%qD of a string of length %wu or more and " "an array of size %wu evaluates to nonzero") - : G_("%G%qD of a string of length %wu and an array " + : G_("%qD of a string of length %wu and an array " "of size %wu evaluates to nonzero")), - stmt, callee, minlen, siz); + callee, minlen, siz); else if (!at_least && siz <= HOST_WIDE_INT_MAX) { if (len[0] != HOST_WIDE_INT_MAX && len[1] != HOST_WIDE_INT_MAX) warned = warning_at (stmt_loc, OPT_Wstring_compare, - "%G%qD of strings of length %wu and %wu " + "%qD of strings of length %wu and %wu " "and bound of %wu evaluates to nonzero", - stmt, callee, len[0], len[1], bound); + callee, len[0], len[1], bound); else warned = warning_at (stmt_loc, OPT_Wstring_compare, - "%G%qD of a string of length %wu, an array " + "%qD of a string of length %wu, an array " "of size %wu and bound of %wu evaluates to " "nonzero", - stmt, callee, minlen, siz, bound); + callee, minlen, siz, bound); } if (!warned) diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 99442d7..24ac031 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -444,7 +444,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, if (wlims.always_executed) { if (warning_at (location, OPT_Wuninitialized, - "%G%qE is used uninitialized", stmt, rhs)) + "%qE is used uninitialized", rhs)) { /* ??? This is only effective for decls as in gcc.dg/uninit-B-O0.c. Avoid doing this for maybe-uninit @@ -457,7 +457,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, } else if (wlims.wmaybe_uninit) warned = warning_at (location, OPT_Wmaybe_uninitialized, - "%G%qE may be used uninitialized", stmt, rhs); + "%qE may be used uninitialized", rhs); return warned ? base : NULL_TREE; } -- cgit v1.1 From 62e43587ef1c874b62a6c4c5c3980969e4a2da97 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 6 Jul 2021 13:45:54 -0600 Subject: Improve warning suppression for inlined functions. gcc/ChangeLog: * config/aarch64/aarch64-builtins.c (aarch64_simd_expand_builtin): Remove %K and use error_at. (aarch64_expand_fcmla_builtin): Same. (aarch64_expand_builtin_tme): Same. (aarch64_expand_builtin_memtag): Same. * config/arm/arm-builtins.c (arm_expand_acle_builtin): Same. (arm_expand_builtin): Same. * config/arm/arm.c (bounds_check): Same. --- gcc/config/aarch64/aarch64-builtins.c | 23 +++++++++++++++-------- gcc/config/arm/arm-builtins.c | 33 ++++++++++++++++++++------------- gcc/config/arm/arm.c | 4 ++-- 3 files changed, 37 insertions(+), 23 deletions(-) (limited to 'gcc') diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c index 3cab3ec..9ed4b72 100644 --- a/gcc/config/aarch64/aarch64-builtins.c +++ b/gcc/config/aarch64/aarch64-builtins.c @@ -1598,8 +1598,9 @@ constant_arg: if (!(*insn_data[icode].operand[opc].predicate) (op[opc], mode)) { - error ("%Kargument %d must be a constant immediate", - exp, opc + 1 - have_retval); + error_at (EXPR_LOCATION (exp), + "argument %d must be a constant immediate", + opc + 1 - have_retval); return const0_rtx; } break; @@ -1669,10 +1670,13 @@ aarch64_simd_expand_builtin (int fcode, tree exp, rtx target) / UINTVAL (elementsize), exp); else - error ("%Klane index must be a constant immediate", exp); + error_at (EXPR_LOCATION (exp), + "lane index must be a constant immediate"); } else - error ("%Ktotal size and element size must be a non-zero constant immediate", exp); + error_at (EXPR_LOCATION (exp), + "total size and element size must be a non-zero " + "constant immediate"); /* Don't generate any RTL. */ return const0_rtx; } @@ -1828,7 +1832,8 @@ aarch64_expand_fcmla_builtin (tree exp, rtx target, int fcode) /* Validate that the lane index is a constant. */ if (!CONST_INT_P (lane_idx)) { - error ("%Kargument %d must be a constant immediate", exp, 4); + error_at (EXPR_LOCATION (exp), + "argument %d must be a constant immediate", 4); return const0_rtx; } @@ -1917,7 +1922,8 @@ aarch64_expand_builtin_tme (int fcode, tree exp, rtx target) emit_insn (GEN_FCN (CODE_FOR_tcancel) (op0)); else { - error ("%Kargument must be a 16-bit constant immediate", exp); + error_at (EXPR_LOCATION (exp), + "argument must be a 16-bit constant immediate"); return const0_rtx; } } @@ -2006,8 +2012,9 @@ aarch64_expand_builtin_memtag (int fcode, tree exp, rtx target) pat = GEN_FCN (icode) (target, op0, const0_rtx, op1); break; } - error ("%Kargument %d must be a constant immediate " - "in range [0,15]", exp, 2); + error_at (EXPR_LOCATION (exp), + "argument %d must be a constant immediate " + "in range [0,15]", 2); return const0_rtx; } else diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index fa0fb0b..3a9ff8f 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -3092,26 +3092,30 @@ constant_arg: unsigned int cp_bit = (CONST_INT_P (op[argc]) ? UINTVAL (op[argc]) : -1); if (IN_RANGE (cp_bit, 0, ARM_CDE_CONST_COPROC)) - error ("%Kcoprocessor %d is not enabled " - "with +cdecp%d", exp, cp_bit, cp_bit); + error_at (EXPR_LOCATION (exp), + "coprocessor %d is not enabled " + "with +cdecp%d", cp_bit, cp_bit); else - error ("%Kcoproc must be a constant immediate in " - "range [0-%d] enabled with +cdecp", exp, - ARM_CDE_CONST_COPROC); + error_at (EXPR_LOCATION (exp), + "coproc must be a constant immediate in " + "range [0-%d] enabled with +cdecp", + ARM_CDE_CONST_COPROC); } else /* Here we mention the builtin name to follow the same format that the C/C++ frontends use for referencing a given argument index. */ - error ("%Kargument %d to %qE must be a constant immediate " - "in range [0-%d]", exp, argc + 1, + error_at (EXPR_LOCATION (exp), + "argument %d to %qE must be a constant " + "immediate in range [0-%d]", argc + 1, arm_builtin_decls[fcode], cde_builtin_data[fcode - ARM_BUILTIN_CDE_PATTERN_START].imm_max); } else - error ("%Kargument %d must be a constant immediate", - exp, argc + 1); + error_at (EXPR_LOCATION (exp), + "argument %d must be a constant immediate", + argc + 1); /* We have failed to expand the pattern, and are safely in to invalid code. But the mid-end will still try to build an assignment for this node while it expands, @@ -3328,11 +3332,13 @@ arm_expand_acle_builtin (int fcode, tree exp, rtx target) if (CONST_INT_P (sat_imm)) { if (!IN_RANGE (sat_imm, min_sat, max_sat)) - error ("%Ksaturation bit range must be in the range [%wd, %wd]", - exp, UINTVAL (min_sat), UINTVAL (max_sat)); + error_at (EXPR_LOCATION (exp), + "saturation bit range must be in the range [%wd, %wd]", + UINTVAL (min_sat), UINTVAL (max_sat)); } else - error ("%Ksaturation bit range must be a constant immediate", exp); + error_at (EXPR_LOCATION (exp), + "saturation bit range must be a constant immediate"); /* Don't generate any RTL. */ return const0_rtx; } @@ -3455,7 +3461,8 @@ arm_expand_builtin (tree exp, if (CONST_INT_P (lane_idx)) neon_lane_bounds (lane_idx, 0, TREE_INT_CST_LOW (nlanes), exp); else - error ("%Klane index must be a constant immediate", exp); + error_at (EXPR_LOCATION (exp), + "lane index must be a constant immediate"); /* Don't generate any RTL. */ return const0_rtx; } diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 7b37e1b..de37c90 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -13244,8 +13244,8 @@ bounds_check (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high, if (lane < low || lane >= high) { if (exp) - error ("%K%s %wd out of range %wd - %wd", - exp, desc, lane, low, high - 1); + error_at (EXPR_LOCATION (exp), + "%s %wd out of range %wd - %wd", desc, lane, low, high - 1); else error ("%s %wd out of range %wd - %wd", desc, lane, low, high - 1); } -- cgit v1.1 From 4f6e181181a48c341e524653cae0885fd170131e Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 6 Jul 2021 14:13:31 -0600 Subject: Remove support for %G and %K. gcc/c-family/ChangeLog: * c-format.c (gcc_tdiag_char_table): Remove support for %G and %K. (gcc_cdiag_char_table): Same. (gcc_cxxdiag_char_table): Same. gcc/c/ChangeLog: * c-objc-common.c (c_tree_printer): Remove support for %G and %K. gcc/cp/ChangeLog: * error.c (cp_printer): Remove support for %G and %K. gcc/ChangeLog: * gimple-pretty-print.c (percent_G_format): Remove. * tree-diagnostic.c (default_tree_printer): Remove calls. * tree-pretty-print.c (percent_K_format): Remove. * tree-pretty-print.h (percent_K_format): Remove. gcc/testsuite/ChangeLog: * gcc.dg/format/gcc_diag-10.c: Update expected warnings. * gcc.dg/plugin/diagnostic_plugin_test_inlining.c: Remove %G. --- gcc/c-family/c-format.c | 12 ---------- gcc/c/c-objc-common.c | 15 ------------- gcc/cp/error.c | 9 -------- gcc/gimple-pretty-print.c | 17 -------------- gcc/testsuite/gcc.dg/format/gcc_diag-10.c | 20 ++++++++--------- .../plugin/diagnostic_plugin_test_inlining.c | 2 +- gcc/tree-diagnostic.c | 9 -------- gcc/tree-pretty-print.c | 26 ---------------------- gcc/tree-pretty-print.h | 1 - 9 files changed, 11 insertions(+), 100 deletions(-) (limited to 'gcc') diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index bda3b18..6fd0bb3 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -781,10 +781,6 @@ static const format_char_info gcc_tdiag_char_table[] = /* These will require a "tree" at runtime. */ { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL }, { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, - { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, - - /* G requires a "gimple*" argument at runtime. */ - { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } }; @@ -799,10 +795,6 @@ static const format_char_info gcc_cdiag_char_table[] = /* These will require a "tree" at runtime. */ { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL }, { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, - { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, - - /* G requires a "gimple*" argument at runtime. */ - { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, @@ -819,10 +811,6 @@ static const format_char_info gcc_cxxdiag_char_table[] = /* These will require a "tree" at runtime. */ { "ADFHISTVX",1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "'", NULL }, { "E", 1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL }, - { "K", 1, STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, - - /* G requires a "gimple*" argument at runtime. */ - { "G", 1, STD_C89,{ T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */ { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c index b945de1..cdb2242 100644 --- a/gcc/c/c-objc-common.c +++ b/gcc/c/c-objc-common.c @@ -247,8 +247,6 @@ print_type (c_pretty_printer *cpp, tree t, bool *quoted) %D: a general decl, %E: an identifier or expression, %F: a function declaration, - %G: a Gimple statement, - %K: a CALL_EXPR, %T: a type. %V: a list of type qualifiers from a tree. %v: an explicit list of type qualifiers @@ -269,19 +267,6 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec, if (precision != 0 || wide) return false; - if (*spec == 'G') - { - percent_G_format (text); - return true; - } - - if (*spec == 'K') - { - t = va_arg (*text->args_ptr, tree); - percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t)); - return true; - } - if (*spec != 'v') { t = va_arg (*text->args_ptr, tree); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 4a89b34..012a4ec 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -4338,10 +4338,8 @@ defer_phase_2_of_type_diff (deferred_printed_type *deferred, %D declaration. %E expression. %F function declaration. - %G gcall * %H type difference (from). %I type difference (to). - %K tree %L language as used in extern "lang". %O binary operator. %P function parameter whose position is indicated by an integer. @@ -4391,9 +4389,6 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec, break; case 'E': result = expr_to_string (next_tree); break; case 'F': result = fndecl_to_string (next_tree, verbose); break; - case 'G': - percent_G_format (text); - return true; case 'H': defer_phase_2_of_type_diff (&postprocessor->m_type_a, next_tree, buffer_ptr, verbose, *quoted); @@ -4402,10 +4397,6 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec, defer_phase_2_of_type_diff (&postprocessor->m_type_b, next_tree, buffer_ptr, verbose, *quoted); return true; - case 'K': - t = va_arg (*text->args_ptr, tree); - percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t)); - return true; case 'L': result = language_to_string (next_lang); break; case 'O': result = op_to_string (false, next_tcode); break; case 'P': result = parm_to_string (next_int); break; diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 8be4041..39c5775 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -3059,23 +3059,6 @@ gimple_dump_bb_for_graph (pretty_printer *pp, basic_block bb) pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true); } - -/* Handle the %G format for TEXT. Same as %K in handle_K_format in - tree-pretty-print.c but with a Gimple statement as an argument. */ - -void -percent_G_format (text_info *text) -{ - gimple *stmt = va_arg (*text->args_ptr, gimple*); - - /* Fall back on the rich location if the statement doesn't have one. */ - location_t loc = gimple_location (stmt); - if (loc == UNKNOWN_LOCATION) - loc = text->m_richloc->get_loc (); - tree block = gimple_block (stmt); - percent_K_format (text, loc, block); -} - #if __GNUC__ >= 10 # pragma GCC diagnostic pop #endif diff --git a/gcc/testsuite/gcc.dg/format/gcc_diag-10.c b/gcc/testsuite/gcc.dg/format/gcc_diag-10.c index a2f99fe..dd930f9 100644 --- a/gcc/testsuite/gcc.dg/format/gcc_diag-10.c +++ b/gcc/testsuite/gcc.dg/format/gcc_diag-10.c @@ -64,8 +64,8 @@ void test_cdiag (tree t, gimple *gc) cdiag ("%D", t); /* { dg-warning ".D. conversion used unquoted" } */ cdiag ("%E", t); cdiag ("%F", t); /* { dg-warning ".F. conversion used unquoted" } */ - cdiag ("%G", gc); - cdiag ("%K", t); + cdiag ("%G", gc); /* { dg-warning "format" } */ + cdiag ("%K", t); /* { dg-warning "format" } */ cdiag ("%R"); /* { dg-warning "unmatched color reset directive" } */ cdiag ("%r", ""); /* { dg-warning "unterminated color directive" } */ @@ -80,8 +80,8 @@ void test_cdiag (tree t, gimple *gc) cdiag ("%<%D%>", t); cdiag ("%<%E%>", t); cdiag ("%<%F%>", t); - cdiag ("%<%G%>", gc); /* { dg-warning ".G. conversion used within a quoted sequence" } */ - cdiag ("%<%K%>", t); /* { dg-warning ".K. conversion used within a quoted sequence" } */ + cdiag ("%<%G%>", gc); /* { dg-warning "format" } */ + cdiag ("%<%K%>", t); /* { dg-warning "format" } */ cdiag ("%<%R%>"); /* { dg-warning "unmatched color reset directive" } */ cdiag ("%<%r%>", ""); /* { dg-warning "unterminated color directive" } */ @@ -103,8 +103,8 @@ void test_tdiag (tree t, gimple *gc) tdiag ("%D", t); /* { dg-warning ".D. conversion used unquoted" } */ tdiag ("%E", t); - tdiag ("%G", gc); - tdiag ("%K", t); + tdiag ("%G", gc); /* { dg-warning "format" } */ + tdiag ("%K", t); /* { dg-warning "format" } */ tdiag ("%R"); /* { dg-warning "unmatched color reset directive" } */ tdiag ("%r", ""); /* { dg-warning "unterminated color directive" } */ @@ -118,8 +118,8 @@ void test_tdiag (tree t, gimple *gc) tdiag ("%<%D%>", t); tdiag ("%<%E%>", t); - tdiag ("%<%G%>", gc); /* { dg-warning ".G. conversion used within a quoted sequence" } */ - tdiag ("%<%K%>", t); /* { dg-warning ".K. conversion used within a quoted sequence" } */ + tdiag ("%<%G%>", gc); /* { dg-warning "format" } */ + tdiag ("%<%K%>", t); /* { dg-warning "format" } */ tdiag ("%<%R%>"); /* { dg-warning "unmatched color reset directive" } */ tdiag ("%<%r%>", ""); /* { dg-warning "unterminated color directive" } */ @@ -138,8 +138,8 @@ void test_cxxdiag (tree t, gimple *gc) cxxdiag ("%D", t); /* { dg-warning ".D. conversion used unquoted" } */ cxxdiag ("%E", t); cxxdiag ("%F", t); /* { dg-warning ".F. conversion used unquoted" } */ - cxxdiag ("%G", gc); - cxxdiag ("%K", t); + cxxdiag ("%G", gc); /* { dg-warning "format" } */ + cxxdiag ("%K", t); /* { dg-warning "format" } */ cxxdiag ("%R"); /* { dg-warning "unmatched color reset directive" } */ cxxdiag ("%r", ""); /* { dg-warning "unterminated color directive" } */ diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_inlining.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_inlining.c index 02c4629..d2bfca0 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_inlining.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_inlining.c @@ -133,7 +133,7 @@ test_inlining (gimple *stmt) return; } - warning_at (call->location, 0, "%G%s", call, + warning_at (call->location, 0, "%s", TREE_STRING_POINTER (t_string)); } diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c index 1b636d7..8bb214b 100644 --- a/gcc/tree-diagnostic.c +++ b/gcc/tree-diagnostic.c @@ -276,15 +276,6 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec, t = va_arg (*text->args_ptr, tree); break; - case 'G': - percent_G_format (text); - return true; - - case 'K': - t = va_arg (*text->args_ptr, tree); - percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t)); - return true; - default: return false; } diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index bcbe669..fde07df 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -4433,32 +4433,6 @@ newline_and_indent (pretty_printer *pp, int spc) INDENT (spc); } -/* Handle the %K format for TEXT. Separate from default_tree_printer - so it can also be used in front ends. - The location LOC and BLOCK are expected to be extracted by the caller - from the %K argument arg via EXPR_LOCATION(arg) and TREE_BLOCK(arg). */ - -void -percent_K_format (text_info *text, location_t loc, tree block) -{ - text->set_location (0, loc, SHOW_RANGE_WITH_CARET); - gcc_assert (pp_ti_abstract_origin (text) != NULL); - *pp_ti_abstract_origin (text) = NULL; - - while (block - && TREE_CODE (block) == BLOCK - && BLOCK_ABSTRACT_ORIGIN (block)) - { - tree ao = BLOCK_ABSTRACT_ORIGIN (block); - if (TREE_CODE (ao) == FUNCTION_DECL) - { - *pp_ti_abstract_origin (text) = block; - break; - } - block = BLOCK_SUPERCONTEXT (block); - } -} - /* Print the identifier ID to PRETTY-PRINTER. */ void diff --git a/gcc/tree-pretty-print.h b/gcc/tree-pretty-print.h index cafe9aa..dacd256 100644 --- a/gcc/tree-pretty-print.h +++ b/gcc/tree-pretty-print.h @@ -52,7 +52,6 @@ extern int op_prio (const_tree); extern const char *op_symbol_code (enum tree_code); extern void pretty_print_string (pretty_printer *, const char *, size_t); extern void print_call_name (pretty_printer *, tree, dump_flags_t); -extern void percent_K_format (text_info *, location_t, tree); extern void pp_tree_identifier (pretty_printer *, tree); extern void dump_function_header (FILE *, tree, dump_flags_t); extern void pp_double_int (pretty_printer *pp, double_int d, bool uns); -- cgit v1.1 From 151b423a82f4bf15e3225833028f5258ea254cb9 Mon Sep 17 00:00:00 2001 From: Indu Bhagat Date: Tue, 6 Jul 2021 13:53:58 -0700 Subject: dwarf2ctf: the unit of sou field location is bits [PR101283] If the value of the DW_AT_data_member_location attribute is constant, the associated unit is bytes. This patch amends incorrect behaviour which was being exercised with -gdwarf-2. This caused some of the failures as noted in PR debug/101283 (specifically the BTF tests involving btm_offset). The testcase ctf-struct-array-2.c was erroneously checking for the value of ctm_offset in number of bytes. The patch fixes the calculation of the field location value for a struct member in dwarf2ctf and adjusts the testcase. This patch also fixes some of the failing tests as noted in PR debug/101283. 2021-07-06 Indu Bhagat gcc/ChangeLog: PR debug/101283 * dwarf2ctf.c (ctf_get_AT_data_member_location): Multiply by 8 to get number of bits. gcc/testsuite/ChangeLog: PR debug/101283 * gcc.dg/debug/ctf/ctf-struct-array-2.c: Adjust the value in the testcase. --- gcc/dwarf2ctf.c | 4 ++-- gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-2.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/dwarf2ctf.c b/gcc/dwarf2ctf.c index 08e1252..5e8a725 100644 --- a/gcc/dwarf2ctf.c +++ b/gcc/dwarf2ctf.c @@ -100,13 +100,13 @@ ctf_get_AT_data_member_location (dw_die_ref die) gcc_assert (!descr->dw_loc_oprnd2.v.val_unsigned); gcc_assert (descr->dw_loc_oprnd2.val_class == dw_val_class_unsigned_const); - field_location = descr->dw_loc_oprnd1.v.val_unsigned; + field_location = descr->dw_loc_oprnd1.v.val_unsigned * 8; } else { attr = get_AT (die, DW_AT_data_member_location); if (attr && AT_class (attr) == dw_val_class_const) - field_location = AT_int (attr); + field_location = AT_int (attr) * 8; else field_location = (get_AT_unsigned (die, DW_AT_data_member_location) diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-2.c index 9e698fd..37094b5d 100644 --- a/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-2.c +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-2.c @@ -10,6 +10,6 @@ /* { dg-final { scan-assembler-times "0x12000000\[\t \]+\[^\n\]*ctt_info" 1 } } */ /* { dg-final { scan-assembler-times "\[\t \]0x4\[\t \]+\[^\n\]*cta_nelems" 1 } } */ /* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctm_offset" 1 } } */ -/* { dg-final { scan-assembler-times "\[\t \]0x4\[\t \]+\[^\n\]*ctm_offset" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x20\[\t \]+\[^\n\]*ctm_offset" 1 } } */ static struct ranges {int from, to;} lim_regs[] = {{ 16, 7}, { 16, 6}, { 20, 7},{ 20, 6}}; -- cgit v1.1 From ee9a0e93156ff3d41450db74172abc8ae2471d1f Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 6 Jul 2021 15:15:53 -0600 Subject: Add test for [PR86650]. PR tree-optimization/86650 - -Warray-bounds missing inlining context gcc/testsuite/ChangeLog: PR tree-optimization/86650 * gcc.dg/Warray-bounds-76.c: New test. --- gcc/testsuite/gcc.dg/Warray-bounds-76.c | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-76.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-76.c b/gcc/testsuite/gcc.dg/Warray-bounds-76.c new file mode 100644 index 0000000..6711dc4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-76.c @@ -0,0 +1,35 @@ +/* PR tree-optimization/86650 - -Warray-bounds missing inlining context + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +static void f0 (int *p, int i) +{ + p[i] = 0; // { dg-warning "\\\[-Warray-bounds" } +} + +// Expect two instances of the text below: +// { dg-regexp "In function 'f0'," "first f0 prefix" { target *-*-* } 0 } +// { dg-regexp "In function 'f0'," "second f0 prefix" { target *-*-* } 0 } + +static void f1 (int *p, int i) { f0 (p + 1, i + 1); } +static void f2 (int *p, int i) { f1 (p + 1, i + 1); } + +extern int a2[2]; // { dg-note "'a2'" } + +void foo (void) +{ + f1 (a2 + 1, 1); +} + +// { dg-regexp " +inlined from 'foo' at \[^:\]+Warray-bounds-76.c:21:\\d+:" "inlined from foo" } + +extern int a3[3]; // { dg-note "'a3'" } + +void bar (void) +{ + f2 (a3 + 1, 1); +} + +// { dg-regexp " +inlined from 'f1' at \[^:\]+Warray-bounds-76.c:14:\\d+," "inlined from f1" } +// { dg-regexp " +inlined from 'f2' at \[^:\]+Warray-bounds-76.c:15:\\d+," "inlined from f2" } +// { dg-regexp " +inlined from 'bar' at \[^:\]+Warray-bounds-76.c:30:\\d+:" "inlined from bar" } -- cgit v1.1 From e8db5f70f27b6de8139339ef1866eaa153c2bf67 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 6 Jul 2021 15:58:02 -0600 Subject: Add test for [PR55881]. PR c++/55881 gcc/testsuite/ChangeLog: * g++.dg/warn/uninit-pr55881.C: New test. --- gcc/testsuite/g++.dg/warn/uninit-pr55881.C | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 gcc/testsuite/g++.dg/warn/uninit-pr55881.C (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/warn/uninit-pr55881.C b/gcc/testsuite/g++.dg/warn/uninit-pr55881.C new file mode 100644 index 0000000..b01f4e7 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/uninit-pr55881.C @@ -0,0 +1,34 @@ +/* PR middle-end/55881 - #pragma GCC diagnostic ignored ignored when inlining + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +struct I +{ + int i; + int foo (struct I *n) + { + return n->i + 10; // { dg-bogus "-Wmaybe-uninitialized" } + } + + I () : i (5) {} +}; + +int main (int argc, char **) +{ + struct I i, *n; + + if (argc > 10) + { + n = new I; + i.i = i.foo (n); + } + + if (argc > 2) + { +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + return i.foo (n); +#pragma GCC diagnostic pop + } + + return 0; +} -- cgit v1.1 From 97bcacfb5ac49afa4e305489dd110cc446451549 Mon Sep 17 00:00:00 2001 From: Indu Bhagat Date: Tue, 6 Jul 2021 16:02:38 -0700 Subject: CTF testsuite: Remove explicit check on ctv_typeidx The value of ctv_typeidx is the CTF type ID of the data type of the associated variable. The order in which the CTF types are added can change across platforms and also as the code evolves, hence changing the CTF type ID. As there is no direct and portable method of testing that the data type of a CTF variable is of a specific kind, remove the check on ctv_typeidx. This also fixes a subset of failures as seen on Darwin. 2021-07-06 Indu Bhagat gcc/testsuite/ChangeLog: PR debug/101283 * gcc.dg/debug/ctf/ctf-attr-mode-1.c: Remove the check for ctv_typeidx. --- gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-mode-1.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-mode-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-mode-1.c index fc3af03..c4801a7 100644 --- a/gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-mode-1.c +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-mode-1.c @@ -1,7 +1,10 @@ /* Test CTF generation works well with ((mode)) attribute. In this testcase, CTF should report type of bqi to be an enum and - not an int. */ + not an int. Also, CTF for typedef of enum should exist. However, there + are no direct and portable methods of checking that a CTF type / CTF + variable refers to a specific CTF type, so this testcase merely asserts + for existence of individual CTF records. */ /* { dg-do compile ) */ /* { dg-options "-O0 -gctf -dA" } */ @@ -16,7 +19,5 @@ /* { dg-final { scan-assembler-times "\[\t \]0x22000003\[\t \]+\[^\n\]*ctt_info" 1 } } */ /* { dg-final { scan-assembler-times "\[\t \]0x2a000000\[\t \]+\[^\n\]*ctt_info" 1 } } */ -/* { dg-final { scan-assembler-times "\[\t \]0x3\[\t \]+\[^\n\]*ctv_typeidx" 1} } */ - typedef enum { B1 = 1, B2 = 2, B3 = 3 } B; B __attribute__ ((mode (QI))) bqi; -- cgit v1.1 From d9e9532bb3bf5db4cd6afd49d343ede5b27c3c9f Mon Sep 17 00:00:00 2001 From: Indu Bhagat Date: Tue, 6 Jul 2021 16:11:47 -0700 Subject: BTF testsuite: Remove explicit check on btm_type The value of btm_type is the BTF type ID of the referred type. The order in which the BTF types are added can change across platforms and also as the code evolves, hence changing the BTF type ID. As there is no direct and portable method of testing that a BTF type refers to another BTF type of a specific kind, remove the explicit check on btm_type. This patch adjusts the testcase without affecting the test coverage as other testcases already have similar constructs. It also fixes a subset of failures as seen on Darwin. 2021-07-06 Indu Bhagat gcc/testsuite/ChangeLog: PR debug/101283 * gcc.dg/debug/btf/btf-bitfields-3.c: Remove the check on btm_type. --- gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c b/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c index 5e68416..0e00f2b 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c @@ -11,7 +11,6 @@ [2] int 'unsigned int' size=4 offset=0 bits=32 [3] struct 'bitt' size=4 member 'f' type=1 bitfield_size=2 bit_offset=0 - member 'data' type=2 bitfield_size=14 bit_offset=2 */ /* { dg-do compile } */ @@ -19,15 +18,12 @@ /* Enum with 4 members. */ /* { dg-final { scan-assembler-times "\[\t \]0x6000004\[\t \]+\[^\n\]*btt_info" 1 } } */ -/* Struct with bitfield members, and 2 members. */ -/* { dg-final { scan-assembler-times "\[\t \]0x84000002\[\t \]+\[^\n\]*btt_info" 1 } } */ +/* Struct with 1 bitfield member. */ +/* { dg-final { scan-assembler-times "\[\t \]0x84000001\[\t \]+\[^\n\]*btt_info" 1 } } */ /* Bitfield "f" points to type ID 1. */ /* { dg-final { scan-assembler-times "\[\t \]0x1\[\t \]+\[^\n\]*btm_type" 1 } } */ -/* Bitfield "data" points to type ID 2. */ -/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*btm_type" 1 } } */ - enum foo { BAR = 0, @@ -39,5 +35,4 @@ enum foo struct bitt { enum foo f : 2; - unsigned data : 14; } bitty; -- cgit v1.1 From 6fba0eea8d6464966ac6d37af98a7487a9a03d19 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Wed, 7 Jul 2021 00:17:12 +0000 Subject: Daily bump. --- gcc/ChangeLog | 140 +++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/ada/ChangeLog | 357 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/c-family/ChangeLog | 6 + gcc/c/ChangeLog | 4 + gcc/cp/ChangeLog | 4 + gcc/fortran/ChangeLog | 7 + gcc/testsuite/ChangeLog | 121 ++++++++++++++++ 8 files changed, 640 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4e6b874..1d07abd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,143 @@ +2021-07-06 Indu Bhagat + + PR debug/101283 + * dwarf2ctf.c (ctf_get_AT_data_member_location): Multiply by 8 to get + number of bits. + +2021-07-06 Martin Sebor + + * gimple-pretty-print.c (percent_G_format): Remove. + * tree-diagnostic.c (default_tree_printer): Remove calls. + * tree-pretty-print.c (percent_K_format): Remove. + * tree-pretty-print.h (percent_K_format): Remove. + +2021-07-06 Martin Sebor + + * config/aarch64/aarch64-builtins.c (aarch64_simd_expand_builtin): + Remove %K and use error_at. + (aarch64_expand_fcmla_builtin): Same. + (aarch64_expand_builtin_tme): Same. + (aarch64_expand_builtin_memtag): Same. + * config/arm/arm-builtins.c (arm_expand_acle_builtin): Same. + (arm_expand_builtin): Same. + * config/arm/arm.c (bounds_check): Same. + +2021-07-06 Martin Sebor + + * builtins.c (warn_string_no_nul): Remove %G. + (maybe_warn_for_bound): Same. + (warn_for_access): Same. + (check_access): Same. + (check_strncat_sizes): Same. + (expand_builtin_strncat): Same. + (expand_builtin_strncmp): Same. + (expand_builtin): Same. + (expand_builtin_object_size): Same. + (warn_dealloc_offset): Same. + (maybe_emit_free_warning): Same. + * calls.c (maybe_warn_alloc_args_overflow): Same. + (maybe_warn_nonstring_arg): Same. + (maybe_warn_rdwr_sizes): Same. + * expr.c (expand_expr_real_1): Remove %K. + * gimple-fold.c (gimple_fold_builtin_strncpy): Remove %G. + (gimple_fold_builtin_strncat): Same. + * gimple-ssa-sprintf.c (format_directive): Same. + (handle_printf_call): Same. + * gimple-ssa-warn-alloca.c (pass_walloca::execute): Same. + * gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same. + (maybe_diag_access_bounds): Same. Call gimple_location. + (check_bounds_or_overlap): Same. + * trans-mem.c (ipa_tm_scan_irr_block): Remove %K. Simplify. + * tree-ssa-ccp.c (pass_post_ipa_warn::execute): Remove %G. + * tree-ssa-strlen.c (maybe_warn_overflow): Same. + (maybe_diag_stxncpy_trunc): Same. + (handle_builtin_stxncpy_strncat): Same. + (maybe_warn_pointless_strcmp): Same. + * tree-ssa-uninit.c (maybe_warn_operand): Same. + +2021-07-06 Uroš Bizjak + + PR target/97194 + * config/i386/predicates.md (vec_setm_operand): Enable + register_operand for TARGET_SSE4_1. + * config/i386/mmx.md (vec_setv2hi): Use vec_setm_operand + as operand 2 predicate. Call ix86_expand_vector_set_var + for non-constant index operand. + (vec_setv4qi): Use vec_setm_mmx_operand as operand 2 predicate. + Call ix86_expand_vector_set_var for non-constant index operand. + +2021-07-06 Jeff Law + + * config/h8300/jumpcall.md (*branch): When possible, generate + the comparison in CCZN mode. + * config/h8300/predicates.md (simple_memory_operand): Reject all + auto-increment addressing modes. + +2021-07-06 Iain Sandoe + + PR bootstrap/100246 + * config/i386/i386.h (struct stringop_algs): Define a CTOR for + this type. + +2021-07-06 Richard Biener + + * doc/md.texi (vec_fmaddsub4): Document. + (vec_fmsubadd4): Likewise. + * optabs.def (vec_fmaddsub$a4): Add. + (vec_fmsubadd$a4): Likewise. + * internal-fn.def (IFN_VEC_FMADDSUB): Add. + (IFN_VEC_FMSUBADD): Likewise. + * tree-vect-slp-patterns.c (addsub_pattern::recognize): + Refactor to handle IFN_VEC_FMADDSUB and IFN_VEC_FMSUBADD. + (addsub_pattern::build): Likewise. + * tree-vect-slp.c (vect_optimize_slp): CFN_VEC_FMADDSUB + and CFN_VEC_FMSUBADD are not transparent for permutes. + * config/i386/sse.md (vec_fmaddsub4): New expander. + (vec_fmsubadd4): Likewise. + +2021-07-06 Richard Biener + + * doc/invoke.texi (fmove-loop-stores): Document. + * common.opt (fmove-loop-stores): New option. + * opts.c (default_options_table): Enable -fmove-loop-stores + at -O1 but not -Og. + * tree-ssa-loop-im.c (pass_lim::execute): Pass + flag_move_loop_stores instead of true to + loop_invariant_motion_in_fun. + +2021-07-06 Iain Sandoe + + * doc/install.texi: Document --with-dsymutil. + +2021-07-06 Andrew Pinski + + PR tree-optimization/101256 + * dbgcnt.def (phiopt_edge_range): New counter. + * tree-ssa-phiopt.c (replace_phi_edge_with_variable): + Check to make sure the new name is defined in the same + bb as the conditional before duplicating range info. + Also add debug counter. + +2021-07-06 Kewen Lin + + PR rtl-optimization/100328 + * config/i386/i386-options.c (ix86_option_override_internal): + Set param_ira_consider_dup_in_all_alts to 0. + +2021-07-06 Kewen Lin + + PR rtl-optimization/100328 + * doc/invoke.texi (ira-consider-dup-in-all-alts): Document new + parameter. + * ira.c (ira_get_dup_out_num): Adjust as parameter + param_ira_consider_dup_in_all_alts. + * params.opt (ira-consider-dup-in-all-alts): New. + * ira-conflicts.c (process_regs_for_copy): Add one parameter + single_input_op_has_cstr_p. + (get_freq_for_shuffle_copy): New function. + (add_insn_allocno_copies): Adjust as single_input_op_has_cstr_p. + * ira-int.h (ira_get_dup_out_num): Add one bool parameter. + 2021-07-05 Jeff Law * config/h8300/shiftrotate.md (shift-by-variable patterns): Update to diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 740061a..b905321 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210706 +20210707 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index d1116c9..7d17f9e 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,360 @@ +2021-07-06 Bob Duff + + * atree.ads (Current_Error_Node): Initialize to Empty. + +2021-07-06 Steve Baird + + * exp_put_image.adb: Eliminate references to + Debug_Flag_Underscore_Z. Change the meaning of the function + Enable_Put_Image. Previously, a result of False for a tagged + type would mean that the type does not get a Put_Image (PI) + routine at all. Now, it means that the type gets a PI routine + with very abbreviated functionality (just a call to + Unknown_Put_Image). This resolves problems in mixing code + compiled with and without the -gnat2022 switch. + * exp_ch3.adb: Enable_Put_Image no longer participates in + determining whether a tagged type gets a Put_Image procedure. A + tagged type does not get a Put_Image procedure if the type + Root_Buffer_Type is unavailable. This is needed to support cross + targets where tagged types are supported but the type + Root_Buffer_Type is not available. + * exp_dist.adb: Add workarounds for some problems that arise + when using the (obsolete?) Garlic implementation of the + distributed systems annex with Ada 2022 constructs. + * libgnat/a-sttebu.ads: Workaround a bootstrapping problem. + Older compilers do not support raise expressions, so revise the + the Pre'Class condition to meet this requirement without + changing the condition's behavior at run time. + +2021-07-06 Eric Botcazou + + * repinfo-input.adb (JSON_Entity_Kind, Read_Variant_Part): Fix + typo in comment. + +2021-07-06 Steve Baird + + * sem_ch5.adb (Analyze_Assignment): Add new nested function, + Omit_Range_Check_For_Streaming, and make call to + Apply_Scalar_Range_Check conditional on the result of this new + function. + * exp_attr.adb (Compile_Stream_Body_In_Scope): Eliminate Check + parameter, update callers. The new + Omit_Range_Check_For_Streaming parameter takes the place of the + old use of calling Insert_Action with Suppress => All_Checks, + which was insufficiently precise (it did not allow suppressing + checks for one component but not for another). + (Expand_N_Attribute_Reference): Eliminate another "Suppress => + All_Checks" from an Insert_Action call, this one in generating + the expansion of a T'Read attribute reference for a composite + type T. + +2021-07-06 Ghjuvan Lacambre + + * sem_ch5.adb (Analyze_Loop_Parameter_Specification): Check for + empty loops caused by constraints. + +2021-07-06 Nicolas Roche + + * rtinit.c (skip_quoted_string): Handle malformed command line + with no closing double quote. + (skip_argument): Handle case in which a null character is + encountered by skip_quote_string. + +2021-07-06 Piotr Trojanek + + * uname.adb (Add_Node_Name): Replace local constant whose + initial expression was evaluated even when unnecessary with just + that expression that is evaluated at most once and only when + needed. + +2021-07-06 Piotr Trojanek + + * lib.adb (Remove_Unit): Replace defensive code with an + assertion. + * par-load.adb (Load): Address a question mark in the comment. + +2021-07-06 Piotr Trojanek + + * sem_util.adb (Enclosing_Comp_Unit_Node): When the loop exits + the Current_Node is either an N_Compilation_Unit node or Empty, + so simply return it without redundant checks. + +2021-07-06 Piotr Trojanek + + * lib-load.adb (Load_Unit): Remove excessive whitespace. + * lib.adb (Is_Internal_Unit, Is_Predefined_Unit): Likewise. + * par-ch10.adb (P_Compilation_Unit): Simplify with membership + test. + * par-load.adb (Load): Likewise. + * uname.adb (Get_Unit_Name): Likewise. + +2021-07-06 Piotr Trojanek + + * lib-writ.adb (Ensure_System_Dependency): Simplify by reusing a + constant name. + +2021-07-06 Steve Baird + + * exp_ch5.adb + (Expand_N_Case_Statement.Expand_General_Case_Statement.Pattern_Match): + When generating an equality test for a statically known discrete + value, only generate the numeric value if the discrete type is + not an enumeration type. If it is an enumeration type, then + call Get_Enum_Lit_From_Pos instead. + +2021-07-06 Justin Squirek + + * par-ch6.adb (Get_Return_Kind): Removed. + (Is_Extended): Created to identify simple and "when" return + statements from extended return statements. + (P_Return_Statement): Merged simple and "when" return statement + processing. + +2021-07-06 Gary Dismukes + + * sem_ch4.adb (Try_One_Prefix_Interpretation): Augment test of + "not Extensions_Allowed" with test for absence of Obj_Type's + primitive operations Elist, as an additional condition for early + return from this procedure. + +2021-07-06 Gary Dismukes + + * exp_ch4.adb (Process_Transient_In_Expression): In one comment, + fix two typos and reorder wording of one sentence, plus minor + reformatting. + +2021-07-06 Justin Squirek + + * exp_ch5.adb (Expand_Formal_Container_Element_Loop): Remove + legacy expansion of element iterators, and use expansion form + used by unconstrained element types in the general case. + +2021-07-06 Ed Schonberg + + * exp_ch4.adb (Process_Transient_In_Expression): Ensure that + Fin_Context, used to insert finalization code for the + expression, is a list member: the value returned by + Find_Hook_Context may be an expression node when the transient + is part of a larger expression and it has a non-boolean type. + +2021-07-06 Yannick Moy + + * sem_case.adb: Fix error message. + +2021-07-06 Bob Duff + + * tbuild.adb (Convert_To): Add assert, along with a comment. + (Make_DT_Access): Remove this function, which is not used. It + was incorrect anyway (the call to New_Occurrence_Of should not + be there). + (Unchecked_Convert_To): Add assert. The previous version's test + for unchecked conversion to the same type was redundant and + could never be true, because the previous 'if' already checked + for ANY expression of the same type. Remove that, and replace + with a test for unchecked conversion to a related type. + Otherwise, we somethings get things like + "finalize(some_type!(some_type!(x)))" in the generated code, + where x is already of type some_type, but we're converting it to + the private type and then to the full type or vice versa (so the + types aren't equal, so the previous 'if' doesn't catch it). + Avoid updating the Parent. This is not necessary; the Parent + will be updated if/when the node is attached to the tree. + * tbuild.ads: Fix comments. No need to say "this is safe" when + we just explained that a few lines earlier. Remove + Make_DT_Access. + * sinfo.ads: Add comments. + * exp_ch7.adb (Make_Finalize_Address_Stmts): Minor comment fix. + * gen_il-gen.adb, gen_il-gen.ads, gen_il-gen-gen_nodes.adb, + gen_il-internals.ads: Implement a feature where you can put: + Nmake_Assert => "expr" where expr is a boolean expression in a + call to Create_Concrete_Node_Type. It is added in a pragma + Assert in the Nmake.Make_... function for that type. + +2021-07-06 Gary Dismukes + + * checks.adb: Remove calls of Set_Do_Tag_Check (N, False). + * einfo.ads: Remove hanging unneeded ??? comment ("this real description + was clobbered"). + * exp_util.ads (Insert_Actions_After): Remove ??? from spec comment. + * gen_il-fields.ads (Opt_Field_Enum): Remove literals + Do_Accessibility_Check and Do_Tag_Check. + * gen_il-gen-gen_nodes.adb: Remove all calls to Sm for + Do_Accessibility_Check and Do_Tag_Check. + * sem_type.ads (Is_Subtype_Of): Remove obsolete ??? + comment (function is not limited to scalar subtypes). + * sem_util.ads (Is_Local_Variable_Reference): Revise comment to + mention out-mode parameters as well, and remove ???. + (Propagate_Concurrent_Flags): Minor reformatting. + (Propagate_Invariant_Attributes): Typo fix. + (Propagate_Predicate_Attributes): Indicate what is propagated + and remove ??? comment. + * sem_util.adb (Cannot_Raise_Constraint_Error): Remove unneeded + test of Do_Tag_Check. + (Is_Local_Variable_Reference): Extend function to testing for + formals of mode out as well. + * sinfo.ads: Remove ??? comment about flag + Convert_To_Return_False indicating that the flag is obsolete (in + fact it's used). Remove references to Do_Accessibility_Check and + Do_Tag_Check (and the two associated ??? comments), as these + flags are unneeded. + * sinfo-cn.adb (Change_Conversion_To_Unchecked): Remove call of + Set_Do_Tag_Check (N, False). + * targparm.ads (Support_Atomic_Primitives_On_Target): Remove ??? + comment, plus minor reformatting. + +2021-07-06 Justin Squirek + + * par-ch6.adb (Get_Return_Kind): Properly handle the case of a + "return when" statement in the procedure case. + +2021-07-06 Bob Duff + + * sem.ads (Node_To_Be_Wrapped): Minor comment fix. + * exp_ch7.adb (Establish_Transient_Scope): Misc cleanups and + comment improvements. + (Set_Node_To_Be_Wrapped): Remove -- not worth putting this code + in a separate procedure, called only once. + * sem_util.adb (Requires_Transient_Scope): Assert that our + parameter has the right Kind. It probably shouldn't be E_Void, + but that is passed in in some cases. + (Ensure_Minimum_Decoration): Move the call later, so we know Typ + is Present, and remove "if Present (Typ)" from this procedure. + * exp_aggr.adb (Convert_To_Assignments): Use membership test, + and avoid the "if False" idiom. + (Expand_Array_Aggregate): Remove a ??? comment. + * sem_ch8.adb (Push_Scope): Take advantage of the full coverage + rules for aggregates. + * sem_res.adb (Resolve_Declare_Expression): Remove test for + Is_Type -- that's all it can be. Use named notation in call to + Establish_Transient_Scope. + * libgnat/a-cdlili.adb (Adjust): Remove redundant code. + (Clear): Remove "pragma Warnings (Off);", which wasn't actually + suppressing any warnings. + +2021-07-06 Bob Duff + + * gen_il-gen-gen_nodes.adb: Change the parent of + N_Exception_Declaration to be N_Declaration. Minor comment fix. + +2021-07-06 Ed Schonberg + + * exp_ch4.adb (Expand_N_Type_Conversion): If the conversion is + the name of an assignment operation do not apply predicate check + to it prior to the assignment. + +2021-07-06 Bob Duff + + * libgnat/a-conhel.adb: Assert that tampering counts remain + between 0 and 2**31-1. This makes debugging of + finalization-related bugs easier. + +2021-07-06 Doug Rupp + + * Makefile.rtl (LIBGNAT_TARGET_PAIRS): Use s-osprim__posix.adb + vice s-osprim__vxworks.adb for all vxworks7r2 targets. + +2021-07-06 Richard Kenner + + * gen_il-types.ads (Void_Or_Type_Kind, + Exception_Or_Object_Kind): Declare. + * gen_il-gen-gen_entities.adb: Likewise. + +2021-07-06 Gary Dismukes + + * doc/gnat_rm/implementation_defined_pragmas.rst: Add a + description of the feature of prefixed-view calls for untagged + types to the section on pragma Extensions_Allowed. + * gnat_rm.texi: Regenerate. + * einfo.ads: Update specification for + Direct_Primitive_Operations to reflect its use for untagged + types when Extensions_Allowed is True. + * gen_il-gen-gen_entities.adb: Allow Direct_Primitive_Operations + as a field of untagged classes of types by removing the "Pre" + test of "Is_Tagged_Type (N)", and making that field generally + available for all types and subtypes by defining it for + Type_Kind and removing its specification for individual classes + of types. + * sem_ch3.adb (Analyze_Full_Type_Declaration): Initialize the + Direct_Primitive_Operations list when not already set for the + new (sub)type and its base type (except when Ekind of the type + is E_Void, which can happen due to errors in cases where + Derived_Type_Declaration is called and perhaps in other + situations). + (Analyze_Subtype_Declaration): Inherit + Direct_Primitive_Operations list from the base type, for record + and private cases. + (Build_Derived_Record_Type): Initialize the + Direct_Primitive_Operations list for derived record and private + types. + (Build_Derived_Type): Initialize the Direct_Primitive_Operations + list for derived types (and also for their associated base types + when needed). + (Process_Full_View): For full types that are untagged record and + private types, copy the primitive operations of the partial view + to the primitives list of the full view. + * sem_ch4.adb (Analyze_Selected_Component): Allow prefixed + notation for subprogram calls in the case of untagged + types (when Extensions_Allowed is True). In the case where + Is_Private_Type (Prefix_Type) is True, call Try_Object_Operation + when a discriminant selector wasn't found. Also call + Try_Object_Operation in other type kind cases (when + Extensions_Allowed is True). + (Try_Object_Operation.Try_One_Prefixed_Interpretation): Prevent + early return in the untagged case (when Extensions_Allowed is + True). Condition main call to Try_Primitive_Operation on the + type having primitives, and after that, if Prim_Result is False, + test for case where the prefix type is a named access type with + primitive operations and in that case call + Try_Primitive_Operation after temporarily resetting Obj_Type to + denote the access type (and restore it to the designated type + after the call) + (Try_Object_Operation.Valid_First_Argument_Of): Do matching type + comparison by testing Base_Type (Obj_Type) against + Base_Type (Typ), rather than against just Typ, to properly + handle cases where the object prefix has a constrained + subtype. (Fixes a bug discovered while working on this + feature.) + * sem_ch6.adb + (New_Overloaded_Entity.Check_For_Primitive_Subprogram): Add a + primitive of an untagged type to the type's list of primitive + operations, for both explicit and implicit (derived, so + Comes_From_Source is False) subprogram declarations. In the case + where the new primitive overrides an inherited subprogram, + locate the primitives Elist that references the overridden + subprogram, and replace that element of the list with the new + subprogram (done by calling the new procedure + Add_Or_Replace_Untagged_Primitive on the result type and each + formal atype). + (Check_For_Primitive_Subprogram.Add_Or_Replace_Untagged_Primitive): + New nested procedure to either add or replace an untagged + primitive subprogram in a given type's list of primitive + operations (replacement happens in case where the new subprogram + overrides a primitive of the type). + * sem_ch7.adb (New_Private_Type): When Extensions_Allowed is + True, initialize the Direct_Primitive_Operations list of a + private type to New_Elmt_List in the case of untagged types. + * sem_ch8.adb (Find_Selected_Component): In the case where the + prefix is an entity name, relax condition that tests + Has_Components so that Analyze_Selected_Component will also be + called when Extensions_Allowed is True and the prefix type is + any type. + +2021-07-06 Ed Schonberg + + * sem_ch6.adb (Analyze_Subprogram_Body_Helper): Do not perform + conformance check when the subprogram body has been created for + an expression function that is not a completion of a previous + specification, because the profile of the constructed body is + copied from the expression function itself. + +2021-07-06 Steve Baird + + * doc/gnat_rm/implementation_of_specific_ada_features.rst: Add a + warning indicating that the details of the default (i.e., + selected by the compiler) implementation of T'Put_Image for a + nonscalar type T are subject to change. + * gnat_rm.texi: Regenerate. + 2021-07-05 Pierre-Marie de Rodat * gnat-style.texi, gnat_rm.texi, gnat_ugn.texi: Regenerate. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index cd01f5c..0f1b45d 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2021-07-06 Martin Sebor + + * c-format.c (gcc_tdiag_char_table): Remove support for %G and %K. + (gcc_cdiag_char_table): Same. + (gcc_cxxdiag_char_table): Same. + 2021-07-02 Jakub Jelinek * c-common.h (enum c_omp_directive_kind): New enum. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 27d6e89..ef6f4ad 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,7 @@ +2021-07-06 Martin Sebor + + * c-objc-common.c (c_tree_printer): Remove support for %G and %K. + 2021-07-02 Jakub Jelinek PR c/101297 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 90a2d2a..31deb04 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,7 @@ +2021-07-06 Martin Sebor + + * error.c (cp_printer): Remove support for %G and %K. + 2021-07-02 Jakub Jelinek * parser.h (struct cp_lexer): Add in_omp_attribute_pragma member. diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index f9c97b0..3cf3e7d 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,10 @@ +2021-07-06 Thomas Koenig + + PR fortran/100227 + * frontend-passes.c (traverse_io_block): Adjust test for + when a variable is eligible for the transformation to + array slice. + 2021-06-28 Martin Sebor * trans-array.c (trans_array_constructor): Replace direct uses diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 87cd3ed7..7e2e6b3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,124 @@ +2021-07-06 Indu Bhagat + + PR debug/101283 + * gcc.dg/debug/btf/btf-bitfields-3.c: Remove the check on btm_type. + +2021-07-06 Indu Bhagat + + PR debug/101283 + * gcc.dg/debug/ctf/ctf-attr-mode-1.c: Remove the check for ctv_typeidx. + +2021-07-06 Martin Sebor + + PR c++/55881 + * g++.dg/warn/uninit-pr55881.C: New test. + +2021-07-06 Martin Sebor + + PR tree-optimization/86650 + * gcc.dg/Warray-bounds-76.c: New test. + +2021-07-06 Indu Bhagat + + PR debug/101283 + * gcc.dg/debug/ctf/ctf-struct-array-2.c: Adjust the value in the testcase. + +2021-07-06 Martin Sebor + + * gcc.dg/format/gcc_diag-10.c: Update expected warnings. + * gcc.dg/plugin/diagnostic_plugin_test_inlining.c: Remove %G. + +2021-07-06 Martin Sebor + + * gcc.dg/Wobjsize-1.c: Prune expected output. + * gcc.dg/Warray-bounds-71.c: New test. + * gcc.dg/Warray-bounds-71.h: New test header. + * gcc.dg/Warray-bounds-72.c: New test. + * gcc.dg/Warray-bounds-73.c: New test. + * gcc.dg/Warray-bounds-74.c: New test. + * gcc.dg/Warray-bounds-75.c: New test. + * gcc.dg/Wfree-nonheap-object-4.c: Adjust expected output. + * gcc.dg/Wfree-nonheap-object-5.c: New test. + * gcc.dg/Wfree-nonheap-object-6.c: New test. + * gcc.dg/pragma-diag-10.c: New test. + * gcc.dg/pragma-diag-9.c: New test. + * gcc.dg/uninit-suppress_3.c: New test. + * gcc.dg/pr79214.c: Xfail tests. + * gcc.dg/tree-ssa/builtin-sprintf-warn-27.c: New test. + * gcc.dg/format/c90-printf-1.c: Adjust expected output. + +2021-07-06 Uroš Bizjak + + PR target/97194 + * gcc.target/i386/sse4_1-vec-set-1a.c: New test. + * gcc.target/i386/sse4_1-vec-set-2a.c: Ditto. + +2021-07-06 Richard Biener + + * gcc.target/i386/vect-fmaddsubXXXpd.c: New testcase. + * gcc.target/i386/vect-fmaddsubXXXps.c: Likewise. + * gcc.target/i386/vect-fmsubaddXXXpd.c: Likewise. + * gcc.target/i386/vect-fmsubaddXXXps.c: Likewise. + +2021-07-06 Andrew Pinski + + PR tree-optimization/101256 + * g++.dg/torture/pr101256.C: New test. + +2021-07-06 Thomas Koenig + + PR fortran/100227 + * gfortran.dg/implied_do_io_7.f90: New test. + +2021-07-06 Kewen Lin + + PR rtl-optimization/100328 + * gcc.target/aarch64/sve/acle/asm/div_f16.c: Remove one xfail. + * gcc.target/aarch64/sve/acle/asm/div_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/div_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/divr_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/divr_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/divr_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mad_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mad_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mad_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mla_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mla_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mla_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mls_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mls_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mls_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/msb_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/msb_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/msb_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mulx_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mulx_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/mulx_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmad_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmad_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmad_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmla_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmla_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmla_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmls_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmls_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmls_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmsb_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmsb_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/nmsb_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/sub_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/sub_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/sub_f64.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/subr_f16.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/subr_f32.c: Likewise. + * gcc.target/aarch64/sve/acle/asm/subr_f64.c: Likewise. + +2021-07-06 Indu Bhagat + + PR debug/101283 + * gcc.dg/debug/btf/btf-cvr-quals-1.c: Use -gdwarf-4 on Darwin targets. + * gcc.dg/debug/ctf/ctf-cvr-quals-1.c: Likewise. + 2021-07-05 Andrew Pinski PR tree-optimization/101039 -- cgit v1.1 From 98bfd845e93937d92ca844d7fa7e853ad51c6193 Mon Sep 17 00:00:00 2001 From: liuhongt Date: Wed, 7 Jul 2021 15:19:42 +0800 Subject: Add avx512 tests for MADDSUB and FMSUBADD SLP vectorization patterns. gcc/testsuite/ChangeLog: * gcc.target/i386/avx512f-vect-fmaddsubXXXpd.c: New test. * gcc.target/i386/avx512f-vect-fmaddsubXXXps.c: New test. * gcc.target/i386/avx512f-vect-fmsubaddXXXpd.c: New test. * gcc.target/i386/avx512f-vect-fmsubaddXXXps.c: New test. --- .../gcc.target/i386/avx512f-vect-fmaddsubXXXpd.c | 41 ++++++++++++++++++ .../gcc.target/i386/avx512f-vect-fmaddsubXXXps.c | 50 ++++++++++++++++++++++ .../gcc.target/i386/avx512f-vect-fmsubaddXXXpd.c | 41 ++++++++++++++++++ .../gcc.target/i386/avx512f-vect-fmsubaddXXXps.c | 50 ++++++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/avx512f-vect-fmaddsubXXXpd.c create mode 100644 gcc/testsuite/gcc.target/i386/avx512f-vect-fmaddsubXXXps.c create mode 100644 gcc/testsuite/gcc.target/i386/avx512f-vect-fmsubaddXXXpd.c create mode 100644 gcc/testsuite/gcc.target/i386/avx512f-vect-fmsubaddXXXps.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-fmaddsubXXXpd.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-fmaddsubXXXpd.c new file mode 100644 index 0000000..734f9e0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-fmaddsubXXXpd.c @@ -0,0 +1,41 @@ +/* { dg-do run } */ +/* { dg-require-effective-target avx512f } */ +/* { dg-options "-O3 -mfma -save-temps -mavx512f -mprefer-vector-width=512" } */ + +#include "fma-check.h" +void __attribute__((noipa)) +check_fmaddsub (double * __restrict a, double *b, double *c, int n) +{ + for (int i = 0; i < n; ++i) + { + a[8*i + 0] = b[8*i + 0] * c[8*i + 0] - a[8*i + 0]; + a[8*i + 1] = b[8*i + 1] * c[8*i + 1] + a[8*i + 1]; + a[8*i + 2] = b[8*i + 2] * c[8*i + 2] - a[8*i + 2]; + a[8*i + 3] = b[8*i + 3] * c[8*i + 3] + a[8*i + 3]; + a[8*i + 4] = b[8*i + 4] * c[8*i + 4] - a[8*i + 4]; + a[8*i + 5] = b[8*i + 5] * c[8*i + 5] + a[8*i + 5]; + a[8*i + 6] = b[8*i + 6] * c[8*i + 6] - a[8*i + 6]; + a[8*i + 7] = b[8*i + 7] * c[8*i + 7] + a[8*i + 7]; + } +} + +static void +fma_test (void) +{ + if (!__builtin_cpu_supports ("avx512f")) + return; + double a[8], b[8], c[8]; + for (int i = 0; i < 8; ++i) + { + a[i] = i; + b[i] = 3*i; + c[i] = 7*i; + } + check_fmaddsub (a, b, c, 1); + const double d[8] = { 0., 22., 82., 192., 332., 530., 750., 1036.}; + for (int i = 0; i < 8; ++i) + if (a[i] != d[i]) + __builtin_abort (); +} + +/* { dg-final { scan-assembler {(?n)fmaddsub...pd[ \t].*%zmm[0-9]} } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-fmaddsubXXXps.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-fmaddsubXXXps.c new file mode 100644 index 0000000..ae196c5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-fmaddsubXXXps.c @@ -0,0 +1,50 @@ +/* { dg-do run } */ +/* { dg-require-effective-target avx512f } */ +/* { dg-options "-O3 -mavx512f -mprefer-vector-width=512 -save-temps" } */ + +#include "fma-check.h" +void __attribute__((noipa)) +check_fmaddsub (float * __restrict a, float *b, float *c, int n) +{ + for (int i = 0; i < n; ++i) + { + a[16*i + 0] = b[16*i + 0] * c[16*i + 0] - a[16*i + 0]; + a[16*i + 1] = b[16*i + 1] * c[16*i + 1] + a[16*i + 1]; + a[16*i + 2] = b[16*i + 2] * c[16*i + 2] - a[16*i + 2]; + a[16*i + 3] = b[16*i + 3] * c[16*i + 3] + a[16*i + 3]; + a[16*i + 4] = b[16*i + 4] * c[16*i + 4] - a[16*i + 4]; + a[16*i + 5] = b[16*i + 5] * c[16*i + 5] + a[16*i + 5]; + a[16*i + 6] = b[16*i + 6] * c[16*i + 6] - a[16*i + 6]; + a[16*i + 7] = b[16*i + 7] * c[16*i + 7] + a[16*i + 7]; + a[16*i + 8] = b[16*i + 8] * c[16*i + 8] - a[16*i + 8]; + a[16*i + 9] = b[16*i + 9] * c[16*i + 9] + a[16*i + 9]; + a[16*i + 10] = b[16*i + 10] * c[16*i + 10] - a[16*i + 10]; + a[16*i + 11] = b[16*i + 11] * c[16*i + 11] + a[16*i + 11]; + a[16*i + 12] = b[16*i + 12] * c[16*i + 12] - a[16*i + 12]; + a[16*i + 13] = b[16*i + 13] * c[16*i + 13] + a[16*i + 13]; + a[16*i + 14] = b[16*i + 14] * c[16*i + 14] - a[16*i + 14]; + a[16*i + 15] = b[16*i + 15] * c[16*i + 15] + a[16*i + 15]; + } +} + +static void +fma_test (void) +{ + if (!__builtin_cpu_supports ("avx512f")) + return; + float a[16], b[16], c[16]; + for (int i = 0; i < 16; ++i) + { + a[i] = i; + b[i] = 3*i; + c[i] = 7*i; + } + check_fmaddsub (a, b, c, 1); + const float d[16] = { 0., 22., 82., 192., 332., 530., 750., 1036., + 1336, 1710., 2090., 2552., 3012., 3562., 4102., 4740.}; + for (int i = 0; i < 16; ++i) + if (a[i] != d[i]) + __builtin_abort (); +} + +/* { dg-final { scan-assembler {(?n)fmaddsub...ps[ \t].*%zmm[0-9]} } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-fmsubaddXXXpd.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-fmsubaddXXXpd.c new file mode 100644 index 0000000..cde76db --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-fmsubaddXXXpd.c @@ -0,0 +1,41 @@ +/* { dg-do run } */ +/* { dg-require-effective-target avx512f } */ +/* { dg-options "-O3 -mavx512f -mprefer-vector-width=512 -save-temps" } */ + +#include "fma-check.h" +void __attribute__((noipa)) +check_fmaddsub (double * __restrict a, double *b, double *c, int n) +{ + for (int i = 0; i < n; ++i) + { + a[8*i + 0] = b[8*i + 0] * c[8*i + 0] + a[8*i + 0]; + a[8*i + 1] = b[8*i + 1] * c[8*i + 1] - a[8*i + 1]; + a[8*i + 2] = b[8*i + 2] * c[8*i + 2] + a[8*i + 2]; + a[8*i + 3] = b[8*i + 3] * c[8*i + 3] - a[8*i + 3]; + a[8*i + 4] = b[8*i + 4] * c[8*i + 4] + a[8*i + 4]; + a[8*i + 5] = b[8*i + 5] * c[8*i + 5] - a[8*i + 5]; + a[8*i + 6] = b[8*i + 6] * c[8*i + 6] + a[8*i + 6]; + a[8*i + 7] = b[8*i + 7] * c[8*i + 7] - a[8*i + 7]; + } +} + +static void +fma_test (void) +{ + if (!__builtin_cpu_supports ("avx512f")) + return; + double a[8], b[8], c[8]; + for (int i = 0; i < 8; ++i) + { + a[i] = i; + b[i] = 3*i; + c[i] = 7*i; + } + check_fmaddsub (a, b, c, 1); + const double d[8] = { 0., 20., 86., 186., 340., 520., 762., 1022.}; + for (int i = 0; i < 8; ++i) + if (a[i] != d[i]) + __builtin_abort (); +} + +/* { dg-final { scan-assembler {(?n)fmsubadd...pd[ \t].*%zmm[0-9]} } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-fmsubaddXXXps.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-fmsubaddXXXps.c new file mode 100644 index 0000000..59de39f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-fmsubaddXXXps.c @@ -0,0 +1,50 @@ +/* { dg-do run } */ +/* { dg-require-effective-target avx512f } */ +/* { dg-options "-O3 -mavx512f -mprefer-vector-width=512 -save-temps" } */ + +#include "fma-check.h" +void __attribute__((noipa)) +check_fmaddsub (float * __restrict a, float *b, float *c, int n) +{ + for (int i = 0; i < n; ++i) + { + a[16*i + 0] = b[16*i + 0] * c[16*i + 0] + a[16*i + 0]; + a[16*i + 1] = b[16*i + 1] * c[16*i + 1] - a[16*i + 1]; + a[16*i + 2] = b[16*i + 2] * c[16*i + 2] + a[16*i + 2]; + a[16*i + 3] = b[16*i + 3] * c[16*i + 3] - a[16*i + 3]; + a[16*i + 4] = b[16*i + 4] * c[16*i + 4] + a[16*i + 4]; + a[16*i + 5] = b[16*i + 5] * c[16*i + 5] - a[16*i + 5]; + a[16*i + 6] = b[16*i + 6] * c[16*i + 6] + a[16*i + 6]; + a[16*i + 7] = b[16*i + 7] * c[16*i + 7] - a[16*i + 7]; + a[16*i + 8] = b[16*i + 8] * c[16*i + 8] + a[16*i + 8]; + a[16*i + 9] = b[16*i + 9] * c[16*i + 9] - a[16*i + 9]; + a[16*i + 10] = b[16*i + 10] * c[16*i + 10] + a[16*i + 10]; + a[16*i + 11] = b[16*i + 11] * c[16*i + 11] - a[16*i + 11]; + a[16*i + 12] = b[16*i + 12] * c[16*i + 12] + a[16*i + 12]; + a[16*i + 13] = b[16*i + 13] * c[16*i + 13] - a[16*i + 13]; + a[16*i + 14] = b[16*i + 14] * c[16*i + 14] + a[16*i + 14]; + a[16*i + 15] = b[16*i + 15] * c[16*i + 15] - a[16*i + 15]; + } +} + +static void +fma_test (void) +{ + if (!__builtin_cpu_supports ("avx512f")) + return; + float a[16], b[16], c[16]; + for (int i = 0; i < 16; ++i) + { + a[i] = i; + b[i] = 3*i; + c[i] = 7*i; + } + check_fmaddsub (a, b, c, 1); + const float d[16] = { 0., 20., 86., 186., 340., 520., 762., 1022., + 1352, 1692., 2110., 2530., 3036., 3536., 4130., 4710.}; + for (int i = 0; i < 16; ++i) + if (a[i] != d[i]) + __builtin_abort (); +} + +/* { dg-final { scan-assembler {(?n)fmsubadd...ps[ \t].*%zmm[0-9]} } } */ -- cgit v1.1 From 9f34b780b0461ec7b2b2defe96e44ab616ea2aa3 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 7 Jul 2021 11:41:03 +0200 Subject: tree-optimization/99728 - improve LIM for loops with aggregate copies This improves LIM by recording aggregate copies for disambiguation purposes instead of as UNANALYZABLE_MEM which will prevent any invariant or store motion across it. This allows four of the six references in the loop of the testcase to be promoted. 2021-07-07 Richard Biener PR tree-optimization/99728 * tree-ssa-loop-im.c (gather_mem_refs_stmt): Record aggregate copies. (mem_refs_may_alias_p): Add assert we handled aggregate copies elsewhere. (sm_seq_valid_bb): Give up when running into aggregate copies. (ref_indep_loop_p): Handle aggregate copies as never being invariant themselves but allow other refs to be disambiguated against them. (can_sm_ref_p): Do not try to apply store-motion to aggregate copies. * g++.dg/opt/pr99728.C: New testcase. --- gcc/testsuite/g++.dg/opt/pr99728.C | 50 ++++++++++++++++++++++++++++++++ gcc/tree-ssa-loop-im.c | 59 +++++++++++++++++++++++++++++++++----- 2 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr99728.C (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/opt/pr99728.C b/gcc/testsuite/g++.dg/opt/pr99728.C new file mode 100644 index 0000000..d439323 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr99728.C @@ -0,0 +1,50 @@ +// PR/99728 +// { dg-do compile } +// { dg-options "-O2 -fdump-tree-lim2-details -w -Wno-psabi" } + +typedef double __m256d __attribute__((vector_size(sizeof (double) * 4))); +extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set1_pd (double __A) +{ + return __extension__ (__m256d){ __A, __A, __A, __A }; +} + +// simple OO wrapper around __m256d +struct Tvsimple + { + __m256d v; + Tvsimple &operator+=(const Tvsimple &other) {v+=other.v; return *this;} + Tvsimple operator*(double val) const { Tvsimple res; res.v = v*_mm256_set1_pd(val); return res;} + Tvsimple operator*(Tvsimple val) const { Tvsimple res; res.v = v*val.v; return res; } + Tvsimple operator+(Tvsimple val) const { Tvsimple res; res.v = v+val.v; return res; } + Tvsimple operator+(double val) const { Tvsimple res; res.v = v+_mm256_set1_pd(val); return res;} + }; + +template struct s0data_s + { vtype sth, corfac, scale, lam1, lam2, csq, p1r, p1i, p2r, p2i; }; + +template void foo(s0data_s & __restrict__ d, + const double * __restrict__ coef, const double * __restrict__ alm, + unsigned long l, unsigned long il, unsigned long lmax) + { +// critical loop + while (l<=lmax) + { + d.p1r += d.lam2*alm[2*l]; + d.p1i += d.lam2*alm[2*l+1]; + d.p2r += d.lam2*alm[2*l+2]; + d.p2i += d.lam2*alm[2*l+3]; + Tvsimple tmp = d.lam2*(d.csq*coef[2*il] + coef[2*il+1]) + d.lam1; + d.lam1 = d.lam2; + d.lam2 = tmp; + ++il; l+=2; + } + } + +// this version has dead stores at the end of the loop +template void foo<>(s0data_s & __restrict__ d, + const double * __restrict__ coef, const double * __restrict__ alm, + unsigned long l, unsigned long il, unsigned long lmax); + +// The aggregate copy in the IL should not prevent all store-motion +// { dg-final { scan-tree-dump-times "Executing store motion" 4 "lim2" } } diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 9ac390b..81b4ec2 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -122,7 +122,9 @@ public: hashval_t hash; /* Its hash value. */ /* The memory access itself and associated caching of alias-oracle - query meta-data. */ + query meta-data. We are using mem.ref == error_mark_node for the + case the reference is represented by its single access stmt + in accesses_in_loop[0]. */ ao_ref mem; bitmap stored; /* The set of loops in that this memory location @@ -130,8 +132,7 @@ public: bitmap loaded; /* The set of loops in that this memory location is loaded from. */ vec accesses_in_loop; - /* The locations of the accesses. Vector - indexed by the loop number. */ + /* The locations of the accesses. */ /* The following set is computed on demand. */ bitmap_head dep_loop; /* The set of loops in that the memory @@ -1465,7 +1466,22 @@ gather_mem_refs_stmt (class loop *loop, gimple *stmt) return; mem = simple_mem_ref_in_stmt (stmt, &is_stored); - if (!mem) + if (!mem && is_gimple_assign (stmt)) + { + /* For aggregate copies record distinct references but use them + only for disambiguation purposes. */ + id = memory_accesses.refs_list.length (); + ref = mem_ref_alloc (NULL, 0, id); + memory_accesses.refs_list.safe_push (ref); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Unhandled memory reference %u: ", id); + print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); + } + record_mem_ref_loc (ref, stmt, mem); + is_stored = gimple_vdef (stmt); + } + else if (!mem) { /* We use the shared mem_ref for all unanalyzable refs. */ id = UNANALYZABLE_MEM_ID; @@ -1595,7 +1611,8 @@ gather_mem_refs_stmt (class loop *loop, gimple *stmt) mark_ref_stored (ref, loop); } /* A not simple memory op is also a read when it is a write. */ - if (!is_stored || id == UNANALYZABLE_MEM_ID) + if (!is_stored || id == UNANALYZABLE_MEM_ID + || ref->mem.ref == error_mark_node) { bitmap_set_bit (&memory_accesses.refs_loaded_in_loop[loop->num], ref->id); mark_ref_loaded (ref, loop); @@ -1714,6 +1731,9 @@ mem_refs_may_alias_p (im_mem_ref *mem1, im_mem_ref *mem2, hash_map **ttae_cache, bool tbaa_p) { + gcc_checking_assert (mem1->mem.ref != error_mark_node + && mem2->mem.ref != error_mark_node); + /* Perform BASE + OFFSET analysis -- if MEM1 and MEM2 are based on the same object and their offset differ in such a way that the locations cannot overlap, then they cannot alias. */ @@ -2490,6 +2510,13 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef, gcc_assert (data); if (data->ref == UNANALYZABLE_MEM_ID) return -1; + /* Stop at memory references which we can't move. */ + else if (memory_accesses.refs_list[data->ref]->mem.ref == error_mark_node) + { + /* Mark refs_not_in_seq as unsupported. */ + bitmap_ior_into (refs_not_supported, refs_not_in_seq); + return 1; + } /* One of the stores we want to apply SM to and we've not yet seen. */ else if (bitmap_clear_bit (refs_not_in_seq, data->ref)) { @@ -2798,7 +2825,8 @@ ref_indep_loop_p (class loop *loop, im_mem_ref *ref, dep_kind kind) else refs_to_check = &memory_accesses.refs_stored_in_loop[loop->num]; - if (bitmap_bit_p (refs_to_check, UNANALYZABLE_MEM_ID)) + if (bitmap_bit_p (refs_to_check, UNANALYZABLE_MEM_ID) + || ref->mem.ref == error_mark_node) indep_p = false; else { @@ -2825,7 +2853,20 @@ ref_indep_loop_p (class loop *loop, im_mem_ref *ref, dep_kind kind) EXECUTE_IF_SET_IN_BITMAP (refs_to_check, 0, i, bi) { im_mem_ref *aref = memory_accesses.refs_list[i]; - if (!refs_independent_p (ref, aref, kind != sm_waw)) + if (aref->mem.ref == error_mark_node) + { + gimple *stmt = aref->accesses_in_loop[0].stmt; + if ((kind == sm_war + && ref_maybe_used_by_stmt_p (stmt, &ref->mem, + kind != sm_waw)) + || stmt_may_clobber_ref_p_1 (stmt, &ref->mem, + kind != sm_waw)) + { + indep_p = false; + break; + } + } + else if (!refs_independent_p (ref, aref, kind != sm_waw)) { indep_p = false; break; @@ -2858,6 +2899,10 @@ can_sm_ref_p (class loop *loop, im_mem_ref *ref) if (!MEM_ANALYZABLE (ref)) return false; + /* Can't hoist/sink aggregate copies. */ + if (ref->mem.ref == error_mark_node) + return false; + /* It should be movable. */ if (!is_gimple_reg_type (TREE_TYPE (ref->mem.ref)) || TREE_THIS_VOLATILE (ref->mem.ref) -- cgit v1.1 From 005f31a0370cf35e332db9415a0ff538320bcddc Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 7 Jul 2021 13:46:48 +0200 Subject: tree-optimization/34195 - testcase for fixed vectorization This adds a testcase for an old fixed PR. 2021-07-07 Richard Biener PR tree-optimization/34195 * gcc.dg/vect/pr34195.c: New testcase. --- gcc/testsuite/gcc.dg/vect/pr34195.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/vect/pr34195.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/vect/pr34195.c b/gcc/testsuite/gcc.dg/vect/pr34195.c new file mode 100644 index 0000000..e36950b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr34195.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_float } */ + +#define M 11 + +struct S +{ + float x; + float y; +} pS[100]; + +float a[1000]; +float b[1000]; + +void +foo (int n) +{ + int i, j; + + for (i = 0; i < n; i++) + { + pS[i].x = 0; + pS[i].y = 0; + + for (j = 0; j < M; j++) + { + pS[i].x += (a[i]+b[i]); + pS[i].y += (a[i]-b[i]); + } + } +} + +/* { dg-final { scan-tree-dump "OUTER LOOP VECTORIZED" "vect" } } */ -- cgit v1.1 From e8073c04536214c856a6340fea23d676cd7436af Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Wed, 7 Jul 2021 12:42:34 +0000 Subject: testsuite: gcc.dg/debug/btf/btf-bitfields-3.c remove -fno-short-enums PR debug/101321 After r12-2094, -fno-short-enums is non longer necessary. 2021-07-07 Christophe Lyon PR debug/101321 gcc/testsuite/ * gcc.dg/debug/btf/btf-bitfields-3.c: Remove -fno-short-enums. --- gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c b/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c index 0e00f2b..2984a33 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-bitfields-3.c @@ -14,7 +14,7 @@ */ /* { dg-do compile } */ -/* { dg-options "-O0 -gbtf -dA -fno-short-enums" } */ +/* { dg-options "-O0 -gbtf -dA" } */ /* Enum with 4 members. */ /* { dg-final { scan-assembler-times "\[\t \]0x6000004\[\t \]+\[^\n\]*btt_info" 1 } } */ -- cgit v1.1 From 06357071d0557c4f0e9b0a6dfc4d37f5680e34cc Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Wed, 7 Jul 2021 08:49:13 -0600 Subject: aarch64: Remove a vestigial %K [PR101363] gcc/ChangeLog: PR target/101363 * config/aarch64/aarch64.c (aarch64_simd_lane_bounds): Remove a stray %K from error_at() missed in r12-2088. --- gcc/config/aarch64/aarch64.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 2753c85..f5b25a7 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -20128,7 +20128,8 @@ aarch64_simd_lane_bounds (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high, if (lane < low || lane >= high) { if (exp) - error ("%Klane %wd out of range %wd - %wd", exp, lane, low, high - 1); + error_at (EXPR_LOCATION (exp), "lane %wd out of range %wd - %wd", + lane, low, high - 1); else error ("lane %wd out of range %wd - %wd", lane, low, high - 1); } -- cgit v1.1 From 0dbe0e11eb75e52885a0f6894a8d3da770f87ca0 Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Fri, 14 May 2021 15:03:02 -0700 Subject: [Ada] Unsynchronized access to a Boolean in tasking state gcc/ada/ * libgnarl/s-tassta.adb (Free_Task): Acquire the Task_Lock before, rather than after, querying the task's Terminated flag. Add a corresponding Task_Unlock call. --- gcc/ada/libgnarl/s-tassta.adb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnarl/s-tassta.adb b/gcc/ada/libgnarl/s-tassta.adb index f18c76f..88850c2 100644 --- a/gcc/ada/libgnarl/s-tassta.adb +++ b/gcc/ada/libgnarl/s-tassta.adb @@ -910,12 +910,12 @@ package body System.Tasking.Stages is Self_Id : constant Task_Id := Self; begin + Initialization.Task_Lock (Self_Id); + if T.Common.State = Terminated then -- It is not safe to call Abort_Defer or Write_Lock at this stage - Initialization.Task_Lock (Self_Id); - Lock_RTS; Initialization.Finalize_Attributes (T); Initialization.Remove_From_All_Tasks_List (T); @@ -930,6 +930,7 @@ package body System.Tasking.Stages is -- upon termination. T.Free_On_Termination := True; + Initialization.Task_Unlock (Self_Id); end if; end Free_Task; -- cgit v1.1 From 738a0e8dd447409a960c84cf14d05e5bdc985ea6 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Mon, 17 May 2021 12:42:20 -0400 Subject: [Ada] Transient scope cleanup gcc/ada/ * checks.adb, exp_attr.adb, exp_ch4.adb, exp_ch6.adb, exp_ch9.adb, exp_disp.adb, exp_util.adb, inline.adb, sem_res.adb: Change all calls to Make_Unchecked_Type_Conversion to call Unchecked_Convert_To instead. This involves removing New_Occurrence_Of on the first parameter, because Unchecked_Convert_To expects a type entity, rather than the name of one. Also, removed calls to Relocate_Node, because Unchecked_Convert_To takes care of that. * sinfo.ads: Change comment to be worded more firmly. --- gcc/ada/checks.adb | 6 +-- gcc/ada/exp_attr.adb | 14 +++---- gcc/ada/exp_ch4.adb | 10 ++--- gcc/ada/exp_ch6.adb | 63 ++++++++++------------------- gcc/ada/exp_ch9.adb | 28 ++++++------- gcc/ada/exp_disp.adb | 111 ++++++++++++++++++++------------------------------- gcc/ada/exp_util.adb | 4 +- gcc/ada/inline.adb | 5 +-- gcc/ada/sem_res.adb | 15 ++----- gcc/ada/sinfo.ads | 2 +- 10 files changed, 93 insertions(+), 165 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index d3d7852..76fd9b0 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -7831,10 +7831,8 @@ package body Checks is New_Occurrence_Of (Target_Base_Type, Loc), Constant_Present => True, Expression => - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of (Target_Base_Type, Loc), - Expression => Duplicate_Subexpr (N))), + Unchecked_Convert_To + (Target_Base_Type, Duplicate_Subexpr (N))), Make_Raise_Constraint_Error (Loc, Condition => diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index e33a36e..f074521 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -2799,10 +2799,9 @@ package body Exp_Attr is Name => New_Occurrence_Of (RTE (RE_Callable), Loc), Parameter_Associations => New_List ( - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc), - Expression => Build_Disp_Get_Task_Id_Call (Pref))))); + Unchecked_Convert_To + (RTE (RO_ST_Task_Id), + Build_Disp_Get_Task_Id_Call (Pref))))); else Rewrite (N, Build_Call_With_Task (Pref, RTE (RE_Callable))); @@ -6746,10 +6745,9 @@ package body Exp_Attr is Name => New_Occurrence_Of (RTE (RE_Terminated), Loc), Parameter_Associations => New_List ( - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc), - Expression => Build_Disp_Get_Task_Id_Call (Pref))))); + Unchecked_Convert_To + (RTE (RO_ST_Task_Id), + Build_Disp_Get_Task_Id_Call (Pref))))); elsif Restricted_Profile then Rewrite (N, diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 7e8a741..0c5b3a2 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -11992,9 +11992,8 @@ package body Exp_Ch4 is -- unchecked conversion to the target fixed-point type. Conv := - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (Target_Type, Loc), - Expression => New_Occurrence_Of (Expr_Id, Loc)); + Unchecked_Convert_To + (Target_Type, New_Occurrence_Of (Expr_Id, Loc)); end; -- All other conversions @@ -12515,10 +12514,7 @@ package body Exp_Ch4 is Conv : Node_Id; begin Make_Tag_Check (Class_Wide_Type (Actual_Targ_Typ)); - Conv := - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (Target_Type, Loc), - Expression => Relocate_Node (Expression (N))); + Conv := Unchecked_Convert_To (Target_Type, Expression (N)); Rewrite (N, Conv); Analyze_And_Resolve (N, Target_Type); end; diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 80ed21b..c1409bf 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -5852,11 +5852,9 @@ package body Exp_Ch6 is Name => New_Occurrence_Of (Alloc_Obj_Id, Loc), Expression => - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of (Ref_Type, Loc), - Expression => - New_Occurrence_Of (Obj_Acc_Formal, Loc)))), + Unchecked_Convert_To + (Ref_Type, + New_Occurrence_Of (Obj_Acc_Formal, Loc)))), Elsif_Parts => New_List ( Make_Elsif_Part (Loc, @@ -5997,11 +5995,9 @@ package body Exp_Ch6 is Object_Definition => New_Occurrence_Of (Ref_Type, Loc), Expression => - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of (Ref_Type, Loc), - Expression => - New_Occurrence_Of (Obj_Acc_Formal, Loc))); + Unchecked_Convert_To + (Ref_Type, + New_Occurrence_Of (Obj_Acc_Formal, Loc))); Insert_Before (Ret_Obj_Decl, Alloc_Obj_Decl); @@ -8514,12 +8510,10 @@ package body Exp_Ch6 is Alloc_Form := Caller_Allocation; Pool := Make_Null (No_Location); - Return_Obj_Actual := - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (Result_Subt, Loc), - Expression => - Make_Explicit_Dereference (Loc, - Prefix => New_Occurrence_Of (Return_Obj_Access, Loc))); + Return_Obj_Actual := Unchecked_Convert_To + (Result_Subt, + Make_Explicit_Dereference (Loc, + Prefix => New_Occurrence_Of (Return_Obj_Access, Loc))); -- When the result subtype is unconstrained, the function itself must -- perform the allocation of the return object, so we pass parameters @@ -8833,11 +8827,7 @@ package body Exp_Ch6 is -- the caller's return object. Add_Access_Actual_To_Build_In_Place_Call - (Func_Call, - Func_Id, - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (Result_Subt, Loc), - Expression => Relocate_Node (Lhs))); + (Func_Call, Func_Id, Unchecked_Convert_To (Result_Subt, Lhs)); -- Create an access type designating the function's result subtype @@ -8861,11 +8851,7 @@ package body Exp_Ch6 is -- Add a conversion if it's the wrong type - if Etype (New_Expr) /= Ptr_Typ then - New_Expr := - Make_Unchecked_Type_Conversion (Loc, - New_Occurrence_Of (Ptr_Typ, Loc), New_Expr); - end if; + New_Expr := Unchecked_Convert_To (Ptr_Typ, New_Expr); Obj_Id := Make_Temporary (Loc, 'R', New_Expr); Set_Etype (Obj_Id, Ptr_Typ); @@ -9124,16 +9110,10 @@ package body Exp_Ch6 is -- it to the access type of the callee's BIP_Object_Access formal. Caller_Object := - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of - (Etype (Build_In_Place_Formal - (Function_Id, BIP_Object_Access)), - Loc), - Expression => - New_Occurrence_Of - (Build_In_Place_Formal (Encl_Func, BIP_Object_Access), - Loc)); + Unchecked_Convert_To + (Etype (Build_In_Place_Formal (Function_Id, BIP_Object_Access)), + New_Occurrence_Of + (Build_In_Place_Formal (Encl_Func, BIP_Object_Access), Loc)); -- In the definite case, add an implicit actual to the function call -- that provides access to the declared object. An unchecked conversion @@ -9141,10 +9121,8 @@ package body Exp_Ch6 is -- the case where the object is declared with a class-wide type. elsif Definite then - Caller_Object := - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (Result_Subt, Loc), - Expression => New_Occurrence_Of (Obj_Def_Id, Loc)); + Caller_Object := Unchecked_Convert_To + (Result_Subt, New_Occurrence_Of (Obj_Def_Id, Loc)); -- When the function has a controlling result, an allocation-form -- parameter must be passed indicating that the caller is allocating @@ -9252,9 +9230,8 @@ package body Exp_Ch6 is Constant_Present => True, Object_Definition => New_Occurrence_Of (Ptr_Typ, Loc), Expression => - Make_Unchecked_Type_Conversion (Loc, - New_Occurrence_Of (Ptr_Typ, Loc), - Make_Reference (Loc, Relocate_Node (Func_Call)))); + Unchecked_Convert_To + (Ptr_Typ, Make_Reference (Loc, Relocate_Node (Func_Call)))); else Res_Decl := Make_Object_Declaration (Loc, diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb index 6b1e284..427b430 100644 --- a/gcc/ada/exp_ch9.adb +++ b/gcc/ada/exp_ch9.adb @@ -6510,14 +6510,12 @@ package body Exp_Ch9 is -- Task_Id (Tasknm._disp_get_task_id) - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc), - Expression => - Make_Selected_Component (Loc, - Prefix => New_Copy_Tree (Tasknm), - Selector_Name => - Make_Identifier (Loc, Name_uDisp_Get_Task_Id))))); + Unchecked_Convert_To + (RTE (RO_ST_Task_Id), + Make_Selected_Component (Loc, + Prefix => New_Copy_Tree (Tasknm), + Selector_Name => + Make_Identifier (Loc, Name_uDisp_Get_Task_Id))))); else Append_To (Component_Associations (Aggr), @@ -7242,10 +7240,9 @@ package body Exp_Ch9 is Make_Assignment_Statement (Loc, Name => New_Occurrence_Of (Bnn, Loc), Expression => - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of (RTE (RE_Communication_Block), Loc), - Expression => Make_Identifier (Loc, Name_uD)))); + Unchecked_Convert_To + (RTE (RE_Communication_Block), + Make_Identifier (Loc, Name_uD)))); -- Generate: -- _Disp_Asynchronous_Select (, S, P'Address, D, B); @@ -7361,10 +7358,9 @@ package body Exp_Ch9 is Name => New_Occurrence_Of (Bnn, Loc), Expression => - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of (RTE (RE_Communication_Block), Loc), - Expression => Make_Identifier (Loc, Name_uD)))); + Unchecked_Convert_To + (RTE (RE_Communication_Block), + Make_Identifier (Loc, Name_uD)))); -- Generate: -- _Disp_Asynchronous_Select (, S, P'Address, D, B); diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb index a2ea7c6..a44af6a 100644 --- a/gcc/ada/exp_disp.adb +++ b/gcc/ada/exp_disp.adb @@ -2575,11 +2575,9 @@ package body Exp_Disp is New_List ( Obj_Ref, - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Occurrence_Of - (RTE (RE_Protected_Entry_Index), Loc), - Expression => Make_Identifier (Loc, Name_uI)), + Unchecked_Convert_To ( -- entry index + RTE (RE_Protected_Entry_Index), + Make_Identifier (Loc, Name_uI)), Make_Identifier (Loc, Name_uP), -- parameter block New_Occurrence_Of -- Asynchronous_Call @@ -2598,11 +2596,9 @@ package body Exp_Disp is Make_Assignment_Statement (Loc, Name => Make_Identifier (Loc, Name_uB), Expression => - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of - (RTE (RE_Dummy_Communication_Block), Loc), - Expression => New_Occurrence_Of (Com_Block, Loc)))); + Unchecked_Convert_To + (RTE (RE_Dummy_Communication_Block), + New_Occurrence_Of (Com_Block, Loc)))); -- Generate: -- F := False; @@ -2636,10 +2632,9 @@ package body Exp_Disp is Prefix => Make_Identifier (Loc, Name_uT), Selector_Name => Make_Identifier (Loc, Name_uTask_Id)), - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Occurrence_Of (RTE (RE_Task_Entry_Index), Loc), - Expression => Make_Identifier (Loc, Name_uI)), + Unchecked_Convert_To ( -- entry index + RTE (RE_Task_Entry_Index), + Make_Identifier (Loc, Name_uI)), Make_Identifier (Loc, Name_uP), -- parameter block New_Occurrence_Of -- Asynchronous_Call @@ -2929,11 +2924,9 @@ package body Exp_Disp is Parameter_Associations => New_List ( Obj_Ref, - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Occurrence_Of - (RTE (RE_Protected_Entry_Index), Loc), - Expression => Make_Identifier (Loc, Name_uI)), + Unchecked_Convert_To ( -- entry index + RTE (RE_Protected_Entry_Index), + Make_Identifier (Loc, Name_uI)), Make_Identifier (Loc, Name_uP), -- parameter block @@ -3006,10 +2999,9 @@ package body Exp_Disp is Prefix => Make_Identifier (Loc, Name_uT), Selector_Name => Make_Identifier (Loc, Name_uTask_Id)), - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Occurrence_Of (RTE (RE_Task_Entry_Index), Loc), - Expression => Make_Identifier (Loc, Name_uI)), + Unchecked_Convert_To ( -- entry index + RTE (RE_Task_Entry_Index), + Make_Identifier (Loc, Name_uI)), Make_Identifier (Loc, Name_uP), -- parameter block New_Occurrence_Of -- Conditional_Call @@ -3219,12 +3211,11 @@ package body Exp_Disp is Ret := Make_Simple_Return_Statement (Loc, Expression => - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (RTE (RE_Address), Loc), - Expression => - Make_Selected_Component (Loc, - Prefix => Make_Identifier (Loc, Name_uT), - Selector_Name => Make_Identifier (Loc, Name_uTask_Id)))); + Unchecked_Convert_To + (RTE (RE_Address), + Make_Selected_Component (Loc, + Prefix => Make_Identifier (Loc, Name_uT), + Selector_Name => Make_Identifier (Loc, Name_uTask_Id)))); -- A null body is constructed for non-task types @@ -3337,12 +3328,9 @@ package body Exp_Disp is Parameter_Associations => New_List ( - Make_Unchecked_Type_Conversion (Loc, -- PEA (P) - Subtype_Mark => - New_Occurrence_Of ( - RTE (RE_Protection_Entries_Access), Loc), - Expression => - Make_Identifier (Loc, Name_uP)), + Unchecked_Convert_To ( -- PEA (P) + RTE (RE_Protection_Entries_Access), + Make_Identifier (Loc, Name_uP)), Make_Attribute_Reference (Loc, -- O._object'Acc Attribute_Name => @@ -3354,11 +3342,9 @@ package body Exp_Disp is Selector_Name => Make_Identifier (Loc, Name_uObject))), - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Occurrence_Of - (RTE (RE_Protected_Entry_Index), Loc), - Expression => Make_Identifier (Loc, Name_uI)), + Unchecked_Convert_To ( -- entry index + RTE (RE_Protected_Entry_Index), + Make_Identifier (Loc, Name_uI)), Make_Identifier (Loc, Name_uA)))), -- abort status @@ -3383,11 +3369,9 @@ package body Exp_Disp is Selector_Name => Make_Identifier (Loc, Name_uObject))), - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Occurrence_Of - (RTE (RE_Protected_Entry_Index), Loc), - Expression => Make_Identifier (Loc, Name_uI)), + Unchecked_Convert_To ( -- entry index + RTE (RE_Protected_Entry_Index), + Make_Identifier (Loc, Name_uI)), Make_Identifier (Loc, Name_uA)))))); -- abort status end if; @@ -3424,20 +3408,17 @@ package body Exp_Disp is Parameter_Associations => New_List ( - Make_Unchecked_Type_Conversion (Loc, -- PEA (P) - Subtype_Mark => - New_Occurrence_Of - (RTE (RE_Protection_Entries_Access), Loc), - Expression => Make_Identifier (Loc, Name_uP)), + Unchecked_Convert_To ( -- PEA (P) + RTE (RE_Protection_Entries_Access), + Make_Identifier (Loc, Name_uP)), Make_Selected_Component (Loc, -- O._task_id Prefix => Make_Identifier (Loc, Name_uO), Selector_Name => Make_Identifier (Loc, Name_uTask_Id)), - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Occurrence_Of (RTE (RE_Task_Entry_Index), Loc), - Expression => Make_Identifier (Loc, Name_uI)), + Unchecked_Convert_To ( -- entry index + RTE (RE_Task_Entry_Index), + Make_Identifier (Loc, Name_uI)), Make_Identifier (Loc, Name_uA)))), -- abort status @@ -3455,10 +3436,9 @@ package body Exp_Disp is Prefix => Make_Identifier (Loc, Name_uO), Selector_Name => Make_Identifier (Loc, Name_uTask_Id)), - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Occurrence_Of (RTE (RE_Task_Entry_Index), Loc), - Expression => Make_Identifier (Loc, Name_uI)), + Unchecked_Convert_To ( -- entry index + RTE (RE_Task_Entry_Index), + Make_Identifier (Loc, Name_uI)), Make_Identifier (Loc, Name_uA)))))); -- abort status end if; @@ -3743,11 +3723,9 @@ package body Exp_Disp is Parameter_Associations => New_List ( Obj_Ref, - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Occurrence_Of - (RTE (RE_Protected_Entry_Index), Loc), - Expression => Make_Identifier (Loc, Name_uI)), + Unchecked_Convert_To ( -- entry index + RTE (RE_Protected_Entry_Index), + Make_Identifier (Loc, Name_uI)), Make_Identifier (Loc, Name_uP), -- parameter block Make_Identifier (Loc, Name_uD), -- delay @@ -3786,10 +3764,9 @@ package body Exp_Disp is Prefix => Make_Identifier (Loc, Name_uT), Selector_Name => Make_Identifier (Loc, Name_uTask_Id)), - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Occurrence_Of (RTE (RE_Task_Entry_Index), Loc), - Expression => Make_Identifier (Loc, Name_uI)), + Unchecked_Convert_To ( -- entry index + RTE (RE_Task_Entry_Index), + Make_Identifier (Loc, Name_uI)), Make_Identifier (Loc, Name_uP), -- parameter block Make_Identifier (Loc, Name_uD), -- delay diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 270242d..2ff1144 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -1467,9 +1467,7 @@ package body Exp_Util is Make_Procedure_Call_Statement (Loc, Name => New_Occurrence_Of (Proc_Id, Loc), Parameter_Associations => New_List ( - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (Formal_Typ, Loc), - Expression => Obj_Name))); + Unchecked_Convert_To (Formal_Typ, Obj_Name))); end Build_DIC_Call; ------------------------------ diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb index fc704e6..589c0f3 100644 --- a/gcc/ada/inline.adb +++ b/gcc/ada/inline.adb @@ -3008,10 +3008,7 @@ package body Inline is if Nkind (A) = N_Type_Conversion and then Ekind (F) /= E_In_Parameter then - New_A := - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (Etype (F), Loc), - Expression => Relocate_Node (Expression (A))); + New_A := Unchecked_Convert_To (Etype (F), Expression (A)); -- In GNATprove mode, keep the most precise type of the actual for -- the temporary variable, when the formal type is unconstrained. diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 3ebf93a..54d476e 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -8825,18 +8825,12 @@ package body Sem_Res is or else Is_Private_Type (T)) then if Etype (L) /= T then - Rewrite (L, - Make_Unchecked_Type_Conversion (Sloc (L), - Subtype_Mark => New_Occurrence_Of (T, Sloc (L)), - Expression => Relocate_Node (L))); + Rewrite (L, Unchecked_Convert_To (T, L)); Analyze_And_Resolve (L, T); end if; if (Etype (R)) /= T then - Rewrite (R, - Make_Unchecked_Type_Conversion (Sloc (R), - Subtype_Mark => New_Occurrence_Of (Etype (L), Sloc (R)), - Expression => Relocate_Node (R))); + Rewrite (R, Unchecked_Convert_To (Etype (L), R)); Analyze_And_Resolve (R, T); end if; end if; @@ -12740,10 +12734,7 @@ package body Sem_Res is Set_Etype (Array_Subtype, Base_Type (Typ)); Set_Is_Constrained (Array_Subtype, True); - Rewrite (N, - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (Array_Subtype, Loc), - Expression => Relocate_Node (N))); + Rewrite (N, Unchecked_Convert_To (Array_Subtype, N)); Set_Etype (N, Array_Subtype); end; end if; diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index f6c5e0d..25a61ad 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -8422,7 +8422,7 @@ package Sinfo is -- It is generated as a result of actual use of Unchecked_Conversion -- and also by the expander. - -- Unchecked type conversion nodes should normally be created by calling + -- Unchecked type conversion nodes should be created by calling -- Tbuild.Unchecked_Convert_To, rather than by directly calling -- Nmake.Make_Unchecked_Type_Conversion. -- cgit v1.1 From 6feab95cbcf0283b6bf4bf2e6e2e38370618930a Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Mon, 17 May 2021 23:06:56 +0200 Subject: [Ada] Simplify iteration over pending instantiations gcc/ada/ * inline.adb (Instantiate_Bodies): Fix white in declaration. (Remove_Dead_Instance): Change iteration from WHILE to FOR. --- gcc/ada/inline.adb | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb index 589c0f3..6c330b2 100644 --- a/gcc/ada/inline.adb +++ b/gcc/ada/inline.adb @@ -4806,7 +4806,7 @@ package body Inline is end if; end Instantiate_Body; - J, K : Nat; + J, K : Nat; Info : Pending_Body_Info; -- Start of processing for Instantiate_Bodies @@ -5153,17 +5153,12 @@ package body Inline is -------------------------- procedure Remove_Dead_Instance (N : Node_Id) is - J : Int; - begin - J := 0; - while J <= Pending_Instantiations.Last loop + for J in 0 .. Pending_Instantiations.Last loop if Pending_Instantiations.Table (J).Inst_Node = N then Pending_Instantiations.Table (J).Inst_Node := Empty; return; end if; - - J := J + 1; end loop; end Remove_Dead_Instance; -- cgit v1.1 From f8776eeb3613b557cea367f01d7d1b6b2fe9d33b Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 18 May 2021 00:55:27 +0200 Subject: [Ada] Tune discovery of No_Elaboration_Code restriction gcc/ada/ * lib-writ.adb (Write_ALI): Exit from loop after seeing first unit that violates No_Elaboration_Code restriction. --- gcc/ada/lib-writ.adb | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb index 1b02b1c..3564f0f 100644 --- a/gcc/ada/lib-writ.adb +++ b/gcc/ada/lib-writ.adb @@ -1256,6 +1256,7 @@ package body Lib.Writ is if Units.Table (Unit).Generate_Code or else Unit = Main_Unit then if not Has_No_Elaboration_Code (Cunit (Unit)) then Main_Restrictions.Violated (No_Elaboration_Code) := True; + exit; end if; end if; end loop; -- cgit v1.1 From f3ff72939e52a381d28f3c4879f2eaa1d154ff73 Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Tue, 18 May 2021 11:03:31 +0600 Subject: [Ada] Add socket options to control keepalive on TCP connection gcc/ada/ * libgnat/g-socket.ads (Option_Name): Add Keep_Alive_Count, Keep_Alive_Idle, and Keep_Alive_Interval items to enumeration. (Option_Type): Add Keep_Alive_Count, Keep_Alive_Idle, and Keep_Alive_Interval alternatives to the case of discriminated record. * libgnat/g-socket.adb (Options): Add Keep_Alive_Count, Keep_Alive_Idle, and Keep_Alive_Interval to items enumerator to OS constant converter. (Set_Socket_Option): Process Keep_Alive_Count, Keep_Alive_Idle, and Keep_Alive_Interval socket options. (Get_Socket_Option): Idem. --- gcc/ada/libgnat/g-socket.adb | 30 +++++++++++++++++++++++++++++ gcc/ada/libgnat/g-socket.ads | 46 ++++++++++++++++++++++++++++++-------------- 2 files changed, 62 insertions(+), 14 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/g-socket.adb b/gcc/ada/libgnat/g-socket.adb index ec4cf29..a246303 100644 --- a/gcc/ada/libgnat/g-socket.adb +++ b/gcc/ada/libgnat/g-socket.adb @@ -96,6 +96,9 @@ package body GNAT.Sockets is Options : constant array (Specific_Option_Name) of C.int := (Keep_Alive => SOSC.SO_KEEPALIVE, + Keep_Alive_Count => SOSC.TCP_KEEPCNT, + Keep_Alive_Idle => SOSC.TCP_KEEPIDLE, + Keep_Alive_Interval => SOSC.TCP_KEEPINTVL, Reuse_Address => SOSC.SO_REUSEADDR, Broadcast => SOSC.SO_BROADCAST, Send_Buffer => SOSC.SO_SNDBUF, @@ -1442,6 +1445,9 @@ package body GNAT.Sockets is | Error | Generic_Option | Keep_Alive + | Keep_Alive_Count + | Keep_Alive_Idle + | Keep_Alive_Interval | Multicast_If_V4 | Multicast_If_V6 | Multicast_Loop_V4 @@ -1511,6 +1517,15 @@ package body GNAT.Sockets is => Opt.Enabled := (V4 /= 0); + when Keep_Alive_Count => + Opt.Count := Natural (V4); + + when Keep_Alive_Idle => + Opt.Idle_Seconds := Natural (V4); + + when Keep_Alive_Interval => + Opt.Interval_Seconds := Natural (V4); + when Busy_Polling => Opt.Microseconds := Natural (V4); @@ -2620,6 +2635,21 @@ package body GNAT.Sockets is Len := V4'Size / 8; Add := V4'Address; + when Keep_Alive_Count => + V4 := C.int (Option.Count); + Len := V4'Size / 8; + Add := V4'Address; + + when Keep_Alive_Idle => + V4 := C.int (Option.Idle_Seconds); + Len := V4'Size / 8; + Add := V4'Address; + + when Keep_Alive_Interval => + V4 := C.int (Option.Interval_Seconds); + Len := V4'Size / 8; + Add := V4'Address; + when Busy_Polling => V4 := C.int (Option.Microseconds); Len := V4'Size / 8; diff --git a/gcc/ada/libgnat/g-socket.ads b/gcc/ada/libgnat/g-socket.ads index 03afd36..4372f3e 100644 --- a/gcc/ada/libgnat/g-socket.ads +++ b/gcc/ada/libgnat/g-socket.ads @@ -845,11 +845,20 @@ package GNAT.Sockets is -- IP_Protocol_For_TCP_Level -- ------------------------------- - No_Delay, -- TCP_NODELAY + No_Delay, -- TCP_NODELAY -- Disable the Nagle algorithm. This means that output buffer content -- is always sent as soon as possible, even if there is only a small -- amount of data. + Keep_Alive_Count, -- TCP_KEEPCNT + -- Maximum number of keepalive probes + + Keep_Alive_Idle, -- TCP_KEEPIDLE + -- Idle time before TCP starts sending keepalive probes + + Keep_Alive_Interval, -- TCP_KEEPINTVL + -- Time between individual keepalive probes + ------------------------------ -- IP_Protocol_For_IP_Level -- ------------------------------ @@ -923,26 +932,35 @@ package GNAT.Sockets is Enabled : Boolean; case Name is - when Linger => + when Linger => Seconds : Natural; - when others => + when others => null; end case; - when Busy_Polling => + when Keep_Alive_Count => + Count : Natural; + + when Keep_Alive_Idle => + Idle_Seconds : Natural; + + when Keep_Alive_Interval => + Interval_Seconds : Natural; + + when Busy_Polling => Microseconds : Natural; - when Send_Buffer | - Receive_Buffer => + when Send_Buffer | + Receive_Buffer => Size : Natural; - when Error => + when Error => Error : Error_Type; - when Add_Membership_V4 | - Add_Membership_V6 | - Drop_Membership_V4 | - Drop_Membership_V6 => + when Add_Membership_V4 | + Add_Membership_V6 | + Drop_Membership_V4 | + Drop_Membership_V6 => Multicast_Address : Inet_Addr_Type; case Name is when Add_Membership_V4 | @@ -958,13 +976,13 @@ package GNAT.Sockets is when Multicast_If_V6 => Outgoing_If_Index : Natural; - when Multicast_TTL => + when Multicast_TTL => Time_To_Live : Natural; - when Multicast_Hops => + when Multicast_Hops => Hop_Limit : Integer range -1 .. 255; - when Send_Timeout | + when Send_Timeout | Receive_Timeout => Timeout : Timeval_Duration; -- cgit v1.1 From 05435609367c0ae1398ac1b4becfae06d217552c Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 18 May 2021 14:54:24 +0200 Subject: [Ada] Simplify handling of Generate_Code flag for compilation units gcc/ada/ * gnat1drv.adb (Gnat1drv): Remove flagging of main unit and its corresponding spec as requiring code generation; now the flags are set much earlier. * lib-load.adb (Load_Main_Source): Set Generate_Code flag on the main unit source. (Make_Instance_Unit): Copy Generate_Code flag from the main unit to instance units. * lib-writ.adb (Write_ALI): Remove redundant condition; Generate_Code flag is always set for the main unit. * par-load.adb (Load): Set Generate_Code flag on the main unit's corresponding spec, if any. --- gcc/ada/gnat1drv.adb | 23 ----------------------- gcc/ada/lib-load.adb | 11 +++++------ gcc/ada/lib-writ.adb | 2 +- gcc/ada/par-load.adb | 6 ++++++ 4 files changed, 12 insertions(+), 30 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb index 22c9311..6f65d74 100644 --- a/gcc/ada/gnat1drv.adb +++ b/gcc/ada/gnat1drv.adb @@ -1287,29 +1287,6 @@ begin Exit_Program (E_Errors); end if; - -- Set Generate_Code on main unit and its spec. We do this even if are - -- not generating code, since Lib-Writ uses this to determine which - -- units get written in the ali file. - - Set_Generate_Code (Main_Unit); - - -- If we have a corresponding spec, and it comes from source or it is - -- not a generated spec for a child subprogram body, then we need object - -- code for the spec unit as well. - - if Nkind (Unit (Main_Unit_Node)) in N_Unit_Body - and then not Acts_As_Spec (Main_Unit_Node) - then - if Nkind (Unit (Main_Unit_Node)) = N_Subprogram_Body - and then not Comes_From_Source (Library_Unit (Main_Unit_Node)) - then - null; - else - Set_Generate_Code - (Get_Cunit_Unit_Number (Library_Unit (Main_Unit_Node))); - end if; - end if; - -- Case of no code required to be generated, exit indicating no error if Original_Operating_Mode = Check_Syntax then diff --git a/gcc/ada/lib-load.adb b/gcc/ada/lib-load.adb index 75b52e2..19afe26 100644 --- a/gcc/ada/lib-load.adb +++ b/gcc/ada/lib-load.adb @@ -364,7 +364,7 @@ package body Lib.Load is Error_Location => No_Location, Expected_Unit => No_Unit_Name, Fatal_Error => None, - Generate_Code => False, + Generate_Code => True, Has_RACW => False, Filler => False, Ident_String => Empty, @@ -964,13 +964,12 @@ package body Lib.Load is Units.Increment_Last; if In_Main then - Units.Table (Units.Last) := Units.Table (Main_Unit); - Units.Table (Units.Last).Cunit := Library_Unit (N); - Units.Table (Units.Last).Generate_Code := True; + Units.Table (Units.Last) := Units.Table (Main_Unit); + Units.Table (Units.Last).Cunit := Library_Unit (N); Init_Unit_Name (Units.Last, Unit_Name (Main_Unit)); - Units.Table (Main_Unit).Cunit := N; - Units.Table (Main_Unit).Version := Source_Checksum (Sind); + Units.Table (Main_Unit).Cunit := N; + Units.Table (Main_Unit).Version := Source_Checksum (Sind); Init_Unit_Name (Main_Unit, Get_Body_Name (Unit_Name (Get_Cunit_Unit_Number (Library_Unit (N))))); diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb index 3564f0f..416052c 100644 --- a/gcc/ada/lib-writ.adb +++ b/gcc/ada/lib-writ.adb @@ -1253,7 +1253,7 @@ package body Lib.Writ is -- for which we have generated code for Unit in Units.First .. Last_Unit loop - if Units.Table (Unit).Generate_Code or else Unit = Main_Unit then + if Units.Table (Unit).Generate_Code then if not Has_No_Elaboration_Code (Cunit (Unit)) then Main_Restrictions.Violated (No_Elaboration_Code) := True; exit; diff --git a/gcc/ada/par-load.adb b/gcc/ada/par-load.adb index 39c445e..0773f36 100644 --- a/gcc/ada/par-load.adb +++ b/gcc/ada/par-load.adb @@ -265,6 +265,12 @@ begin -- and this is also where we generate the SCO's for this spec. if Cur_Unum = Main_Unit then + + -- We generate code for the main unit body, so we need to generate + -- code for its spec too. + + Set_Generate_Code (Unum, True); + Main_Unit_Entity := Cunit_Entity (Unum); if Generate_SCO then -- cgit v1.1 From 6dcf89443d781561bfddf372ee33bf78fcad3a75 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Wed, 19 May 2021 00:26:30 +0200 Subject: [Ada] Replace chopped string copy with renaming gcc/ada/ * par.adb (Par): A local Name variable is now a renaming of a constant slice. --- gcc/ada/par.adb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/par.adb b/gcc/ada/par.adb index 649d2a0..312c411 100644 --- a/gcc/ada/par.adb +++ b/gcc/ada/par.adb @@ -1650,14 +1650,12 @@ begin Uname : constant String := Get_Name_String (Unit_Name (Current_Source_Unit)); - Name : String (1 .. Uname'Length - 2); - - begin + Name : String renames + Uname (Uname'First .. Uname'Last - 2); -- Because Unit_Name includes "%s"/"%b", we need to strip -- the last two characters to get the real unit name. - Name := Uname (Uname'First .. Uname'Last - 2); - + begin if Name = "ada" or else Name = "interfaces" or else Name = "system" -- cgit v1.1 From d557a5f9cea39c4871af06e0684f94590d8bd97d Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Mon, 17 May 2021 15:58:26 +0200 Subject: [Ada] Fix precondition of Cot for code analyzers gcc/ada/ * libgnat/a-ngelfu.ads (Cot): Fix precondition. --- gcc/ada/libgnat/a-ngelfu.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/a-ngelfu.ads b/gcc/ada/libgnat/a-ngelfu.ads index 055c282..523e64f 100644 --- a/gcc/ada/libgnat/a-ngelfu.ads +++ b/gcc/ada/libgnat/a-ngelfu.ads @@ -126,7 +126,7 @@ is Pre => Cycle > 0.0 and then X /= 0.0 and then Float_Type'Base'Remainder (X, Cycle) /= 0.0 - and then abs Float_Type'Base'Remainder (X, Cycle) = 0.5 * Cycle; + and then abs Float_Type'Base'Remainder (X, Cycle) /= 0.5 * Cycle; function Arcsin (X : Float_Type'Base) return Float_Type'Base with Pre => abs X <= 1.0, -- cgit v1.1 From 19456797d1d0aa059b9892698f0f979fa29d824c Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Mon, 17 May 2021 15:39:29 -0400 Subject: [Ada] Linker_Section_Pragma cleanup gcc/ada/ * gen_il-gen-gen_entities.adb: Remove Linker_Section_Pragma field from Record_Field_Kind. Minor comment improvement. --- gcc/ada/gen_il-gen-gen_entities.adb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb index 1c6a518..d5977ad 100644 --- a/gcc/ada/gen_il-gen-gen_entities.adb +++ b/gcc/ada/gen_il-gen-gen_entities.adb @@ -315,15 +315,14 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Entry_Formal, Node_Id), Sm (Esize, Uint), Sm (Interface_Name, Node_Id), - Sm (Linker_Section_Pragma, Node_Id), Sm (Normalized_First_Bit, Uint), Sm (Normalized_Position, Uint), Sm (Normalized_Position_Max, Uint), Sm (Original_Record_Component, Node_Id))); Cc (E_Component, Record_Field_Kind, - -- Components of a record declaration, private declarations of - -- protected objects. + -- Components (other than discriminants) of a record declaration, + -- private declarations of protected objects. (Sm (Discriminant_Checking_Func, Node_Id), Sm (DT_Entry_Count, Uint, Pre => "Is_Tag (N)"), -- cgit v1.1 From 131c9affbde6ed68d2c42a0bea8839e1ba8a9f7e Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Wed, 19 May 2021 12:05:31 +0200 Subject: [Ada] Replace low-level membership tests with Is_Private_Type gcc/ada/ * exp_ch3.adb, exp_ch6.adb, sem_ch6.adb: Replace Ekind membership test in Private_Kind with a call to Is_Private_Type. --- gcc/ada/exp_ch3.adb | 4 ++-- gcc/ada/exp_ch6.adb | 2 +- gcc/ada/sem_ch6.adb | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index ad6c7a7..ad82e56 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -6000,7 +6000,7 @@ package body Exp_Ch3 is -- The parent type is private then we need to inherit any TSS operations -- from the full view. - if Ekind (Par_Id) in Private_Kind + if Is_Private_Type (Par_Id) and then Present (Full_View (Par_Id)) then Par_Id := Base_Type (Full_View (Par_Id)); @@ -6036,7 +6036,7 @@ package body Exp_Ch3 is -- If the derived type itself is private with a full view, then -- associate the full view with the inherited TSS_Elist as well. - if Ekind (B_Id) in Private_Kind + if Is_Private_Type (B_Id) and then Present (Full_View (B_Id)) then Ensure_Freeze_Node (Base_Type (Full_View (B_Id))); diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index c1409bf..dbae760 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -3761,7 +3761,7 @@ package body Exp_Ch6 is -- because the object has underlying discriminants with defaults. if Present (Extra_Constrained (Formal)) then - if Ekind (Etype (Prev)) in Private_Kind + if Is_Private_Type (Etype (Prev)) and then not Has_Discriminants (Base_Type (Etype (Prev))) then Add_Extra_Actual diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index abe8060..b0db7fe 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -8901,7 +8901,7 @@ package body Sem_Ch6 is end if; if not Has_Discriminants (Formal_Type) - and then Ekind (Formal_Type) in Private_Kind + and then Is_Private_Type (Formal_Type) and then Present (Underlying_Type (Formal_Type)) then Formal_Type := Underlying_Type (Formal_Type); @@ -11253,7 +11253,7 @@ package body Sem_Ch6 is -- If the entity is a private type, then it must be declared in a -- visible part. - if Ekind (T) in Private_Kind then + if Is_Private_Type (T) then return True; elsif Is_Type (T) and then Has_Private_Declaration (T) then -- cgit v1.1 From a7bb69067afdea57aadd10583342c315925d2cbd Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Wed, 19 May 2021 12:06:55 +0200 Subject: [Ada] Simplify code by reusing List_Length gcc/ada/ * exp_disp.adb (CPP_Num_Prims): Reuse List_Length. --- gcc/ada/exp_disp.adb | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb index a44af6a..e9d6e74 100644 --- a/gcc/ada/exp_disp.adb +++ b/gcc/ada/exp_disp.adb @@ -588,19 +588,7 @@ package body Exp_Disp is -- Otherwise, count the primitives of the enclosing CPP type else - declare - Count : Nat := 0; - Elmt : Elmt_Id; - - begin - Elmt := First_Elmt (Primitive_Operations (CPP_Typ)); - while Present (Elmt) loop - Count := Count + 1; - Next_Elmt (Elmt); - end loop; - - return Count; - end; + return List_Length (Primitive_Operations (CPP_Typ)); end if; end if; end CPP_Num_Prims; -- cgit v1.1 From f78c17d267271cf339e4a0efc3bfe7eb0c00b502 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Wed, 19 May 2021 12:07:42 +0200 Subject: [Ada] Reduce scope of local variables gcc/ada/ * sem_ch6.adb (Check_For_Primitive_Subprogram): Move declarations of local variables after nested subprogram bodies. --- gcc/ada/sem_ch6.adb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index b0db7fe..75e5a99 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -11018,10 +11018,6 @@ package body Sem_Ch6 is (Is_Primitive : out Boolean; Is_Overriding : Boolean := False) is - Formal : Entity_Id; - F_Typ : Entity_Id; - B_Typ : Entity_Id; - procedure Add_Or_Replace_Untagged_Primitive (Typ : Entity_Id); -- Either add the new subprogram to the list of primitives for -- untagged type Typ, or if it overrides a primitive of Typ, then @@ -11270,6 +11266,12 @@ package body Sem_Ch6 is end if; end Visible_Part_Type; + -- Local variables + + Formal : Entity_Id; + F_Typ : Entity_Id; + B_Typ : Entity_Id; + -- Start of processing for Check_For_Primitive_Subprogram begin -- cgit v1.1 From a7f66404a62179ed8d759e8d454635f775cef016 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Tue, 18 May 2021 12:35:08 +0200 Subject: [Ada] Simplify handling of sure errors in GNATprove mode gcc/ada/ * checks.adb (Apply_Scalar_Range_Check): Remove special case for GNATprove mode. * sem_res.adb (Resolve_Arithmetic_Op): Same. * sem_util.adb (Apply_Compile_Time_Constraint_Error): Same. --- gcc/ada/checks.adb | 7 ------- gcc/ada/sem_res.adb | 7 ------- gcc/ada/sem_util.adb | 11 ----------- 3 files changed, 25 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 76fd9b0..61ce9c2 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -3323,13 +3323,6 @@ package body Checks is Bad_Value (Warn => SPARK_Mode = On); - -- In GNATprove mode, we enable the range check so that - -- GNATprove will issue a message if it cannot be proved. - - if GNATprove_Mode then - Enable_Range_Check (Expr); - end if; - return; end if; diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 54d476e..5791d3d 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -6151,13 +6151,6 @@ package body Sem_Res is raise Program_Error; end case; - -- In GNATprove mode, we enable the division check so that - -- GNATprove will issue a message if it cannot be proved. - - if GNATprove_Mode then - Activate_Division_Check (N); - end if; - -- Otherwise just set the flag to check at run time else diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 9d54309..799f720 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -1533,17 +1533,6 @@ package body Sem_Util is Discard_Node (Compile_Time_Constraint_Error (N, Msg, Ent, Loc, Warn => Warn)); - -- In GNATprove mode, do not replace the node with an exception raised. - -- In such a case, either the call to Compile_Time_Constraint_Error - -- issues an error which stops analysis, or it issues a warning in - -- a few cases where a suitable check flag is set for GNATprove to - -- generate a check message. - - if GNATprove_Mode then - Set_Raises_Constraint_Error (N); - return; - end if; - -- Now we replace the node by an N_Raise_Constraint_Error node -- This does not need reanalyzing, so set it as analyzed now. -- cgit v1.1 From ebef9784ef665511b407ed9081153a7eb52f816b Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Wed, 19 May 2021 07:52:32 -0400 Subject: [Ada] Unchecked_Convert_To: set Parent gcc/ada/ * tbuild.adb (Unchecked_Convert_To): Set the Parent of the new node to the Parent of the old node. * tbuild.ads (Unchecked_Convert_To): Document differences between Convert_To and Unchecked_Convert_To. The previous documentation claimed they are identical except for the uncheckedness of the conversion. --- gcc/ada/tbuild.adb | 13 +++++++++---- gcc/ada/tbuild.ads | 5 ++++- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/tbuild.adb b/gcc/ada/tbuild.adb index e718644..4d9c1c4 100644 --- a/gcc/ada/tbuild.adb +++ b/gcc/ada/tbuild.adb @@ -919,10 +919,15 @@ package body Tbuild is -- All other cases else - Result := - Make_Unchecked_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (Typ, Loc), - Expression => Relocate_Node (Expr)); + declare + Expr_Parent : constant Node_Id := Parent (Expr); + begin + Result := + Make_Unchecked_Type_Conversion (Loc, + Subtype_Mark => New_Occurrence_Of (Typ, Loc), + Expression => Relocate_Node (Expr)); + Set_Parent (Result, Expr_Parent); + end; end if; Set_Etype (Result, Typ); diff --git a/gcc/ada/tbuild.ads b/gcc/ada/tbuild.ads index f2f9809..eb17865 100644 --- a/gcc/ada/tbuild.ads +++ b/gcc/ada/tbuild.ads @@ -340,7 +340,10 @@ package Tbuild is (Typ : Entity_Id; Expr : Node_Id) return Node_Id; -- Like Convert_To, but if a conversion is actually needed, constructs an - -- N_Unchecked_Type_Conversion node to do the required conversion. + -- N_Unchecked_Type_Conversion node to do the required conversion. Unlike + -- Convert_To, a new node is not required if Expr is already of the correct + -- BASE type, and if a new node is created, the Parent of Expr is copied to + -- it. ------------------------------------- -- Subprograms for Use by Gnat1drv -- -- cgit v1.1 From 4fa7097a140f007f86e81f62cd08fff15b16ef6e Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Wed, 19 May 2021 18:26:16 +0600 Subject: [Ada] Timeout correction on Get_Socket_Option gcc/ada/ * libgnat/g-socket.adb (Get_Socket_Option): Add 500ms only when Minus_500ms_Windows_Timeout is True. (Set_Socket_Option): Use "* 1000" instead of "/ 0.001" to convert to milliseconds. --- gcc/ada/libgnat/g-socket.adb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/g-socket.adb b/gcc/ada/libgnat/g-socket.adb index a246303..75a2b27 100644 --- a/gcc/ada/libgnat/g-socket.adb +++ b/gcc/ada/libgnat/g-socket.adb @@ -1570,14 +1570,18 @@ package body GNAT.Sockets is | Send_Timeout => if Is_Windows then - - -- Timeout is in milliseconds, actual value is 500 ms + - -- returned value (unless it is 0). - if U4 = 0 then Opt.Timeout := 0.0; + else - Opt.Timeout := Duration (U4) / 1000 + 0.500; + if Minus_500ms_Windows_Timeout then + -- Timeout is in milliseconds, actual value is 500 ms + + -- returned value (unless it is 0). + + U4 := U4 + 500; + end if; + + Opt.Timeout := Duration (U4) / 1000; end if; else @@ -2724,7 +2728,7 @@ package body GNAT.Sockets is Len := U4'Size / 8; Add := U4'Address; - U4 := C.unsigned (Option.Timeout / 0.001); + U4 := C.unsigned (Option.Timeout * 1000); if Option.Timeout > 0.0 and then U4 = 0 then -- Avoid round to zero. Zero timeout mean unlimited -- cgit v1.1 From 2d71668e64c4b20aec823dbe5a1feb6338d527a2 Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Tue, 18 May 2021 18:26:24 -0700 Subject: [Ada] Improve interactions between DSA and Put_Image routines for tagged types gcc/ada/ * exp_dist.adb (Add_RACW_Primitive_Declarations_And_Bodies): Add TSS_Put_Image to list of predefined primitives that need special treatment. (Build_General_Calling_Stubs, Build_Subprogram_Receiving_Stubs): Remove previous hack for dealing with TSS_Put_Image procedures. --- gcc/ada/exp_dist.adb | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_dist.adb b/gcc/ada/exp_dist.adb index 35ccf9d..5cb8fb5 100644 --- a/gcc/ada/exp_dist.adb +++ b/gcc/ada/exp_dist.adb @@ -1424,6 +1424,7 @@ package body Exp_Dist is and then Chars (Current_Primitive) /= Name_uAlignment and then not (Is_TSS (Current_Primitive, TSS_Deep_Finalize) or else + Is_TSS (Current_Primitive, TSS_Put_Image) or else Is_TSS (Current_Primitive, TSS_Stream_Input) or else Is_TSS (Current_Primitive, TSS_Stream_Output) or else Is_TSS (Current_Primitive, TSS_Stream_Read) or else @@ -4211,14 +4212,6 @@ package body Exp_Dist is -- Used only for the PolyORB case begin - -- workaround for later failures in Exp_Util.Find_Prim_Op - if Is_TSS (Defining_Unit_Name (Spec), TSS_Put_Image) then - Append_To (Statements, - Make_Raise_Program_Error (Loc, - Reason => PE_Stream_Operation_Not_Allowed)); - return; - end if; - -- The general form of a calling stub for a given subprogram is: -- procedure X (...) is P : constant Partition_ID := @@ -4734,11 +4727,11 @@ package body Exp_Dist is -- Formal parameter for receiving stubs: a descriptor for an incoming -- request. - Decls : List_Id := New_List; + Decls : constant List_Id := New_List; -- All the parameters will get declared before calling the real -- subprograms. Also the out parameters will be declared. - Statements : List_Id := New_List; + Statements : constant List_Id := New_List; Extra_Formal_Statements : constant List_Id := New_List; -- Statements concerning extra formal parameters @@ -5173,19 +5166,6 @@ package body Exp_Dist is Parameter_Type => New_Occurrence_Of (RTE (RE_Request_Access), Loc)))); - -- workaround for later failures in Exp_Util.Find_Prim_Op - if Is_TSS (Defining_Unit_Name (Specification (Vis_Decl)), - TSS_Put_Image) - then - -- drop everything on the floor - Decls := New_List; - Statements := New_List; - Excep_Handlers := New_List; - Append_To (Statements, - Make_Raise_Program_Error (Loc, - Reason => PE_Stream_Operation_Not_Allowed)); - end if; - return Make_Subprogram_Body (Loc, Specification => Subp_Spec, -- cgit v1.1 From a547eea2669af282dfca4f3c38362f109b285308 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Wed, 19 May 2021 11:37:47 -0400 Subject: [Ada] Fix bugs in Value_Size clauses and refactor gcc/ada/ * sem_ch13.adb (Analyze_Attribute_Definition_Clause): Combine processing of Size and Value_Size clauses. Ensure that Value_Size is treated the same as Size, in the cases where both are allowed (i.e. the prefix denotes a first subtype). Misc cleanup. * einfo-utils.adb (Init_Size): Add assertions. (Size_Clause): Return a Value_Size clause if present, instead of just looking for a Size clause. * einfo.ads (Has_Size_Clause, Size_Clause): Change documentation to include Value_Size. * sem_ch13.ads, layout.ads, layout.adb: Comment modifications. --- gcc/ada/einfo-utils.adb | 17 +++- gcc/ada/einfo.ads | 23 +++--- gcc/ada/layout.adb | 10 +-- gcc/ada/layout.ads | 7 +- gcc/ada/sem_ch13.adb | 208 +++++++++++++++++++++++------------------------- gcc/ada/sem_ch13.ads | 22 ++--- 6 files changed, 145 insertions(+), 142 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/einfo-utils.adb b/gcc/ada/einfo-utils.adb index 6e8a772..22143d6 100644 --- a/gcc/ada/einfo-utils.adb +++ b/gcc/ada/einfo-utils.adb @@ -481,7 +481,13 @@ package body Einfo.Utils is procedure Init_Size (Id : E; V : Int) is begin - pragma Assert (not Is_Object (Id)); + pragma Assert (Is_Type (Id)); + pragma Assert + (not Known_Esize (Id) or else Esize (Id) = V); + pragma Assert + (RM_Size (Id) = No_Uint + or else RM_Size (Id) = Uint_0 + or else RM_Size (Id) = V); Set_Esize (Id, UI_From_Int (V)); Set_RM_Size (Id, UI_From_Int (V)); end Init_Size; @@ -492,7 +498,7 @@ package body Einfo.Utils is procedure Init_Size_Align (Id : E) is begin - pragma Assert (not Is_Object (Id)); + pragma Assert (Ekind (Id) in Type_Kind | E_Void); Set_Esize (Id, Uint_0); Set_RM_Size (Id, Uint_0); Set_Alignment (Id, Uint_0); @@ -2927,8 +2933,13 @@ package body Einfo.Utils is ----------------- function Size_Clause (Id : E) return N is + Result : N := Get_Attribute_Definition_Clause (Id, Attribute_Size); begin - return Get_Attribute_Definition_Clause (Id, Attribute_Size); + if No (Result) then + Result := Get_Attribute_Definition_Clause (Id, Attribute_Value_Size); + end if; + + return Result; end Size_Clause; ------------------------ diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index 2feef7a..6a8d493 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -2015,11 +2015,11 @@ package Einfo is -- which at least one of the shift operators is defined. -- Has_Size_Clause --- Defined in entities for types and objects. Set if a size clause is --- defined for the entity. Used to prevent multiple Size clauses for a --- given entity. Note that it is always initially cleared for a derived --- type, even though the Size for such a type is inherited from a Size --- clause given for the parent type. +-- Defined in entities for types and objects. Set if a size or value size +-- clause is defined for the entity. Used to prevent multiple clauses +-- for a given entity. Note that it is always initially cleared for a +-- derived type, even though the Size or Value_Size clause for such a +-- type might be inherited from an ancestor type. -- Has_Small_Clause -- Defined in ordinary fixed point types (but not subtypes). Indicates @@ -4321,13 +4321,12 @@ package Einfo is -- suppress this code if a subsequent address clause is encountered. -- Size_Clause (synthesized) --- Applies to all entities. If a size clause is present in the rep --- item chain for an entity then the attribute definition clause node --- for the size clause is returned. Otherwise Size_Clause returns Empty --- if no item is present. Usually this is only meaningful if the flag --- Has_Size_Clause is set. This is because when the representation item --- chain is copied for a derived type, it can inherit a size clause that --- is not applicable to the entity. +-- Applies to all entities. If a size or value size clause is present in +-- the rep item chain for an entity then that attribute definition clause +-- is returned. Otherwise Size_Clause returns Empty. Usually this is only +-- meaningful if the flag Has_Size_Clause is set. This is because when +-- the representation item chain is copied for a derived type, it can +-- inherit a size clause that is not applicable to the entity. -- Size_Depends_On_Discriminant -- Defined in all entities for types and subtypes. Indicates that the diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb index 5bafbcc..6dc4d7f 100644 --- a/gcc/ada/layout.adb +++ b/gcc/ada/layout.adb @@ -270,15 +270,15 @@ package body Layout is Desig_Type := Non_Limited_View (Designated_Type (E)); end if; - -- If Esize already set (e.g. by a size clause), then nothing further - -- to be done here. + -- If Esize already set (e.g. by a size or value size clause), then + -- nothing further to be done here. if Known_Esize (E) then null; - -- Access to subprogram is a strange beast, and we let the backend - -- figure out what is needed (it may be some kind of fat pointer, - -- including the static link for example. + -- Access to protected subprogram is a strange beast, and we let the + -- backend figure out what is needed (it may be some kind of fat + -- pointer, including the static link for example). elsif Is_Access_Protected_Subprogram_Type (E) then null; diff --git a/gcc/ada/layout.ads b/gcc/ada/layout.ads index 32caee0..89ee5bd 100644 --- a/gcc/ada/layout.ads +++ b/gcc/ada/layout.ads @@ -32,10 +32,9 @@ with Types; use Types; package Layout is - -- The following procedures are called from Freeze, so all entities - -- for types and objects that get frozen (which should be all such - -- entities which are seen by the back end) will get laid out by one - -- of these two procedures. + -- The following procedures are called from Freeze, so all entities for + -- types and objects that get frozen (i.e. all types and objects seen by + -- the back end) will get laid out by one of these two procedures. procedure Layout_Type (E : Entity_Id); -- This procedure may set or adjust the fields Esize, RM_Size and diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index cdc0083..92d5249 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -7180,109 +7180,136 @@ package body Sem_Ch13 is Set_SSO_Set_High_By_Default (Base_Type (U_Ent), False); end if; - ---------- - -- Size -- - ---------- + ------------------------ + -- Size or Value_Size -- + ------------------------ - -- Size attribute definition clause + -- Size or Value_Size attribute definition clause. These are treated + -- the same, except that Size is allowed on objects, and Value_Size + -- is allowed on nonfirst subtypes. First subtypes allow both Size + -- and Value_Size; the treatment is the same for both. - when Attribute_Size => Size : declare + when Attribute_Size | Attribute_Value_Size => Size : declare Size : constant Uint := Static_Integer (Expr); - Etyp : Entity_Id; - Biased : Boolean; + + Attr_Name : constant String := + (if Id = Attribute_Size then "size" + elsif Id = Attribute_Value_Size then "value size" + else ""); -- can't happen + -- Name of the attribute for printing in messages + + OK_Prefix : constant Boolean := + (if Id = Attribute_Size then + Ekind (U_Ent) in Type_Kind | Constant_Or_Variable_Kind + elsif Id = Attribute_Value_Size then + Ekind (U_Ent) in Type_Kind + else False); -- can't happen + -- For X'Size, X can be a type or object; for X'Value_Size, + -- X can be a type. Note that we already checked that 'Size + -- can be specified only for a first subytype. begin FOnly := True; - if Duplicate_Clause then - null; + if not OK_Prefix then + Error_Msg_N (Attr_Name & " cannot be given for &", Nam); - elsif not Is_Type (U_Ent) - and then Ekind (U_Ent) /= E_Variable - and then Ekind (U_Ent) /= E_Constant - then - Error_Msg_N ("size cannot be given for &", Nam); + elsif Duplicate_Clause then + null; elsif Is_Array_Type (U_Ent) and then not Is_Constrained (U_Ent) then Error_Msg_N - ("size cannot be given for unconstrained array", Nam); + (Attr_Name & " cannot be given for unconstrained array", Nam); elsif Size /= No_Uint then - if Is_Type (U_Ent) then - Etyp := U_Ent; - else - Etyp := Etype (U_Ent); - end if; + declare + Etyp : constant Entity_Id := + (if Is_Type (U_Ent) then U_Ent else Etype (U_Ent)); - -- Check size, note that Gigi is in charge of checking that the - -- size of an array or record type is OK. Also we do not check - -- the size in the ordinary fixed-point case, since it is too - -- early to do so (there may be subsequent small clause that - -- affects the size). We can check the size if a small clause - -- has already been given. + begin + -- Check size, note that Gigi is in charge of checking that + -- the size of an array or record type is OK. Also we do not + -- check the size in the ordinary fixed-point case, since + -- it is too early to do so (there may be subsequent small + -- clause that affects the size). We can check the size if + -- a small clause has already been given. + + if not Is_Ordinary_Fixed_Point_Type (U_Ent) + or else Has_Small_Clause (U_Ent) + then + declare + Biased : Boolean; + begin + Check_Size (Expr, Etyp, Size, Biased); + Set_Biased (U_Ent, N, Attr_Name & " clause", Biased); + end; + end if; - if not Is_Ordinary_Fixed_Point_Type (U_Ent) - or else Has_Small_Clause (U_Ent) - then - Check_Size (Expr, Etyp, Size, Biased); - Set_Biased (U_Ent, N, "size clause", Biased); - end if; + -- For types, set RM_Size and Esize if appropriate - -- For types set RM_Size and Esize if possible + if Is_Type (U_Ent) then + Set_RM_Size (U_Ent, Size); - if Is_Type (U_Ent) then - Set_RM_Size (U_Ent, Size); + -- If we are specifying the Size or Value_Size of a + -- first subtype, then for elementary types, increase + -- Object_Size to power of 2, but not less than a storage + -- unit in any case (normally this means it will be byte + -- addressable). - -- For elementary types, increase Object_Size to power of 2, - -- but not less than a storage unit in any case (normally - -- this means it will be byte addressable). + -- For all other types, nothing else to do, we leave + -- Esize (object size) unset; the back end will set it + -- from the size and alignment in an appropriate manner. - -- For all other types, nothing else to do, we leave Esize - -- (object size) unset, the back end will set it from the - -- size and alignment in an appropriate manner. + -- In both cases, we check whether the alignment must be + -- reset in the wake of the size change. - -- In both cases, we check whether the alignment must be - -- reset in the wake of the size change. + -- For nonfirst subtypes ('Value_Size only), we do + -- nothing here. - if Is_Elementary_Type (U_Ent) then - if Size <= System_Storage_Unit then - Init_Esize (U_Ent, System_Storage_Unit); - elsif Size <= 16 then - Init_Esize (U_Ent, 16); - elsif Size <= 32 then - Init_Esize (U_Ent, 32); - else - Set_Esize (U_Ent, (Size + 63) / 64 * 64); + if Is_First_Subtype (U_Ent) then + if Is_Elementary_Type (U_Ent) then + if Size <= System_Storage_Unit then + Init_Esize (U_Ent, System_Storage_Unit); + elsif Size <= 16 then + Init_Esize (U_Ent, 16); + elsif Size <= 32 then + Init_Esize (U_Ent, 32); + else + Set_Esize (U_Ent, (Size + 63) / 64 * 64); + end if; + + Alignment_Check_For_Size_Change + (U_Ent, Esize (U_Ent)); + else + Alignment_Check_For_Size_Change (U_Ent, Size); + end if; end if; - Alignment_Check_For_Size_Change (U_Ent, Esize (U_Ent)); - else - Alignment_Check_For_Size_Change (U_Ent, Size); - end if; + -- For Object'Size, set Esize only - -- For objects, set Esize only + else + if Is_Elementary_Type (Etyp) + and then Size /= System_Storage_Unit + and then Size /= 16 + and then Size /= 32 + and then Size /= 64 + and then Size /= System_Max_Integer_Size + then + Error_Msg_Uint_1 := UI_From_Int (System_Storage_Unit); + Error_Msg_Uint_2 := + UI_From_Int (System_Max_Integer_Size); + Error_Msg_N + ("size for primitive object must be a power of 2 in " + & "the range ^-^", N); + end if; - else - if Is_Elementary_Type (Etyp) - and then Size /= System_Storage_Unit - and then Size /= 16 - and then Size /= 32 - and then Size /= 64 - and then Size /= System_Max_Integer_Size - then - Error_Msg_Uint_1 := UI_From_Int (System_Storage_Unit); - Error_Msg_Uint_2 := UI_From_Int (System_Max_Integer_Size); - Error_Msg_N - ("size for primitive object must be a power of 2 in " - & "the range ^-^", N); + Set_Esize (U_Ent, Size); end if; - Set_Esize (U_Ent, Size); - end if; - - Set_Has_Size_Clause (U_Ent); + Set_Has_Size_Clause (U_Ent); + end; end if; end Size; @@ -7744,39 +7771,6 @@ package body Sem_Ch13 is end if; end Stream_Size; - ---------------- - -- Value_Size -- - ---------------- - - -- Value_Size attribute definition clause - - when Attribute_Value_Size => Value_Size : declare - Size : constant Uint := Static_Integer (Expr); - Biased : Boolean; - - begin - if not Is_Type (U_Ent) then - Error_Msg_N ("Value_Size cannot be given for &", Nam); - - elsif Duplicate_Clause then - null; - - elsif Is_Array_Type (U_Ent) - and then not Is_Constrained (U_Ent) - then - Error_Msg_N - ("Value_Size cannot be given for unconstrained array", Nam); - - else - if Is_Elementary_Type (U_Ent) then - Check_Size (Expr, U_Ent, Size, Biased); - Set_Biased (U_Ent, N, "value size clause", Biased); - end if; - - Set_RM_Size (U_Ent, Size); - end if; - end Value_Size; - ----------------------- -- Variable_Indexing -- ----------------------- diff --git a/gcc/ada/sem_ch13.ads b/gcc/ada/sem_ch13.ads index 7579812..3b21484 100644 --- a/gcc/ada/sem_ch13.ads +++ b/gcc/ada/sem_ch13.ads @@ -115,17 +115,17 @@ package Sem_Ch13 is Siz : Uint; Biased : out Boolean); -- Called when size Siz is specified for subtype T. This subprogram checks - -- that the size is appropriate, posting errors on node N as required. - -- This check is effective for elementary types and bit-packed arrays. - -- For other non-elementary types, a check is only made if an explicit - -- size has been given for the type (and the specified size must match). - -- The parameter Biased is set False if the size specified did not require - -- the use of biased representation, and True if biased representation - -- was required to meet the size requirement. Note that Biased is only - -- set if the type is not currently biased, but biasing it is the only - -- way to meet the requirement. If the type is currently biased, then - -- this biased size is used in the initial check, and Biased is False. - -- For a Component_Size clause, T is the component type. + -- that the size is appropriate, posting errors on node N as required. This + -- check is effective for elementary types and bit-packed arrays. For + -- composite types, a check is only made if an explicit size has been given + -- for the type (and the specified size must match). The parameter Biased + -- is set False if the size specified did not require the use of biased + -- representation, and True if biased representation was required to meet + -- the size requirement. Note that Biased is only set if the type is not + -- currently biased, but biasing it is the only way to meet the + -- requirement. If the type is currently biased, then this biased size is + -- used in the initial check, and Biased is False. For a Component_Size + -- clause, T is the component type. function Has_Compatible_Representation (Target_Type, Operand_Type : Entity_Id) return Boolean; -- cgit v1.1 From d1d2bbcc858ac473213af0bc2bd0c22a584ec80f Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 11 May 2021 16:44:40 +0200 Subject: [Ada] Replace obsolete calls that use global name buffer gcc/ada/ * uname.adb (Get_Body_Name, Get_Parent_Body_Name, Get_Parent_Spec_Name, Get_Spec_Name, Is_Child_Name, Is_Body_Name, Is_Spec_Name, Name_To_Unit_Name): Use a local instead of the global buffer. --- gcc/ada/uname.adb | 100 +++++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 47 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/uname.adb b/gcc/ada/uname.adb index 5dc8ac6..2391180 100644 --- a/gcc/ada/uname.adb +++ b/gcc/ada/uname.adb @@ -47,15 +47,18 @@ package body Uname is ------------------- function Get_Body_Name (N : Unit_Name_Type) return Unit_Name_Type is + Buffer : Bounded_String; begin - Get_Name_String (N); + Append (Buffer, N); - pragma Assert (Name_Len > 2 - and then Name_Buffer (Name_Len - 1) = '%' - and then Name_Buffer (Name_Len) = 's'); + pragma Assert + (Buffer.Length > 2 + and then Buffer.Chars (Buffer.Length - 1) = '%' + and then Buffer.Chars (Buffer.Length) = 's'); - Name_Buffer (Name_Len) := 'b'; - return Name_Find; + Buffer.Chars (Buffer.Length) := 'b'; + + return Name_Find (Buffer); end Get_Body_Name; ----------------------------------- @@ -111,19 +114,19 @@ package body Uname is -------------------------- function Get_Parent_Body_Name (N : Unit_Name_Type) return Unit_Name_Type is + Buffer : Bounded_String; begin - Get_Name_String (N); + Append (Buffer, N); - while Name_Buffer (Name_Len) /= '.' loop - pragma Assert (Name_Len > 1); -- not a child or subunit name - Name_Len := Name_Len - 1; + while Buffer.Chars (Buffer.Length) /= '.' loop + pragma Assert (Buffer.Length > 1); -- not a child or subunit name + Buffer.Length := Buffer.Length - 1; end loop; - Name_Buffer (Name_Len) := '%'; - Name_Len := Name_Len + 1; - Name_Buffer (Name_Len) := 'b'; - return Name_Find; + Buffer.Chars (Buffer.Length) := '%'; + Append (Buffer, 'b'); + return Name_Find (Buffer); end Get_Parent_Body_Name; -------------------------- @@ -131,22 +134,22 @@ package body Uname is -------------------------- function Get_Parent_Spec_Name (N : Unit_Name_Type) return Unit_Name_Type is + Buffer : Bounded_String; begin - Get_Name_String (N); + Append (Buffer, N); - while Name_Buffer (Name_Len) /= '.' loop - if Name_Len = 1 then + while Buffer.Chars (Buffer.Length) /= '.' loop + if Buffer.Length = 1 then return No_Unit_Name; else - Name_Len := Name_Len - 1; + Buffer.Length := Buffer.Length - 1; end if; end loop; - Name_Buffer (Name_Len) := '%'; - Name_Len := Name_Len + 1; - Name_Buffer (Name_Len) := 's'; - return Name_Find; + Buffer.Chars (Buffer.Length) := '%'; + Append (Buffer, 's'); + return Name_Find (Buffer); end Get_Parent_Spec_Name; ------------------- @@ -154,15 +157,18 @@ package body Uname is ------------------- function Get_Spec_Name (N : Unit_Name_Type) return Unit_Name_Type is + Buffer : Bounded_String; begin - Get_Name_String (N); + Append (Buffer, N); - pragma Assert (Name_Len > 2 - and then Name_Buffer (Name_Len - 1) = '%' - and then Name_Buffer (Name_Len) = 'b'); + pragma Assert + (Buffer.Length > 2 + and then Buffer.Chars (Buffer.Length - 1) = '%' + and then Buffer.Chars (Buffer.Length) = 'b'); - Name_Buffer (Name_Len) := 's'; - return Name_Find; + Buffer.Chars (Buffer.Length) := 's'; + + return Name_Find (Buffer); end Get_Spec_Name; ------------------- @@ -489,11 +495,12 @@ package body Uname is ------------------ function Is_Body_Name (N : Unit_Name_Type) return Boolean is + Buffer : Bounded_String; begin - Get_Name_String (N); - return Name_Len > 2 - and then Name_Buffer (Name_Len - 1) = '%' - and then Name_Buffer (Name_Len) = 'b'; + Append (Buffer, N); + return Buffer.Length > 2 + and then Buffer.Chars (Buffer.Length - 1) = '%' + and then Buffer.Chars (Buffer.Length) = 'b'; end Is_Body_Name; ------------------- @@ -501,17 +508,16 @@ package body Uname is ------------------- function Is_Child_Name (N : Unit_Name_Type) return Boolean is - J : Natural; + Buffer : Bounded_String; begin - Get_Name_String (N); - J := Name_Len; + Append (Buffer, N); - while Name_Buffer (J) /= '.' loop - if J = 1 then + while Buffer.Chars (Buffer.Length) /= '.' loop + if Buffer.Length = 1 then return False; -- not a child or subunit name else - J := J - 1; + Buffer.Length := Buffer.Length - 1; end if; end loop; @@ -589,11 +595,12 @@ package body Uname is ------------------ function Is_Spec_Name (N : Unit_Name_Type) return Boolean is + Buffer : Bounded_String; begin - Get_Name_String (N); - return Name_Len > 2 - and then Name_Buffer (Name_Len - 1) = '%' - and then Name_Buffer (Name_Len) = 's'; + Append (Buffer, N); + return Buffer.Length > 2 + and then Buffer.Chars (Buffer.Length - 1) = '%' + and then Buffer.Chars (Buffer.Length) = 's'; end Is_Spec_Name; ----------------------- @@ -601,12 +608,11 @@ package body Uname is ----------------------- function Name_To_Unit_Name (N : Name_Id) return Unit_Name_Type is + Buffer : Bounded_String; begin - Get_Name_String (N); - Name_Buffer (Name_Len + 1) := '%'; - Name_Buffer (Name_Len + 2) := 's'; - Name_Len := Name_Len + 2; - return Name_Find; + Append (Buffer, N); + Append (Buffer, "%s"); + return Name_Find (Buffer); end Name_To_Unit_Name; --------------- -- cgit v1.1 From 768f69696a054a0709b114d3ad3d73265daf115d Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 11 May 2021 12:16:14 +0200 Subject: [Ada] Use bounded string buffer in Get_Unit_Name gcc/ada/ * uname.adb (Get_Unit_Name): Simplify with a bounded string buffer; also, this addresses a ??? comment about the max length being exceeded. --- gcc/ada/uname.adb | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/uname.adb b/gcc/ada/uname.adb index 2391180..18cb6d1 100644 --- a/gcc/ada/uname.adb +++ b/gcc/ada/uname.adb @@ -177,13 +177,8 @@ package body Uname is function Get_Unit_Name (N : Node_Id) return Unit_Name_Type is - Unit_Name_Buffer : String (1 .. Hostparm.Max_Name_Length); - -- Buffer used to build name of unit. Note that we cannot use the - -- Name_Buffer in package Name_Table because we use it to read - -- component names. - - Unit_Name_Length : Natural := 0; - -- Length of name stored in Unit_Name_Buffer + Unit_Name_Buffer : Bounded_String; + -- Buffer used to build name of unit Node : Node_Id; -- Program unit node @@ -206,9 +201,7 @@ package body Uname is procedure Add_Char (C : Character) is begin - -- Should really check for max length exceeded here??? - Unit_Name_Length := Unit_Name_Length + 1; - Unit_Name_Buffer (Unit_Name_Length) := C; + Append (Unit_Name_Buffer, C); end Add_Char; -------------- @@ -217,11 +210,7 @@ package body Uname is procedure Add_Name (Name : Name_Id) is begin - Get_Name_String (Name); - - for J in 1 .. Name_Len loop - Add_Char (Name_Buffer (J)); - end loop; + Append (Unit_Name_Buffer, Name); end Add_Name; ------------------- @@ -414,11 +403,7 @@ package body Uname is raise Program_Error; end case; - Name_Buffer (1 .. Unit_Name_Length) := - Unit_Name_Buffer (1 .. Unit_Name_Length); - Name_Len := Unit_Name_Length; - return Name_Find; - + return Name_Find (Unit_Name_Buffer); end Get_Unit_Name; -------------------------- -- cgit v1.1 From e5be1e443cef81f458545f5dae1a91860ca1ae71 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Wed, 19 May 2021 15:18:54 +0200 Subject: [Ada] Fix location of errors about volatile compatibility gcc/ada/ * sem_ch12.adb (Check_Shared_Variable_Control_Aspects): Errors emitted via Check_Volatility_Compatibility are now emitted at Actual, just like other errors emitted by Check_Shared_Variable_Control_Aspects. --- gcc/ada/sem_ch12.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index 339bb42..1c8f64e 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -12825,7 +12825,7 @@ package body Sem_Ch12 is Check_Volatility_Compatibility (Act_T, A_Gen_T, "actual type", "its corresponding formal type", - Srcpos_Bearer => Act_T); + Srcpos_Bearer => Actual); end if; end Check_Shared_Variable_Control_Aspects; -- cgit v1.1 From 14212dc422ed09f8324bbfd1dec662cbb2fdbe0e Mon Sep 17 00:00:00 2001 From: Gary Dismukes Date: Mon, 17 May 2021 03:35:25 -0400 Subject: [Ada] Implement new legality checks specified by AI12-0412 gcc/ada/ * freeze.adb (Check_Inherited_Conditions): Setting of Ekind, LSP_Subprogram, and Is_Wrapper needs to happen for null procedures as well as other wrapper cases, so the code is moved from the else part in front of the if statement. (Fixes a latent bug encountered while working on this set of changes.) * sem_attr.adb (Resolve_Attribute): Report an error for the case of an Access attribute applied to a primitive of an abstract type when the primitive has any nonstatic Pre'Class or Post'Class expressions. * sem_ch8.adb (Analyze_Subprogram_Renaming): Report an error for the case of a actual subprogram associated with a nonabstract formal subprogram when the actual is a primitive of an abstract type and the primitive has any nonstatic Pre'Class or Post'Class expressions. * sem_disp.adb (Check_Dispatching_Context): Remove special testing for null procedures, and replace it with a relaxed test that avoids getting an error about illegal calls to abstract subprograms in cases where RM 6.1.1(7/5) applies in Pre/Post'Class aspects. Also, remove special test for Postcondition, which seems to be unnecessary, update associated comments, and fix a typo in one comment. (Check_Dispatching_Call): Remove an unneeded return statement, and report an error for the case of a nondispatching call to a nonabstract subprogram of an abstract type where the subprogram has nonstatic Pre/Post'Class aspects. * sem_util.ads (Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post): New function. (In_Pre_Post_Condition): Add a flag formal Class_Wide_Only, defaulted to False, for indicating whether the function should only test for the node being within class-wide pre- and postconditions. * sem_util.adb (Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post): New function to determine whether a subprogram is a primitive of an abstract type where the primitive has class-wide Pre/Post'Class aspects specified with nonstatic expressions. (In_Pre_Post_Condition): Extend testing to account for the new formal Class_Wide_Only. --- gcc/ada/freeze.adb | 12 +++++----- gcc/ada/sem_attr.adb | 19 +++++++++++++++ gcc/ada/sem_ch8.adb | 28 +++++++++++++++++----- gcc/ada/sem_disp.adb | 67 +++++++++++++++++++++++++++++++++------------------- gcc/ada/sem_util.adb | 67 +++++++++++++++++++++++++++++++++++++++++++++------- gcc/ada/sem_util.ads | 12 ++++++++-- 6 files changed, 159 insertions(+), 46 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index fa16887..3796433 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -1671,6 +1671,12 @@ package body Freeze is -- type declaration that generates inherited operation. For -- a null procedure, the declaration implies a null body. + -- Before insertion, do some minimal decoration of fields + + Mutate_Ekind (New_Id, Ekind (Par_Prim)); + Set_LSP_Subprogram (New_Id, Par_Prim); + Set_Is_Wrapper (New_Id); + if Nkind (New_Spec) = N_Procedure_Specification and then Null_Present (New_Spec) then @@ -1684,12 +1690,6 @@ package body Freeze is Build_Class_Wide_Clone_Call (Loc, Decls, Par_Prim, New_Spec); - -- Adding minimum decoration - - Mutate_Ekind (New_Id, Ekind (Par_Prim)); - Set_LSP_Subprogram (New_Id, Par_Prim); - Set_Is_Wrapper (New_Id); - Insert_List_After_And_Analyze (Par_R, New_List (New_Decl, New_Body)); diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb index e0b2072..d1a91d8 100644 --- a/gcc/ada/sem_attr.adb +++ b/gcc/ada/sem_attr.adb @@ -11499,6 +11499,25 @@ package body Sem_Attr is Error_Msg_F ("context requires a non-protected subprogram", P); end if; + -- AI12-0412: The rule in RM 6.1.1(18.2/5) disallows applying + -- attribute Access to a primitive of an abstract type when the + -- primitive has any Pre'Class or Post'Class aspects specified + -- with nonstatic expressions. + + if Attr_Id = Attribute_Access + and then Ekind (Btyp) in E_Access_Subprogram_Type + | E_Anonymous_Access_Subprogram_Type + and then Is_Entity_Name (P) + and then Is_Dispatching_Operation (Entity (P)) + and then + Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post (Entity (P)) + then + Error_Msg_N + ("attribute not allowed for primitive of abstract type with " + & "nonstatic class-wide pre/postconditions", + N); + end if; + -- The context cannot be a pool-specific type, but this is a -- legality rule, not a resolution rule, so it must be checked -- separately, after possibly disambiguation (see AI-245). diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index f056a18..78d2426 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -3790,15 +3790,31 @@ package body Sem_Ch8 is Set_Has_Delayed_Freeze (New_S, False); Freeze_Before (N, New_S); - -- An abstract subprogram is only allowed as an actual in the case - -- where the formal subprogram is also abstract. - if (Ekind (Old_S) = E_Procedure or else Ekind (Old_S) = E_Function) - and then Is_Abstract_Subprogram (Old_S) and then not Is_Abstract_Subprogram (Formal_Spec) then - Error_Msg_N - ("abstract subprogram not allowed as generic actual", Nam); + -- An abstract subprogram is only allowed as an actual in the + -- case where the formal subprogram is also abstract. + + if Is_Abstract_Subprogram (Old_S) then + Error_Msg_N + ("abstract subprogram not allowed as generic actual", Nam); + end if; + + -- AI12-0412: A primitive of an abstract type with Pre'Class + -- or Post'Class aspects specified with nonstatic expressions + -- is not allowed as actual for a nonabstract formal subprogram + -- (see RM 6.1.1(18.2/5). + + if Is_Dispatching_Operation (Old_S) + and then + Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post (Old_S) + then + Error_Msg_N + ("primitive of abstract type with nonstatic class-wide " + & "pre/postconditions not allowed as actual", + Nam); + end if; end if; end if; diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb index 06c4b07..064e2b5 100644 --- a/gcc/ada/sem_disp.adb +++ b/gcc/ada/sem_disp.adb @@ -612,29 +612,32 @@ package body Sem_Disp is Set_Entity (Name (N), Alias (Subp)); return; - -- An obscure special case: a null procedure may have a class- - -- wide pre/postcondition that includes a call to an abstract - -- subp. Calls within the expression may not have been rewritten - -- as dispatching calls yet, because the null body appears in - -- the current declarative part. The expression will be properly - -- rewritten/reanalyzed when the postcondition procedure is built. - - -- Similarly, if this is a pre/postcondition for an abstract - -- subprogram, it may call another abstract function which is - -- a primitive of an abstract type. The call is non-dispatching - -- but will be legal in overridings of the operation. However, - -- if the call is tag-indeterminate we want to continue with - -- with the error checking below, as this case is illegal even - -- for abstract subprograms (see AI12-0170). - - elsif (Is_Subprogram (Scop) - or else Chars (Scop) = Name_Postcondition) + -- If this is a pre/postcondition for an abstract subprogram, + -- it may call another abstract function that is a primitive + -- of an abstract type. The call is nondispatching but will be + -- legal in overridings of the operation. However, if the call + -- is tag-indeterminate we want to continue with with the error + -- checking below, as this case is illegal even for abstract + -- subprograms (see AI12-0170). + + -- Similarly, as per AI12-0412, a nonabstract subprogram may + -- have a class-wide pre/postcondition that includes a call to + -- an abstract primitive of the subprogram's controlling type. + -- Certain operations (nondispatching calls, 'Access, use as + -- a generic actual) applied to such a nonabstract subprogram + -- are illegal in the case where the type is abstract (see + -- RM 6.1.1(18.2/5)). + + elsif Is_Subprogram (Scop) + and then not Is_Tag_Indeterminate (N) + and then In_Pre_Post_Condition (Call, Class_Wide_Only => True) + + -- The tagged type associated with the called subprogram must be + -- the same as that of the subprogram with a class-wide aspect. + + and then Is_Dispatching_Operation (Scop) and then - ((Is_Abstract_Subprogram (Scop) - and then not Is_Tag_Indeterminate (N)) - or else - (Nkind (Parent (Scop)) = N_Procedure_Specification - and then Null_Present (Parent (Scop)))) + Find_Dispatching_Type (Subp) = Find_Dispatching_Type (Scop) then null; @@ -663,7 +666,7 @@ package body Sem_Disp is -- provides a tag to make the call dispatching. This requires -- the call to be the actual in an enclosing call, and that -- actual must be controlling. If the call is an operand of - -- equality, the other operand must not ve abstract. + -- equality, the other operand must not be abstract. if not Is_Tagged_Type (Typ) and then not @@ -970,7 +973,6 @@ package body Sem_Disp is end loop; Check_Dispatching_Context (N); - return; elsif Nkind (Parent (N)) in N_Subexpr then Check_Dispatching_Context (N); @@ -985,6 +987,23 @@ package body Sem_Disp is return; end if; + -- If this is a nondispatching call to a nonabstract subprogram + -- and the subprogram has any Pre'Class or Post'Class aspects with + -- nonstatic values, then report an error. This is specified by + -- RM 6.1.1(18.2/5) (by AI12-0412). + + if No (Control) + and then not Is_Abstract_Subprogram (Subp_Entity) + and then + Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post (Subp_Entity) + then + Error_Msg_N + ("nondispatching call to nonabstract subprogram of " + & "abstract type with nonstatic class-wide " + & "pre/postconditions", + N); + end if; + else -- If dispatching on result, the enclosing call, if any, will -- determine the controlling argument. Otherwise this is the diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 799f720..12e5aa8 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -13295,6 +13295,44 @@ package body Sem_Util is and then Nkind (Node (First_Elmt (Constits))) = N_Null; end Has_Null_Refinement; + ------------------------------------------ + -- Has_Nonstatic_Class_Wide_Pre_Or_Post -- + ------------------------------------------ + + function Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post + (Subp : Entity_Id) return Boolean + is + Disp_Type : constant Entity_Id := Find_Dispatching_Type (Subp); + Prag : Node_Id; + Pragma_Arg : Node_Id; + + begin + if Present (Disp_Type) + and then Is_Abstract_Type (Disp_Type) + and then Present (Contract (Subp)) + then + Prag := Pre_Post_Conditions (Contract (Subp)); + + while Present (Prag) loop + if Pragma_Name (Prag) in Name_Precondition | Name_Postcondition + and then Class_Present (Prag) + then + Pragma_Arg := + Nlists.First + (Pragma_Argument_Associations (Prag)); + + if not Is_Static_Expression (Expression (Pragma_Arg)) then + return True; + end if; + end if; + + Prag := Next_Pragma (Prag); + end loop; + end if; + + return False; + end Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post; + ------------------------------- -- Has_Overriding_Initialize -- ------------------------------- @@ -14431,7 +14469,9 @@ package body Sem_Util is -- In_Pre_Post_Condition -- --------------------------- - function In_Pre_Post_Condition (N : Node_Id) return Boolean is + function In_Pre_Post_Condition + (N : Node_Id; Class_Wide_Only : Boolean := False) return Boolean + is Par : Node_Id; Prag : Node_Id := Empty; Prag_Id : Pragma_Id; @@ -14457,13 +14497,24 @@ package body Sem_Util is if Present (Prag) then Prag_Id := Get_Pragma_Id (Prag); - return - Prag_Id = Pragma_Post - or else Prag_Id = Pragma_Post_Class - or else Prag_Id = Pragma_Postcondition - or else Prag_Id = Pragma_Pre - or else Prag_Id = Pragma_Pre_Class - or else Prag_Id = Pragma_Precondition; + if Class_Wide_Only then + return + Prag_Id = Pragma_Post_Class + or else Prag_Id = Pragma_Pre_Class + or else (Class_Present (Prag) + and then (Prag_Id = Pragma_Post + or else Prag_Id = Pragma_Postcondition + or else Prag_Id = Pragma_Pre + or else Prag_Id = Pragma_Precondition)); + else + return + Prag_Id = Pragma_Post + or else Prag_Id = Pragma_Post_Class + or else Prag_Id = Pragma_Postcondition + or else Prag_Id = Pragma_Pre + or else Prag_Id = Pragma_Pre_Class + or else Prag_Id = Pragma_Precondition; + end if; -- Otherwise the node is not enclosed by a pre/postcondition pragma diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index bacf8b4..fb8309f 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -1516,6 +1516,12 @@ package Sem_Util is -- integer for use in compile-time checking. Note: Level is restricted to -- be non-dynamic. + function Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post + (Subp : Entity_Id) return Boolean; + -- Return True if Subp is a primitive of an abstract type, where the + -- primitive has a class-wide pre- or postcondition whose expression + -- is nonstatic. + function Has_Overriding_Initialize (T : Entity_Id) return Boolean; -- Predicate to determine whether a controlled type has a user-defined -- Initialize primitive (and, in Ada 2012, whether that primitive is @@ -1634,9 +1640,11 @@ package Sem_Util is function In_Pragma_Expression (N : Node_Id; Nam : Name_Id) return Boolean; -- Returns true if the expression N occurs within a pragma with name Nam - function In_Pre_Post_Condition (N : Node_Id) return Boolean; + function In_Pre_Post_Condition + (N : Node_Id; Class_Wide_Only : Boolean := False) return Boolean; -- Returns True if node N appears within a pre/postcondition pragma. Note - -- the pragma Check equivalents are NOT considered. + -- the pragma Check equivalents are NOT considered. If Class_Wide_Only is + -- True, then tests for N appearing within a class-wide pre/postcondition. function In_Quantified_Expression (N : Node_Id) return Boolean; -- Returns true if the expression N occurs within a quantified expression -- cgit v1.1 From 347d939028d648d55e72738c7500743ddcc70147 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Wed, 12 May 2021 05:28:29 -0400 Subject: [Ada] Code cleanups in System.Atomic_Counters gcc/ada/ * libgnat/s-atocou.ads, libgnat/s-atocou__builtin.adb: Code cleanups. --- gcc/ada/libgnat/s-atocou.ads | 1 - gcc/ada/libgnat/s-atocou__builtin.adb | 20 +++++--------------- 2 files changed, 5 insertions(+), 16 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/s-atocou.ads b/gcc/ada/libgnat/s-atocou.ads index a75173a..9488b6d 100644 --- a/gcc/ada/libgnat/s-atocou.ads +++ b/gcc/ada/libgnat/s-atocou.ads @@ -101,7 +101,6 @@ private type Atomic_Counter is record Value : aliased Atomic_Unsigned := 1; - pragma Atomic (Value); end record; end System.Atomic_Counters; diff --git a/gcc/ada/libgnat/s-atocou__builtin.adb b/gcc/ada/libgnat/s-atocou__builtin.adb index 2ca8b9e..d87f9ad 100644 --- a/gcc/ada/libgnat/s-atocou__builtin.adb +++ b/gcc/ada/libgnat/s-atocou__builtin.adb @@ -51,24 +51,19 @@ package body System.Atomic_Counters is procedure Decrement (Item : aliased in out Atomic_Unsigned) is begin - if Sync_Sub_And_Fetch (Item'Unrestricted_Access, 1) = 0 then + if Sync_Sub_And_Fetch (Item'Unchecked_Access, 1) = 0 then null; end if; end Decrement; function Decrement (Item : aliased in out Atomic_Unsigned) return Boolean is begin - return Sync_Sub_And_Fetch (Item'Unrestricted_Access, 1) = 0; + return Sync_Sub_And_Fetch (Item'Unchecked_Access, 1) = 0; end Decrement; function Decrement (Item : in out Atomic_Counter) return Boolean is begin - -- Note: the use of Unrestricted_Access here is required because we - -- are obtaining an access-to-volatile pointer to a non-volatile object. - -- This is not allowed for [Unchecked_]Access, but is safe in this case - -- because we know that no aliases are being created. - - return Sync_Sub_And_Fetch (Item.Value'Unrestricted_Access, 1) = 0; + return Sync_Sub_And_Fetch (Item.Value'Unchecked_Access, 1) = 0; end Decrement; --------------- @@ -77,17 +72,12 @@ package body System.Atomic_Counters is procedure Increment (Item : aliased in out Atomic_Unsigned) is begin - Sync_Add_And_Fetch (Item'Unrestricted_Access, 1); + Sync_Add_And_Fetch (Item'Unchecked_Access, 1); end Increment; procedure Increment (Item : in out Atomic_Counter) is begin - -- Note: the use of Unrestricted_Access here is required because we are - -- obtaining an access-to-volatile pointer to a non-volatile object. - -- This is not allowed for [Unchecked_]Access, but is safe in this case - -- because we know that no aliases are being created. - - Sync_Add_And_Fetch (Item.Value'Unrestricted_Access, 1); + Sync_Add_And_Fetch (Item.Value'Unchecked_Access, 1); end Increment; ---------------- -- cgit v1.1 From 9e76a063f11197aee9667b59ed8aa071e83237aa Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Thu, 20 May 2021 04:21:39 -0400 Subject: [Ada] Minor code cleanup gcc/ada/ * libgnat/g-debpoo.adb (Code_Address_For_Allocate_End): Default Initialize. --- gcc/ada/libgnat/g-debpoo.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/g-debpoo.adb b/gcc/ada/libgnat/g-debpoo.adb index 40e5279..0092139 100644 --- a/gcc/ada/libgnat/g-debpoo.adb +++ b/gcc/ada/libgnat/g-debpoo.adb @@ -362,7 +362,7 @@ package body GNAT.Debug_Pools is -- These procedures are used as markers when computing the stacktraces, -- so that addresses in the debug pool itself are not reported to the user. - Code_Address_For_Allocate_End : System.Address; + Code_Address_For_Allocate_End : System.Address := System.Null_Address; Code_Address_For_Deallocate_End : System.Address; Code_Address_For_Dereference_End : System.Address; -- Taking the address of the above procedures will not work on some -- cgit v1.1 From e1eb4441733ca9b80faf4f51a29418d720014ae1 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Wed, 19 May 2021 14:05:01 +0200 Subject: [Ada] Simplify code by reusing Remove on list of primitive operations gcc/ada/ * sem_prag.adb (Analyze_Pragma): Simplify processing of pragma CPP_Constructor. --- gcc/ada/sem_prag.adb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 41e887d..5705aa7 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -14738,7 +14738,6 @@ package body Sem_Prag is -- [, [Link_Name =>] static_string_EXPRESSION ]); when Pragma_CPP_Constructor => CPP_Constructor : declare - Elmt : Elmt_Id; Id : Entity_Id; Def_Id : Entity_Id; Tag_Typ : Entity_Id; @@ -14805,12 +14804,7 @@ package body Sem_Prag is then Tag_Typ := Etype (Def_Id); - Elmt := First_Elmt (Primitive_Operations (Tag_Typ)); - while Present (Elmt) and then Node (Elmt) /= Def_Id loop - Next_Elmt (Elmt); - end loop; - - Remove_Elmt (Primitive_Operations (Tag_Typ), Elmt); + Remove (Primitive_Operations (Tag_Typ), Def_Id); Set_Is_Dispatching_Operation (Def_Id, False); end if; -- cgit v1.1 From 29d3965161a8c9337a8b46019eea184ff3a6ac61 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Wed, 19 May 2021 14:24:13 -0400 Subject: [Ada] Optimize away certain elaboration checks gcc/ada/ * checks.adb (Install_Primitive_Elaboration_Check): Do not generate elaboration checks for primitives if pragma Pure or Preelaborate is present. Misc comment fixes, including referring to the correct kind of check (elaboration, not accessibility). * checks.ads, restrict.adb, sem_cat.ads, sinfo.ads: Minor reformatting and comment fixes. --- gcc/ada/checks.adb | 23 +++++++++++++++-------- gcc/ada/checks.ads | 2 +- gcc/ada/restrict.adb | 5 ++--- gcc/ada/sem_cat.ads | 2 +- gcc/ada/sinfo.ads | 2 +- 5 files changed, 20 insertions(+), 14 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 61ce9c2..cebeac5 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -48,6 +48,7 @@ with Sem; use Sem; with Sem_Aux; use Sem_Aux; with Sem_Ch3; use Sem_Ch3; with Sem_Ch8; use Sem_Ch8; +with Sem_Cat; use Sem_Cat; with Sem_Disp; use Sem_Disp; with Sem_Eval; use Sem_Eval; with Sem_Mech; use Sem_Mech; @@ -84,7 +85,7 @@ package body Checks is -- such as Apply_Scalar_Range_Check that do not insert any code can be -- safely called even when the Expander is inactive (but Errors_Detected -- is 0). The benefit of executing this code when expansion is off, is - -- the ability to emit constraint error warning for static expressions + -- the ability to emit constraint error warnings for static expressions -- even when we are not generating code. -- The above is modified in gnatprove mode to ensure that proper check @@ -8634,7 +8635,7 @@ package body Checks is return; -- Do not generate an elaboration check if the related subprogram is - -- not subjected to accessibility checks. + -- not subject to elaboration checks. elsif Elaboration_Checks_Suppressed (Subp_Id) then return; @@ -8644,14 +8645,20 @@ package body Checks is elsif Restriction_Active (No_Elaboration_Code) then return; + -- If pragma Pure or Preelaborate applies, then these elaboration checks + -- cannot fail, so do not generate them. + + elsif In_Preelaborated_Unit then + return; + -- Do not generate an elaboration check if exceptions cannot be used, -- caught, or propagated. elsif not Exceptions_OK then return; - -- Do not consider subprograms which act as compilation units, because - -- they cannot be the target of a dispatching call. + -- Do not consider subprograms that are compilation units, because they + -- cannot be the target of a dispatching call. elsif Nkind (Context) = N_Compilation_Unit then return; @@ -8681,10 +8688,10 @@ package body Checks is elsif Analyzed (Subp_Body) then return; - -- Do not consider primitives which occur within an instance that acts - -- as a compilation unit. Such an instance defines its spec and body out - -- of order (body is first) within the tree, which causes the reference - -- to the elaboration flag to appear as an undefined symbol. + -- Do not consider primitives that occur within an instance that is a + -- compilation unit. Such an instance defines its spec and body out of + -- order (body is first) within the tree, which causes the reference to + -- the elaboration flag to appear as an undefined symbol. elsif Within_Compilation_Unit_Instance (Subp_Id) then return; diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads index 130f871..a3835d9 100644 --- a/gcc/ada/checks.ads +++ b/gcc/ada/checks.ads @@ -357,7 +357,7 @@ package Checks is -- if so inserts the appropriate run-time check. procedure Install_Primitive_Elaboration_Check (Subp_Body : Node_Id); - -- Insert a check which ensures that subprogram body Subp_Body has been + -- Insert a check to ensure that subprogram body Subp_Body has been -- properly elaborated. The check is installed only when Subp_Body is the -- body of a nonabstract library-level primitive of a tagged type. Further -- restrictions may apply, see the body for details. diff --git a/gcc/ada/restrict.adb b/gcc/ada/restrict.adb index 4f1dea4..d97a42e 100644 --- a/gcc/ada/restrict.adb +++ b/gcc/ada/restrict.adb @@ -396,10 +396,9 @@ package body Restrict is N : Node_Id; V : Uint := Uint_Minus_1) is - Msg_Issued : Boolean; - pragma Unreferenced (Msg_Issued); + Ignore_Msg_Issued : Boolean; begin - Check_Restriction (Msg_Issued, R, N, V); + Check_Restriction (Ignore_Msg_Issued, R, N, V); end Check_Restriction; procedure Check_Restriction diff --git a/gcc/ada/sem_cat.ads b/gcc/ada/sem_cat.ads index 3fa3339..90a713b 100644 --- a/gcc/ada/sem_cat.ads +++ b/gcc/ada/sem_cat.ads @@ -27,7 +27,7 @@ -- the semantic restrictions required for the categorization pragmas: -- -- Preelaborate --- Pure, +-- Pure -- Remote_Call_Interface -- Remote_Types -- Shared_Passive diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index 25a61ad..71da7fc 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -2082,7 +2082,7 @@ package Sinfo is -- that no elaboration check is needed on the call, because it appears in -- the context of a local Suppress pragma. This is used on calls within -- task bodies, where the actual elaboration checks are applied after - -- analysis, when the local scope stack is not present + -- analysis, when the local scope stack is not present. -- No_Entities_Ref_In_Spec -- Present in N_With_Clause nodes. Set if the with clause is on the -- cgit v1.1 From 125bb16bece454843ca420fd033351d1a80976a4 Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Thu, 20 May 2021 19:55:02 +0600 Subject: [Ada] Keepalive control on Windows gcc/ada/ * s-oscons-tmplt.c (TCP_KEEPCNT TCP_KEEPIDLE, TCP_KEEPINTVL): Hardcode on Windows if undefined. --- gcc/ada/s-oscons-tmplt.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c index d42e663..044e203 100644 --- a/gcc/ada/s-oscons-tmplt.c +++ b/gcc/ada/s-oscons-tmplt.c @@ -1502,18 +1502,36 @@ CNS(MSG_Forced_Flags, "") CND(TCP_NODELAY, "Do not coalesce packets") #ifndef TCP_KEEPCNT +#ifdef __MINGW32__ +/* Windows headers can be too old to have all available constants. + * We know this one. */ +# define TCP_KEEPCNT 16 +#else # define TCP_KEEPCNT -1 #endif +#endif CND(TCP_KEEPCNT, "Maximum number of keepalive probes") #ifndef TCP_KEEPIDLE +#ifdef __MINGW32__ +/* Windows headers can be too old to have all available constants. + * We know this one. */ +# define TCP_KEEPIDLE 3 +#else # define TCP_KEEPIDLE -1 #endif +#endif CND(TCP_KEEPIDLE, "Idle time before TCP starts sending keepalive probes") #ifndef TCP_KEEPINTVL +#ifdef __MINGW32__ +/* Windows headers can be too old to have all available constants. + * We know this one. */ +# define TCP_KEEPINTVL 17 +#else # define TCP_KEEPINTVL -1 #endif +#endif CND(TCP_KEEPINTVL, "Time between individual keepalive probes") #ifndef SO_REUSEADDR -- cgit v1.1 From 18b267aeeb126290355ec394fbc0f6a1fba1f340 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Thu, 20 May 2021 06:40:48 -0400 Subject: [Ada] Front-end inlining and instantiations of UC gcc/ada/ * sem_ch12.adb (Analyze_Subprogram_Instantiation): Mark Anon_Id intrinsic before calling Analyze_Instance_And_Renamings because this flag may be propagated to other nodes. --- gcc/ada/sem_ch12.adb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index 1c8f64e..bf51ce9 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -5796,6 +5796,14 @@ package body Sem_Ch12 is Set_SPARK_Mode (Gen_Unit); end if; + -- Need to mark Anon_Id intrinsic before calling + -- Analyze_Instance_And_Renamings because this flag may be propagated + -- to other nodes. + + if Is_Intrinsic_Subprogram (Gen_Unit) then + Set_Is_Intrinsic_Subprogram (Anon_Id); + end if; + Analyze_Instance_And_Renamings; -- Restore SPARK_Mode from the context after analysis of the package @@ -5817,7 +5825,6 @@ package body Sem_Ch12 is -- not within the main unit. if Is_Intrinsic_Subprogram (Gen_Unit) then - Set_Is_Intrinsic_Subprogram (Anon_Id); Set_Is_Intrinsic_Subprogram (Act_Decl_Id); if Chars (Gen_Unit) = Name_Unchecked_Conversion then -- cgit v1.1 From cce46226b0bb33c688398f861c70dbb06c3e7bda Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 21 May 2021 11:47:45 +0200 Subject: [Ada] Stronger assertion about flag for checking static expressions gcc/ada/ * sem_eval.adb (Set_Checking_Potentially_Static_Expression): Stronger assertion. --- gcc/ada/sem_eval.adb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb index 7a70fd8..a3a2864 100644 --- a/gcc/ada/sem_eval.adb +++ b/gcc/ada/sem_eval.adb @@ -6481,11 +6481,10 @@ package body Sem_Eval is procedure Set_Checking_Potentially_Static_Expression (Value : Boolean) is begin - -- Verify that we're not currently checking for a potentially static - -- expression unless we're disabling such checking. + -- Verify that we only start/stop checking for a potentially static + -- expression and do not start or stop it twice in a row. - pragma Assert - (not Checking_For_Potentially_Static_Expression or else not Value); + pragma Assert (Checking_For_Potentially_Static_Expression /= Value); Checking_For_Potentially_Static_Expression := Value; end Set_Checking_Potentially_Static_Expression; -- cgit v1.1 From 2c03e97c5a50acc10fcb3545385fac4c1a9fa543 Mon Sep 17 00:00:00 2001 From: Gary Dismukes Date: Fri, 21 May 2021 13:59:30 -0400 Subject: [Ada] Assertion errors on concurrent types with -gnatc and extensions enabled gcc/ada/ * einfo-utils.adb (Primitive_Operations): Default to returning Direct_Primitive_Operations in the case of concurrent types (when Corresponding_Record_Type not present). * sem_ch9.adb (Analyze_Protected_Type_Declaration): Initialize Direct_Primitive_Operations to an empty element list. (Analyze_Task_Type_Declaration): Initialize Direct_Primitive_Operations to an empty element list. --- gcc/ada/einfo-utils.adb | 12 ++++++------ gcc/ada/sem_ch9.adb | 12 ++++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/einfo-utils.adb b/gcc/ada/einfo-utils.adb index 22143d6..b2d8a84 100644 --- a/gcc/ada/einfo-utils.adb +++ b/gcc/ada/einfo-utils.adb @@ -2493,15 +2493,15 @@ package body Einfo.Utils is return Direct_Primitive_Operations (Corresponding_Record_Type (Id)); - -- If expansion is disabled the corresponding record type is absent, - -- but if the type has ancestors it may have primitive operations. - - elsif Is_Tagged_Type (Id) then - return Direct_Primitive_Operations (Id); + -- When expansion is disabled, the corresponding record type is + -- absent, but if this is a tagged type with ancestors, or if the + -- extension of prefixed calls for untagged types is enabled, then + -- it may have associated primitive operations. else - return No_Elist; + return Direct_Primitive_Operations (Id); end if; + else return Direct_Primitive_Operations (Id); end if; diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb index 969eff5..65f48a7 100644 --- a/gcc/ada/sem_ch9.adb +++ b/gcc/ada/sem_ch9.adb @@ -2031,6 +2031,12 @@ package body Sem_Ch9 is Set_Has_Delayed_Freeze (T); Set_Stored_Constraint (T, No_Elist); + -- Initialize type's primitive operations list, for possible use when + -- the extension of prefixed call notation for untagged types is enabled + -- (such as by use of -gnatX). + + Set_Direct_Primitive_Operations (T, New_Elmt_List); + -- Mark this type as a protected type for the sake of restrictions, -- unless the protected type is declared in a private part of a package -- of the runtime. With this exception, the Suspension_Object from @@ -3152,6 +3158,12 @@ package body Sem_Ch9 is Set_Has_Delayed_Freeze (T, True); Set_Stored_Constraint (T, No_Elist); + -- Initialize type's primitive operations list, for possible use when + -- the extension of prefixed call notation for untagged types is enabled + -- (such as by use of -gnatX). + + Set_Direct_Primitive_Operations (T, New_Elmt_List); + -- Set the SPARK_Mode from the current context (may be overwritten later -- with an explicit pragma). -- cgit v1.1 From a5b5c7c2840ebb0aaa0d0f1e090fb2fc6942196d Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Thu, 20 May 2021 22:58:31 +0600 Subject: [Ada] Remove unused define gcc/ada/ * s-oscons-tmplt.c (MSG_WAITALL): Remove wrong #ifdef __MINWGW32__. --- gcc/ada/s-oscons-tmplt.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c index 044e203..f373c39 100644 --- a/gcc/ada/s-oscons-tmplt.c +++ b/gcc/ada/s-oscons-tmplt.c @@ -1463,14 +1463,8 @@ CND(MSG_PEEK, "Peek at incoming data") CND(MSG_EOR, "Send end of record") #ifndef MSG_WAITALL -#ifdef __MINWGW32__ -/* The value of MSG_WAITALL is 8. Nevertheless winsock.h doesn't - define it, but it is still usable as we link to winsock2 API. */ -# define MSG_WAITALL (1 << 3) -#else # define MSG_WAITALL -1 #endif -#endif CND(MSG_WAITALL, "Wait for full reception") #ifndef MSG_NOSIGNAL -- cgit v1.1 From 6278065af07634278ba30029d92a82b089969baa Mon Sep 17 00:00:00 2001 From: Peter Bergner Date: Wed, 7 Jul 2021 11:39:34 -0500 Subject: rs6000: Harden mma_init_builtins The previous MMA patch added some fragile code to initialize its new built-ins. This patch hardens the initialization. 2021-07-07 Peter Bergner gcc/ * config/rs6000/rs6000-call.c (mma_init_builtins): Use VSX_BUILTIN_LXVP and VSX_BUILTIN_STXVP. --- gcc/config/rs6000/rs6000-call.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index 6115e3b..904e104 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -14293,7 +14293,8 @@ mma_init_builtins (void) /* Some MMA built-ins that are expanded into gimple are converted into internal MMA built-ins that are expanded into rtl. The internal built-in follows immediately after this built-in. */ - if (d[1].icode != CODE_FOR_nothing) + if (d->code != VSX_BUILTIN_LXVP + && d->code != VSX_BUILTIN_STXVP) { op[nopnds++] = void_type_node; icode = d[1].icode; -- cgit v1.1 From a110855667782dac7b674d3e328b253b3b3c919b Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Wed, 7 Jul 2021 14:05:25 -0600 Subject: Correct handling of variable offset minus constant in -Warray-bounds [PR100137] Resolves: PR tree-optimization/100137 - -Warray-bounds false positive on varying offset plus negative PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional PR tree-optimization/97027 - missing warning on buffer overflow storing a larger scalar into a smaller array gcc/ChangeLog: PR tree-optimization/100137 PR tree-optimization/99121 PR tree-optimization/97027 * builtins.c (access_ref::access_ref): Also set offmax. (access_ref::offset_in_range): Define new function. (access_ref::add_offset): Set offmax. (access_ref::inform_access): Handle access_none. (handle_mem_ref): Clear ostype. (compute_objsize_r): Handle ASSERT_EXPR. * builtins.h (struct access_ref): Add offmax member. * gimple-array-bounds.cc (array_bounds_checker::check_mem_ref): Use compute_objsize() and simplify. gcc/testsuite/ChangeLog: PR tree-optimization/100137 PR tree-optimization/99121 PR tree-optimization/97027 * c-c++-common/Warray-bounds-3.c: Remove xfail * c-c++-common/Warray-bounds-4.c: Add an expected warning. * c-c++-common/Warray-bounds-9.c: New test. * c-c++-common/Warray-bounds-10.c: New test. * g++.dg/asan/asan_test.C: Suppress expected warnings. * g++.dg/pr95768.C: Same. * g++.dg/warn/Warray-bounds-10.C: Adjust text of expected messages. * g++.dg/warn/Warray-bounds-11.C: Same. * g++.dg/warn/Warray-bounds-12.C: Same. * g++.dg/warn/Warray-bounds-13.C: Same. * g++.dg/warn/Warray-bounds-17.C: Same. * g++.dg/warn/Warray-bounds-20.C: Same. * gcc.dg/Warray-bounds-29.c: Same. * gcc.dg/Warray-bounds-30.c: Add xfail. * gcc.dg/Warray-bounds-31.c: Adjust text of expected messages. * gcc.dg/Warray-bounds-32.c: Same. * gcc.dg/Warray-bounds-52.c: Same. * gcc.dg/Warray-bounds-53.c: Same. * gcc.dg/Warray-bounds-58.c: Remove xfail. * gcc.dg/Warray-bounds-63.c: Adjust text of expected messages. * gcc.dg/Warray-bounds-66.c: Same. * gcc.dg/Warray-bounds-69.c: Same. * gcc.dg/Wstringop-overflow-34.c: Same. * gcc.dg/Wstringop-overflow-47.c: Same. * gcc.dg/Wstringop-overflow-61.c: Same. * gcc.dg/Warray-bounds-77.c: New test. * gcc.dg/Warray-bounds-78.c: New test. * gcc.dg/Warray-bounds-79.c: New test. --- gcc/builtins.c | 69 +++++- gcc/builtins.h | 5 + gcc/gimple-array-bounds.cc | 336 ++++---------------------- gcc/testsuite/c-c++-common/Warray-bounds-10.c | 114 +++++++++ gcc/testsuite/c-c++-common/Warray-bounds-3.c | 4 +- gcc/testsuite/c-c++-common/Warray-bounds-4.c | 12 +- gcc/testsuite/c-c++-common/Warray-bounds-9.c | 144 +++++++++++ gcc/testsuite/g++.dg/asan/asan_test.C | 2 +- gcc/testsuite/g++.dg/pr95768.C | 2 +- gcc/testsuite/g++.dg/warn/Warray-bounds-10.C | 4 +- gcc/testsuite/g++.dg/warn/Warray-bounds-11.C | 4 +- gcc/testsuite/g++.dg/warn/Warray-bounds-12.C | 4 +- gcc/testsuite/g++.dg/warn/Warray-bounds-13.C | 4 +- gcc/testsuite/g++.dg/warn/Warray-bounds-17.C | 2 +- gcc/testsuite/g++.dg/warn/Warray-bounds-20.C | 8 +- gcc/testsuite/gcc.dg/Warray-bounds-29.c | 22 +- gcc/testsuite/gcc.dg/Warray-bounds-30.c | 2 +- gcc/testsuite/gcc.dg/Warray-bounds-31.c | 8 +- gcc/testsuite/gcc.dg/Warray-bounds-32.c | 26 +- gcc/testsuite/gcc.dg/Warray-bounds-52.c | 6 +- gcc/testsuite/gcc.dg/Warray-bounds-53.c | 6 +- gcc/testsuite/gcc.dg/Warray-bounds-58.c | 2 +- gcc/testsuite/gcc.dg/Warray-bounds-63.c | 6 +- gcc/testsuite/gcc.dg/Warray-bounds-66.c | 12 +- gcc/testsuite/gcc.dg/Warray-bounds-69.c | 2 +- gcc/testsuite/gcc.dg/Warray-bounds-77.c | 135 +++++++++++ gcc/testsuite/gcc.dg/Warray-bounds-78.c | 109 +++++++++ gcc/testsuite/gcc.dg/Warray-bounds-79.c | 112 +++++++++ gcc/testsuite/gcc.dg/Wstringop-overflow-34.c | 8 +- gcc/testsuite/gcc.dg/Wstringop-overflow-47.c | 14 +- gcc/testsuite/gcc.dg/Wstringop-overflow-61.c | 4 +- 31 files changed, 817 insertions(+), 371 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/Warray-bounds-10.c create mode 100644 gcc/testsuite/c-c++-common/Warray-bounds-9.c create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-77.c create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-78.c create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-79.c (limited to 'gcc') diff --git a/gcc/builtins.c b/gcc/builtins.c index e52fe42..39ab139 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -206,6 +206,7 @@ access_ref::access_ref (tree bound /* = NULL_TREE */, { /* Set to valid. */ offrng[0] = offrng[1] = 0; + offmax[0] = offmax[1] = 0; /* Invalidate. */ sizrng[0] = sizrng[1] = -1; @@ -457,6 +458,21 @@ access_ref::size_remaining (offset_int *pmin /* = NULL */) const return sizrng[1] - or0; } +/* Return true if the offset and object size are in range for SIZE. */ + +bool +access_ref::offset_in_range (const offset_int &size) const +{ + if (size_remaining () < size) + return false; + + if (base0) + return offmax[0] >= 0 && offmax[1] <= sizrng[1]; + + offset_int maxoff = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node)); + return offmax[0] > -maxoff && offmax[1] < maxoff; +} + /* Add the range [MIN, MAX] to the offset range. For known objects (with zero-based offsets) at least one of whose offset's bounds is in range, constrain the other (or both) to the bounds of the object (i.e., zero @@ -493,6 +509,8 @@ void access_ref::add_offset (const offset_int &min, const offset_int &max) if (max >= 0) { offrng[0] = 0; + if (offmax[0] > 0) + offmax[0] = 0; return; } @@ -509,6 +527,12 @@ void access_ref::add_offset (const offset_int &min, const offset_int &max) offrng[0] = 0; } + /* Set the minimum and maximmum computed so far. */ + if (offrng[1] < 0 && offrng[1] < offmax[0]) + offmax[0] = offrng[1]; + if (offrng[0] > 0 && offrng[0] > offmax[1]) + offmax[1] = offrng[0]; + if (!base0) return; @@ -4571,23 +4595,46 @@ access_ref::inform_access (access_mode mode) const return; } + if (mode == access_read_only) + { + if (allocfn == NULL_TREE) + { + if (*offstr) + inform (loc, "at offset %s into source object %qE of size %s", + offstr, ref, sizestr); + else + inform (loc, "source object %qE of size %s", ref, sizestr); + + return; + } + + if (*offstr) + inform (loc, + "at offset %s into source object of size %s allocated by %qE", + offstr, sizestr, allocfn); + else + inform (loc, "source object of size %s allocated by %qE", + sizestr, allocfn); + return; + } + if (allocfn == NULL_TREE) { if (*offstr) - inform (loc, "at offset %s into source object %qE of size %s", + inform (loc, "at offset %s into object %qE of size %s", offstr, ref, sizestr); else - inform (loc, "source object %qE of size %s", ref, sizestr); + inform (loc, "object %qE of size %s", ref, sizestr); return; } if (*offstr) inform (loc, - "at offset %s into source object of size %s allocated by %qE", + "at offset %s into object of size %s allocated by %qE", offstr, sizestr, allocfn); else - inform (loc, "source object of size %s allocated by %qE", + inform (loc, "object of size %s allocated by %qE", sizestr, allocfn); } @@ -5433,16 +5480,16 @@ handle_mem_ref (tree mref, int ostype, access_ref *pref, if (VECTOR_TYPE_P (TREE_TYPE (mref))) { - /* Hack: Give up for MEM_REFs of vector types; those may be - synthesized from multiple assignments to consecutive data - members (see PR 93200 and 96963). + /* Hack: Handle MEM_REFs of vector types as those to complete + objects; those may be synthesized from multiple assignments + to consecutive data members (see PR 93200 and 96963). FIXME: Vectorized assignments should only be present after vectorization so this hack is only necessary after it has run and could be avoided in calls from prior passes (e.g., tree-ssa-strlen.c). FIXME: Deal with this more generally, e.g., by marking up such MEM_REFs at the time they're created. */ - return false; + ostype = 0; } tree mrefop = TREE_OPERAND (mref, 0); @@ -5796,6 +5843,12 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref, tree rhs = gimple_assign_rhs1 (stmt); + if (code == ASSERT_EXPR) + { + rhs = TREE_OPERAND (rhs, 0); + return compute_objsize_r (rhs, ostype, pref, snlim, qry); + } + if (code == POINTER_PLUS_EXPR && TREE_CODE (TREE_TYPE (rhs)) == POINTER_TYPE) { diff --git a/gcc/builtins.h b/gcc/builtins.h index e71f40c..a64ece3 100644 --- a/gcc/builtins.h +++ b/gcc/builtins.h @@ -222,6 +222,9 @@ struct access_ref argument to the minimum. */ offset_int size_remaining (offset_int * = NULL) const; +/* Return true if the offset and object size are in range for SIZE. */ + bool offset_in_range (const offset_int &) const; + /* Return true if *THIS is an access to a declared object. */ bool ref_declared () const { @@ -261,6 +264,8 @@ struct access_ref /* Range of byte offsets into and sizes of the object(s). */ offset_int offrng[2]; offset_int sizrng[2]; + /* The minimum and maximum offset computed. */ + offset_int offmax[2]; /* Range of the bound of the access: denotes that the access is at least BNDRNG[0] bytes but no more than BNDRNG[1]. For string functions the size of the actual access is diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc index 13f0868..83b8db9 100644 --- a/gcc/gimple-array-bounds.cc +++ b/gcc/gimple-array-bounds.cc @@ -414,269 +414,72 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref, if (warning_suppressed_p (ref, OPT_Warray_bounds)) return false; - tree arg = TREE_OPERAND (ref, 0); - /* The constant and variable offset of the reference. */ - tree cstoff = TREE_OPERAND (ref, 1); - tree varoff = NULL_TREE; - - const offset_int maxobjsize = tree_to_shwi (max_object_size ()); - - /* The zero-based array or string constant bounds in bytes. Initially - set to [-MAXOBJSIZE - 1, MAXOBJSIZE] until a tighter bound is - determined. */ - offset_int arrbounds[2] = { -maxobjsize - 1, maxobjsize }; - - /* The minimum and maximum intermediate offset. For a reference - to be valid, not only does the final offset/subscript must be - in bounds but all intermediate offsets should be as well. - GCC may be able to deal gracefully with such out-of-bounds - offsets so the checking is only enabled at -Warray-bounds=2 - where it may help detect bugs in uses of the intermediate - offsets that could otherwise not be detectable. */ - offset_int ioff = wi::to_offset (fold_convert (ptrdiff_type_node, cstoff)); - offset_int extrema[2] = { 0, wi::abs (ioff) }; - - /* The range of the byte offset into the reference. */ - offset_int offrange[2] = { 0, 0 }; - /* The statement used to allocate the array or null. */ gimple *alloc_stmt = NULL; /* For an allocation statement, the low bound of the size range. */ offset_int minbound = 0; + /* The type and size of the access. */ + tree axstype = TREE_TYPE (ref); + offset_int axssize = 0; + if (TREE_CODE (axstype) != UNION_TYPE) + if (tree access_size = TYPE_SIZE_UNIT (axstype)) + if (TREE_CODE (access_size) == INTEGER_CST) + axssize = wi::to_offset (access_size); - /* Determine the offsets and increment OFFRANGE for the bounds of each. - The loop computes the range of the final offset for expressions such - as (A + i0 + ... + iN)[CSTOFF] where i0 through iN are SSA_NAMEs in - some range. */ - const unsigned limit = param_ssa_name_def_chain_limit; - for (unsigned n = 0; TREE_CODE (arg) == SSA_NAME && n < limit; ++n) - { - gimple *def = SSA_NAME_DEF_STMT (arg); - if (is_gimple_call (def)) - { - /* Determine the byte size of the array from an allocation call. */ - wide_int sizrng[2]; - if (gimple_call_alloc_size (def, sizrng)) - { - arrbounds[0] = 0; - arrbounds[1] = offset_int::from (sizrng[1], UNSIGNED); - minbound = offset_int::from (sizrng[0], UNSIGNED); - alloc_stmt = def; - } - break; - } - - if (gimple_nop_p (def)) - { - /* For a function argument try to determine the byte size - of the array from the current function declaratation - (e.g., attribute access or related). */ - wide_int wr[2]; - tree ref = gimple_parm_array_size (arg, wr); - if (!ref) - break; - arrbounds[0] = offset_int::from (wr[0], UNSIGNED); - arrbounds[1] = offset_int::from (wr[1], UNSIGNED); - arg = ref; - break; - } - - if (!is_gimple_assign (def)) - break; - - tree_code code = gimple_assign_rhs_code (def); - if (code == POINTER_PLUS_EXPR) - { - arg = gimple_assign_rhs1 (def); - varoff = gimple_assign_rhs2 (def); - } - else if (code == ASSERT_EXPR) - { - arg = TREE_OPERAND (gimple_assign_rhs1 (def), 0); - continue; - } - else - return false; - - /* VAROFF should always be a SSA_NAME here (and not even - INTEGER_CST) but there's no point in taking chances. */ - if (TREE_CODE (varoff) != SSA_NAME) - break; - - const value_range* const vr = get_value_range (varoff); - if (!vr || vr->undefined_p () || vr->varying_p ()) - break; - - if (!vr->constant_p ()) - break; - - if (vr->kind () == VR_RANGE) - { - offset_int min - = wi::to_offset (fold_convert (ptrdiff_type_node, vr->min ())); - offset_int max - = wi::to_offset (fold_convert (ptrdiff_type_node, vr->max ())); - if (min < max) - { - offrange[0] += min; - offrange[1] += max; - } - else - { - /* When MIN >= MAX, the offset is effectively in a union - of two ranges: [-MAXOBJSIZE -1, MAX] and [MIN, MAXOBJSIZE]. - Since there is no way to represent such a range across - additions, conservatively add [-MAXOBJSIZE -1, MAXOBJSIZE] - to OFFRANGE. */ - offrange[0] += arrbounds[0]; - offrange[1] += arrbounds[1]; - } - } - else - { - /* For an anti-range, analogously to the above, conservatively - add [-MAXOBJSIZE -1, MAXOBJSIZE] to OFFRANGE. */ - offrange[0] += arrbounds[0]; - offrange[1] += arrbounds[1]; - } - - /* Keep track of the minimum and maximum offset. */ - if (offrange[1] < 0 && offrange[1] < extrema[0]) - extrema[0] = offrange[1]; - if (offrange[0] > 0 && offrange[0] > extrema[1]) - extrema[1] = offrange[0]; - - if (offrange[0] < arrbounds[0]) - offrange[0] = arrbounds[0]; - - if (offrange[1] > arrbounds[1]) - offrange[1] = arrbounds[1]; - } + access_ref aref; + if (!compute_objsize (ref, 1, &aref, ranges)) + return false; - tree reftype = NULL_TREE; - offset_int eltsize = -1; - if (arrbounds[0] >= 0) - { - /* The byte size of the array has already been determined above - based on a pointer ARG. Set ELTSIZE to the size of the type - it points to and REFTYPE to the array with the size, rounded - down as necessary. */ - reftype = TREE_TYPE (TREE_TYPE (arg)); - if (TREE_CODE (reftype) == ARRAY_TYPE) - reftype = TREE_TYPE (reftype); - if (tree refsize = TYPE_SIZE_UNIT (reftype)) - if (TREE_CODE (refsize) == INTEGER_CST) - eltsize = wi::to_offset (refsize); - - if (eltsize < 0) - return false; + if (aref.offset_in_range (axssize)) + return false; - offset_int nelts = arrbounds[1] / eltsize; - reftype = build_printable_array_type (reftype, nelts.to_uhwi ()); - } - else if (TREE_CODE (arg) == ADDR_EXPR) + if (TREE_CODE (aref.ref) == SSA_NAME) { - arg = TREE_OPERAND (arg, 0); - if (TREE_CODE (arg) != STRING_CST - && TREE_CODE (arg) != PARM_DECL - && TREE_CODE (arg) != VAR_DECL) - return false; - - /* The type of the object being referred to. It can be an array, - string literal, or a non-array type when the MEM_REF represents - a reference/subscript via a pointer to an object that is not - an element of an array. Incomplete types are excluded as well - because their size is not known. */ - reftype = TREE_TYPE (arg); - if (POINTER_TYPE_P (reftype) - || !COMPLETE_TYPE_P (reftype) - || TREE_CODE (TYPE_SIZE_UNIT (reftype)) != INTEGER_CST) - return false; - - /* Except in declared objects, references to trailing array members - of structs and union objects are excluded because MEM_REF doesn't - make it possible to identify the member where the reference - originated. */ - if (RECORD_OR_UNION_TYPE_P (reftype) - && (!VAR_P (arg) - || (DECL_EXTERNAL (arg) && array_at_struct_end_p (ref)))) - return false; - - /* FIXME: Should this be 1 for Fortran? */ - arrbounds[0] = 0; - - if (TREE_CODE (reftype) == ARRAY_TYPE) - { - /* Set to the size of the array element (and adjust below). */ - eltsize = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (reftype))); - /* Use log2 of size to convert the array byte size in to its - upper bound in elements. */ - const offset_int eltsizelog2 = wi::floor_log2 (eltsize); - if (tree dom = TYPE_DOMAIN (reftype)) - { - tree bnds[] = { TYPE_MIN_VALUE (dom), TYPE_MAX_VALUE (dom) }; - if (TREE_CODE (arg) == COMPONENT_REF) - { - offset_int size = maxobjsize; - if (tree fldsize = component_ref_size (arg)) - size = wi::to_offset (fldsize); - arrbounds[1] = wi::lrshift (size, eltsizelog2); - } - else if (array_at_struct_end_p (arg) || !bnds[0] || !bnds[1]) - arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2); - else - arrbounds[1] = (wi::to_offset (bnds[1]) - wi::to_offset (bnds[0]) - + 1) * eltsize; - } - else - arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2); - - /* Determine a tighter bound of the non-array element type. */ - tree eltype = TREE_TYPE (reftype); - while (TREE_CODE (eltype) == ARRAY_TYPE) - eltype = TREE_TYPE (eltype); - eltsize = wi::to_offset (TYPE_SIZE_UNIT (eltype)); - } - else + gimple *def = SSA_NAME_DEF_STMT (aref.ref); + if (is_gimple_call (def)) { - eltsize = 1; - tree size = TYPE_SIZE_UNIT (reftype); - if (VAR_P (arg)) - if (tree initsize = DECL_SIZE_UNIT (arg)) - if (tree_int_cst_lt (size, initsize)) - size = initsize; - - arrbounds[1] = wi::to_offset (size); + /* Save the allocation call and the low bound on the size. */ + alloc_stmt = def; + minbound = aref.sizrng[0]; } } - else - return false; - - offrange[0] += ioff; - offrange[1] += ioff; + + /* The range of the byte offset into the reference. Adjusted below. */ + offset_int offrange[2] = { aref.offrng[0], aref.offrng[1] }; + + /* The type of the referenced object. */ + tree reftype = TREE_TYPE (aref.ref); + /* The size of the referenced array element. */ + offset_int eltsize = 1; + /* The byte size of the array has already been determined above + based on a pointer ARG. Set ELTSIZE to the size of the type + it points to and REFTYPE to the array with the size, rounded + down as necessary. */ + if (POINTER_TYPE_P (reftype)) + reftype = TREE_TYPE (reftype); + if (TREE_CODE (reftype) == ARRAY_TYPE) + reftype = TREE_TYPE (reftype); + if (tree refsize = TYPE_SIZE_UNIT (reftype)) + if (TREE_CODE (refsize) == INTEGER_CST) + eltsize = wi::to_offset (refsize); + + const offset_int nelts = aref.sizrng[1] / eltsize; + reftype = build_printable_array_type (reftype, nelts.to_uhwi ()); /* Compute the more permissive upper bound when IGNORE_OFF_BY_ONE is set (when taking the address of the one-past-last element of an array) but always use the stricter bound in diagnostics. */ - offset_int ubound = arrbounds[1]; + offset_int ubound = aref.sizrng[1]; if (ignore_off_by_one) ubound += eltsize; - bool warned = false; /* Set if the lower bound of the subscript is out of bounds. */ - const bool lboob = (arrbounds[0] == arrbounds[1] + const bool lboob = (aref.sizrng[1] == 0 || offrange[0] >= ubound - || offrange[1] < arrbounds[0]); + || offrange[1] < 0); /* Set if only the upper bound of the subscript is out of bounds. This can happen when using a bigger type to index into an array of a smaller type, as is common with unsigned char. */ - tree axstype = TREE_TYPE (ref); - offset_int axssize = 0; - if (TREE_CODE (axstype) != UNION_TYPE) - if (tree access_size = TYPE_SIZE_UNIT (axstype)) - if (TREE_CODE (access_size) == INTEGER_CST) - axssize = wi::to_offset (access_size); - const bool uboob = !lboob && offrange[0] + axssize > ubound; if (lboob || uboob) { @@ -689,9 +492,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref, to compute the index to print in the diagnostic; arrays in MEM_REF don't mean anything. A type with no size like void is as good as having a size of 1. */ - tree type = TREE_TYPE (ref); - while (TREE_CODE (type) == ARRAY_TYPE) - type = TREE_TYPE (type); + tree type = strip_array_types (TREE_TYPE (ref)); if (tree size = TYPE_SIZE_UNIT (type)) { offrange[0] = offrange[0] / wi::to_offset (size); @@ -699,6 +500,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref, } } + bool warned = false; if (lboob) { if (offrange[0] == offrange[1]) @@ -720,7 +522,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref, /* If the memory was dynamically allocated refer to it as if it were an untyped array of bytes. */ backtype = build_array_type_nelts (unsigned_char_type_node, - arrbounds[1].to_uhwi ()); + aref.sizrng[1].to_uhwi ()); warned = warning_at (location, OPT_Warray_bounds, "array subscript %<%T[%wi]%> is partly " @@ -730,46 +532,8 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref, if (warned) { - if (DECL_P (arg)) - inform (DECL_SOURCE_LOCATION (arg), "while referencing %qD", arg); - else if (alloc_stmt) - { - location_t loc = gimple_location (alloc_stmt); - if (gimple_call_builtin_p (alloc_stmt, BUILT_IN_ALLOCA_WITH_ALIGN)) - { - if (minbound == arrbounds[1]) - inform (loc, "referencing a variable length array " - "of size %wu", minbound.to_uhwi ()); - else - inform (loc, "referencing a variable length array " - "of size between %wu and %wu", - minbound.to_uhwi (), arrbounds[1].to_uhwi ()); - } - else if (tree fndecl = gimple_call_fndecl (alloc_stmt)) - { - if (minbound == arrbounds[1]) - inform (loc, "referencing an object of size %wu " - "allocated by %qD", - minbound.to_uhwi (), fndecl); - else - inform (loc, "referencing an object of size between " - "%wu and %wu allocated by %qD", - minbound.to_uhwi (), arrbounds[1].to_uhwi (), fndecl); - } - else - { - tree fntype = gimple_call_fntype (alloc_stmt); - if (minbound == arrbounds[1]) - inform (loc, "referencing an object of size %wu " - "allocated by %qT", - minbound.to_uhwi (), fntype); - else - inform (loc, "referencing an object of size between " - "%wu and %wu allocated by %qT", - minbound.to_uhwi (), arrbounds[1].to_uhwi (), fntype); - } - } - + /* TODO: Determine the access from the statement and use it. */ + aref.inform_access (access_none); suppress_warning (ref, OPT_Warray_bounds); return true; } @@ -779,9 +543,9 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref, /* At level 2 check also intermediate offsets. */ int i = 0; - if (extrema[i] < -arrbounds[1] || extrema[i = 1] > ubound) + if (aref.offmax[i] < -aref.sizrng[1] || aref.offmax[i = 1] > ubound) { - HOST_WIDE_INT tmpidx = extrema[i].to_shwi () / eltsize.to_shwi (); + HOST_WIDE_INT tmpidx = aref.offmax[i].to_shwi () / eltsize.to_shwi (); if (warning_at (location, OPT_Warray_bounds, "intermediate array offset %wi is outside array bounds " diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-10.c b/gcc/testsuite/c-c++-common/Warray-bounds-10.c new file mode 100644 index 0000000..cfe9a38 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Warray-bounds-10.c @@ -0,0 +1,114 @@ +/* PR tree-optimization/99475 - bogus -Warray-bounds accessing an array + element of empty structs + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +struct S +{ +#if SOME_CONFIG_MACRO + /* Suppose the contents are empty in the development configuration + but non-empty in others. Out of bounds accesses to elements of + the arrays below should be diagnosed in all configurations, + including when S is empty, even if they are folded away. */ + int member; +#endif +}; + +extern struct S sa3[3]; +extern struct S sa2_3[2][3]; +extern struct S sa3_4_5[3][4][5]; + +void sink (void*); + + +void access_sa3 (struct S s) +{ + sa3[0] = s; + sa3[1] = s; + sa3[2] = s; + sa3[3] = s; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } +} + +void access_sa3_ptr (struct S s) +{ + struct S *p = &sa3[0]; + + p[0] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[3] = s; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } +} + +void access_sa2_3_ptr (struct S s) +{ + struct S *p = &sa2_3[0][0]; + + p[0] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[6] = s; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } +} + +void access_sa3_4_5_ptr (struct S s, int i) +{ + struct S *p = &sa3_4_5[0][0][0]; + + p[0] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[60] = s; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } +} + + +void access_vla3 (struct S s, unsigned n) +{ + struct S vla3[3 < n ? 3 : n]; + + vla3[0] = s; + vla3[1] = s; + vla3[2] = s; + vla3[3] = s; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + + sink (vla3); +} + +void access_vla3_ptr (struct S s, unsigned n) +{ + struct S vla3[3 < n ? 3 : n]; + struct S *p = &vla3[0]; + + p[0] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[3] = s; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + + sink (vla3); +} + +void access_vla2_3_ptr (struct S s, unsigned n) +{ + struct S vla2_3[2 < n ? 2 : n][3 < n ? 3 : n]; + struct S *p = &vla2_3[0][0]; + + p[0] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[6] = s; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + + sink (vla2_3); +} + +void access_vla3_4_5_ptr (struct S s, unsigned n) +{ + struct S vla3_4_5[3 < n ? 3 : n][4 < n ? 4 : n][5 < n ? 5 : n]; + struct S *p = &vla3_4_5[0][0][0]; + + p[0] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = s; // { dg-bogus "\\\[-Warray-bounds" } + p[60] = s; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + + sink (vla3_4_5); +} + +// { dg-prune-output "empty struct has size 0 in C" } diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-3.c b/gcc/testsuite/c-c++-common/Warray-bounds-3.c index aae4999..3d7c768 100644 --- a/gcc/testsuite/c-c++-common/Warray-bounds-3.c +++ b/gcc/testsuite/c-c++-common/Warray-bounds-3.c @@ -158,7 +158,7 @@ void test_memcpy_overflow (char *d, const char *s, size_t n) but known access size is detected. This works except with small sizes that are powers of 2 due to bug . */ T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 1); - T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 2); /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 2 accessing array " "bug " { xfail non_strict_align } } */ + T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 2); /* { dg-warning "\\\[-Warray-bounds" } */ T (char, 1, arr + SR (DIFF_MAX - 2, DIFF_MAX), s, 3); /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 3 accessing array " "memcpy" } */ T (char, 1, arr + SR (DIFF_MAX - 4, DIFF_MAX), s, 5); /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 5 accessing array " "memcpy" } */ } @@ -178,7 +178,7 @@ void test_memcpy_bounds_memarray_range (void) TM (ma.a5, ma.a5 + i, ma.a5, 1); TM (ma.a5, ma.a5 + i, ma.a5, 3); - TM (ma.a5, ma.a5 + i, ma.a5, 5); + TM (ma.a5, ma.a5 + i, ma.a5, 5); /* { dg-warning "\\\[-Warray-bounds" } */ TM (ma.a5, ma.a5 + i, ma.a5, 7); /* diagnosed with -Warray-bounds=2 */ } diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-4.c b/gcc/testsuite/c-c++-common/Warray-bounds-4.c index 22a23a1..1f73f119 100644 --- a/gcc/testsuite/c-c++-common/Warray-bounds-4.c +++ b/gcc/testsuite/c-c++-common/Warray-bounds-4.c @@ -43,7 +43,17 @@ void test_memcpy_bounds_memarray_range (void) TM (ma.a5, ma.a5 + j, ma.a5, 1); TM (ma.a5, ma.a5 + j, ma.a5, 3); - TM (ma.a5, ma.a5 + j, ma.a5, 5); + + /* The copy below is invalid for two reasons: 1) it overlaps and 2) it + writes past the end of ma.a5. The warning is a little cryptic here + because the GIMPLE is: + _4 = &ma.a5 + prephitmp_14; + MEM [(char * {ref-all})_4] + = MEM [(char * {ref-all})&ma]; + and could be improved. Just verify that one is issued but not its + full text. */ + TM (ma.a5, ma.a5 + j, ma.a5, 5); /* { dg-warning "\\\[-Warray-bounds" } */ + TM (ma.a5, ma.a5 + j, ma.a5, 7); /* { dg-warning "offset \\\[5, 7] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]. at offset 0" } */ TM (ma.a5, ma.a5 + j, ma.a5, 9); /* { dg-warning "offset \\\[5, 9] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]. at offset 0" } */ } diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-9.c b/gcc/testsuite/c-c++-common/Warray-bounds-9.c new file mode 100644 index 0000000..be05775 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Warray-bounds-9.c @@ -0,0 +1,144 @@ +/* PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional + VLA + { dg-do compile } + { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */ + +#define NOIPA __attribute__ ((noipa)) + +void sink (void*, ...); +#define T(a, x) sink (a, x) + + +NOIPA void a_0_n (int n) +{ + int a[0][n]; + + sink (a); + + T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void a_n_0 (int n) +{ + int a[n][0]; + + sink (a); + + T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" } +} + + +NOIPA void a_1_n_0 (int n) +{ + int a[1][n][0]; + + sink (a); + + T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void a_1_0_n (int n) +{ + int a[1][0][n]; + + sink (a); + + T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void a_0_1_n (int n) +{ + int a[0][1][n]; + + sink (a); + + T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void a_0_n_1 (int n) +{ + int a[0][n][1]; + + sink (a); + + T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void a_n_0_n (int n) +{ + int a[n][0][n]; + + sink (a); + + T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void a_n_n_0 (int n) +{ + int a[n][n][0]; + + sink (a); + + T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void a_0_n_n (int n) +{ + int a[0][n][n]; + + sink (a); + + T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void a_0_0_n (int n) +{ + int a[0][0][n]; + + sink (a); + + T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void a_n_0_0 (int n) +{ + int a[n][0][0]; + + sink (a); + + T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" } + T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void a_n_n_n (int n) +{ + int a[n][n][n]; + + sink (a); + + T (a, ((int *) a)[-1]); // { dg-warning "\\\[-Warray-bounds" "pr99140" } + T (a, ((int *) a)[0]); + T (a, ((char *) a)[1]); + T (a, ((float *) a)[n]); +} diff --git a/gcc/testsuite/g++.dg/asan/asan_test.C b/gcc/testsuite/g++.dg/asan/asan_test.C index c62568f..49933ab 100644 --- a/gcc/testsuite/g++.dg/asan/asan_test.C +++ b/gcc/testsuite/g++.dg/asan/asan_test.C @@ -2,7 +2,7 @@ // { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } // { dg-skip-if "" { *-*-* } { "-flto" } { "" } } // { dg-additional-sources "asan_globals_test-wrapper.cc" } -// { dg-options "-std=c++11 -fsanitize=address -fno-builtin -Wall -Werror -Wno-alloc-size-larger-than -Wno-stringop-overflow -g -DASAN_UAR=0 -DASAN_HAS_EXCEPTIONS=1 -DASAN_HAS_BLACKLIST=0 -DSANITIZER_USE_DEJAGNU_GTEST=1 -lasan -lpthread" } +// { dg-options "-std=c++11 -fsanitize=address -fno-builtin -Wall -Werror -Wno-alloc-size-larger-than -Wno-array-bounds -Wno-stringop-overflow -g -DASAN_UAR=0 -DASAN_HAS_EXCEPTIONS=1 -DASAN_HAS_BLACKLIST=0 -DSANITIZER_USE_DEJAGNU_GTEST=1 -lasan -lpthread" } // { dg-additional-options "-ldl" { target { ! *-*-freebsd* } } } // { dg-additional-options "-DASAN_NEEDS_SEGV=1" { target { ! arm*-*-* } } } // { dg-additional-options "-DASAN_LOW_MEMORY=1 -DASAN_NEEDS_SEGV=0" { target arm*-*-* } } diff --git a/gcc/testsuite/g++.dg/pr95768.C b/gcc/testsuite/g++.dg/pr95768.C index 5e2c8c4..d34d513 100644 --- a/gcc/testsuite/g++.dg/pr95768.C +++ b/gcc/testsuite/g++.dg/pr95768.C @@ -1,6 +1,6 @@ /* PR c++/95768 - pretty-printer ICE on -Wuninitialized with allocated storage { dg-do compile } - { dg-options "-O2 -Wall" } */ + { dg-options "-O2 -Wall -Wno-array-bounds" } */ extern "C" void *malloc (__SIZE_TYPE__); diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-10.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-10.C index 4deea31..4b758aa 100644 --- a/gcc/testsuite/g++.dg/warn/Warray-bounds-10.C +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-10.C @@ -18,7 +18,7 @@ void sink (void*); void warn_op_new () { T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } - // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 } + // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 } T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } @@ -44,7 +44,7 @@ void warn_op_array_new () #define OP_NEW(n) operator new[] (n) T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } - // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 } + // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 } T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C index 45d2719..70b3912 100644 --- a/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C @@ -20,7 +20,7 @@ void sink (void*); void warn_op_new () { T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } - // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(std::size_t, const std::nothrow_t.\\\)'" "note" { target *-*-* } .-1 } + // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 } T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } @@ -46,7 +46,7 @@ void warn_op_array_new () #define OP_NEW(n) operator new[] (n, std::nothrow) T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } - // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(std::size_t, const std::nothrow_t&\\\)'" "note" { target *-*-* } .-1 } + // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 } T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-12.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-12.C index 3f1555b..07fa351 100644 --- a/gcc/testsuite/g++.dg/warn/Warray-bounds-12.C +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-12.C @@ -20,7 +20,7 @@ void sink (void*); void warn_new () { T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } - // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 } + // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 } T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } @@ -46,7 +46,7 @@ void warn_array_new () #define NEW(n) new char [n] T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } - // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 } + // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 } T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C index 890620d..2d3e9dc 100644 --- a/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C @@ -24,7 +24,7 @@ void sink (void*); void warn_nothrow_new () { T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } - // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(std::size_t, const std::nothrow_t.\\\)'" "note" { target *-*-* } .-1 } + // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 } T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } @@ -50,7 +50,7 @@ void warn_nothrow_array_new () #define NEW(n) new (std::nothrow) char [n] T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } - // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(std::size_t, const std::nothrow_t&\\\)'" "note" { target *-*-* } .-1 } + // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 } T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-17.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-17.C index 64fbd08..518f9bb 100644 --- a/gcc/testsuite/g++.dg/warn/Warray-bounds-17.C +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-17.C @@ -8,7 +8,7 @@ void foo (int *); void bar (void) { - A b; // { dg-message "while referencing" } + A b; // { dg-message "at offset -\\d into object 'b' of size 4" "note" } int *p = &b; int *x = (p - 1); // { dg-warning "outside array bounds" } foo (x); diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C index e142ea1..a65b29e 100644 --- a/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C @@ -35,7 +35,7 @@ void sink (void*); void warn_derived_ctor_access_new_decl () { - char a[sizeof (D1)]; // { dg-message "referencing 'a'" "note" } + char a[sizeof (D1)]; // { dg-message "at offset 1 into object 'a' of size 40" "note" } char *p = a; ++p; D1 *q = new (p) D1; @@ -44,7 +44,7 @@ void warn_derived_ctor_access_new_decl () void warn_derived_ctor_access_new_alloc () { - char *p = (char*)operator new (sizeof (D1)); // { dg-message "referencing an object of size \\d+ allocated by 'void\\\* operator new\\\(" "note" } + char *p = (char*)operator new (sizeof (D1)); // { dg-message "at offset 1 into object of size \\d+ allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" } ++p; D1 *q = new (p) D1; sink (q); @@ -52,7 +52,7 @@ void warn_derived_ctor_access_new_alloc () void warn_derived_ctor_access_new_array_decl () { - char b[sizeof (D1) * 2]; // { dg-message "referencing 'b'" "note" } + char b[sizeof (D1) * 2]; // { dg-message "at offset \\d+ into object 'b' of size 80" "note" } char *p = b; ++p; D1 *q = new (p) D1[2]; @@ -61,7 +61,7 @@ void warn_derived_ctor_access_new_array_decl () void warn_derived_ctor_access_new_array_alloc () { - char *p = new char[sizeof (D1) * 2]; // { dg-message "referencing an object of size \\d+ allocated by 'void\\\* operator new \\\[]\\\(" "note" } + char *p = new char[sizeof (D1) * 2]; // { dg-message "at offset \\d+ into object of size \\d+ allocated by '\[^\n\r]*operator new\[^\n\r]*" "note" } ++p; D1 *q = new (p) D1[2]; sink (q); diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-29.c b/gcc/testsuite/gcc.dg/Warray-bounds-29.c index 72c5d1c..44e5bd3 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-29.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-29.c @@ -44,7 +44,7 @@ void test_narrow (void) T (p1[-1]); T (p1[ 0]); T (p1[ 1]); - T (p1[ 2]); /* { dg-warning "array subscript \\\[3, 4] is outside array bounds of .char\\\[3]." } */ + T (p1[ 2]); /* { dg-warning "array subscript 3 is outside array bounds of .char\\\[3]." } */ T (p1[ 3]); /* { dg-warning "array subscript \\\[4, 5] is outside array bounds of .char\\\[3]." } */ T (&p1[-3]); /* { dg-warning "array subscript \\\[-2, -1] is outside array bounds of .char\\\[3]." "bug" { xfail *-*-* } } */ @@ -55,7 +55,7 @@ void test_narrow (void) T (&p1[ 2]); T (&p1[ 3]); /* { dg-warning "array subscript \\\[4, 6] is outside array bounds of .char\\\[3]." "bug" { xfail *-*-* } } */ - T (p2[-4]); /* { dg-warning "intermediate array offset 4 is outside array bounds of .char\\\[3]." } */ + T (p2[-4]); /* { dg-warning "subscript \\\[-2, -1\\\] is outside array bounds of .char\\\[3]." } */ T (p2[-3]); T (p2[-2]); T (p2[-1]); @@ -64,19 +64,19 @@ void test_narrow (void) /* Even though the lower bound of p3's offsets is in bounds, in order to subtract 4 from p3 and get a dereferenceable pointer its value would have to be out-of-bounds. */ - T (p3[-4]); /* { dg-warning "intermediate array offset 4 is outside array bounds of .char\\\[3]." } */ + T (p3[-4]); /* { dg-warning "array subscript -1 is outside array bounds of .char\\\[3]." } */ T (p3[-3]); T (p3[-2]); T (p3[-1]); - T (p3[ 0]); /* { dg-warning "array subscript \\\[3, 6] is outside array bounds of .char\\\[3]." } */ + T (p3[ 0]); /* { dg-warning "array subscript 3 is outside array bounds of .char\\\[3]." } */ T (p4[-4]); /* { dg-warning "intermediate array offset 4 is outside array bounds of .char\\\[3]." } */ T (p4[-3]); /* { dg-warning "intermediate array offset 4 is outside array bounds of .char\\\[3]." } */ T (p4[-2]); /* { dg-warning "intermediate array offset 4 is outside array bounds of .char\\\[3]." } */ /* The final subscripts below are invalid. */ - T (p4[-1]); /* { dg-warning "array subscript \\\[3, 7] is outside array bounds of .char\\\[3]." } */ - T (p4[ 0]); /* { dg-warning "array subscript \\\[4, 8] is outside array bounds of .char\\\[3]." } */ + T (p4[-1]); /* { dg-warning "array subscript 3 is outside array bounds of .char\\\[3]." } */ + T (p4[ 0]); /* { dg-warning "array subscript \\\[4, 5] is outside array bounds of .char\\\[3]." } */ } @@ -114,7 +114,7 @@ void test_wide (void) T (p1[ 0]); T (p1[ 1]); T (p1[ 2]); - T (p1[ 3]); /* { dg-warning "array subscript \\\[4, 5] is outside array bounds of .\[a-z \]+\\\[4]." } */ + T (p1[ 3]); /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[4]." } */ T (&p1[-1]); T (&p1[ 0]); @@ -133,18 +133,18 @@ void test_wide (void) /* Even though the lower bound of p3's offsets is in bounds, in order to subtract 5 from p3 and get a dereferenceable pointer its value would have to be out-of-bounds. */ - T (p3[-5]); /* { dg-warning "intermediate array offset 5 is outside array bounds of .\[a-z \]+\\\[4]." } */ + T (p3[-5]); /* { dg-warning "array subscript \\\[-2, -1\\\] is outside array bounds of .\[a-z \]+\\\[4]." } */ T (p3[-4]); T (p3[-3]); T (p3[-2]); T (p3[-1]); T (p3[ 0]); - T (p3[ 1]); /* { dg-warning "array subscript \\\[4, 7] is outside array bounds of .\[a-z \]+\\\[4]." } */ + T (p3[ 1]); /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[4]." } */ - T (p4[-5]); /* { dg-warning "intermediate array offset 5 is outside array bounds of .\[a-z \]+\\\[4]." } */ + T (p4[-5]); /* { dg-warning "array subscript -1 is outside array bounds of .\[a-z \]+\\\[4]." } */ T (p4[-4]); T (p4[-3]); T (p4[-2]); T (p4[-1]); - T (p4[ 0]); /* { dg-warning "array subscript \\\[4, 8] is outside array bounds of .\[a-z \]+\\\[4]." } */ + T (p4[ 0]); /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[4]." } */ } diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-30.c b/gcc/testsuite/gcc.dg/Warray-bounds-30.c index 048a95d..b837ad0 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-30.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-30.c @@ -120,7 +120,7 @@ void test_global_short_2dim_array (void) T (&p[1]); T (&p[2]); T (&p[3]); - T (&p[16]); /* { dg-warning "subscript 16 is \(above|outside\) array bounds of .short int\\\[3]" } */ + T (&p[16]); /* { dg-warning "subscript 16 is \(above|outside\) array bounds of .short int\\\[3]" "pr??????" { xfail *-*-* } } */ T (&p[MAX]); /* { dg-warning "subscript -?\[0-9\]+ is \(above|outside\) array bounds of .short int\\\[3]" } */ } diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-31.c b/gcc/testsuite/gcc.dg/Warray-bounds-31.c index 389afaf..921461a 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-31.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-31.c @@ -174,7 +174,7 @@ void narrow_ptr_deref_range (ptrdiff_t i, size_t j) T (*p); p = S1 + SR (2, 3); - T (*p); /* { dg-warning "array subscript \\\[2, 3] is outside array bounds of .char\\\[2]." } */ + T (*p); /* { dg-warning "array subscript 2 is outside array bounds of .char\\\[2]." } */ p = S1 + SR (9, 99); T (*p); /* { dg-warning "array subscript \\\[9, 99] is outside array bounds of .char\\\[2]." } */ @@ -198,7 +198,7 @@ void narrow_ptr_deref_range (ptrdiff_t i, size_t j) T (*p); p = S8 + SR (9, 123); - T (*p); /* { dg-warning "array subscript \\\[9, 123] is outside array bounds of .char\\\[9]." } */ + T (*p); /* { dg-warning "array subscript 9 is outside array bounds of .char\\\[9]." } */ { const char *p1 = S3 + i; @@ -226,7 +226,7 @@ void narrow_ptr_deref_range (ptrdiff_t i, size_t j) T (*p1); T (*p2); T (*p3); - T (*p4); /* { dg-warning "array subscript \\\[4, \[0-9\]+] is outside array bounds of .char\\\[4]." } */ + T (*p4); /* { dg-warning "array subscript 4 is outside array bounds of .char\\\[4]." } */ T (*p5); /* { dg-warning "array subscript \\\[5, \[0-9\]+] is outside array bounds of .char\\\[4]." } */ } } @@ -241,7 +241,7 @@ void narrow_ptr_index_range (void) T (p[SR (-8, 0)]); T (p[SR (0, MAX)]); T (p[SR (1, 9)]); - T (p[SR (8, 9)]); /* { dg-warning "array subscript \\\[8, 9] is outside array bounds of .char\\\[8]." } */ + T (p[SR (8, 9)]); /* { dg-warning "array subscript 8 is outside array bounds of .char\\\[8]." } */ p = S7 + SR (4, 6); T (p[5]); /* { dg-warning "array subscript \\\[9, 11] is outside array bounds of .char\\\[8]." } */ diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-32.c b/gcc/testsuite/gcc.dg/Warray-bounds-32.c index 9b5f333..02dac65 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-32.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-32.c @@ -87,7 +87,7 @@ void wide_ptr_deref_range (ptrdiff_t i, size_t j) T (*p); p = W8 + SR (9, 123); - T (*p); /* { dg-warning "array subscript \\\[9, 123] is outside array bounds of .\[a-z \]+\\\[9]." } */ + T (*p); /* { dg-warning "array subscript 9 is outside array bounds of .\[a-z \]+\\\[9]." } */ } void wide_ptr_index_range (void) @@ -99,7 +99,7 @@ void wide_ptr_index_range (void) T (p[SR (-8, 0)]); T (p[SR (0, MAX)]); T (p[SR (1, 9)]); - T (p[SR (8, 9)]); /* { dg-warning "array subscript \\\[8, 9] is outside array bounds of .\[a-z \]+\\\[8]." } */ + T (p[SR (8, 9)]); /* { dg-warning "array subscript 8 is outside array bounds of .\[a-z \]+\\\[8]." } */ p = W7 + SR (4, 6); T (p[5]); /* { dg-warning "array subscript \\\[9, 11] is outside array bounds of .\[a-z \]+\\\[8]." } */ @@ -123,7 +123,7 @@ void wide_ptr_index_range_1 (void) int i = SR (1, 2); const wchar_t *p1 = W2 + i; - T (p1[2]); /* { dg-warning "array subscript \\\[3, 4] is outside array bounds of .\[a-z \]+\\\[3]." } */ + T (p1[2]); /* { dg-warning "array subscript 3 is outside array bounds of .\[a-z \]+\\\[3]." } */ } } @@ -140,17 +140,17 @@ void wide_ptr_index_range_chain (void) T (p1[-1]); T (p1[0]); T (p1[1]); - T (p1[2]); /* { dg-warning "array subscript \\\[3, 4] is outside array bounds of .\[a-z \]+\\\[3]." } */ + T (p1[2]); /* { dg-warning "array subscript 3 is outside array bounds of .\[a-z \]+\\\[3]." } */ - T (p2[-5]); /* { dg-warning "array subscript \\\[-3, -1] is outside array bounds of .\[a-z \]+\\\[3]." } */ - T (p2[-4]); + T (p2[-5]); /* { dg-warning "array subscript \\\[-3, -2] is outside array bounds of .\[a-z \]+\\\[3]." } */ + T (p2[-4]); /* { dg-warning "array subscript \\\[-2, -1] is outside array bounds of .\[a-z \]+\\\[3]." } */ T (p2[-1]); T (p2[0]); - T (p2[1]); /* { dg-warning "array subscript \\\[3, 5] is outside array bounds of .\[a-z \]+\\\[3]." } */ + T (p2[1]); /* { dg-warning "array subscript 3 is outside array bounds of .\[a-z \]+\\\[3]." } */ - T (p3[0]); /* { dg-warning "array subscript \\\[3, 6] is outside array bounds of .\[a-z \]+\\\[3]." } */ - T (p3[1]); /* { dg-warning "array subscript \\\[4, 7] is outside array bounds of .\[a-z \]+\\\[3]." } */ - T (p3[9999]); /* { dg-warning "array subscript \\\[10002, 10005] is outside array bounds of .\[a-z \]+\\\[3]." "" { target size20plus} } */ + T (p3[0]); /* { dg-warning "array subscript 3 is outside array bounds of .\[a-z \]+\\\[3]." } */ + T (p3[1]); /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[3]." } */ + T (p3[9999]); /* { dg-warning "array subscript 10002 is outside array bounds of .\[a-z \]+\\\[3]." "" { target size20plus} } */ /* { dg-warning "array subscript \\\[-6382, -6379] is outside array bounds of .\[a-z \]+\\\[3]." "" { target { ! size20plus } } .-1 } */ /* Large offsets are indistinguishable from negative values. */ T (p3[DIFF_MAX]); /* { dg-warning "array subscript" "bug" { xfail *-*-* } } */ @@ -166,9 +166,9 @@ void wide_ptr_index_range_chain (void) T (p1[-2]); T (p1[1]); T (p1[2]); - T (p1[3]); /* { dg-warning "array subscript \\\[4, 5] is outside array bounds of .\[a-z \]+\\\[4]." } */ + T (p1[3]); /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[4]." } */ - T (p3[1]); /* { dg-warning "array subscript \\\[4, 7] is outside array bounds of .\[a-z \]+\\\[4]." } */ + T (p3[1]); /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[4]." } */ } } @@ -180,5 +180,5 @@ void wide_ptr_index_range_4 (void) const wchar_t *p3 = p2 + i; const wchar_t *p4 = p3 + i; - T (p4[1]); /* { dg-warning "array subscript \\\[5, 9] is outside array bounds of .\[a-z \]+\\\[5]." } */ + T (p4[1]); /* { dg-warning "array subscript 5 is outside array bounds of .\[a-z \]+\\\[5]." } */ } diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-52.c b/gcc/testsuite/gcc.dg/Warray-bounds-52.c index 729ad45..c7217ad 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-52.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-52.c @@ -83,17 +83,17 @@ void ptr_idx_range (void) i = SR (0, 1); - T (i, (int[]){ }); // { dg-warning "array subscript \\\[0, 1] is outside array bounds of 'int\\\[0]'" } + T (i, (int[]){ }); // { dg-warning "array subscript 0 is outside array bounds of 'int\\\[0]'" } T (i, (int[]){ 1 }); i = SR (1, 2); - T (i, (int[]){ 1 }); // { dg-warning "array subscript \\\[1, 2] is outside array bounds of 'int\\\[1]'" } + T (i, (int[]){ 1 }); // { dg-warning "array subscript 1 is outside array bounds of 'int\\\[1]'" } i = SR (2, 3); T (i, (int[]){ 1, 2, 3 }); i = SR (3, 4); - T (i, (int[]){ 2, 3, 4 }); // { dg-warning "array subscript \\\[3, 4] is outside array bounds of 'int\\\[3]'" } + T (i, (int[]){ 2, 3, 4 }); // { dg-warning "array subscript 3 is outside array bounds of 'int\\\[3]'" } } /* Some of the invalid accesses above also trigger -Wuninitialized. diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-53.c b/gcc/testsuite/gcc.dg/Warray-bounds-53.c index 80db314..591cca2 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-53.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-53.c @@ -83,17 +83,17 @@ void ptr_idx_range (void) i = SR (0, 1); - T (i, (int[]){ }); // { dg-warning "array subscript \\\[0, 1] is outside array bounds of 'int\\\[0]'" } + T (i, (int[]){ }); // { dg-warning "array subscript 0 is outside array bounds of 'int\\\[0]'" } T (i, (int[]){ 1 }); i = SR (1, 2); - T (i, (int[]){ 1 }); // { dg-warning "array subscript \\\[1, 2] is outside array bounds of 'int\\\[1]'" } + T (i, (int[]){ 1 }); // { dg-warning "array subscript 1 is outside array bounds of 'int\\\[1]'" } i = SR (2, 3); T (i, (int[]){ 1, 2, 3 }); i = SR (3, 4); - T (i, (int[]){ 2, 3, 4 }); // { dg-warning "array subscript \\\[3, 4] is outside array bounds of 'int\\\[3]'" } + T (i, (int[]){ 2, 3, 4 }); // { dg-warning "array subscript 3 is outside array bounds of 'int\\\[3]'" } } /* Some of the invalid accesses above also trigger -Wuninitialized. diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-58.c b/gcc/testsuite/gcc.dg/Warray-bounds-58.c index 849457e5..616145b 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-58.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-58.c @@ -36,7 +36,7 @@ extern struct Ax ax; void fax_extern (void) { - sink (strlen (ax.a - 2)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } } + sink (strlen (ax.a - 2)); // { dg-warning "\\\[-Warray-bounds" "pr93514" } sink (strlen (ax.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } } sink (strlen (ax.a)); sink (strlen (ax.a + 123)); diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-63.c b/gcc/testsuite/gcc.dg/Warray-bounds-63.c index a3fc918..530e2c5 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-63.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-63.c @@ -14,7 +14,7 @@ void sink (void*); void byte_store_to_decl (void) { - struct S6 { char a[6]; } s; // { dg-message "referencing 's'" } + struct S6 { char a[6]; } s; // { dg-message "at offset 6 into object 's' of size 6" "note" } char *p = (char*)&s; @@ -27,7 +27,7 @@ void byte_store_to_decl (void) void word_store_to_decl (void) { - struct S6 { char a[6]; } s; // { dg-message "referencing 's'" } + struct S6 { char a[6]; } s; // { dg-message "at offset 5 into object 's' of size 6" "note" } char *p = (char*)&s; @@ -43,7 +43,7 @@ void word_store_to_decl (void) void word_store_to_alloc (void) { struct S6 { char a[6]; } *p; - p = alloca (sizeof *p); // { dg-message "referencing an object of size 6 allocated by 'alloca'" } + p = alloca (sizeof *p); // { dg-message "at offset 5 into object of size 6 allocated by 'alloca'" "note" } int16_t *q = (int16_t*)((char*)p + 1); diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-66.c b/gcc/testsuite/gcc.dg/Warray-bounds-66.c index c61891f..6ab3398 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-66.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-66.c @@ -117,14 +117,14 @@ void test_alloca_int16_range (unsigned n) } { - p = alloca (UR (0, 1)); // { dg-message "object of size between 0 and 1 allocated by '__builtin_alloca'" } + p = alloca (UR (0, 1)); // { dg-message "at offset \\d+ into object of size \\\[0, 1] allocated by '__builtin_alloca'" "note" } sink (p); T (p[0]); // { dg-warning "subscript 'int16_t {aka short int}\\\[0\\\]' is partly outside array bounds of 'unsigned char\\\[1]'" } T (p[1]); // { dg-warning "subscript 1 is outside array bounds of 'int16_t\\\[0]'" } } { - p = alloca (UR (0, 2)); // { dg-message "object of size between 0 and 2 allocated by '__builtin_alloca'" } + p = alloca (UR (0, 2)); // { dg-message "at offset \\d+ into object of size \\\[0, 2] allocated by '__builtin_alloca'" "note" } sink (p); sink (p[0]); sink (p[1]); // { dg-warning "subscript 1 is outside array bounds of 'int16_t\\\[1]'" } @@ -132,7 +132,7 @@ void test_alloca_int16_range (unsigned n) } { - p = alloca (UR (0, 3)); // { dg-message "object of size between 0 and 3 allocated by '__builtin_alloca'" } + p = alloca (UR (0, 3)); // { dg-message "at offset \\d+ into object of size \\\[0, 3] allocated by '__builtin_alloca'" "note" } sink (p); T (p[0]); T (p[1]); // { dg-warning "subscript 'int16_t {aka short int}\\\[1\\\]' is partly outside array bounds of 'unsigned char\\\[3]'" } @@ -141,7 +141,7 @@ void test_alloca_int16_range (unsigned n) } { - p = alloca (UR (1, 3)); // { dg-message "object of size between 1 and 3 allocated by '__builtin_alloca'" } + p = alloca (UR (1, 3)); // { dg-message "at offset 1|2|3 into object of size \\\[1, 3] allocated by '__builtin_alloca'" "note" } sink (p); T (p[0]); T (p[1]); // { dg-warning "subscript 'int16_t {aka short int}\\\[1\\\]' is partly outside array bounds of 'unsigned char\\\[3]'" } @@ -150,7 +150,7 @@ void test_alloca_int16_range (unsigned n) } { - p = alloca (UR (2, 3)); // { dg-message "object of size between 2 and 3 allocated by '__builtin_alloca'" } + p = alloca (UR (2, 3)); // { dg-message "at offset 2|4 into object of size \\\[2, 3] allocated by '__builtin_alloca'" "note" } sink (p); T (p[0]); T (p[1]); // { dg-warning "subscript 'int16_t {aka short int}\\\[1\\\]' is partly outside array bounds of 'unsigned char\\\[3]'" } @@ -159,7 +159,7 @@ void test_alloca_int16_range (unsigned n) } { - p = alloca (UR (3, 4)); // { dg-message "object of size between 3 and 4 allocated by '__builtin_alloca'" } + p = alloca (UR (3, 4)); // { dg-message "at offset 4|6 into object of size \\\[3, 4] allocated by '__builtin_alloca'" "note" } sink (p); T (p[0]); T (p[1]); diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-69.c b/gcc/testsuite/gcc.dg/Warray-bounds-69.c index 5a95577..80503f8 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-69.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-69.c @@ -1,6 +1,6 @@ /* Verify that storing a bigger vector into smaller space is diagnosed. { dg-do compile } - { dg-options "-O2 -Warray-bounds" } */ + { dg-options "-O2 -Warray-bounds -Wno-stringop-overflow" } */ typedef __INT16_TYPE__ int16_t; typedef __attribute__ ((__vector_size__ (32))) char C32; diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-77.c b/gcc/testsuite/gcc.dg/Warray-bounds-77.c new file mode 100644 index 0000000..6487613 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-77.c @@ -0,0 +1,135 @@ +/* PR middle-end/100137 - -Warray-bounds false positive on varying offset + plus negative + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +extern char ax[], a1[1], a2[2], a3[3], a4[4], a5[5]; + +int* ptr; +#define X (*ptr++) + + +__attribute__ ((noipa)) void +array_plus_var_minus_cstint (int i, int j) +{ + { + const char *p = ax; + p += i; + X = p[-1]; + X = p[-123]; + } + + { + const char *p = a1; + p += i; + X = p[-1]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-2]; // { dg-warning "\\\[-Warray-bounds" } + X = p[-3]; // { dg-warning "\\\[-Warray-bounds" } + X = p[-4]; // { dg-warning "\\\[-Warray-bounds" } + } + + { + const char *p = a2; + p += i; + X = p[-1]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-2]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-3]; // { dg-warning "\\\[-Warray-bounds" } + X = p[-4]; // { dg-warning "\\\[-Warray-bounds" } + } + + { + const char *p = a3; + p += i; + X = p[-1]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-2]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-3]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-4]; // { dg-warning "\\\[-Warray-bounds" } + X = p[-5]; // { dg-warning "\\\[-Warray-bounds" } + } + + { + const char *p = a4; + p += i; + X = p[-1]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-2]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-3]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-4]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-5]; // { dg-warning "\\\[-Warray-bounds" } + X = p[-6]; // { dg-warning "\\\[-Warray-bounds" } + } + + { + const char *p = a5; + p += i; + p += j; + X = p[-1]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-2]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-3]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-4]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-5]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-6]; // { dg-warning "\\\[-Warray-bounds" } + } +} + + +__attribute__ ((noipa)) void +array_plus_var_minus_cstlong (long i, long j) +{ + { + const char *p = ax; + p += i; + X = p[-1]; + X = p[-123]; + } + + { + const char *p = a1; + p += i; + X = p[-1]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-2]; // { dg-warning "\\\[-Warray-bounds" } + X = p[-3]; // { dg-warning "\\\[-Warray-bounds" } + X = p[-4]; // { dg-warning "\\\[-Warray-bounds" } + } + + { + const char *p = a2; + p += i; + X = p[-1]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-2]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-3]; // { dg-warning "\\\[-Warray-bounds" } + X = p[-4]; // { dg-warning "\\\[-Warray-bounds" } + } + + { + const char *p = a3; + p += i; + X = p[-1]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-2]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-3]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-4]; // { dg-warning "\\\[-Warray-bounds" } + X = p[-5]; // { dg-warning "\\\[-Warray-bounds" } + } + + { + const char *p = a4; + p += i; + X = p[-1]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-2]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-3]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-4]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-5]; // { dg-warning "\\\[-Warray-bounds" } + X = p[-6]; // { dg-warning "\\\[-Warray-bounds" } + } + + { + const char *p = a5; + p += i; + p += j; + X = p[-1]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-2]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-3]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-4]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-5]; // { dg-bogus "\\\[-Warray-bounds" } + X = p[-6]; // { dg-warning "\\\[-Warray-bounds" } + } +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-78.c b/gcc/testsuite/gcc.dg/Warray-bounds-78.c new file mode 100644 index 0000000..73c335f --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-78.c @@ -0,0 +1,109 @@ +/* PR tree-optimization/99475 - bogus -Warray-bounds accessing an array + element of empty structs + { dg-do compile } + { dg-options "-O2 -Wall -Wno-strict-aliasing" } */ + +typedef _Bool bool; + +#define NOIPA __attribute__ ((noipa)) + +struct S { }; + +extern struct S sa3[3]; +extern struct S sa2_3[2][3]; +extern struct S sa3_4_5[3][4][5]; + +void sink (void*); + + +NOIPA void access_sa3 (void) +{ + ((bool*)sa3)[0] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + ((bool*)sa3)[1] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + ((bool*)sa3)[2] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + ((bool*)sa3)[3] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void access_sa3_ptr (void) +{ + bool *p = (bool*)&sa3[0]; + + p[0] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[1] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[2] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[3] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void access_sa2_3_ptr (void) +{ + bool *p = (bool*)&sa2_3[0][0]; + + p[0] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[1] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[2] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[6] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } +} + +NOIPA void access_sa3_4_5_ptr (struct S s, int i) +{ + bool *p = (bool*)&sa3_4_5[0][0][0]; + + p[0] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[1] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[2] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[60] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } +} + + +NOIPA void access_vla3 (struct S s, unsigned n) +{ + struct S vla3[3 < n ? 3 : n]; + + ((bool*)vla3)[0] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + ((bool*)vla3)[1] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + ((bool*)vla3)[2] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + ((bool*)vla3)[3] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + + sink (vla3); +} + +NOIPA void access_vla3_ptr (struct S s, unsigned n) +{ + struct S vla3[3 < n ? 3 : n]; + bool *p = (bool*)&vla3[0]; + + p[0] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[1] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[2] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[3] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + + sink (vla3); +} + +NOIPA void access_vla2_3_ptr (struct S s, unsigned n) +{ + struct S vla2_3[2 < n ? 2 : n][3 < n ? 3 : n]; + bool *p = (bool*)&vla2_3[0][0]; + + p[0] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[1] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[2] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[6] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + + sink (vla2_3); +} + +NOIPA void access_vla3_4_5_ptr (struct S s, unsigned n) +{ + struct S vla3_4_5[3 < n ? 3 : n][4 < n ? 4 : n][5 < n ? 5 : n]; + bool *p = (bool*)&vla3_4_5[0][0][0]; + + p[0] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[1] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[2] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + p[60] = __LINE__; // { dg-warning "\\\[-Warray-bounds" } + + sink (vla3_4_5); +} + +// { dg-prune-output "empty struct has size 0 in C" } diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-79.c b/gcc/testsuite/gcc.dg/Warray-bounds-79.c new file mode 100644 index 0000000..b44ac9d --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-79.c @@ -0,0 +1,112 @@ +/* PR tree-optimization/99475 - bogus -Warray-bounds accessing an array + element of empty structs + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +struct S +{ +#if SOME_CONFIG_MACRO + /* Suppose the contents are empty in the development configuration + but non-empty in others. Out of bounds accesses to elements of + the arrays below should be diagnosed in all configurations, + including when S is empty, even if they are folded away. */ + int member; +#endif +}; + +extern struct S sa3[3]; +extern struct S sa2_3[2][3]; +extern struct S sa3_4_5[3][4][5]; + +void sink (void*); + + +void access_sa3 (void) +{ + sa3[0] = (struct S){ }; + sa3[1] = (struct S){ }; + sa3[2] = (struct S){ }; + sa3[3] = (struct S){ }; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } +} + +void access_sa3_ptr (void) +{ + struct S *p = &sa3[0]; + + p[0] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[3] = (struct S){ }; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } +} + +void access_sa2_3_ptr (void) +{ + struct S *p = &sa2_3[0][0]; + + p[0] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[6] = (struct S){ }; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } +} + +void access_sa3_4_5_ptr (struct S s, int i) +{ + struct S *p = &sa3_4_5[0][0][0]; + + p[0] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[60] = (struct S){ }; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } +} + + +void access_vla3 (struct S s, unsigned n) +{ + struct S vla3[3 < n ? 3 : n]; + + vla3[0] = (struct S){ }; + vla3[1] = (struct S){ }; + vla3[2] = (struct S){ }; + vla3[3] = (struct S){ }; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + + sink (vla3); +} + +void access_vla3_ptr (struct S s, unsigned n) +{ + struct S vla3[3 < n ? 3 : n]; + struct S *p = &vla3[0]; + + p[0] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[3] = (struct S){ }; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + + sink (vla3); +} + +void access_vla2_3_ptr (struct S s, unsigned n) +{ + struct S vla2_3[2 < n ? 2 : n][3 < n ? 3 : n]; + struct S *p = &vla2_3[0][0]; + + p[0] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[6] = (struct S){ }; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + + sink (vla2_3); +} + +void access_vla3_4_5_ptr (struct S s, unsigned n) +{ + struct S vla3_4_5[3 < n ? 3 : n][4 < n ? 4 : n][5 < n ? 5 : n]; + struct S *p = &vla3_4_5[0][0][0]; + + p[0] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[1] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[2] = (struct S){ }; // { dg-bogus "\\\[-Warray-bounds" } + p[60] = (struct S){ }; // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + + sink (vla3_4_5); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c index a1b1039..d9ca344 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c @@ -112,7 +112,7 @@ void s2_warn_cstoff_cstidx (struct S2 *p) void s2_warn_varoff_cstdix (struct S2 *p, int i) { char *q = p->a + i; - q[2] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" } + q[2] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } } void s2_warn_cstoff_varidx (struct S2 *p, int i) @@ -235,8 +235,8 @@ void si0_warn_cstoff_cstidx (struct Si0 *p) void si0_warn_varoff_cstdix (struct Si0 *p, int i) { char *q = p->a + i; - q[1] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" } - q[9] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" } + q[1] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } + q[9] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } } void si0_warn_cstoff_varidx (struct Si0 *p, int i) @@ -248,5 +248,5 @@ void si0_warn_cstoff_varidx (struct Si0 *p, int i) void si0_warn_varoff_varidx (struct Si0 *p, int i, int j) { char *q = p->a + i; - q[j] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" } + q[j] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c index 9bfc84a..6412874 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c @@ -24,22 +24,22 @@ void nowarn_c32 (char c) sink (p); } -/* The tests below fail as a result of the hack for PR 96963. However, - with -Wall, the invalid stores are diagnosed by -Warray-bounds which - runs before vectorization and so doesn't need the hack. If/when - -Warray changes to use compute_objsize() this will need adjusting. */ +/* The tests below failed as a result of the hack for PR 96963. However, + with -Wall, the invalid stores were diagnosed by -Warray-bounds which + runs before vectorization and so doesn't need the hack. Now that + -Warray-bounds has changed to use compute_objsize() the tests pass. */ void warn_c32 (char c) { - extern char warn_a32[32]; // { dg-message "at offset 32 into destination object 'warn_a32' of size 32" "pr97027" { xfail *-*-* } } + extern char warn_a32[32]; // { dg-message "at offset 32 into destination object 'warn_a32' of size 32" "pr97027" } void *p = warn_a32 + 1; - *(C32*)p = (C32){ c }; // { dg-warning "writing 1 byte into a region of size 0" "pr97027" { xfail *-*-* } } + *(C32*)p = (C32){ c }; // { dg-warning "writing 1 byte into a region of size 0" "pr97027" } /* Verify a local variable too. */ char a32[32]; p = a32 + 1; - *(C32*)p = (C32){ c }; // { dg-warning "writing 1 byte into a region of size 0" "pr97027" { xfail *-*-* } } + *(C32*)p = (C32){ c }; // { dg-warning "writing 1 byte into a region of size 0" "pr97027" } sink (p); } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c index 7601679..93c54c6 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c @@ -65,7 +65,7 @@ void nowarn_cond_escape (int c, int *x) void warn_cond_escape (int c, int *x) { extern char a3_2[3]; - extern char a5_2[5]; // { dg-message "at offset 5 into destination object 'a5_2'" } + extern char a5_2[5]; // { dg-message "at offset 5 into object 'a5_2'" } char *p; if (c) @@ -84,5 +84,5 @@ void warn_cond_escape (int c, int *x) if (*x == 2) p[2] = 0; else if (*x == 5) - p[5] = 0; // { dg-warning "\\\[-Wstringop-overflow" } + p[5] = 0; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } } -- cgit v1.1 From 48e8a7a677b8356df946cd12fbb215538828e747 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 7 Jul 2021 19:29:30 -0400 Subject: analyzer: remove add_any_constraints_from_ssa_def_stmt I'm working on reimplementing -Wanalyzer-use-of-uninitialized-value, but I ran into issues with region_model::add_any_constraints_from_ssa_def_stmt. This function is from the initial commit of the analyzer and walks the SSA names finding conditions that were missed due to the GCC 10 era region_model not retaining useful information on how values were created; as of GCC 11 the symbolic values contain this information, and so the conditions can be reconstructed from them instead. region_model::add_any_constraints_from_ssa_def_stmt is a liability when tracking uninitialized values as it requires looking up SSA values when those values may have been purged, thus greatly complicating detection of uses of uninitialized values. It's simplest to eliminate it and reimplement the condition-finding via the makeup of the svalues, which this patch does. Doing so requires supporting add_condition on svalues rather than just on trees, which requires some changes to ana::state_machine and its subclasses. gcc/analyzer/ChangeLog: * diagnostic-manager.cc (null_assignment_sm_context::get_state): New overload. (null_assignment_sm_context::set_next_state): New overload. (null_assignment_sm_context::get_diagnostic_tree): New. * engine.cc (impl_sm_context::get_state): New overload. (impl_sm_context::set_next_state): New overload. (impl_sm_context::get_diagnostic_tree): New overload. (impl_region_model_context::on_condition): Convert params from tree to const svalue *. * exploded-graph.h (impl_region_model_context::on_condition): Likewise. * region-model.cc (region_model::on_call_pre): Move handling of internal calls to before checking for get_fndecl_for_call. (region_model::add_constraints_from_binop): New. (region_model::add_constraint): Split out into a new overload working on const svalue * rather than tree. Call add_constraints_from_binop. Drop call to add_any_constraints_from_ssa_def_stmt. (region_model::add_any_constraints_from_ssa_def_stmt): Delete. (region_model::add_any_constraints_from_gassign): Delete. (region_model::add_any_constraints_from_gcall): Delete. * region-model.h (region_model::add_any_constraints_from_ssa_def_stmt): Delete. (region_model::add_any_constraints_from_gassign): Delete. (region_model::add_any_constraints_from_gcall): Delete. (region_model::add_constraint): Add overload decl. (region_model::add_constraints_from_binop): New decl. (region_model_context::on_condition): Convert params from tree to const svalue *. (noop_region_model_context::on_condition): Likewise. * sm-file.cc (fileptr_state_machine::condition): Likewise. * sm-malloc.cc (malloc_state_machine::on_condition): Likewise. * sm-pattern-test.cc: Include tristate.h, selftest.h, analyzer/call-string.h, analyzer/program-point.h, analyzer/store.h, and analyzer/region-model.h. (pattern_test_state_machine::on_condition): Convert params from tree to const svalue *. * sm-sensitive.cc (sensitive_state_machine::on_condition): Delete. * sm-signal.cc (signal_state_machine::on_condition): Delete. * sm-taint.cc (taint_state_machine::on_condition): Convert params from tree to const svalue *. * sm.cc: Include tristate.h, selftest.h, analyzer/call-string.h, analyzer/program-point.h, analyzer/store.h, and analyzer/region-model.h. (any_pointer_p): Add overload taking const svalue *sval. * sm.h (any_pointer_p): Add overload taking const svalue *sval. (state_machine::on_condition): Convert params from tree to const svalue *. Provide no-op default implementation. (sm_context::get_state): Add overload taking const svalue *sval. (sm_context::set_next_state): Likewise. (sm_context::on_transition): Likewise. (sm_context::get_diagnostic_tree): Likewise. * svalue.cc (svalue::all_zeroes_p): New. (constant_svalue::all_zeroes_p): New. (repeated_svalue::all_zeroes_p): Convert to vfunc. * svalue.h (svalue::all_zeroes_p): New decl. (constant_svalue::all_zeroes_p): New decl. (repeated_svalue::all_zeroes_p): Convert decl to vfunc. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/pattern-test-2.c: Update expected results. * gcc.dg/plugin/analyzer_gil_plugin.c (gil_state_machine::on_condition): Remove. Signed-off-by: David Malcolm --- gcc/analyzer/diagnostic-manager.cc | 35 +++ gcc/analyzer/engine.cc | 54 +++- gcc/analyzer/exploded-graph.h | 4 +- gcc/analyzer/region-model.cc | 304 +++++++++++----------- gcc/analyzer/region-model.h | 29 +-- gcc/analyzer/sm-file.cc | 15 +- gcc/analyzer/sm-malloc.cc | 10 +- gcc/analyzer/sm-pattern-test.cc | 24 +- gcc/analyzer/sm-sensitive.cc | 18 -- gcc/analyzer/sm-signal.cc | 21 -- gcc/analyzer/sm-taint.cc | 8 +- gcc/analyzer/sm.cc | 14 + gcc/analyzer/sm.h | 34 ++- gcc/analyzer/svalue.cc | 24 +- gcc/analyzer/svalue.h | 6 +- gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c | 10 +- gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c | 21 -- 17 files changed, 361 insertions(+), 270 deletions(-) (limited to 'gcc') diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index 7eb4ed8..b7d263b 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -1377,6 +1377,14 @@ struct null_assignment_sm_context : public sm_context return current; } + state_machine::state_t get_state (const gimple *stmt ATTRIBUTE_UNUSED, + const svalue *sval) FINAL OVERRIDE + { + const sm_state_map *old_smap = m_old_state->m_checker_states[m_sm_idx]; + state_machine::state_t current = old_smap->get_state (sval, m_ext_state); + return current; + } + void set_next_state (const gimple *stmt, tree var, state_machine::state_t to, @@ -1401,6 +1409,28 @@ struct null_assignment_sm_context : public sm_context *m_new_state)); } + void set_next_state (const gimple *stmt, + const svalue *sval, + state_machine::state_t to, + tree origin ATTRIBUTE_UNUSED) FINAL OVERRIDE + { + state_machine::state_t from = get_state (stmt, sval); + if (from != m_sm.get_start_state ()) + return; + + const supernode *supernode = m_point->get_supernode (); + int stack_depth = m_point->get_stack_depth (); + + m_emission_path->add_event (new state_change_event (supernode, + m_stmt, + stack_depth, + m_sm, + sval, + from, to, + NULL, + *m_new_state)); + } + void warn (const supernode *, const gimple *, tree, pending_diagnostic *d) FINAL OVERRIDE { @@ -1412,6 +1442,11 @@ struct null_assignment_sm_context : public sm_context return expr; } + tree get_diagnostic_tree (const svalue *sval) FINAL OVERRIDE + { + return m_new_state->m_region_model->get_representative_tree (sval); + } + state_machine::state_t get_global_state () const FINAL OVERRIDE { return 0; diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 4456d9b..01b83a4 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -245,6 +245,16 @@ public: = m_old_smap->get_state (var_old_sval, m_eg.get_ext_state ()); return current; } + state_machine::state_t get_state (const gimple *stmt ATTRIBUTE_UNUSED, + const svalue *sval) + { + logger * const logger = get_logger (); + LOG_FUNC (logger); + state_machine::state_t current + = m_old_smap->get_state (sval, m_eg.get_ext_state ()); + return current; + } + void set_next_state (const gimple *stmt, tree var, @@ -280,6 +290,41 @@ public: to, origin_new_sval, m_eg.get_ext_state ()); } + void set_next_state (const gimple *stmt, + const svalue *sval, + state_machine::state_t to, + tree origin) + { + logger * const logger = get_logger (); + LOG_FUNC (logger); + impl_region_model_context old_ctxt + (m_eg, m_enode_for_diag, NULL, NULL/*m_enode->get_state ()*/, + NULL, stmt); + + impl_region_model_context new_ctxt (m_eg, m_enode_for_diag, + m_old_state, m_new_state, + NULL, + stmt); + const svalue *origin_new_sval + = m_new_state->m_region_model->get_rvalue (origin, &new_ctxt); + + state_machine::state_t current + = m_old_smap->get_state (sval, m_eg.get_ext_state ()); + if (logger) + { + logger->start_log_line (); + logger->log_partial ("%s: state transition of ", + m_sm.get_name ()); + sval->dump_to_pp (logger->get_printer (), true); + logger->log_partial (": %s -> %s", + current->get_name (), + to->get_name ()); + logger->end_log_line (); + } + m_new_smap->set_state (m_new_state->m_region_model, sval, + to, origin_new_sval, m_eg.get_ext_state ()); + } + void warn (const supernode *snode, const gimple *stmt, tree var, pending_diagnostic *d) FINAL OVERRIDE { @@ -323,6 +368,11 @@ public: return expr; } + tree get_diagnostic_tree (const svalue *sval) FINAL OVERRIDE + { + return m_new_state->m_region_model->get_representative_tree (sval); + } + state_machine::state_t get_global_state () const FINAL OVERRIDE { return m_old_state->m_checker_states[m_sm_idx]->get_global_state (); @@ -654,7 +704,9 @@ impl_region_model_context::on_state_leak (const state_machine &sm, state transitions. */ void -impl_region_model_context::on_condition (tree lhs, enum tree_code op, tree rhs) +impl_region_model_context::on_condition (const svalue *lhs, + enum tree_code op, + const svalue *rhs) { int sm_idx; sm_state_map *smap; diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index eb1baef..2d25e5e 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -59,7 +59,9 @@ class impl_region_model_context : public region_model_context const svalue *sval, state_machine::state_t state); - void on_condition (tree lhs, enum tree_code op, tree rhs) FINAL OVERRIDE; + void on_condition (const svalue *lhs, + enum tree_code op, + const svalue *rhs) FINAL OVERRIDE; void on_unknown_change (const svalue *sval, bool is_mutable) FINAL OVERRIDE; diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 4fb6bc9..acbbd11 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -881,12 +881,23 @@ bool region_model::on_call_pre (const gcall *call, region_model_context *ctxt, bool *out_terminate_path) { + call_details cd (call, this, ctxt); + bool unknown_side_effects = false; - if (tree callee_fndecl = get_fndecl_for_call (call, ctxt)) + if (gimple_call_internal_p (call)) { - call_details cd (call, this, ctxt); + switch (gimple_call_internal_fn (call)) + { + default: + break; + case IFN_BUILTIN_EXPECT: + return impl_call_builtin_expect (cd); + } + } + if (tree callee_fndecl = get_fndecl_for_call (call, ctxt)) + { /* The various impl_call_* member functions are implemented in region-model-impl-calls.cc. Having them split out into separate functions makes it easier @@ -958,16 +969,6 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt, on the return value. */ break; } - else if (gimple_call_internal_p (call)) - switch (gimple_call_internal_fn (call)) - { - default: - if (!DECL_PURE_P (callee_fndecl)) - unknown_side_effects = true; - break; - case IFN_BUILTIN_EXPECT: - return impl_call_builtin_expect (cd); - } else if (is_named_call_p (callee_fndecl, "malloc", call, 1)) return impl_call_malloc (cd); else if (is_named_call_p (callee_fndecl, "calloc", call, 2)) @@ -2251,6 +2252,123 @@ region_model::compare_initial_and_pointer (const initial_svalue *init, return tristate::TS_UNKNOWN; } +/* Handle various constraints of the form: + LHS: ((bool)INNER_LHS INNER_OP INNER_RHS)) + OP : == or != + RHS: zero + and (with a cast): + LHS: CAST([long]int, ((bool)INNER_LHS INNER_OP INNER_RHS)) + OP : == or != + RHS: zero + by adding constraints for INNER_LHS INNEROP INNER_RHS. + + Return true if this function can fully handle the constraint; if + so, add the implied constraint(s) and write true to *OUT if they + are consistent with existing constraints, or write false to *OUT + if they contradicts existing constraints. + + Return false for cases that this function doeesn't know how to handle. + + For example, if we're checking a stored conditional, we'll have + something like: + LHS: CAST(long int, (&HEAP_ALLOCATED_REGION(8)!=(int *)0B)) + OP : NE_EXPR + RHS: zero + which this function can turn into an add_constraint of: + (&HEAP_ALLOCATED_REGION(8) != (int *)0B) + + Similarly, optimized && and || conditionals lead to e.g. + if (p && q) + becoming gimple like this: + _1 = p_6 == 0B; + _2 = q_8 == 0B + _3 = _1 | _2 + On the "_3 is false" branch we can have constraints of the form: + ((&HEAP_ALLOCATED_REGION(8)!=(int *)0B) + | (&HEAP_ALLOCATED_REGION(10)!=(int *)0B)) + == 0 + which implies that both _1 and _2 are false, + which this function can turn into a pair of add_constraints of + (&HEAP_ALLOCATED_REGION(8)!=(int *)0B) + and: + (&HEAP_ALLOCATED_REGION(10)!=(int *)0B). */ + +bool +region_model::add_constraints_from_binop (const svalue *outer_lhs, + enum tree_code outer_op, + const svalue *outer_rhs, + bool *out, + region_model_context *ctxt) +{ + while (const svalue *cast = outer_lhs->maybe_undo_cast ()) + outer_lhs = cast; + const binop_svalue *binop_sval = outer_lhs->dyn_cast_binop_svalue (); + if (!binop_sval) + return false; + if (!outer_rhs->all_zeroes_p ()) + return false; + + const svalue *inner_lhs = binop_sval->get_arg0 (); + enum tree_code inner_op = binop_sval->get_op (); + const svalue *inner_rhs = binop_sval->get_arg1 (); + + if (outer_op != NE_EXPR && outer_op != EQ_EXPR) + return false; + + /* We have either + - "OUTER_LHS != false" (i.e. OUTER is true), or + - "OUTER_LHS == false" (i.e. OUTER is false). */ + bool is_true = outer_op == NE_EXPR; + + switch (inner_op) + { + default: + return false; + + case EQ_EXPR: + case NE_EXPR: + { + /* ...and "(inner_lhs OP inner_rhs) == 0" + then (inner_lhs OP inner_rhs) must have the same + logical value as LHS. */ + if (!is_true) + inner_op = invert_tree_comparison (inner_op, false /* honor_nans */); + *out = add_constraint (inner_lhs, inner_op, inner_rhs, ctxt); + return true; + } + break; + + case BIT_AND_EXPR: + if (is_true) + { + /* ...and "(inner_lhs & inner_rhs) != 0" + then both inner_lhs and inner_rhs must be true. */ + const svalue *false_sval + = m_mgr->get_or_create_constant_svalue (boolean_false_node); + bool sat1 = add_constraint (inner_lhs, NE_EXPR, false_sval, ctxt); + bool sat2 = add_constraint (inner_rhs, NE_EXPR, false_sval, ctxt); + *out = sat1 && sat2; + return true; + } + return false; + + case BIT_IOR_EXPR: + if (!is_true) + { + /* ...and "(inner_lhs | inner_rhs) == 0" + i.e. "(inner_lhs | inner_rhs)" is false + then both inner_lhs and inner_rhs must be false. */ + const svalue *false_sval + = m_mgr->get_or_create_constant_svalue (boolean_false_node); + bool sat1 = add_constraint (inner_lhs, EQ_EXPR, false_sval, ctxt); + bool sat2 = add_constraint (inner_rhs, EQ_EXPR, false_sval, ctxt); + *out = sat1 && sat2; + return true; + } + return false; + } +} + /* Attempt to add the constraint "LHS OP RHS" to this region_model. If it is consistent with existing constraints, add it, and return true. Return false if it contradicts existing constraints. @@ -2268,7 +2386,21 @@ region_model::add_constraint (tree lhs, enum tree_code op, tree rhs, const svalue *lhs_sval = get_rvalue (lhs, ctxt); const svalue *rhs_sval = get_rvalue (rhs, ctxt); - tristate t_cond = eval_condition (lhs_sval, op, rhs_sval); + return add_constraint (lhs_sval, op, rhs_sval, ctxt); +} + +/* Attempt to add the constraint "LHS OP RHS" to this region_model. + If it is consistent with existing constraints, add it, and return true. + Return false if it contradicts existing constraints. + Use CTXT for reporting any diagnostics associated with the accesses. */ + +bool +region_model::add_constraint (const svalue *lhs, + enum tree_code op, + const svalue *rhs, + region_model_context *ctxt) +{ + tristate t_cond = eval_condition (lhs, op, rhs); /* If we already have the condition, do nothing. */ if (t_cond.is_true ()) @@ -2279,10 +2411,12 @@ region_model::add_constraint (tree lhs, enum tree_code op, tree rhs, if (t_cond.is_false ()) return false; - /* Store the constraint. */ - m_constraints->add_constraint (lhs_sval, op, rhs_sval); + bool out; + if (add_constraints_from_binop (lhs, op, rhs, &out, ctxt)) + return out; - add_any_constraints_from_ssa_def_stmt (lhs, op, rhs, ctxt); + /* Store the constraint. */ + m_constraints->add_constraint (lhs, op, rhs); /* Notify the context, if any. This exists so that the state machines in a program_state can be notified about the condition, and so can @@ -2293,9 +2427,10 @@ region_model::add_constraint (tree lhs, enum tree_code op, tree rhs, /* If we have ®ION == NULL, then drop dynamic extents for REGION (for the case where REGION is heap-allocated and thus could be NULL). */ - if (op == EQ_EXPR && zerop (rhs)) - if (const region_svalue *region_sval = lhs_sval->dyn_cast_region_svalue ()) - unset_dynamic_extents (region_sval->get_pointee ()); + if (tree rhs_cst = rhs->maybe_get_constant ()) + if (op == EQ_EXPR && zerop (rhs_cst)) + if (const region_svalue *region_sval = lhs->dyn_cast_region_svalue ()) + unset_dynamic_extents (region_sval->get_pointee ()); return true; } @@ -2314,137 +2449,6 @@ region_model::add_constraint (tree lhs, enum tree_code op, tree rhs, return sat; } -/* Subroutine of region_model::add_constraint for handling optimized - && and || conditionals. - - If we have an SSA_NAME for a boolean compared against 0, - look at anything implied by the def stmt and call add_constraint - for it (which could recurse). - - For example, if we have - _1 = p_6 == 0B; - _2 = p_8 == 0B - _3 = _1 | _2 - and add the constraint - (_3 == 0), - then the def stmt for _3 implies that _1 and _2 are both false, - and hence we can add the constraints: - p_6 != 0B - p_8 != 0B. */ - -void -region_model::add_any_constraints_from_ssa_def_stmt (tree lhs, - enum tree_code op, - tree rhs, - region_model_context *ctxt) -{ - if (TREE_CODE (lhs) != SSA_NAME) - return; - - if (!zerop (rhs)) - return; - - if (op != NE_EXPR && op != EQ_EXPR) - return; - - gimple *def_stmt = SSA_NAME_DEF_STMT (lhs); - if (const gassign *assign = dyn_cast (def_stmt)) - add_any_constraints_from_gassign (op, rhs, assign, ctxt); - else if (gcall *call = dyn_cast (def_stmt)) - add_any_constraints_from_gcall (op, rhs, call, ctxt); -} - -/* Add any constraints for an SSA_NAME defined by ASSIGN - where the result OP RHS. */ - -void -region_model::add_any_constraints_from_gassign (enum tree_code op, - tree rhs, - const gassign *assign, - region_model_context *ctxt) -{ - /* We have either - - "LHS != false" (i.e. LHS is true), or - - "LHS == false" (i.e. LHS is false). */ - bool is_true = op == NE_EXPR; - - enum tree_code rhs_code = gimple_assign_rhs_code (assign); - - switch (rhs_code) - { - default: - break; - - case NOP_EXPR: - case VIEW_CONVERT_EXPR: - { - add_constraint (gimple_assign_rhs1 (assign), op, rhs, ctxt); - } - break; - - case BIT_AND_EXPR: - { - if (is_true) - { - /* ...and "LHS == (rhs1 & rhs2) i.e. "(rhs1 & rhs2)" is true - then both rhs1 and rhs2 must be true. */ - tree rhs1 = gimple_assign_rhs1 (assign); - tree rhs2 = gimple_assign_rhs2 (assign); - add_constraint (rhs1, NE_EXPR, boolean_false_node, ctxt); - add_constraint (rhs2, NE_EXPR, boolean_false_node, ctxt); - } - } - break; - - case BIT_IOR_EXPR: - { - if (!is_true) - { - /* ...and "LHS == (rhs1 | rhs2) - i.e. "(rhs1 | rhs2)" is false - then both rhs1 and rhs2 must be false. */ - tree rhs1 = gimple_assign_rhs1 (assign); - tree rhs2 = gimple_assign_rhs2 (assign); - add_constraint (rhs1, EQ_EXPR, boolean_false_node, ctxt); - add_constraint (rhs2, EQ_EXPR, boolean_false_node, ctxt); - } - } - break; - - case EQ_EXPR: - case NE_EXPR: - { - /* ...and "LHS == (rhs1 OP rhs2)" - then rhs1 OP rhs2 must have the same logical value as LHS. */ - tree rhs1 = gimple_assign_rhs1 (assign); - tree rhs2 = gimple_assign_rhs2 (assign); - if (!is_true) - rhs_code - = invert_tree_comparison (rhs_code, false /* honor_nans */); - add_constraint (rhs1, rhs_code, rhs2, ctxt); - } - break; - } -} - -/* Add any constraints for an SSA_NAME defined by CALL - where the result OP RHS. */ - -void -region_model::add_any_constraints_from_gcall (enum tree_code op, - tree rhs, - const gcall *call, - region_model_context *ctxt) -{ - if (gimple_call_builtin_p (call, BUILT_IN_EXPECT) - || gimple_call_builtin_p (call, BUILT_IN_EXPECT_WITH_PROBABILITY) - || gimple_call_internal_p (call, IFN_BUILTIN_EXPECT)) - { - /* __builtin_expect's return value is its initial argument. */ - add_constraint (gimple_call_arg (call, 0), op, rhs, ctxt); - } -} - /* Determine what is known about the condition "LHS OP RHS" within this model. Use CTXT for reporting any diagnostics associated with the accesses. */ diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index b42852b..cf5232d 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -691,18 +691,15 @@ class region_model get_representative_path_var_1 (const region *reg, svalue_set *visited) const; - void add_any_constraints_from_ssa_def_stmt (tree lhs, - enum tree_code op, - tree rhs, - region_model_context *ctxt); - void add_any_constraints_from_gassign (enum tree_code op, - tree rhs, - const gassign *assign, - region_model_context *ctxt); - void add_any_constraints_from_gcall (enum tree_code op, - tree rhs, - const gcall *call, - region_model_context *ctxt); + bool add_constraint (const svalue *lhs, + enum tree_code op, + const svalue *rhs, + region_model_context *ctxt); + bool add_constraints_from_binop (const svalue *outer_lhs, + enum tree_code outer_op, + const svalue *outer_rhs, + bool *out, + region_model_context *ctxt); void update_for_call_superedge (const call_superedge &call_edge, region_model_context *ctxt); @@ -781,7 +778,9 @@ class region_model_context and use them to trigger sm-state transitions (e.g. transitions due to ptrs becoming known to be NULL or non-NULL, rather than just "unchecked") */ - virtual void on_condition (tree lhs, enum tree_code op, tree rhs) = 0; + virtual void on_condition (const svalue *lhs, + enum tree_code op, + const svalue *rhs) = 0; /* Hooks for clients to be notified when an unknown change happens to SVAL (in response to a call to an unknown function). */ @@ -812,9 +811,9 @@ public: void on_liveness_change (const svalue_set &, const region_model *) OVERRIDE {} logger *get_logger () OVERRIDE { return NULL; } - void on_condition (tree lhs ATTRIBUTE_UNUSED, + void on_condition (const svalue *lhs ATTRIBUTE_UNUSED, enum tree_code op ATTRIBUTE_UNUSED, - tree rhs ATTRIBUTE_UNUSED) OVERRIDE + const svalue *rhs ATTRIBUTE_UNUSED) OVERRIDE { } void on_unknown_change (const svalue *sval ATTRIBUTE_UNUSED, diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc index 3a5f95d..b40a9a1 100644 --- a/gcc/analyzer/sm-file.cc +++ b/gcc/analyzer/sm-file.cc @@ -77,9 +77,9 @@ public: void on_condition (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, - tree lhs, + const svalue *lhs, enum tree_code op, - tree rhs) const FINAL OVERRIDE; + const svalue *rhs) const FINAL OVERRIDE; bool can_purge_p (state_t s) const FINAL OVERRIDE; pending_diagnostic *on_leak (tree var) const FINAL OVERRIDE; @@ -381,19 +381,18 @@ void fileptr_state_machine::on_condition (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, - tree lhs, + const svalue *lhs, enum tree_code op, - tree rhs) const + const svalue *rhs) const { - if (!zerop (rhs)) + if (!rhs->all_zeroes_p ()) return; // TODO: has to be a FILE *, specifically - if (TREE_CODE (TREE_TYPE (lhs)) != POINTER_TYPE) + if (!any_pointer_p (lhs)) return; - // TODO: has to be a FILE *, specifically - if (TREE_CODE (TREE_TYPE (rhs)) != POINTER_TYPE) + if (!any_pointer_p (rhs)) return; if (op == NE_EXPR) diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc index a1582ca..40e64b3 100644 --- a/gcc/analyzer/sm-malloc.cc +++ b/gcc/analyzer/sm-malloc.cc @@ -375,9 +375,9 @@ public: void on_condition (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, - tree lhs, + const svalue *lhs, enum tree_code op, - tree rhs) const FINAL OVERRIDE; + const svalue *rhs) const FINAL OVERRIDE; bool can_purge_p (state_t s) const FINAL OVERRIDE; pending_diagnostic *on_leak (tree var) const FINAL OVERRIDE; @@ -1863,11 +1863,11 @@ void malloc_state_machine::on_condition (sm_context *sm_ctxt, const supernode *node ATTRIBUTE_UNUSED, const gimple *stmt, - tree lhs, + const svalue *lhs, enum tree_code op, - tree rhs) const + const svalue *rhs) const { - if (!zerop (rhs)) + if (!rhs->all_zeroes_p ()) return; if (!any_pointer_p (lhs)) diff --git a/gcc/analyzer/sm-pattern-test.cc b/gcc/analyzer/sm-pattern-test.cc index 43b8475..4e28549 100644 --- a/gcc/analyzer/sm-pattern-test.cc +++ b/gcc/analyzer/sm-pattern-test.cc @@ -37,6 +37,12 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" #include "analyzer/pending-diagnostic.h" +#include "tristate.h" +#include "selftest.h" +#include "analyzer/call-string.h" +#include "analyzer/program-point.h" +#include "analyzer/store.h" +#include "analyzer/region-model.h" #if ENABLE_ANALYZER @@ -61,9 +67,9 @@ public: void on_condition (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, - tree lhs, + const svalue *lhs, enum tree_code op, - tree rhs) const FINAL OVERRIDE; + const svalue *rhs) const FINAL OVERRIDE; bool can_purge_p (state_t s) const FINAL OVERRIDE; }; @@ -118,18 +124,22 @@ void pattern_test_state_machine::on_condition (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, - tree lhs, + const svalue *lhs, enum tree_code op, - tree rhs) const + const svalue *rhs) const { if (stmt == NULL) return; - if (!CONSTANT_CLASS_P (rhs)) + tree rhs_cst = rhs->maybe_get_constant (); + if (!rhs_cst) return; - pending_diagnostic *diag = new pattern_match (lhs, op, rhs); - sm_ctxt->warn (node, stmt, lhs, diag); + if (tree lhs_expr = sm_ctxt->get_diagnostic_tree (lhs)) + { + pending_diagnostic *diag = new pattern_match (lhs_expr, op, rhs_cst); + sm_ctxt->warn (node, stmt, lhs_expr, diag); + } } bool diff --git a/gcc/analyzer/sm-sensitive.cc b/gcc/analyzer/sm-sensitive.cc index 9703f7e..4add55e 100644 --- a/gcc/analyzer/sm-sensitive.cc +++ b/gcc/analyzer/sm-sensitive.cc @@ -58,13 +58,6 @@ public: const supernode *node, const gimple *stmt) const FINAL OVERRIDE; - void on_condition (sm_context *sm_ctxt, - const supernode *node, - const gimple *stmt, - tree lhs, - enum tree_code op, - tree rhs) const FINAL OVERRIDE; - bool can_purge_p (state_t s) const FINAL OVERRIDE; /* State for "sensitive" data, such as a password. */ @@ -222,17 +215,6 @@ sensitive_state_machine::on_stmt (sm_context *sm_ctxt, return false; } -void -sensitive_state_machine::on_condition (sm_context *sm_ctxt ATTRIBUTE_UNUSED, - const supernode *node ATTRIBUTE_UNUSED, - const gimple *stmt ATTRIBUTE_UNUSED, - tree lhs ATTRIBUTE_UNUSED, - enum tree_code op ATTRIBUTE_UNUSED, - tree rhs ATTRIBUTE_UNUSED) const -{ - /* Empty. */ -} - bool sensitive_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const { diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc index 42be809..fcbf322 100644 --- a/gcc/analyzer/sm-signal.cc +++ b/gcc/analyzer/sm-signal.cc @@ -81,13 +81,6 @@ public: const supernode *node, const gimple *stmt) const FINAL OVERRIDE; - void on_condition (sm_context *sm_ctxt, - const supernode *node, - const gimple *stmt, - tree lhs, - enum tree_code op, - tree rhs) const FINAL OVERRIDE; - bool can_purge_p (state_t s) const FINAL OVERRIDE; /* These states are "global", rather than per-expression. */ @@ -363,20 +356,6 @@ signal_state_machine::on_stmt (sm_context *sm_ctxt, return false; } -/* Implementation of state_machine::on_condition vfunc for - signal_state_machine. */ - -void -signal_state_machine::on_condition (sm_context *sm_ctxt ATTRIBUTE_UNUSED, - const supernode *node ATTRIBUTE_UNUSED, - const gimple *stmt ATTRIBUTE_UNUSED, - tree lhs ATTRIBUTE_UNUSED, - enum tree_code op ATTRIBUTE_UNUSED, - tree rhs ATTRIBUTE_UNUSED) const -{ - // Empty -} - bool signal_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const { diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc index e2460f9..721d3ea 100644 --- a/gcc/analyzer/sm-taint.cc +++ b/gcc/analyzer/sm-taint.cc @@ -61,9 +61,9 @@ public: void on_condition (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, - tree lhs, + const svalue *lhs, enum tree_code op, - tree rhs) const FINAL OVERRIDE; + const svalue *rhs) const FINAL OVERRIDE; bool can_purge_p (state_t s) const FINAL OVERRIDE; @@ -281,9 +281,9 @@ void taint_state_machine::on_condition (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, - tree lhs, + const svalue *lhs, enum tree_code op, - tree rhs ATTRIBUTE_UNUSED) const + const svalue *rhs ATTRIBUTE_UNUSED) const { if (stmt == NULL) return; diff --git a/gcc/analyzer/sm.cc b/gcc/analyzer/sm.cc index 2d227dd..db07bf3 100644 --- a/gcc/analyzer/sm.cc +++ b/gcc/analyzer/sm.cc @@ -35,6 +35,11 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" +#include "tristate.h" +#include "analyzer/call-string.h" +#include "analyzer/program-point.h" +#include "analyzer/store.h" +#include "analyzer/svalue.h" #if ENABLE_ANALYZER @@ -48,6 +53,15 @@ any_pointer_p (tree var) return POINTER_TYPE_P (TREE_TYPE (var)); } +/* Return true if SVAL has pointer or reference type. */ + +bool +any_pointer_p (const svalue *sval) +{ + if (!sval->get_type ()) + return false; + return POINTER_TYPE_P (sval->get_type ()); +} /* class state_machine::state. */ diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h index 8d4d030..6bb036e 100644 --- a/gcc/analyzer/sm.h +++ b/gcc/analyzer/sm.h @@ -29,7 +29,8 @@ class state_machine; class sm_context; class pending_diagnostic; -extern bool any_pointer_p (tree var); +extern bool any_pointer_p (tree expr); +extern bool any_pointer_p (const svalue *sval); /* An abstract base class for a state machine describing an API. Manages a set of state objects, and has various virtual functions @@ -89,10 +90,14 @@ public: { } - virtual void on_condition (sm_context *sm_ctxt, - const supernode *node, - const gimple *stmt, - tree lhs, enum tree_code op, tree rhs) const = 0; + virtual void on_condition (sm_context *sm_ctxt ATTRIBUTE_UNUSED, + const supernode *node ATTRIBUTE_UNUSED, + const gimple *stmt ATTRIBUTE_UNUSED, + const svalue *lhs ATTRIBUTE_UNUSED, + enum tree_code op ATTRIBUTE_UNUSED, + const svalue *rhs ATTRIBUTE_UNUSED) const + { + } /* Return true if it safe to discard the given state (to help when simplifying state objects). @@ -182,6 +187,8 @@ public: /* Get the old state of VAR at STMT. */ virtual state_machine::state_t get_state (const gimple *stmt, tree var) = 0; + virtual state_machine::state_t get_state (const gimple *stmt, + const svalue *) = 0; /* Set the next state of VAR to be TO, recording the "origin" of the state as ORIGIN. Use STMT for location information. */ @@ -189,6 +196,10 @@ public: tree var, state_machine::state_t to, tree origin = NULL_TREE) = 0; + virtual void set_next_state (const gimple *stmt, + const svalue *var, + state_machine::state_t to, + tree origin = NULL_TREE) = 0; /* Called by state_machine in response to pattern matches: if VAR is in state FROM, transition it to state TO, potentially @@ -206,6 +217,18 @@ public: set_next_state (stmt, var, to, origin); } + void on_transition (const supernode *node ATTRIBUTE_UNUSED, + const gimple *stmt, + const svalue *var, + state_machine::state_t from, + state_machine::state_t to, + tree origin = NULL_TREE) + { + state_machine::state_t current = get_state (stmt, var); + if (current == from) + set_next_state (stmt, var, to, origin); + } + /* Called by state_machine in response to pattern matches: issue a diagnostic D using NODE and STMT for location information. */ virtual void warn (const supernode *node, const gimple *stmt, @@ -220,6 +243,7 @@ public: { return expr; } + virtual tree get_diagnostic_tree (const svalue *) = 0; virtual state_machine::state_t get_global_state () const = 0; virtual void set_global_state (state_machine::state_t) = 0; diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc index 6c8afef..70c23f0 100644 --- a/gcc/analyzer/svalue.cc +++ b/gcc/analyzer/svalue.cc @@ -557,6 +557,15 @@ svalue::maybe_fold_bits_within (tree, return NULL; } +/* Base implementation of svalue::all_zeroes_p. + Return true if this value is known to be all zeroes. */ + +bool +svalue::all_zeroes_p () const +{ + return false; +} + /* class region_svalue : public svalue. */ /* Implementation of svalue::dump_to_pp vfunc for region_svalue. */ @@ -742,6 +751,14 @@ constant_svalue::maybe_fold_bits_within (tree type, return NULL; } +/* Implementation of svalue::all_zeroes_p for constant_svalue. */ + +bool +constant_svalue::all_zeroes_p () const +{ + return zerop (m_cst_expr); +} + /* class unknown_svalue : public svalue. */ /* Implementation of svalue::dump_to_pp vfunc for unknown_svalue. */ @@ -1154,15 +1171,12 @@ repeated_svalue::accept (visitor *v) const m_inner_svalue->accept (v); } -/* Return true if this value is known to be all zeroes. */ +/* Implementation of svalue::all_zeroes_p for repeated_svalue. */ bool repeated_svalue::all_zeroes_p () const { - if (tree cst = m_inner_svalue->maybe_get_constant ()) - if (zerop (cst)) - return true; - return false; + return m_inner_svalue->all_zeroes_p (); } /* Implementation of svalue::maybe_fold_bits_within vfunc diff --git a/gcc/analyzer/svalue.h b/gcc/analyzer/svalue.h index 3965a5f..5552fcf 100644 --- a/gcc/analyzer/svalue.h +++ b/gcc/analyzer/svalue.h @@ -157,6 +157,8 @@ public: const bit_range &subrange, region_model_manager *mgr) const; + virtual bool all_zeroes_p () const; + protected: svalue (complexity c, tree type) : m_complexity (c), m_type (type) @@ -277,6 +279,8 @@ public: const bit_range &subrange, region_model_manager *mgr) const FINAL OVERRIDE; + bool all_zeroes_p () const FINAL OVERRIDE; + private: tree m_cst_expr; }; @@ -858,7 +862,7 @@ public: const svalue *get_outer_size () const { return m_outer_size; } const svalue *get_inner_svalue () const { return m_inner_svalue; } - bool all_zeroes_p () const; + bool all_zeroes_p () const FINAL OVERRIDE; const svalue * maybe_fold_bits_within (tree type, diff --git a/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c b/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c index f5424f5..7c8d1b3 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c @@ -25,11 +25,8 @@ void test_2 (void *p, void *q) return; foo(p); - /* { dg-warning "pattern match on 'tmp1 == 0'" "tmp1 == 0" { target *-*-* } cond_2 } */ - /* { dg-warning "pattern match on 'tmp2 == 0'" "tmp2 == 0" { target *-*-* } cond_2 } */ - /* { dg-warning "pattern match on ' == 0'" " == 0" { target *-*-* } cond_2 } */ - /* { dg-warning "pattern match on ' != 0'" " != 0" { target *-*-* } cond_2 } */ /* { dg-warning "pattern match on 'p != 0'" "p != 0" { target *-*-* } cond_2 } */ + /* { dg-warning "pattern match on 'tmp1 | tmp2 != 0'" "tmp1 | tmp2 != 0" { target *-*-* } cond_2 } */ /* { dg-warning "pattern match on 'q != 0'" "q != 0" { target *-*-* } cond_2 } */ } @@ -44,10 +41,7 @@ void test_3 (void *p, void *q) return; foo(p); - /* { dg-warning "pattern match on 'tmp1 != 0'" "tmp1 != 0" { target *-*-* } cond_3 } */ - /* { dg-warning "pattern match on 'tmp2 != 0'" "tmp2 != 0" { target *-*-* } cond_3 } */ - /* { dg-warning "pattern match on ' == 0'" " == 0" { target *-*-* } cond_3 } */ - /* { dg-warning "pattern match on ' != 0'" " != 0" { target *-*-* } cond_3 } */ /* { dg-warning "pattern match on 'p == 0'" "p == 0" { target *-*-* } cond_3 } */ + /* { dg-warning "pattern match on 'tmp1 & tmp2 == 0'" "tmp1 & tmp2 == 0" { target *-*-* } cond_3 } */ /* { dg-warning "pattern match on 'q == 0'" "q == 0" { target *-*-* } cond_3 } */ } diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c index 05133d5..61dd490 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c @@ -53,13 +53,6 @@ public: const supernode *node, const gimple *stmt) const FINAL OVERRIDE; - void on_condition (sm_context *sm_ctxt, - const supernode *node, - const gimple *stmt, - tree lhs, - enum tree_code op, - tree rhs) const FINAL OVERRIDE; - bool can_purge_p (state_t s) const FINAL OVERRIDE; void check_for_pyobject_usage_without_gil (sm_context *sm_ctxt, @@ -365,20 +358,6 @@ gil_state_machine::on_stmt (sm_context *sm_ctxt, return false; } -/* Implementation of state_machine::on_condition vfunc for - gil_state_machine. */ - -void -gil_state_machine::on_condition (sm_context *sm_ctxt ATTRIBUTE_UNUSED, - const supernode *node ATTRIBUTE_UNUSED, - const gimple *stmt ATTRIBUTE_UNUSED, - tree lhs ATTRIBUTE_UNUSED, - enum tree_code op ATTRIBUTE_UNUSED, - tree rhs ATTRIBUTE_UNUSED) const -{ - // Empty -} - bool gil_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const { -- cgit v1.1 From c24a97078221fad98d1f48ed9bd1af2094e1a01d Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 8 Jul 2021 00:16:27 +0000 Subject: Daily bump. --- gcc/ChangeLog | 40 ++++++++ gcc/DATESTAMP | 2 +- gcc/ada/ChangeLog | 246 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/analyzer/ChangeLog | 61 ++++++++++++ gcc/testsuite/ChangeLog | 62 ++++++++++++ 5 files changed, 410 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1d07abd..8f06b05 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,43 @@ +2021-07-07 Martin Sebor + + PR tree-optimization/100137 + PR tree-optimization/99121 + PR tree-optimization/97027 + * builtins.c (access_ref::access_ref): Also set offmax. + (access_ref::offset_in_range): Define new function. + (access_ref::add_offset): Set offmax. + (access_ref::inform_access): Handle access_none. + (handle_mem_ref): Clear ostype. + (compute_objsize_r): Handle ASSERT_EXPR. + * builtins.h (struct access_ref): Add offmax member. + * gimple-array-bounds.cc (array_bounds_checker::check_mem_ref): Use + compute_objsize() and simplify. + +2021-07-07 Peter Bergner + + * config/rs6000/rs6000-call.c (mma_init_builtins): Use VSX_BUILTIN_LXVP + and VSX_BUILTIN_STXVP. + +2021-07-07 Martin Sebor + + PR target/101363 + * config/aarch64/aarch64.c (aarch64_simd_lane_bounds): Remove + a stray %K from error_at() missed in r12-2088. + +2021-07-07 Richard Biener + + PR tree-optimization/99728 + * tree-ssa-loop-im.c (gather_mem_refs_stmt): Record + aggregate copies. + (mem_refs_may_alias_p): Add assert we handled aggregate + copies elsewhere. + (sm_seq_valid_bb): Give up when running into aggregate copies. + (ref_indep_loop_p): Handle aggregate copies as never + being invariant themselves but allow other refs to be + disambiguated against them. + (can_sm_ref_p): Do not try to apply store-motion to aggregate + copies. + 2021-07-06 Indu Bhagat PR debug/101283 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index b905321..d944002 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210707 +20210708 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7d17f9e..f04e184 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,249 @@ +2021-07-07 Dmitriy Anisimkov + + * s-oscons-tmplt.c (MSG_WAITALL): Remove wrong #ifdef + __MINWGW32__. + +2021-07-07 Gary Dismukes + + * einfo-utils.adb (Primitive_Operations): Default to returning + Direct_Primitive_Operations in the case of concurrent types + (when Corresponding_Record_Type not present). + * sem_ch9.adb (Analyze_Protected_Type_Declaration): Initialize + Direct_Primitive_Operations to an empty element list. + (Analyze_Task_Type_Declaration): Initialize + Direct_Primitive_Operations to an empty element list. + +2021-07-07 Piotr Trojanek + + * sem_eval.adb (Set_Checking_Potentially_Static_Expression): + Stronger assertion. + +2021-07-07 Arnaud Charlet + + * sem_ch12.adb (Analyze_Subprogram_Instantiation): Mark Anon_Id + intrinsic before calling Analyze_Instance_And_Renamings because + this flag may be propagated to other nodes. + +2021-07-07 Dmitriy Anisimkov + + * s-oscons-tmplt.c (TCP_KEEPCNT TCP_KEEPIDLE, TCP_KEEPINTVL): + Hardcode on Windows if undefined. + +2021-07-07 Bob Duff + + * checks.adb (Install_Primitive_Elaboration_Check): Do not + generate elaboration checks for primitives if pragma Pure or + Preelaborate is present. Misc comment fixes, including + referring to the correct kind of check (elaboration, not + accessibility). + * checks.ads, restrict.adb, sem_cat.ads, sinfo.ads: Minor + reformatting and comment fixes. + +2021-07-07 Piotr Trojanek + + * sem_prag.adb (Analyze_Pragma): Simplify processing of pragma + CPP_Constructor. + +2021-07-07 Arnaud Charlet + + * libgnat/g-debpoo.adb (Code_Address_For_Allocate_End): Default + Initialize. + +2021-07-07 Arnaud Charlet + + * libgnat/s-atocou.ads, libgnat/s-atocou__builtin.adb: Code + cleanups. + +2021-07-07 Gary Dismukes + + * freeze.adb (Check_Inherited_Conditions): Setting of Ekind, + LSP_Subprogram, and Is_Wrapper needs to happen for null + procedures as well as other wrapper cases, so the code is moved + from the else part in front of the if statement. (Fixes a + latent bug encountered while working on this set of changes.) + * sem_attr.adb (Resolve_Attribute): Report an error for the case + of an Access attribute applied to a primitive of an abstract + type when the primitive has any nonstatic Pre'Class or + Post'Class expressions. + * sem_ch8.adb (Analyze_Subprogram_Renaming): Report an error for + the case of a actual subprogram associated with a nonabstract + formal subprogram when the actual is a primitive of an abstract + type and the primitive has any nonstatic Pre'Class or Post'Class + expressions. + * sem_disp.adb (Check_Dispatching_Context): Remove special + testing for null procedures, and replace it with a relaxed test + that avoids getting an error about illegal calls to abstract + subprograms in cases where RM 6.1.1(7/5) applies in + Pre/Post'Class aspects. Also, remove special test for + Postcondition, which seems to be unnecessary, update associated + comments, and fix a typo in one comment. + (Check_Dispatching_Call): Remove an unneeded return statement, + and report an error for the case of a nondispatching call to a + nonabstract subprogram of an abstract type where the subprogram + has nonstatic Pre/Post'Class aspects. + * sem_util.ads + (Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post): New function. + (In_Pre_Post_Condition): Add a flag formal Class_Wide_Only, + defaulted to False, for indicating whether the function should + only test for the node being within class-wide pre- and + postconditions. + * sem_util.adb + (Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post): New function + to determine whether a subprogram is a primitive of an abstract + type where the primitive has class-wide Pre/Post'Class aspects + specified with nonstatic expressions. + (In_Pre_Post_Condition): Extend testing to account for the new + formal Class_Wide_Only. + +2021-07-07 Piotr Trojanek + + * sem_ch12.adb (Check_Shared_Variable_Control_Aspects): Errors + emitted via Check_Volatility_Compatibility are now emitted at + Actual, just like other errors emitted by + Check_Shared_Variable_Control_Aspects. + +2021-07-07 Piotr Trojanek + + * uname.adb (Get_Unit_Name): Simplify with a bounded string + buffer; also, this addresses a ??? comment about the max length + being exceeded. + +2021-07-07 Piotr Trojanek + + * uname.adb (Get_Body_Name, Get_Parent_Body_Name, + Get_Parent_Spec_Name, Get_Spec_Name, Is_Child_Name, + Is_Body_Name, Is_Spec_Name, Name_To_Unit_Name): Use a local + instead of the global buffer. + +2021-07-07 Bob Duff + + * sem_ch13.adb (Analyze_Attribute_Definition_Clause): Combine + processing of Size and Value_Size clauses. Ensure that + Value_Size is treated the same as Size, in the cases where both + are allowed (i.e. the prefix denotes a first subtype). Misc + cleanup. + * einfo-utils.adb (Init_Size): Add assertions. + (Size_Clause): Return a Value_Size clause if present, instead of + just looking for a Size clause. + * einfo.ads (Has_Size_Clause, Size_Clause): Change documentation + to include Value_Size. + * sem_ch13.ads, layout.ads, layout.adb: Comment modifications. + +2021-07-07 Steve Baird + + * exp_dist.adb (Add_RACW_Primitive_Declarations_And_Bodies): Add + TSS_Put_Image to list of predefined primitives that need special + treatment. + (Build_General_Calling_Stubs, Build_Subprogram_Receiving_Stubs): + Remove previous hack for dealing with TSS_Put_Image procedures. + +2021-07-07 Dmitriy Anisimkov + + * libgnat/g-socket.adb (Get_Socket_Option): Add 500ms only when + Minus_500ms_Windows_Timeout is True. + (Set_Socket_Option): Use "* 1000" instead of "/ 0.001" to + convert to milliseconds. + +2021-07-07 Bob Duff + + * tbuild.adb (Unchecked_Convert_To): Set the Parent of the new + node to the Parent of the old node. + * tbuild.ads (Unchecked_Convert_To): Document differences + between Convert_To and Unchecked_Convert_To. The previous + documentation claimed they are identical except for the + uncheckedness of the conversion. + +2021-07-07 Yannick Moy + + * checks.adb (Apply_Scalar_Range_Check): Remove special case for + GNATprove mode. + * sem_res.adb (Resolve_Arithmetic_Op): Same. + * sem_util.adb (Apply_Compile_Time_Constraint_Error): Same. + +2021-07-07 Piotr Trojanek + + * sem_ch6.adb (Check_For_Primitive_Subprogram): Move + declarations of local variables after nested subprogram bodies. + +2021-07-07 Piotr Trojanek + + * exp_disp.adb (CPP_Num_Prims): Reuse List_Length. + +2021-07-07 Piotr Trojanek + + * exp_ch3.adb, exp_ch6.adb, sem_ch6.adb: Replace Ekind + membership test in Private_Kind with a call to Is_Private_Type. + +2021-07-07 Bob Duff + + * gen_il-gen-gen_entities.adb: Remove Linker_Section_Pragma + field from Record_Field_Kind. Minor comment improvement. + +2021-07-07 Yannick Moy + + * libgnat/a-ngelfu.ads (Cot): Fix precondition. + +2021-07-07 Piotr Trojanek + + * par.adb (Par): A local Name variable is now a renaming of a + constant slice. + +2021-07-07 Piotr Trojanek + + * gnat1drv.adb (Gnat1drv): Remove flagging of main unit and its + corresponding spec as requiring code generation; now the flags + are set much earlier. + * lib-load.adb (Load_Main_Source): Set Generate_Code flag on the + main unit source. + (Make_Instance_Unit): Copy Generate_Code flag from the main unit + to instance units. + * lib-writ.adb (Write_ALI): Remove redundant condition; + Generate_Code flag is always set for the main unit. + * par-load.adb (Load): Set Generate_Code flag on the main unit's + corresponding spec, if any. + +2021-07-07 Dmitriy Anisimkov + + * libgnat/g-socket.ads (Option_Name): Add Keep_Alive_Count, + Keep_Alive_Idle, and Keep_Alive_Interval items to enumeration. + (Option_Type): Add Keep_Alive_Count, Keep_Alive_Idle, and + Keep_Alive_Interval alternatives to the case of discriminated + record. + * libgnat/g-socket.adb (Options): Add Keep_Alive_Count, + Keep_Alive_Idle, and Keep_Alive_Interval to items enumerator to + OS constant converter. + (Set_Socket_Option): Process Keep_Alive_Count, Keep_Alive_Idle, + and Keep_Alive_Interval socket options. + (Get_Socket_Option): Idem. + +2021-07-07 Piotr Trojanek + + * lib-writ.adb (Write_ALI): Exit from loop after seeing first + unit that violates No_Elaboration_Code restriction. + +2021-07-07 Piotr Trojanek + + * inline.adb (Instantiate_Bodies): Fix white in declaration. + (Remove_Dead_Instance): Change iteration from WHILE to FOR. + +2021-07-07 Bob Duff + + * checks.adb, exp_attr.adb, exp_ch4.adb, exp_ch6.adb, + exp_ch9.adb, exp_disp.adb, exp_util.adb, inline.adb, + sem_res.adb: Change all calls to Make_Unchecked_Type_Conversion + to call Unchecked_Convert_To instead. This involves removing + New_Occurrence_Of on the first parameter, because + Unchecked_Convert_To expects a type entity, rather than the name + of one. Also, removed calls to Relocate_Node, because + Unchecked_Convert_To takes care of that. + * sinfo.ads: Change comment to be worded more firmly. + +2021-07-07 Steve Baird + + * libgnarl/s-tassta.adb (Free_Task): Acquire the Task_Lock + before, rather than after, querying the task's Terminated flag. + Add a corresponding Task_Unlock call. + 2021-07-06 Bob Duff * atree.ads (Current_Error_Node): Initialize to Empty. diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index bb9f4d3..f0b2d96 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,64 @@ +2021-07-07 David Malcolm + + * diagnostic-manager.cc (null_assignment_sm_context::get_state): + New overload. + (null_assignment_sm_context::set_next_state): New overload. + (null_assignment_sm_context::get_diagnostic_tree): New. + * engine.cc (impl_sm_context::get_state): New overload. + (impl_sm_context::set_next_state): New overload. + (impl_sm_context::get_diagnostic_tree): New overload. + (impl_region_model_context::on_condition): Convert params from + tree to const svalue *. + * exploded-graph.h (impl_region_model_context::on_condition): + Likewise. + * region-model.cc (region_model::on_call_pre): Move handling of + internal calls to before checking for get_fndecl_for_call. + (region_model::add_constraints_from_binop): New. + (region_model::add_constraint): Split out into a new overload + working on const svalue * rather than tree. Call + add_constraints_from_binop. Drop call to + add_any_constraints_from_ssa_def_stmt. + (region_model::add_any_constraints_from_ssa_def_stmt): Delete. + (region_model::add_any_constraints_from_gassign): Delete. + (region_model::add_any_constraints_from_gcall): Delete. + * region-model.h + (region_model::add_any_constraints_from_ssa_def_stmt): Delete. + (region_model::add_any_constraints_from_gassign): Delete. + (region_model::add_any_constraints_from_gcall): Delete. + (region_model::add_constraint): Add overload decl. + (region_model::add_constraints_from_binop): New decl. + (region_model_context::on_condition): Convert params from tree to + const svalue *. + (noop_region_model_context::on_condition): Likewise. + * sm-file.cc (fileptr_state_machine::condition): Likewise. + * sm-malloc.cc (malloc_state_machine::on_condition): Likewise. + * sm-pattern-test.cc: Include tristate.h, selftest.h, + analyzer/call-string.h, analyzer/program-point.h, + analyzer/store.h, and analyzer/region-model.h. + (pattern_test_state_machine::on_condition): Convert params from tree to + const svalue *. + * sm-sensitive.cc (sensitive_state_machine::on_condition): Delete. + * sm-signal.cc (signal_state_machine::on_condition): Delete. + * sm-taint.cc (taint_state_machine::on_condition): Convert params + from tree to const svalue *. + * sm.cc: Include tristate.h, selftest.h, analyzer/call-string.h, + analyzer/program-point.h, analyzer/store.h, and + analyzer/region-model.h. + (any_pointer_p): Add overload taking const svalue *sval. + * sm.h (any_pointer_p): Add overload taking const svalue *sval. + (state_machine::on_condition): Convert params from tree to + const svalue *. Provide no-op default implementation. + (sm_context::get_state): Add overload taking const svalue *sval. + (sm_context::set_next_state): Likewise. + (sm_context::on_transition): Likewise. + (sm_context::get_diagnostic_tree): Likewise. + * svalue.cc (svalue::all_zeroes_p): New. + (constant_svalue::all_zeroes_p): New. + (repeated_svalue::all_zeroes_p): Convert to vfunc. + * svalue.h (svalue::all_zeroes_p): New decl. + (constant_svalue::all_zeroes_p): New decl. + (repeated_svalue::all_zeroes_p): Convert decl to vfunc. + 2021-06-30 David Malcolm PR analyzer/95006 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7e2e6b3..5543edb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,65 @@ +2021-07-07 David Malcolm + + * gcc.dg/analyzer/pattern-test-2.c: Update expected results. + * gcc.dg/plugin/analyzer_gil_plugin.c + (gil_state_machine::on_condition): Remove. + +2021-07-07 Martin Sebor + + PR tree-optimization/100137 + PR tree-optimization/99121 + PR tree-optimization/97027 + * c-c++-common/Warray-bounds-3.c: Remove xfail + * c-c++-common/Warray-bounds-4.c: Add an expected warning. + * c-c++-common/Warray-bounds-9.c: New test. + * c-c++-common/Warray-bounds-10.c: New test. + * g++.dg/asan/asan_test.C: Suppress expected warnings. + * g++.dg/pr95768.C: Same. + * g++.dg/warn/Warray-bounds-10.C: Adjust text of expected messages. + * g++.dg/warn/Warray-bounds-11.C: Same. + * g++.dg/warn/Warray-bounds-12.C: Same. + * g++.dg/warn/Warray-bounds-13.C: Same. + * g++.dg/warn/Warray-bounds-17.C: Same. + * g++.dg/warn/Warray-bounds-20.C: Same. + * gcc.dg/Warray-bounds-29.c: Same. + * gcc.dg/Warray-bounds-30.c: Add xfail. + * gcc.dg/Warray-bounds-31.c: Adjust text of expected messages. + * gcc.dg/Warray-bounds-32.c: Same. + * gcc.dg/Warray-bounds-52.c: Same. + * gcc.dg/Warray-bounds-53.c: Same. + * gcc.dg/Warray-bounds-58.c: Remove xfail. + * gcc.dg/Warray-bounds-63.c: Adjust text of expected messages. + * gcc.dg/Warray-bounds-66.c: Same. + * gcc.dg/Warray-bounds-69.c: Same. + * gcc.dg/Wstringop-overflow-34.c: Same. + * gcc.dg/Wstringop-overflow-47.c: Same. + * gcc.dg/Wstringop-overflow-61.c: Same. + * gcc.dg/Warray-bounds-77.c: New test. + * gcc.dg/Warray-bounds-78.c: New test. + * gcc.dg/Warray-bounds-79.c: New test. + +2021-07-07 Christophe Lyon + + PR debug/101321 + * gcc.dg/debug/btf/btf-bitfields-3.c: Remove -fno-short-enums. + +2021-07-07 Richard Biener + + PR tree-optimization/34195 + * gcc.dg/vect/pr34195.c: New testcase. + +2021-07-07 Richard Biener + + PR tree-optimization/99728 + * g++.dg/opt/pr99728.C: New testcase. + +2021-07-07 liuhongt + + * gcc.target/i386/avx512f-vect-fmaddsubXXXpd.c: New test. + * gcc.target/i386/avx512f-vect-fmaddsubXXXps.c: New test. + * gcc.target/i386/avx512f-vect-fmsubaddXXXpd.c: New test. + * gcc.target/i386/avx512f-vect-fmsubaddXXXps.c: New test. + 2021-07-06 Indu Bhagat PR debug/101283 -- cgit v1.1 From 852b11da11a181df517c0348df044354ff0656d6 Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Wed, 7 Jul 2021 21:55:38 -0400 Subject: Generate 128-bit int divide/modulus on power10. This patch adds support for the VDIVSQ, VDIVUQ, VMODSQ, and VMODUQ instructions to do 128-bit arithmetic. 2021-07-07 Michael Meissner gcc/ PR target/100809 * config/rs6000/rs6000.md (udivti3): New insn. (divti3): New insn. (umodti3): New insn. (modti3): New insn. gcc/testsuite/ PR target/100809 * gcc.target/powerpc/p10-vdivq-vmodq.c: New test. --- gcc/config/rs6000/rs6000.md | 34 ++++++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/p10-vdivq-vmodq.c | 27 +++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 gcc/testsuite/gcc.target/powerpc/p10-vdivq-vmodq.c (limited to 'gcc') diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index e84d031..2368153 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -3234,6 +3234,14 @@ [(set_attr "type" "div") (set_attr "size" "")]) +(define_insn "udivti3" + [(set (match_operand:TI 0 "altivec_register_operand" "=v") + (udiv:TI (match_operand:TI 1 "altivec_register_operand" "v") + (match_operand:TI 2 "altivec_register_operand" "v")))] + "TARGET_POWER10 && TARGET_POWERPC64" + "vdivuq %0,%1,%2" + [(set_attr "type" "vecdiv") + (set_attr "size" "128")]) ;; For powers of two we can do sra[wd]i/addze for divide and then adjust for ;; modulus. If it isn't a power of two, force operands into register and do @@ -3324,6 +3332,15 @@ (set_attr "length" "8,12") (set_attr "cell_micro" "not")]) +(define_insn "divti3" + [(set (match_operand:TI 0 "altivec_register_operand" "=v") + (div:TI (match_operand:TI 1 "altivec_register_operand" "v") + (match_operand:TI 2 "altivec_register_operand" "v")))] + "TARGET_POWER10 && TARGET_POWERPC64" + "vdivsq %0,%1,%2" + [(set_attr "type" "vecdiv") + (set_attr "size" "128")]) + (define_expand "mod3" [(set (match_operand:GPR 0 "gpc_reg_operand") (mod:GPR (match_operand:GPR 1 "gpc_reg_operand") @@ -3424,6 +3441,23 @@ (minus:GPR (match_dup 1) (match_dup 3)))]) +(define_insn "umodti3" + [(set (match_operand:TI 0 "altivec_register_operand" "=v") + (umod:TI (match_operand:TI 1 "altivec_register_operand" "v") + (match_operand:TI 2 "altivec_register_operand" "v")))] + "TARGET_POWER10 && TARGET_POWERPC64" + "vmoduq %0,%1,%2" + [(set_attr "type" "vecdiv") + (set_attr "size" "128")]) + +(define_insn "modti3" + [(set (match_operand:TI 0 "altivec_register_operand" "=v") + (mod:TI (match_operand:TI 1 "altivec_register_operand" "v") + (match_operand:TI 2 "altivec_register_operand" "v")))] + "TARGET_POWER10 && TARGET_POWERPC64" + "vmodsq %0,%1,%2" + [(set_attr "type" "vecdiv") + (set_attr "size" "128")]) ;; Logical instructions ;; The logical instructions are mostly combined by using match_operator, diff --git a/gcc/testsuite/gcc.target/powerpc/p10-vdivq-vmodq.c b/gcc/testsuite/gcc.target/powerpc/p10-vdivq-vmodq.c new file mode 100644 index 0000000..84685e5 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/p10-vdivq-vmodq.c @@ -0,0 +1,27 @@ +/* { dg-require-effective-target int128 } */ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ + +unsigned __int128 u_div(unsigned __int128 a, unsigned __int128 b) +{ + return a/b; +} + +unsigned __int128 u_mod(unsigned __int128 a, unsigned __int128 b) +{ + return a%b; +} +__int128 s_div(__int128 a, __int128 b) +{ + return a/b; +} + +__int128 s_mod(__int128 a, __int128 b) +{ + return a%b; +} + +/* { dg-final { scan-assembler {\mvdivsq\M} } } */ +/* { dg-final { scan-assembler {\mvdivuq\M} } } */ +/* { dg-final { scan-assembler {\mvmodsq\M} } } */ +/* { dg-final { scan-assembler {\mvmoduq\M} } } */ -- cgit v1.1 From 663a014e77709bfbd4145c605b178169eaf334fc Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 8 Jul 2021 12:19:54 +0200 Subject: i386: Add pack/unpack patterns for 32bit vectors [PR100637] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit V1SI mode shift is needed to shift 32bit operands and consequently we need to implement V1SI moves and pushes. 2021-07-08 Uroš Bizjak gcc/ PR target/100637 * config/i386/i386-expand.c (ix86_expand_sse_unpack): Handle V4QI mode. * config/i386/mmx.md (V_32): New mode iterator. (mov): Use V_32 mode iterator. (*mov_internal): Ditto. (*push2_rex64): Ditto. (*push2): Ditto. (movmisalign): Ditto. (mmx_v1si3): New insn pattern. (sse4_1_v2qiv2hi2): Ditto. (vec_unpacks_lo_v4qi): New expander. (vec_unpacks_hi_v4qi): Ditto. (vec_unpacku_lo_v4qi): Ditto. (vec_unpacku_hi_v4qi): Ditto. * config/i386/i386.h (VALID_SSE2_REG_MODE): Add V1SImode. (VALID_INT_MODE_P): Ditto. --- gcc/config/i386/i386-expand.c | 18 ++++++++ gcc/config/i386/i386.h | 4 +- gcc/config/i386/mmx.md | 100 +++++++++++++++++++++++++++++++++++------- 3 files changed, 105 insertions(+), 17 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index 58c208e..65764ad 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -5355,6 +5355,12 @@ ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p) else unpack = gen_sse4_1_sign_extendv2hiv2si2; break; + case E_V4QImode: + if (unsigned_p) + unpack = gen_sse4_1_zero_extendv2qiv2hi2; + else + unpack = gen_sse4_1_sign_extendv2qiv2hi2; + break; default: gcc_unreachable (); } @@ -5380,6 +5386,12 @@ ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p) emit_insn (gen_mmx_lshrv1di3 (tmp, gen_lowpart (V1DImode, src), GEN_INT (32))); break; + case 4: + /* Shift higher 2 bytes to lower 2 bytes. */ + tmp = gen_reg_rtx (V1SImode); + emit_insn (gen_mmx_lshrv1si3 (tmp, gen_lowpart (V1SImode, src), + GEN_INT (16))); + break; default: gcc_unreachable (); } @@ -5427,6 +5439,12 @@ ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p) else unpack = gen_mmx_punpcklwd; break; + case E_V4QImode: + if (high_p) + unpack = gen_mmx_punpckhbw_low; + else + unpack = gen_mmx_punpcklbw_low; + break; default: gcc_unreachable (); } diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 03d1761..8c3eace 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1016,7 +1016,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define VALID_SSE2_REG_MODE(MODE) \ ((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode \ - || (MODE) == V4QImode || (MODE) == V2HImode \ + || (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode \ || (MODE) == V2DImode || (MODE) == DFmode) #define VALID_SSE_REG_MODE(MODE) \ @@ -1048,7 +1048,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); || (MODE) == SImode || (MODE) == DImode \ || (MODE) == CQImode || (MODE) == CHImode \ || (MODE) == CSImode || (MODE) == CDImode \ - || (MODE) == V4QImode || (MODE) == V2HImode \ + || (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode \ || (TARGET_64BIT \ && ((MODE) == TImode || (MODE) == CTImode \ || (MODE) == TFmode || (MODE) == TCmode \ diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index 7e83b64..986b758 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -57,10 +57,13 @@ (define_mode_iterator MMXMODE24 [V4HI V2SI]) (define_mode_iterator MMXMODE248 [V4HI V2SI V1DI]) -;; All 32bit integer vector modes +;; All 4-byte integer vector modes +(define_mode_iterator V_32 [V4QI V2HI V1SI]) + +;; 4-byte integer vector modes (define_mode_iterator VI_32 [V4QI V2HI]) -;; All V2S* modes +;; V2S* modes (define_mode_iterator V2FI [V2SF V2SI]) ;; Mapping from integer vector mode to mnemonic suffix @@ -238,8 +241,8 @@ }) (define_expand "mov" - [(set (match_operand:VI_32 0 "nonimmediate_operand") - (match_operand:VI_32 1 "nonimmediate_operand"))] + [(set (match_operand:V_32 0 "nonimmediate_operand") + (match_operand:V_32 1 "nonimmediate_operand"))] "TARGET_SSE2" { ix86_expand_vector_move (mode, operands); @@ -247,9 +250,9 @@ }) (define_insn "*mov_internal" - [(set (match_operand:VI_32 0 "nonimmediate_operand" + [(set (match_operand:V_32 0 "nonimmediate_operand" "=r ,m ,v,v,v,m,r,v") - (match_operand:VI_32 1 "general_operand" + (match_operand:V_32 1 "general_operand" "rmC,rC,C,v,m,v,v,r"))] "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))" @@ -304,8 +307,8 @@ ;; For TARGET_64BIT we always round up to 8 bytes. (define_insn "*push2_rex64" - [(set (match_operand:VI_32 0 "push_operand" "=X,X") - (match_operand:VI_32 1 "nonmemory_no_elim_operand" "rC,*v"))] + [(set (match_operand:V_32 0 "push_operand" "=X,X") + (match_operand:V_32 1 "nonmemory_no_elim_operand" "rC,*v"))] "TARGET_SSE2 && TARGET_64BIT" "@ push{q}\t%q1 @@ -314,8 +317,8 @@ (set_attr "mode" "DI")]) (define_insn "*push2" - [(set (match_operand:VI_32 0 "push_operand" "=<,<") - (match_operand:VI_32 1 "general_no_elim_operand" "rC*m,*v"))] + [(set (match_operand:V_32 0 "push_operand" "=<,<") + (match_operand:V_32 1 "general_no_elim_operand" "rC*m,*v"))] "TARGET_SSE2 && !TARGET_64BIT" "@ push{l}\t%1 @@ -324,20 +327,20 @@ (set_attr "mode" "SI")]) (define_split - [(set (match_operand:VI_32 0 "push_operand") - (match_operand:VI_32 1 "sse_reg_operand"))] + [(set (match_operand:V_32 0 "push_operand") + (match_operand:V_32 1 "sse_reg_operand"))] "TARGET_SSE2 && reload_completed" [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2))) (set (match_dup 0) (match_dup 1))] { - operands[2] = GEN_INT (-PUSH_ROUNDING (GET_MODE_SIZE (mode))); + operands[2] = GEN_INT (-PUSH_ROUNDING (GET_MODE_SIZE (mode))); /* Preserve memory attributes. */ operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx); }) (define_expand "movmisalign" - [(set (match_operand:VI_32 0 "nonimmediate_operand") - (match_operand:VI_32 1 "nonimmediate_operand"))] + [(set (match_operand:V_32 0 "nonimmediate_operand") + (match_operand:V_32 1 "nonimmediate_operand"))] "TARGET_SSE2" { ix86_expand_vector_move (mode, operands); @@ -2006,6 +2009,23 @@ (match_operand:DI 2 "nonmemory_operand")))] "TARGET_MMX_WITH_SSE") +(define_insn "mmx_v1si3" + [(set (match_operand:V1SI 0 "register_operand" "=x,Yw") + (any_lshift:V1SI + (match_operand:V1SI 1 "register_operand" "0,Yw") + (match_operand:DI 2 "nonmemory_operand" "xN,YwN")))] + "TARGET_SSE2" + "@ + pd\t{%2, %0|%0, %2} + vpd\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "noavx,avx") + (set_attr "type" "sseishft") + (set (attr "length_immediate") + (if_then_else (match_operand 2 "const_int_operand") + (const_string "1") + (const_string "0"))) + (set_attr "mode" "TI")]) + (define_insn "v2hi3" [(set (match_operand:V2HI 0 "register_operand" "=x,Yw") (any_shift:V2HI @@ -2732,6 +2752,20 @@ (set_attr "prefix" "orig,orig,maybe_evex") (set_attr "mode" "TI")]) +(define_insn "sse4_1_v2qiv2hi2" + [(set (match_operand:V2HI 0 "register_operand" "=Yr,*x,Yw") + (any_extend:V2HI + (vec_select:V2QI + (match_operand:V4QI 1 "register_operand" "Yr,*x,Yw") + (parallel [(const_int 0) (const_int 1)]))))] + "TARGET_SSE4_1" + "%vpmovbw\t{%1, %0|%0, %1}" + [(set_attr "isa" "noavx,noavx,avx") + (set_attr "type" "ssemov") + (set_attr "prefix_extra" "1") + (set_attr "prefix" "orig,orig,maybe_evex") + (set_attr "mode" "TI")]) + ;; Pack/unpack vector modes (define_mode_attr mmxpackmode [(V4HI "V8QI") (V2SI "V4HI")]) @@ -2748,6 +2782,18 @@ DONE; }) +(define_expand "vec_pack_trunc_v2hi" + [(match_operand:V4QI 0 "register_operand") + (match_operand:V2HI 1 "register_operand") + (match_operand:V2HI 2 "register_operand")] + "TARGET_SSE2" +{ + rtx op1 = gen_lowpart (V4QImode, operands[1]); + rtx op2 = gen_lowpart (V4QImode, operands[2]); + ix86_expand_vec_extract_even_odd (operands[0], op1, op2, 0); + DONE; +}) + (define_mode_attr mmxunpackmode [(V8QI "V4HI") (V4HI "V2SI")]) @@ -2775,6 +2821,30 @@ "TARGET_MMX_WITH_SSE" "ix86_expand_sse_unpack (operands[0], operands[1], true, true); DONE;") +(define_expand "vec_unpacks_lo_v4qi" + [(match_operand:V2HI 0 "register_operand") + (match_operand:V4QI 1 "register_operand")] + "TARGET_SSE2" + "ix86_expand_sse_unpack (operands[0], operands[1], false, false); DONE;") + +(define_expand "vec_unpacks_hi_v4qi" + [(match_operand:V2HI 0 "register_operand") + (match_operand:V4QI 1 "register_operand")] + "TARGET_SSE2" + "ix86_expand_sse_unpack (operands[0], operands[1], false, true); DONE;") + +(define_expand "vec_unpacku_lo_v4qi" + [(match_operand:V2HI 0 "register_operand") + (match_operand:V4QI 1 "register_operand")] + "TARGET_SSE2" + "ix86_expand_sse_unpack (operands[0], operands[1], true, false); DONE;") + +(define_expand "vec_unpacku_hi_v4qi" + [(match_operand:V2HI 0 "register_operand") + (match_operand:V4QI 1 "register_operand")] + "TARGET_SSE2" + "ix86_expand_sse_unpack (operands[0], operands[1], true, true); DONE;") + (define_insn "*mmx_pinsrd" [(set (match_operand:V2SI 0 "register_operand" "=x,Yv") (vec_merge:V2SI -- cgit v1.1 From 4c619132b3f14dc5e672a7f2f0e09cb784193559 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Thu, 8 Jul 2021 11:46:14 +0100 Subject: PR tree-optimization/40210: Fold (bswap(X)>>C1)&C2 to (X>>C3)&C2 in match.pd All of the optimizations/transformations mentioned in bugzilla for PR tree-optimization/40210 are already implemented in mainline GCC, with one exception. In comment #5, there's a suggestion that (bswap64(x)>>56)&0xff can be implemented without the bswap as (unsigned char)x, or equivalently x&0xff. This patch implements the above optimization, and closely related variants. For any single bit, (bswap(X)>>C1)&1 can be simplified to (X>>C2)&1, where bit position C2 is the appropriate permutation of C1. Similarly, the bswap can eliminated if the desired set of bits all lie within the same byte, hence (bswap(x)>>8)&255 can always be optimized, as can (bswap(x)>>8)&123. Previously, int foo(long long x) { return (__builtin_bswap64(x) >> 56) & 0xff; } compiled with -O2 to foo: movq %rdi, %rax bswap %rax shrq $56, %rax ret with this patch, it now compiles to foo: movzbl %dil, %eax ret 2021-07-08 Roger Sayle Richard Biener gcc/ChangeLog PR tree-optimization/40210 * match.pd (bswap optimizations): Simplify (bswap(x)>>C1)&C2 as (x>>C3)&C2 when possible. Simplify bswap(x)>>C1 as ((T)x)>>C2 when possible. Simplify bswap(x)&C1 as (x>>C2)&C1 when 0<=C1<=255. gcc/testsuite/ChangeLog PR tree-optimization/40210 * gcc.dg/builtin-bswap-13.c: New test. * gcc.dg/builtin-bswap-14.c: New test. --- gcc/match.pd | 68 ++++++- gcc/testsuite/gcc.dg/builtin-bswap-13.c | 329 ++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/builtin-bswap-14.c | 302 +++++++++++++++++++++++++++++ 3 files changed, 697 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/builtin-bswap-13.c create mode 100644 gcc/testsuite/gcc.dg/builtin-bswap-14.c (limited to 'gcc') diff --git a/gcc/match.pd b/gcc/match.pd index 72860fb..334e8cc 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3610,7 +3610,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (complex (convert:itype @0) (negate (convert:itype @1))))) /* BSWAP simplifications, transforms checked by gcc.dg/builtin-bswap-8.c. */ -(for bswap (BUILT_IN_BSWAP16 BUILT_IN_BSWAP32 BUILT_IN_BSWAP64) +(for bswap (BUILT_IN_BSWAP16 BUILT_IN_BSWAP32 + BUILT_IN_BSWAP64 BUILT_IN_BSWAP128) (simplify (bswap (bswap @0)) @0) @@ -3620,7 +3621,70 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (for bitop (bit_xor bit_ior bit_and) (simplify (bswap (bitop:c (bswap @0) @1)) - (bitop @0 (bswap @1))))) + (bitop @0 (bswap @1)))) + /* (bswap(x) >> C1) & C2 can sometimes be simplified to (x >> C3) & C2. */ + (simplify + (bit_and (convert1? (rshift@0 (convert2? (bswap@4 @1)) INTEGER_CST@2)) + INTEGER_CST@3) + (if (BITS_PER_UNIT == 8 + && tree_fits_uhwi_p (@2) + && tree_fits_uhwi_p (@3)) + (with + { + unsigned HOST_WIDE_INT prec = TYPE_PRECISION (TREE_TYPE (@4)); + unsigned HOST_WIDE_INT bits = tree_to_uhwi (@2); + unsigned HOST_WIDE_INT mask = tree_to_uhwi (@3); + unsigned HOST_WIDE_INT lo = bits & 7; + unsigned HOST_WIDE_INT hi = bits - lo; + } + (if (bits < prec + && mask < (256u>>lo) + && bits < TYPE_PRECISION (TREE_TYPE(@0))) + (with { unsigned HOST_WIDE_INT ns = (prec - (hi + 8)) + lo; } + (if (ns == 0) + (bit_and (convert @1) @3) + (with + { + tree utype = unsigned_type_for (TREE_TYPE (@1)); + tree nst = build_int_cst (integer_type_node, ns); + } + (bit_and (convert (rshift:utype (convert:utype @1) {nst;})) @3)))))))) + /* bswap(x) >> C1 can sometimes be simplified to (T)x >> C2. */ + (simplify + (rshift (convert? (bswap@2 @0)) INTEGER_CST@1) + (if (BITS_PER_UNIT == 8 + && CHAR_TYPE_SIZE == 8 + && tree_fits_uhwi_p (@1)) + (with + { + unsigned HOST_WIDE_INT prec = TYPE_PRECISION (TREE_TYPE (@2)); + unsigned HOST_WIDE_INT bits = tree_to_uhwi (@1); + } + (if (bits + 8 == prec) + (if (TYPE_UNSIGNED (type)) + (convert (convert:unsigned_char_type_node @0)) + (convert (convert:signed_char_type_node @0))) + (if (bits < prec && bits + 8 > prec) + (with + { + tree nst = build_int_cst (integer_type_node, bits & 7); + tree bt = TYPE_UNSIGNED (type) ? unsigned_char_type_node + : signed_char_type_node; + } + (convert (rshift:bt (convert:bt @0) {nst;})))))))) + /* bswap(x) & C1 can sometimes be simplified to (x >> C2) & C1. */ + (simplify + (bit_and (convert? (bswap@2 @0)) INTEGER_CST@1) + (if (BITS_PER_UNIT == 8 + && tree_fits_uhwi_p (@1) + && tree_to_uhwi (@1) < 256) + (with + { + unsigned HOST_WIDE_INT prec = TYPE_PRECISION (TREE_TYPE (@2)); + tree utype = unsigned_type_for (TREE_TYPE (@0)); + tree nst = build_int_cst (integer_type_node, prec - 8); + } + (bit_and (convert (rshift:utype (convert:utype @0) {nst;})) @1))))) /* Combine COND_EXPRs and VEC_COND_EXPRs. */ diff --git a/gcc/testsuite/gcc.dg/builtin-bswap-13.c b/gcc/testsuite/gcc.dg/builtin-bswap-13.c new file mode 100644 index 0000000..6dc4c15 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-bswap-13.c @@ -0,0 +1,329 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int test_s32_0_1(int x) { return __builtin_bswap32(x) & 1; } +int test_s32_0_2(int x) { return __builtin_bswap32(x) & 2; } +int test_s32_0_240(int x) { return __builtin_bswap32(x) & 240; } +int test_s32_0_255(int x) { return __builtin_bswap32(x) & 255; } +int test_s32_1_1(int x) { return (__builtin_bswap32(x) >> 1) & 1; } +int test_s32_7_1(int x) { return (__builtin_bswap32(x) >> 7) & 1; } +int test_s32_8_1(int x) { return (__builtin_bswap32(x) >> 8) & 1; } +int test_s32_8_240(int x) { return (__builtin_bswap32(x) >> 8) & 240; } +int test_s32_8_255(int x) { return (__builtin_bswap32(x) >> 8) & 255; } +int test_s32_15_1(int x) { return (__builtin_bswap32(x) >> 15) & 1; } +int test_s32_16_1(int x) { return (__builtin_bswap32(x) >> 16) & 1; } +int test_s32_16_240(int x) { return (__builtin_bswap32(x) >> 16) & 240; } +int test_s32_16_255(int x) { return (__builtin_bswap32(x) >> 16) & 255; } +int test_s32_24_1(int x) { return (__builtin_bswap32(x) >> 24) & 1; } +int test_s32_24_240(int x) { return (__builtin_bswap32(x) >> 24) & 240; } +int test_s32_24_255(int x) { return (__builtin_bswap32(x) >> 24) & 255; } +int test_s32_31_1(int x) { return (__builtin_bswap32(x) >> 31) & 1; } + +int test_S32_0_1(int x) { return (int)__builtin_bswap32(x) & 1; } +int test_S32_0_2(int x) { return (int)__builtin_bswap32(x) & 2; } +int test_S32_0_240(int x) { return (int)__builtin_bswap32(x) & 240; } +int test_S32_0_255(int x) { return (int)__builtin_bswap32(x) & 255; } +int test_S32_1_1(int x) { return ((int)__builtin_bswap32(x) >> 1) & 1; } +int test_S32_7_1(int x) { return ((int)__builtin_bswap32(x) >> 7) & 1; } +int test_S32_8_1(int x) { return ((int)__builtin_bswap32(x) >> 8) & 1; } +int test_S32_8_240(int x) { return ((int)__builtin_bswap32(x) >> 8) & 240; } +int test_S32_8_255(int x) { return ((int)__builtin_bswap32(x) >> 8) & 255; } +int test_S32_15_1(int x) { return ((int)__builtin_bswap32(x) >> 15) & 1; } +int test_S32_16_1(int x) { return ((int)__builtin_bswap32(x) >> 16) & 1; } +int test_S32_16_240(int x) { return ((int)__builtin_bswap32(x) >> 16) & 240; } +int test_S32_16_255(int x) { return ((int)__builtin_bswap32(x) >> 16) & 255; } +int test_S32_24_1(int x) { return ((int)__builtin_bswap32(x) >> 24) & 1; } +int test_S32_24_240(int x) { return ((int)__builtin_bswap32(x) >> 24) & 240; } +int test_S32_24_255(int x) { return ((int)__builtin_bswap32(x) >> 24) & 255; } +int test_S32_31_1(int x) { return ((int)__builtin_bswap32(x) >> 31) & 1; } + +unsigned int test_u32_24_255(unsigned int x) { + return (__builtin_bswap32(x) >> 24) & 255; +} + +long long test_s64_0_1(long long x) { + return __builtin_bswap64(x) & 1; +} +long long test_s64_0_2(long long x) { + return __builtin_bswap64(x) & 2; +} +long long test_s64_0_240(long long x) { + return __builtin_bswap64(x) & 240; +} +long long test_s64_0_255(long long x) { + return __builtin_bswap64(x) & 255; +} +long long test_s64_7_1(long long x) { + return (__builtin_bswap64(x) >> 7) & 1; +} +long long test_s64_8_1(long long x) { + return (__builtin_bswap64(x) >> 8) & 1; +} +long long test_s64_8_240(long long x) { + return (__builtin_bswap64(x) >> 56) & 240; +} +long long test_s64_8_255(long long x) { + return (__builtin_bswap64(x) >> 8) & 255; +} +long long test_s64_9_1(long long x) { + return (__builtin_bswap64(x) >> 9) & 1; +} +long long test_s64_31_1(long long x) { + return (__builtin_bswap64(x) >> 31) & 1; +} +long long test_s64_32_1(long long x) { + return (__builtin_bswap64(x) >> 32) & 1; +} +long long test_s64_32_240(long long x) { + return (__builtin_bswap64(x) >> 32) & 240; +} +long long test_s64_32_255(long long x) { + return (__builtin_bswap64(x) >> 32) & 255; +} +long long test_s64_33_1(long long x) { + return (__builtin_bswap64(x) >> 33) & 1; +} +long long test_s64_48_1(long long x) { + return (__builtin_bswap64(x) >> 48) & 1; +} +long long test_s64_48_240(long long x) { + return (__builtin_bswap64(x) >> 48) & 240; +} +long long test_s64_48_255(long long x) { + return (__builtin_bswap64(x) >> 48) & 255; +} +long long test_s64_56_1(long long x) { + return (__builtin_bswap64(x) >> 56) & 1; +} +long long test_s64_56_240(long long x) { + return (__builtin_bswap64(x) >> 56) & 240; +} +long long test_s64_56_255(long long x) { + return (__builtin_bswap64(x) >> 56) & 255; +} +long long test_s64_57_1(long long x) { + return (__builtin_bswap64(x) >> 57) & 1; +} +long long test_s64_63_1(long long x) { + return (__builtin_bswap64(x) >> 63) & 1; +} + +long long test_S64_0_1(long long x) { + return (long long)__builtin_bswap64(x) & 1; +} +long long test_S64_0_2(long long x) { + return (long long)__builtin_bswap64(x) & 2; +} +long long test_S64_0_240(long long x) { + return (long long)__builtin_bswap64(x) & 240; +} +long long test_S64_0_255(long long x) { + return (long long)__builtin_bswap64(x) & 255; +} +long long test_S64_7_1(long long x) { + return ((long long)__builtin_bswap64(x) >> 7) & 1; +} +long long test_S64_8_1(long long x) { + return ((long long)__builtin_bswap64(x) >> 8) & 1; +} +long long test_S64_8_240(long long x) { + return ((long long)__builtin_bswap64(x) >> 56) & 240; +} +long long test_S64_8_255(long long x) { + return ((long long)__builtin_bswap64(x) >> 8) & 255; +} +long long test_S64_9_1(long long x) { + return ((long long)__builtin_bswap64(x) >> 9) & 1; +} +long long test_S64_31_1(long long x) { + return ((long long)__builtin_bswap64(x) >> 31) & 1; +} +long long test_S64_32_1(long long x) { + return ((long long)__builtin_bswap64(x) >> 32) & 1; +} +long long test_S64_32_240(long long x) { + return ((long long)__builtin_bswap64(x) >> 32) & 240; +} +long long test_S64_32_255(long long x) { + return ((long long)__builtin_bswap64(x) >> 32) & 255; +} +long long test_S64_33_1(long long x) { + return ((long long)__builtin_bswap64(x) >> 33) & 1; +} +long long test_S64_48_1(long long x) { + return ((long long)__builtin_bswap64(x) >> 48) & 1; +} +long long test_S64_48_240(long long x) { + return ((long long)__builtin_bswap64(x) >> 48) & 240; +} +long long test_S64_48_255(long long x) { + return ((long long)__builtin_bswap64(x) >> 48) & 255; +} +long long test_S64_56_1(long long x) { + return ((long long)__builtin_bswap64(x) >> 56) & 1; +} +long long test_S64_56_240(long long x) { + return ((long long)__builtin_bswap64(x) >> 56) & 240; +} +long long test_S64_56_255(long long x) { + return ((long long)__builtin_bswap64(x) >> 56) & 255; +} +long long test_S64_57_1(long long x) { + return ((long long)__builtin_bswap64(x) >> 57) & 1; +} +long long test_S64_63_1(long long x) { + return ((long long)__builtin_bswap64(x) >> 63) & 1; +} + +unsigned long long test_u64_56_255(unsigned long long x) { + return (__builtin_bswap64(x) >> 56) & 255; +} + +short test_s16_0_1(short x) { + return __builtin_bswap16(x) & 1; +} +short test_s16_0_240(short x) { + return __builtin_bswap16(x) & 240; +} +short test_s16_0_255(short x) { + return __builtin_bswap16(x) & 255; +} +short test_s16_1_1(short x) { + return (__builtin_bswap16(x) >> 1) & 1; +} +short test_s16_7_1(short x) { + return (__builtin_bswap16(x) >> 7) & 1; +} +short test_s16_8_1(short x) { + return (__builtin_bswap16(x) >> 8) & 1; +} +short test_s16_8_240(short x) { + return (__builtin_bswap16(x) >> 8) & 240; +} +short test_s16_8_255(short x) { + return (__builtin_bswap16(x) >> 8) & 255; +} +short test_s16_9_1(short x) { + return (__builtin_bswap16(x) >> 9) & 1; +} +short test_s16_15_1(short x) { + return (__builtin_bswap16(x) >> 15) & 1; +} + +short test_S16_0_1(short x) { + return (short)__builtin_bswap16(x) & 1; +} +short test_S16_0_240(short x) { + return (short)__builtin_bswap16(x) & 240; +} +short test_S16_0_255(short x) { + return (short)__builtin_bswap16(x) & 255; +} +short test_S16_1_1(short x) { + return ((short)__builtin_bswap16(x) >> 1) & 1; +} +short test_S16_7_1(short x) { + return ((short)__builtin_bswap16(x) >> 7) & 1; +} +short test_S16_8_1(short x) { + return ((short)__builtin_bswap16(x) >> 8) & 1; +} +short test_S16_8_240(short x) { + return ((short)__builtin_bswap16(x) >> 8) & 240; +} +short test_S16_8_255(short x) { + return ((short)__builtin_bswap16(x) >> 8) & 255; +} +short test_S16_9_1(short x) { + return ((short)__builtin_bswap16(x) >> 9) & 1; +} +short test_S16_15_1(short x) { + return ((short)__builtin_bswap16(x) >> 15) & 1; +} + +unsigned short test_u16_8_255(unsigned short x) { + return (__builtin_bswap16(x) >> 8) & 255; +} + + +/* Shifts only */ +int test_s32_24(int x) { + return __builtin_bswap32(x) >> 24; +} +int test_s32_25(int x) { + return __builtin_bswap32(x) >> 25; +} +int test_s32_30(int x) { + return __builtin_bswap32(x) >> 30; +} +int test_s32_31(int x) { + return __builtin_bswap32(x) >> 31; +} + +unsigned int test_u32_24(unsigned int x) { + return __builtin_bswap32(x) >> 24; +} +unsigned int test_u32_25(unsigned int x) { + return __builtin_bswap32(x) >> 25; +} +unsigned int test_u32_30(unsigned int x) { + return __builtin_bswap32(x) >> 30; +} +unsigned int test_u32_31(unsigned int x) { + return __builtin_bswap32(x) >> 31; +} + +long long test_s64_56(long long x) { + return __builtin_bswap64(x) >> 56; +} +long long test_s64_57(long long x) { + return __builtin_bswap64(x) >> 57; +} +long long test_s64_62(long long x) { + return __builtin_bswap64(x) >> 62; +} +long long test_s64_63(long long x) { + return __builtin_bswap64(x) >> 63; +} + +unsigned long long test_u64_56(unsigned long long x) { + return __builtin_bswap64(x) >> 56; +} +unsigned long long test_u64_57(unsigned long long x) { + return __builtin_bswap64(x) >> 57; +} +unsigned long long test_u64_62(unsigned long long x) { + return __builtin_bswap64(x) >> 62; +} +unsigned long long test_u64_63(unsigned long long x) { + return __builtin_bswap64(x) >> 63; +} + +short test_s16_8(short x) { + return __builtin_bswap16(x) >> 8; +} +short test_s16_9(short x) { + return __builtin_bswap16(x) >> 9; +} +short test_s16_14(short x) { + return __builtin_bswap16(x) >> 14; +} +short test_s16_15(short x) { + return __builtin_bswap16(x) >> 15; +} + +unsigned short test_u16_8(unsigned short x) { + return __builtin_bswap16(x) >> 8; +} +unsigned short test_u16_9(unsigned short x) { + return __builtin_bswap16(x) >> 9; +} +unsigned short test_u16_14(unsigned short x) { + return __builtin_bswap16(x) >> 14; +} +unsigned short test_u16_15(unsigned short x) { + return __builtin_bswap16(x) >> 15; +} + +/* { dg-final { scan-tree-dump-not "__builtin_bswap" "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/builtin-bswap-14.c b/gcc/testsuite/gcc.dg/builtin-bswap-14.c new file mode 100644 index 0000000..62711d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-bswap-14.c @@ -0,0 +1,302 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern void abort (void); + + +__attribute__ ((noinline, noclone)) +static int rt32 (int x, int y, int z) { + return (__builtin_bswap32(x) >> y) & z; +} +#define TEST32(X,Y,Z) if(((__builtin_bswap32(X)>>Y)&Z)!=rt32(X,Y,Z)) abort() +void test32(int x) +{ + TEST32(x,0,1); + TEST32(x,0,255); + TEST32(x,1,1); + TEST32(x,2,1); + TEST32(x,3,1); + TEST32(x,4,1); + TEST32(x,5,1); + TEST32(x,6,1); + TEST32(x,7,1); + TEST32(x,8,1); + TEST32(x,8,255); + TEST32(x,9,1); + TEST32(x,10,1); + TEST32(x,11,1); + TEST32(x,12,1); + TEST32(x,13,1); + TEST32(x,14,1); + TEST32(x,15,1); + TEST32(x,16,1); + TEST32(x,16,255); + TEST32(x,17,1); + TEST32(x,18,1); + TEST32(x,19,1); + TEST32(x,20,1); + TEST32(x,21,1); + TEST32(x,22,1); + TEST32(x,23,1); + TEST32(x,24,1); + TEST32(x,24,255); + TEST32(x,25,1); + TEST32(x,26,1); + TEST32(x,27,1); + TEST32(x,28,1); + TEST32(x,29,1); + TEST32(x,30,1); + TEST32(x,31,1); +} + +#if __SIZEOF_LONG_LONG__ == 8 +__attribute__ ((noinline, noclone)) +static long long rt64 (long long x, int y, long long z) { + return (__builtin_bswap64(x) >> y) & z; +} +#define TEST64(X,Y,Z) if(((__builtin_bswap64(X)>>Y)&Z)!=rt64(X,Y,Z)) abort() +void test64(long long x) +{ + TEST64(x,0,1); + TEST64(x,0,255); + TEST64(x,1,1); + TEST64(x,2,1); + TEST64(x,3,1); + TEST64(x,4,1); + TEST64(x,5,1); + TEST64(x,6,1); + TEST64(x,7,1); + TEST64(x,8,1); + TEST64(x,8,255); + TEST64(x,9,1); + TEST64(x,10,1); + TEST64(x,11,1); + TEST64(x,12,1); + TEST64(x,13,1); + TEST64(x,14,1); + TEST64(x,15,1); + TEST64(x,16,1); + TEST64(x,16,255); + TEST64(x,17,1); + TEST64(x,18,1); + TEST64(x,19,1); + TEST64(x,20,1); + TEST64(x,21,1); + TEST64(x,22,1); + TEST64(x,23,1); + TEST64(x,24,1); + TEST64(x,24,255); + TEST64(x,25,1); + TEST64(x,26,1); + TEST64(x,27,1); + TEST64(x,28,1); + TEST64(x,29,1); + TEST64(x,30,1); + TEST64(x,31,1); + TEST64(x,32,1); + TEST64(x,32,255); + TEST64(x,33,1); + TEST64(x,34,1); + TEST64(x,35,1); + TEST64(x,36,1); + TEST64(x,37,1); + TEST64(x,38,1); + TEST64(x,39,1); + TEST64(x,40,1); + TEST64(x,40,255); + TEST64(x,41,1); + TEST64(x,42,1); + TEST64(x,43,1); + TEST64(x,44,1); + TEST64(x,45,1); + TEST64(x,46,1); + TEST64(x,47,1); + TEST64(x,48,1); + TEST64(x,48,255); + TEST64(x,49,1); + TEST64(x,50,1); + TEST64(x,51,1); + TEST64(x,52,1); + TEST64(x,53,1); + TEST64(x,54,1); + TEST64(x,55,1); + TEST64(x,56,1); + TEST64(x,56,255); + TEST64(x,57,1); + TEST64(x,58,1); + TEST64(x,59,1); + TEST64(x,60,1); + TEST64(x,61,1); + TEST64(x,62,1); + TEST64(x,63,1); +} +#endif + +__attribute__ ((noinline, noclone)) +static int rt16 (int x, int y, int z) { + return (__builtin_bswap16(x) >> y) & z; +} +#define TEST16(X,Y,Z) if(((__builtin_bswap16(X)>>Y)&Z)!=rt16(X,Y,Z)) abort() +void test16(int x) +{ + TEST16(x,0,1); + TEST16(x,0,255); + TEST16(x,1,1); + TEST16(x,2,1); + TEST16(x,3,1); + TEST16(x,4,1); + TEST16(x,5,1); + TEST16(x,6,1); + TEST16(x,7,1); + TEST16(x,8,1); + TEST16(x,8,255); + TEST16(x,9,1); + TEST16(x,10,1); + TEST16(x,11,1); + TEST16(x,12,1); + TEST16(x,13,1); + TEST16(x,14,1); + TEST16(x,15,1); +} + +int main() +{ + test32(0x00000000); + test32(0xffffffff); + test32(0x00000001); + test32(0x00000002); + test32(0x00000004); + test32(0x00000008); + test32(0x00000010); + test32(0x00000020); + test32(0x00000040); + test32(0x00000080); + test32(0x00000100); + test32(0x00000200); + test32(0x00000400); + test32(0x00000800); + test32(0x00001000); + test32(0x00002000); + test32(0x00004000); + test32(0x00008000); + test32(0x00010000); + test32(0x00020000); + test32(0x00040000); + test32(0x00080000); + test32(0x00100000); + test32(0x00200000); + test32(0x00400000); + test32(0x00800000); + test32(0x01000000); + test32(0x02000000); + test32(0x04000000); + test32(0x08000000); + test32(0x10000000); + test32(0x20000000); + test32(0x40000000); + test32(0x80000000); + test32(0x12345678); + test32(0x87654321); + test32(0xdeadbeef); + test32(0xcafebabe); + +#if __SIZEOF_LONG_LONG__ == 8 + test64(0x0000000000000000ll); + test64(0xffffffffffffffffll); + test64(0x0000000000000001ll); + test64(0x0000000000000002ll); + test64(0x0000000000000004ll); + test64(0x0000000000000008ll); + test64(0x0000000000000010ll); + test64(0x0000000000000020ll); + test64(0x0000000000000040ll); + test64(0x0000000000000080ll); + test64(0x0000000000000100ll); + test64(0x0000000000000200ll); + test64(0x0000000000000400ll); + test64(0x0000000000000800ll); + test64(0x0000000000001000ll); + test64(0x0000000000002000ll); + test64(0x0000000000004000ll); + test64(0x0000000000008000ll); + test64(0x0000000000010000ll); + test64(0x0000000000020000ll); + test64(0x0000000000040000ll); + test64(0x0000000000080000ll); + test64(0x0000000000100000ll); + test64(0x0000000000200000ll); + test64(0x0000000000400000ll); + test64(0x0000000000800000ll); + test64(0x0000000001000000ll); + test64(0x0000000002000000ll); + test64(0x0000000004000000ll); + test64(0x0000000008000000ll); + test64(0x0000000010000000ll); + test64(0x0000000020000000ll); + test64(0x0000000040000000ll); + test64(0x0000000080000000ll); + test64(0x0000000100000000ll); + test64(0x0000000200000000ll); + test64(0x0000000400000000ll); + test64(0x0000000800000000ll); + test64(0x0000001000000000ll); + test64(0x0000002000000000ll); + test64(0x0000004000000000ll); + test64(0x0000008000000000ll); + test64(0x0000010000000000ll); + test64(0x0000020000000000ll); + test64(0x0000040000000000ll); + test64(0x0000080000000000ll); + test64(0x0000100000000000ll); + test64(0x0000200000000000ll); + test64(0x0000400000000000ll); + test64(0x0000800000000000ll); + test64(0x0001000000000000ll); + test64(0x0002000000000000ll); + test64(0x0004000000000000ll); + test64(0x0008000000000000ll); + test64(0x0010000000000000ll); + test64(0x0020000000000000ll); + test64(0x0040000000000000ll); + test64(0x0080000000000000ll); + test64(0x0100000000000000ll); + test64(0x0200000000000000ll); + test64(0x0400000000000000ll); + test64(0x0800000000000000ll); + test64(0x1000000000000000ll); + test64(0x2000000000000000ll); + test64(0x4000000000000000ll); + test64(0x8000000000000000ll); + test64(0x0123456789abcdefll); + test64(0xfedcba9876543210ll); + test64(0xdeadbeefdeadbeefll); + test64(0xcafebabecafebabell); +#endif + + test16(0x0000); + test16(0xffff); + test16(0x0001); + test16(0x0002); + test16(0x0004); + test16(0x0008); + test16(0x0010); + test16(0x0020); + test16(0x0040); + test16(0x0080); + test16(0x0100); + test16(0x0200); + test16(0x0400); + test16(0x0800); + test16(0x1000); + test16(0x2000); + test16(0x4000); + test16(0x8000); + test16(0x1234); + test16(0x4321); + test16(0xdead); + test16(0xbeef); + test16(0xcafe); + test16(0xbabe); + + return 0; +} -- cgit v1.1 From 298b0db76dfcc82427d987fbbd239afcb0c3dbfd Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 8 Jul 2021 12:49:44 +0100 Subject: match.pd: Relax rule to include POLY_INT_CSTs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit match.pd has a rule to simplify an extension, operation and truncation back to the original type: (simplify (convert (op:s@0 (convert1?@3 @1) (convert2?@4 @2))) Currently it handles cases in which @2 is an INTEGER_CST, but it also works for POLY_INT_CSTs.[*] For INTEGER_CST it doesn't matter whether we test @2 or @4, but for POLY_INT_CST it is possible to have unfolded (convert …)s. Originally I saw this leading to some bad ivopts decisions, because we weren't folding away redundancies from candidate iv expressions. It's also possible to test the fold directly using the SVE ACLE. [*] Not all INTEGER_CST rules work for POLY_INT_CSTs, since extensions don't necessarily distribute over the internals of the POLY_INT_CST. But in this case that isn't an issue. gcc/ * match.pd: Simplify an extend-operate-truncate sequence involving a POLY_INT_CST. gcc/testsuite/ * gcc.target/aarch64/sve/acle/general/cntb_1.c: New test. --- gcc/match.pd | 2 +- gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntb_1.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntb_1.c (limited to 'gcc') diff --git a/gcc/match.pd b/gcc/match.pd index 334e8cc..30680d4 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6175,7 +6175,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && (types_match (@1, @2) /* Or the second operand is const integer or converted const integer from valueize. */ - || TREE_CODE (@2) == INTEGER_CST)) + || poly_int_tree_p (@4))) (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1))) (op @1 (convert @2)) (with { tree utype = unsigned_type_for (TREE_TYPE (@1)); } diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntb_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntb_1.c new file mode 100644 index 0000000..b43fcf0 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntb_1.c @@ -0,0 +1,14 @@ +/* { dg-options "-O -fdump-tree-optimized" } */ + +#include + +unsigned int +foo (unsigned int x) +{ + unsigned long tmp = x; + tmp += svcntb (); + x = tmp; + return x - svcntb (); +} + +/* { dg-final { scan-tree-dump-not { POLY_INT_CST } optimized } } */ -- cgit v1.1 From 2e9ef3929b0305235b968c431c8d7fec92885101 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 8 Jul 2021 12:58:13 +0100 Subject: vect: Remove always-true condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vectorizable_reduction had code guarded by: if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def || STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def) But that's always true after: if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_reduction_def && STMT_VINFO_DEF_TYPE (stmt_info) != vect_double_reduction_def && STMT_VINFO_DEF_TYPE (stmt_info) != vect_nested_cycle) return false; if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_nested_cycle) { … return true; } (I wasn't sure at first how the empty “else” for the first “if” above was supposed to work.) gcc/ * tree-vect-loop.c (vectorizable_reduction): Remove always-true if condition. --- gcc/tree-vect-loop.c | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'gcc') diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index 51a46a6..bc523d1 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -6516,33 +6516,31 @@ vectorizable_reduction (loop_vec_info loop_vinfo, stmt_vec_info orig_stmt_of_analysis = stmt_info; stmt_vec_info phi_info = stmt_info; - if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def - || STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def) + if (!is_a (stmt_info->stmt)) { - if (!is_a (stmt_info->stmt)) - { - STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type; - return true; - } - if (slp_node) - { - slp_node_instance->reduc_phis = slp_node; - /* ??? We're leaving slp_node to point to the PHIs, we only - need it to get at the number of vector stmts which wasn't - yet initialized for the instance root. */ - } - if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def) - stmt_info = vect_stmt_to_vectorize (STMT_VINFO_REDUC_DEF (stmt_info)); - else /* STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def */ - { - use_operand_p use_p; - gimple *use_stmt; - bool res = single_imm_use (gimple_phi_result (stmt_info->stmt), - &use_p, &use_stmt); - gcc_assert (res); - phi_info = loop_vinfo->lookup_stmt (use_stmt); - stmt_info = vect_stmt_to_vectorize (STMT_VINFO_REDUC_DEF (phi_info)); - } + STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type; + return true; + } + if (slp_node) + { + slp_node_instance->reduc_phis = slp_node; + /* ??? We're leaving slp_node to point to the PHIs, we only + need it to get at the number of vector stmts which wasn't + yet initialized for the instance root. */ + } + if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def) + stmt_info = vect_stmt_to_vectorize (STMT_VINFO_REDUC_DEF (stmt_info)); + else + { + gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info) + == vect_double_reduction_def); + use_operand_p use_p; + gimple *use_stmt; + bool res = single_imm_use (gimple_phi_result (stmt_info->stmt), + &use_p, &use_stmt); + gcc_assert (res); + phi_info = loop_vinfo->lookup_stmt (use_stmt); + stmt_info = vect_stmt_to_vectorize (STMT_VINFO_REDUC_DEF (phi_info)); } /* PHIs should not participate in patterns. */ -- cgit v1.1 From 999a2dd00d3cb8127bc1e7a2a5264d2131c92242 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Mon, 24 May 2021 15:27:28 +0200 Subject: [Ada] Simplify string manipulation related to preprocessing gcc/ada/ * sinput-l.adb (Load_File): Simplify foreword manipulation with concatenation; similar for filename with preprocessed output. --- gcc/ada/sinput-l.adb | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sinput-l.adb b/gcc/ada/sinput-l.adb index 102f363..2d5efb0 100644 --- a/gcc/ada/sinput-l.adb +++ b/gcc/ada/sinput-l.adb @@ -551,19 +551,10 @@ package body Sinput.L is Set_Source_File_Index_Table (X); if Opt.List_Preprocessing_Symbols then - Get_Name_String (N); - declare - Foreword : String (1 .. Foreword_Start'Length + - Name_Len + Foreword_End'Length); - + Foreword : constant String := + Foreword_Start & Get_Name_String (N) & Foreword_End; begin - Foreword (1 .. Foreword_Start'Length) := Foreword_Start; - Foreword (Foreword_Start'Length + 1 .. - Foreword_Start'Length + Name_Len) := - Name_Buffer (1 .. Name_Len); - Foreword (Foreword'Last - Foreword_End'Length + 1 .. - Foreword'Last) := Foreword_End; Prep.List_Symbols (Foreword); end; end if; @@ -654,14 +645,13 @@ package body Sinput.L is NB : Integer; Status : Boolean; - begin - Get_Name_String (N); - Add_Str_To_Name_Buffer (Prep_Suffix); + Prep_Filename : constant String := + Get_Name_String (N) & Prep_Suffix; - Delete_File (Name_Buffer (1 .. Name_Len), Status); + begin + Delete_File (Prep_Filename, Status); - FD := - Create_New_File (Name_Buffer (1 .. Name_Len), Text); + FD := Create_New_File (Prep_Filename, Text); Status := FD /= Invalid_FD; -- cgit v1.1 From 79a8b14237eca20a0e8256f5683d6ca092f38a0b Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Mon, 24 May 2021 16:14:40 +0200 Subject: [Ada] Avoid linear search when ensuring dependency on System gcc/ada/ * lib-writ.adb (Ensure_System_Dependency): Replace search in Lib.Units with a search in Lib.Unit_Names. --- gcc/ada/lib-writ.adb | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb index 416052c..1b2912a 100644 --- a/gcc/ada/lib-writ.adb +++ b/gcc/ada/lib-writ.adb @@ -137,7 +137,8 @@ package body Lib.Writ is ------------------------------ procedure Ensure_System_Dependency is - System_Uname : Unit_Name_Type; + System_Uname : constant Unit_Name_Type := + Name_To_Unit_Name (Name_System); -- Unit name for system spec if needed for dummy entry System_Fname : File_Name_Type; @@ -146,11 +147,9 @@ package body Lib.Writ is begin -- Nothing to do if we already compiled System - for Unum in Units.First .. Last_Unit loop - if Source_Index (Unum) = System_Source_File_Index then - return; - end if; - end loop; + if Unit_Names.Get (System_Uname) /= No_Unit then + return; + end if; -- If no entry for system.ads in the units table, then add a entry -- to the units table for system.ads, which will be referenced when @@ -158,7 +157,6 @@ package body Lib.Writ is -- on system as a result of Targparm scanning the system.ads file to -- determine the target dependent parameters for the compilation. - System_Uname := Name_To_Unit_Name (Name_System); System_Fname := File_Name (System_Source_File_Index); Units.Increment_Last; -- cgit v1.1 From 3cb32058b49f20d6532beabf6bee4f7862a515d5 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Mon, 24 May 2021 07:07:49 -0400 Subject: [Ada] Make tools compatible with No_Dynamic_Accessibility_Checks gcc/ada/ * make.adb, osint.adb: Make code compatible with No_Dynamic_Accessibility_Checks restriction. --- gcc/ada/make.adb | 9 +++++---- gcc/ada/osint.adb | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/make.adb b/gcc/ada/make.adb index f7f166c..6e74e90 100644 --- a/gcc/ada/make.adb +++ b/gcc/ada/make.adb @@ -2364,7 +2364,7 @@ package body Make is Osint.Full_Source_Name (Source.File, Full_File => Full_Source_File, - Attr => Source_File_Attr'Access); + Attr => Source_File_Attr'Unchecked_Access); Lib_File := Osint.Lib_File_Name (Source.File, Source.Index); @@ -2392,7 +2392,7 @@ package body Make is Get_Name_String (Full_Lib_File); Name_Buffer (Name_Len + 1) := ASCII.NUL; Read_Only := not Is_Writable_File - (Name_Buffer'Address, Lib_File_Attr'Access); + (Name_Buffer'Address, Lib_File_Attr'Unchecked_Access); else Read_Only := False; end if; @@ -2460,7 +2460,7 @@ package body Make is The_Args => Args, Lib_File => Lib_File, Full_Lib_File => Full_Lib_File, - Lib_File_Attr => Lib_File_Attr'Access, + Lib_File_Attr => Lib_File_Attr'Unchecked_Access, Read_Only => Read_Only, ALI => ALI, O_File => Obj_File, @@ -2630,7 +2630,8 @@ package body Make is Text := Read_Library_Info_From_Full - (Data.Full_Lib_File, Data.Lib_File_Attr'Access); + (Data.Full_Lib_File, + Data.Lib_File_Attr'Unchecked_Access); -- Restore Check_Object_Consistency to its initial value diff --git a/gcc/ada/osint.adb b/gcc/ada/osint.adb index 3e5db36..4ee6aa8 100644 --- a/gcc/ada/osint.adb +++ b/gcc/ada/osint.adb @@ -1915,7 +1915,8 @@ package body Osint is begin if Opt.Look_In_Primary_Dir then Locate_File - (N, Source, Primary_Directory, File_Name, File, Attr'Access); + (N, Source, Primary_Directory, File_Name, File, + Attr'Unchecked_Access); if File /= No_File and then T = File_Stamp (N) then return File; @@ -1925,7 +1926,7 @@ package body Osint is Last_Dir := Src_Search_Directories.Last; for D in Primary_Directory + 1 .. Last_Dir loop - Locate_File (N, Source, D, File_Name, File, Attr'Access); + Locate_File (N, Source, D, File_Name, File, Attr'Unchecked_Access); if File /= No_File and then T = File_Stamp (File) then return File; -- cgit v1.1 From a2f91a52b4b989b52f0ccdabc2d9aead05c8056b Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Mon, 24 May 2021 08:38:20 -0400 Subject: [Ada] Revert meaning of -gnatd_b gcc/ada/ * debug.adb, sem_util.adb: Revert meaning of -gnatd_b. * sem_res.adb: Minor reformatting. --- gcc/ada/debug.adb | 6 +++++- gcc/ada/sem_res.adb | 3 +-- gcc/ada/sem_util.adb | 56 ++++++++++++++++++++++++++-------------------------- 3 files changed, 34 insertions(+), 31 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index 5a4d1d3..599c9c9 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -140,7 +140,7 @@ package body Debug is -- d.Z Do not enable expansion in configurable run-time mode -- d_a Stop elaboration checks on accept or select statement - -- d_b Use compatibility model under No_Dynamic_Accessibility_Checks + -- d_b Use designated type model under No_Dynamic_Accessibility_Checks -- d_c CUDA compilation : compile for the host -- d_d -- d_e Ignore entry calls and requeue statements for elaboration @@ -956,6 +956,10 @@ package body Debug is -- behavior is similar to that of No_Entry_Calls_In_Elaboration_Code, -- but does not penalize actual entry calls in elaboration code. + -- d_b When the restriction No_Dynamic_Accessibility_Checks is enabled, + -- use the simple "designated type" accessibility model, instead of + -- using the implicit level of the anonymous access type declaration. + -- d_e The compiler ignores simple entry calls, asynchronous transfer of -- control, conditional entry calls, timed entry calls, and requeue -- statements in both the static and dynamic elaboration models. diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 5791d3d..26e4a07 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -13738,8 +13738,7 @@ package body Sem_Res is Deepest_Type_Access_Level (Target_Type) and then (Nkind (Associated_Node_For_Itype (Opnd_Type)) /= N_Function_Specification - or else Ekind (Target_Type) in - Anonymous_Access_Kind) + or else Ekind (Target_Type) in Anonymous_Access_Kind) -- Check we are not in a return value ??? diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 12e5aa8..ba84029 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -410,17 +410,18 @@ package body Sem_Util is and then No_Dynamic_Accessibility_Checks_Enabled (N) and then Is_Anonymous_Access_Type (Etype (N)) then - -- In the alternative model the level is that of the subprogram + -- In the alternative model the level is that of the + -- designated type. if Debug_Flag_Underscore_B then + return Make_Level_Literal (Typ_Access_Level (Etype (N))); + + -- Otherwise the level is that of the subprogram + + else return Make_Level_Literal (Subprogram_Access_Level (Current_Subprogram)); end if; - - -- Otherwise the level is that of the designated type - - return Make_Level_Literal - (Typ_Access_Level (Etype (N))); end if; if Nkind (N) = N_Function_Call then @@ -659,24 +660,22 @@ package body Sem_Util is if Allow_Alt_Model and then No_Dynamic_Accessibility_Checks_Enabled (E) then - -- In the alternative model the level depends on the - -- entity's context. + -- In the alternative model the level is that of the + -- designated type entity's context. if Debug_Flag_Underscore_B then - if Is_Formal (E) then - return Make_Level_Literal - (Subprogram_Access_Level - (Enclosing_Subprogram (E))); - end if; + return Make_Level_Literal (Typ_Access_Level (Etype (E))); + + -- Otherwise the level depends on the entity's context + elsif Is_Formal (E) then + return Make_Level_Literal + (Subprogram_Access_Level + (Enclosing_Subprogram (E))); + else return Make_Level_Literal (Scope_Depth (Enclosing_Dynamic_Scope (E))); end if; - - -- Otherwise the level is that of the designated type - - return Make_Level_Literal - (Typ_Access_Level (Etype (E))); end if; -- Return the dynamic level in the normal case @@ -701,10 +700,11 @@ package body Sem_Util is elsif Is_Type (E) then -- When restriction No_Dynamic_Accessibility_Checks is active + -- along with -gnatd_b. if Allow_Alt_Model and then No_Dynamic_Accessibility_Checks_Enabled (E) - and then not Debug_Flag_Underscore_B + and then Debug_Flag_Underscore_B then return Make_Level_Literal (Typ_Access_Level (E)); end if; @@ -799,11 +799,11 @@ package body Sem_Util is = E_Discriminant) then -- When restriction No_Dynamic_Accessibility_Checks is active - -- the level is that of the designated type. + -- and -gnatd_b set, the level is that of the designated type. if Allow_Alt_Model and then No_Dynamic_Accessibility_Checks_Enabled (E) - and then not Debug_Flag_Underscore_B + and then Debug_Flag_Underscore_B then return Make_Level_Literal (Typ_Access_Level (Etype (E))); @@ -825,11 +825,11 @@ package body Sem_Util is = E_Anonymous_Access_Type then -- When restriction No_Dynamic_Accessibility_Checks is active - -- the level is that of the designated type. + -- and -gnatd_b set, the level is that of the designated type. if Allow_Alt_Model and then No_Dynamic_Accessibility_Checks_Enabled (E) - and then not Debug_Flag_Underscore_B + and then Debug_Flag_Underscore_B then return Make_Level_Literal (Typ_Access_Level (Etype (E))); @@ -7212,7 +7212,7 @@ package body Sem_Util is if Allow_Alt_Model and then No_Dynamic_Accessibility_Checks_Enabled (Typ) - and then Debug_Flag_Underscore_B + and then not Debug_Flag_Underscore_B then return Type_Access_Level (Typ, Allow_Alt_Model); end if; @@ -29176,16 +29176,16 @@ package body Sem_Util is if Allow_Alt_Model and then No_Dynamic_Accessibility_Checks_Enabled (Btyp) then - -- In the normal model, the level of an anonymous access + -- In the -gnatd_b model, the level of an anonymous access -- type is always that of the designated type. - if not Debug_Flag_Underscore_B then + if Debug_Flag_Underscore_B then return Type_Access_Level (Designated_Type (Btyp), Allow_Alt_Model); end if; - -- Otherwise the secondary model dictates special handling - -- depending on the context of the anonymous access type. + -- Otherwise take the context of the anonymous access type into + -- account. -- Obtain the defining entity for the internally generated -- anonymous access type. -- cgit v1.1 From c5b1e8e9a5808d612ad20fdf2f77c52cfa5907d3 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Tue, 25 May 2021 04:18:21 -0400 Subject: [Ada] Make runtime code compatible with No_Dynamic_Accessibility_Checks gcc/ada/ * libgnat/a-cbdlli.adb, libgnat/a-cbhama.adb, libgnat/a-cbhase.adb, libgnat/a-cbmutr.adb, libgnat/a-cborma.adb, libgnat/a-cborse.adb, libgnat/a-cobove.adb, libgnat/a-textio.adb, libgnat/a-witeio.adb, libgnat/a-ztexio.adb: Make code compatible with No_Dynamic_Accessibility_Checks restriction. --- gcc/ada/libgnat/a-cbdlli.adb | 4 ++-- gcc/ada/libgnat/a-cbhama.adb | 8 ++++---- gcc/ada/libgnat/a-cbhase.adb | 4 ++-- gcc/ada/libgnat/a-cbmutr.adb | 4 ++-- gcc/ada/libgnat/a-cborma.adb | 8 ++++---- gcc/ada/libgnat/a-cborse.adb | 8 ++++---- gcc/ada/libgnat/a-cobove.adb | 8 ++++---- gcc/ada/libgnat/a-textio.adb | 13 ++++++------- gcc/ada/libgnat/a-witeio.adb | 13 ++++++------- gcc/ada/libgnat/a-ztexio.adb | 13 ++++++------- 10 files changed, 40 insertions(+), 43 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/a-cbdlli.adb b/gcc/ada/libgnat/a-cbdlli.adb index bb92bda..143805e 100644 --- a/gcc/ada/libgnat/a-cbdlli.adb +++ b/gcc/ada/libgnat/a-cbdlli.adb @@ -312,7 +312,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -1608,7 +1608,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); diff --git a/gcc/ada/libgnat/a-cbhama.adb b/gcc/ada/libgnat/a-cbhama.adb index 78a590f..26c01f5 100644 --- a/gcc/ada/libgnat/a-cbhama.adb +++ b/gcc/ada/libgnat/a-cbhama.adb @@ -213,7 +213,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -239,7 +239,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -1028,7 +1028,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -1053,7 +1053,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); diff --git a/gcc/ada/libgnat/a-cbhase.adb b/gcc/ada/libgnat/a-cbhase.adb index f8ca4d2..d6ab353 100644 --- a/gcc/ada/libgnat/a-cbhase.adb +++ b/gcc/ada/libgnat/a-cbhase.adb @@ -232,7 +232,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -1643,7 +1643,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); diff --git a/gcc/ada/libgnat/a-cbmutr.adb b/gcc/ada/libgnat/a-cbmutr.adb index 714dea1..e80eb5c 100644 --- a/gcc/ada/libgnat/a-cbmutr.adb +++ b/gcc/ada/libgnat/a-cbmutr.adb @@ -600,7 +600,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => Container.Elements (Position.Node)'Access, + (Element => Container.Elements (Position.Node)'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -2533,7 +2533,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Reference_Type := - (Element => Container.Elements (Position.Node)'Access, + (Element => Container.Elements (Position.Node)'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); diff --git a/gcc/ada/libgnat/a-cborma.adb b/gcc/ada/libgnat/a-cborma.adb index 67e6108..f26a1e3 100644 --- a/gcc/ada/libgnat/a-cborma.adb +++ b/gcc/ada/libgnat/a-cborma.adb @@ -420,7 +420,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -445,7 +445,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -1417,7 +1417,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -1442,7 +1442,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); diff --git a/gcc/ada/libgnat/a-cborse.adb b/gcc/ada/libgnat/a-cborse.adb index 0b9e0cc..5c9a86e 100644 --- a/gcc/ada/libgnat/a-cborse.adb +++ b/gcc/ada/libgnat/a-cborse.adb @@ -420,7 +420,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -752,7 +752,7 @@ is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -943,7 +943,7 @@ is N : Node_Type renames Container.Nodes (Position.Node); begin return R : constant Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with Container.TC'Unrestricted_Access, @@ -971,7 +971,7 @@ is N : Node_Type renames Container.Nodes (Node); begin return R : constant Reference_Type := - (Element => N.Element'Access, + (Element => N.Element'Unchecked_Access, Control => (Controlled with Container.TC'Unrestricted_Access, diff --git a/gcc/ada/libgnat/a-cobove.adb b/gcc/ada/libgnat/a-cobove.adb index f32afa1..e56cb94 100644 --- a/gcc/ada/libgnat/a-cobove.adb +++ b/gcc/ada/libgnat/a-cobove.adb @@ -415,7 +415,7 @@ package body Ada.Containers.Bounded_Vectors is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => A (J)'Access, + (Element => A (J)'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -439,7 +439,7 @@ package body Ada.Containers.Bounded_Vectors is Container.TC'Unrestricted_Access; begin return R : constant Constant_Reference_Type := - (Element => A (J)'Access, + (Element => A (J)'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -2238,7 +2238,7 @@ package body Ada.Containers.Bounded_Vectors is Container.TC'Unrestricted_Access; begin return R : constant Reference_Type := - (Element => A (J)'Access, + (Element => A (J)'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); @@ -2262,7 +2262,7 @@ package body Ada.Containers.Bounded_Vectors is Container.TC'Unrestricted_Access; begin return R : constant Reference_Type := - (Element => A (J)'Access, + (Element => A (J)'Unchecked_Access, Control => (Controlled with TC)) do Busy (TC.all); diff --git a/gcc/ada/libgnat/a-textio.adb b/gcc/ada/libgnat/a-textio.adb index dc67091..717f529 100644 --- a/gcc/ada/libgnat/a-textio.adb +++ b/gcc/ada/libgnat/a-textio.adb @@ -171,15 +171,15 @@ is -- is required (RM A.10.3(23)) but it seems reasonable, and besides -- ACVC test CE3208A expects this behavior. - if File_Type (File) = Current_In then + if File = Current_In then Current_In := null; - elsif File_Type (File) = Current_Out then + elsif File = Current_Out then Current_Out := null; - elsif File_Type (File) = Current_Err then + elsif File = Current_Err then Current_Err := null; end if; - Terminate_Line (File_Type (File)); + Terminate_Line (File.all'Access); end AFCB_Close; --------------- @@ -187,10 +187,9 @@ is --------------- procedure AFCB_Free (File : not null access Text_AFCB) is - type FCB_Ptr is access all Text_AFCB; - FT : FCB_Ptr := FCB_Ptr (File); + FT : File_Type := File.all'Access; - procedure Free is new Ada.Unchecked_Deallocation (Text_AFCB, FCB_Ptr); + procedure Free is new Ada.Unchecked_Deallocation (Text_AFCB, File_Type); begin Free (FT); diff --git a/gcc/ada/libgnat/a-witeio.adb b/gcc/ada/libgnat/a-witeio.adb index dbd3fc8..7dbd3b3 100644 --- a/gcc/ada/libgnat/a-witeio.adb +++ b/gcc/ada/libgnat/a-witeio.adb @@ -136,15 +136,15 @@ package body Ada.Wide_Text_IO is -- is required (RM A.10.3(23)) but it seems reasonable, and besides -- ACVC test CE3208A expects this behavior. - if File_Type (File) = Current_In then + if File = Current_In then Current_In := null; - elsif File_Type (File) = Current_Out then + elsif File = Current_Out then Current_Out := null; - elsif File_Type (File) = Current_Err then + elsif File = Current_Err then Current_Err := null; end if; - Terminate_Line (File_Type (File)); + Terminate_Line (File.all'Access); end AFCB_Close; --------------- @@ -152,11 +152,10 @@ package body Ada.Wide_Text_IO is --------------- procedure AFCB_Free (File : not null access Wide_Text_AFCB) is - type FCB_Ptr is access all Wide_Text_AFCB; - FT : FCB_Ptr := FCB_Ptr (File); + FT : File_Type := File.all'Access; procedure Free is - new Ada.Unchecked_Deallocation (Wide_Text_AFCB, FCB_Ptr); + new Ada.Unchecked_Deallocation (Wide_Text_AFCB, File_Type); begin Free (FT); diff --git a/gcc/ada/libgnat/a-ztexio.adb b/gcc/ada/libgnat/a-ztexio.adb index 0dfabd5..71d733e 100644 --- a/gcc/ada/libgnat/a-ztexio.adb +++ b/gcc/ada/libgnat/a-ztexio.adb @@ -136,15 +136,15 @@ package body Ada.Wide_Wide_Text_IO is -- is required (RM A.10.3(23)) but it seems reasonable, and besides -- ACVC test CE3208A expects this behavior. - if File_Type (File) = Current_In then + if File = Current_In then Current_In := null; - elsif File_Type (File) = Current_Out then + elsif File = Current_Out then Current_Out := null; - elsif File_Type (File) = Current_Err then + elsif File = Current_Err then Current_Err := null; end if; - Terminate_Line (File_Type (File)); + Terminate_Line (File.all'Access); end AFCB_Close; --------------- @@ -152,11 +152,10 @@ package body Ada.Wide_Wide_Text_IO is --------------- procedure AFCB_Free (File : not null access Wide_Wide_Text_AFCB) is - type FCB_Ptr is access all Wide_Wide_Text_AFCB; - FT : FCB_Ptr := FCB_Ptr (File); + FT : File_Type := File.all'Access; procedure Free is new - Ada.Unchecked_Deallocation (Wide_Wide_Text_AFCB, FCB_Ptr); + Ada.Unchecked_Deallocation (Wide_Wide_Text_AFCB, File_Type); begin Free (FT); -- cgit v1.1 From b927d936e339ddd47779b522b80552306ebb5604 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Fri, 21 May 2021 15:51:13 -0400 Subject: [Ada] Incorrect iteration over hashed containers after multiple Inserts gcc/ada/ * libgnat/a-cohama.ads: Introduce an equality operator over cursors. * libgnat/a-cohase.ads: Ditto. * libgnat/a-cohama.adb: Add body for "=" over cursors. (Insert): Do not set the Position component of the cursor that denotes the inserted element. * libgnat/a-cohase.adb: Ditto. --- gcc/ada/libgnat/a-cohama.adb | 14 ++++++++++++-- gcc/ada/libgnat/a-cohama.ads | 8 ++++++++ gcc/ada/libgnat/a-cohase.adb | 14 ++++++++++++-- gcc/ada/libgnat/a-cohase.ads | 9 +++++++++ 4 files changed, 41 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/a-cohama.adb b/gcc/ada/libgnat/a-cohama.adb index 26bdd55..e6d6e4d 100644 --- a/gcc/ada/libgnat/a-cohama.adb +++ b/gcc/ada/libgnat/a-cohama.adb @@ -116,6 +116,13 @@ is -- "=" -- --------- + function "=" (Left, Right : Cursor) return Boolean is + begin + return + Left.Container = Right.Container + and then Left.Node = Right.Node; + end "="; + function "=" (Left, Right : Map) return Boolean is begin return Is_Equal (Left.HT, Right.HT); @@ -636,7 +643,11 @@ is end if; Position.Container := Container'Unrestricted_Access; - Position.Position := HT_Ops.Index (HT, Position.Node); + + -- Note that we do not set the Position component of the cursor, + -- because it may become incorrect on subsequent insertions/deletions + -- from the container. This will lose some optimizations but prevents + -- anomalies when the underlying hash-table is expanded or shrunk. end Insert; procedure Insert @@ -679,7 +690,6 @@ is end if; Position.Container := Container'Unrestricted_Access; - Position.Position := HT_Ops.Index (HT, Position.Node); end Insert; procedure Insert diff --git a/gcc/ada/libgnat/a-cohama.ads b/gcc/ada/libgnat/a-cohama.ads index a04cb3a..3f172bd 100644 --- a/gcc/ada/libgnat/a-cohama.ads +++ b/gcc/ada/libgnat/a-cohama.ads @@ -110,6 +110,14 @@ is type Cursor is private; pragma Preelaborable_Initialization (Cursor); + function "=" (Left, Right : Cursor) return Boolean; + -- The representation of cursors includes a component used to optimize + -- iteration over maps. This component may become unreliable after + -- multiple map insertions, and must be excluded from cursor equality, + -- so we need to provide an explicit definition for it, instead of + -- using predefined equality (as implied by a questionable comment + -- in the RM). + Empty_Map : constant Map; -- Map objects declared without an initialization expression are -- initialized to the value Empty_Map. diff --git a/gcc/ada/libgnat/a-cohase.adb b/gcc/ada/libgnat/a-cohase.adb index 31374f6..2342116 100644 --- a/gcc/ada/libgnat/a-cohase.adb +++ b/gcc/ada/libgnat/a-cohase.adb @@ -145,6 +145,13 @@ is -- "=" -- --------- + function "=" (Left, Right : Cursor) return Boolean is + begin + return + Left.Container = Right.Container + and then Left.Node = Right.Node; + end "="; + function "=" (Left, Right : Set) return Boolean is begin return Is_Equal (Left.HT, Right.HT); @@ -763,11 +770,14 @@ is Position : out Cursor; Inserted : out Boolean) is - HT : Hash_Table_Type renames Container'Unrestricted_Access.HT; begin Insert (Container.HT, New_Item, Position.Node, Inserted); Position.Container := Container'Unchecked_Access; - Position.Position := HT_Ops.Index (HT, Position.Node); + + -- Note that we do not set the Position component of the cursor, + -- because it may become incorrect on subsequent insertions/deletions + -- from the container. This will lose some optimizations but prevents + -- anomalies when the underlying hash-table is expanded or shrunk. end Insert; procedure Insert diff --git a/gcc/ada/libgnat/a-cohase.ads b/gcc/ada/libgnat/a-cohase.ads index f0763af..2356ba7 100644 --- a/gcc/ada/libgnat/a-cohase.ads +++ b/gcc/ada/libgnat/a-cohase.ads @@ -69,6 +69,15 @@ is type Cursor is private; pragma Preelaborable_Initialization (Cursor); + function "=" (Left, Right : Cursor) return Boolean; + -- The representation of cursors includes a component used to optimize + -- iteration over sets. This component may become unreliable after + -- multiple set insertions, and must be excluded from cursor equality, + -- so we need to provide an explicit definition for it, instead of + -- using predefined equality (as implied by a questionable comment + -- in the RM). This is also the case for hashed maps, and affects the + -- use of Insert primitives in hashed structures. + Empty_Set : constant Set; -- Set objects declared without an initialization expression are -- initialized to the value Empty_Set. -- cgit v1.1 From 076c1a91574d5abcd32898ec1a1a5975254c32a3 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Fri, 21 May 2021 04:04:55 -0400 Subject: [Ada] Add No_Tasking restriction is system.ads for bootstrap gcc/ada/ * gcc-interface/system.ads: Add No_Tasking restriction. --- gcc/ada/gcc-interface/system.ads | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/gcc-interface/system.ads b/gcc/ada/gcc-interface/system.ads index a468ae7..cfd9bb9 100644 --- a/gcc/ada/gcc-interface/system.ads +++ b/gcc/ada/gcc-interface/system.ads @@ -50,6 +50,10 @@ pragma Restrictions (No_Finalization); -- access type on incomplete type Perm_Tree_Wrapper (which is required for -- defining a recursive type). +pragma Restrictions (No_Tasking); +-- Make it explicit that tasking is not used in the compiler, which also +-- allows generating simpler and more efficient code. + package System is pragma Pure; -- Note that we take advantage of the implementation permission to make -- cgit v1.1 From 5478d8a7aefbec4d93d32237fb29b9fdb8347b6b Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Mon, 24 May 2021 14:38:07 -0700 Subject: [Ada] Unsynchronized concurrent access to a Boolean variable gcc/ada/ * rtsfind.ads, rtsfind.adb: Add support for finding the packages System.Atomic_Operations and System.Atomic_Operations.Test_And_Set and the declarations within that latter package of the type Test_And_Set_Flag and the function Atomic_Test_And_Set. * exp_ch11.adb (Expand_N_Exception_Declaration): If an exception is declared other than at library level, then we need to call Register_Exception the first time (and only the first time) the declaration is elaborated. In order to decide whether to perform this call for a given elaboration of the declaration, we used to unconditionally use a (library-level) Boolean variable. Now we instead use a variable of type System.Atomic_Operations.Test_And_Set.Test_And_Set_Flag unless either that type is unavailable or a No_Tasking restriction is in effect (in which case we use a Boolean variable as before). --- gcc/ada/exp_ch11.adb | 83 +++++++++++++++++++++++++++++++++++++++------------- gcc/ada/rtsfind.adb | 8 +++++ gcc/ada/rtsfind.ads | 11 +++++++ 3 files changed, 81 insertions(+), 21 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_ch11.adb b/gcc/ada/exp_ch11.adb index 6058826..40288e4 100644 --- a/gcc/ada/exp_ch11.adb +++ b/gcc/ada/exp_ch11.adb @@ -1088,10 +1088,19 @@ package body Exp_Ch11 is -- (protecting test only needed if not at library level) - -- exceptF : Boolean := True -- static data + -- exceptF : aliased System.Atomic_Operations.Test_And_Set. + -- .Test_And_Set_Flag := 0; -- static data + -- if not Atomic_Test_And_Set (exceptF) then + -- Register_Exception (except'Unrestricted_Access); + -- end if; + + -- If a No_Tasking restriction is in effect, or if Test_And_Set_Flag + -- is unavailable, then use Boolean instead. In that case, we generate: + -- + -- exceptF : Boolean := True; -- static data -- if exceptF then - -- exceptF := False; - -- Register_Exception (except'Unchecked_Access); + -- ExceptF := False; + -- Register_Exception (except'Unrestricted_Access); -- end if; procedure Expand_N_Exception_Declaration (N : Node_Id) is @@ -1275,7 +1284,7 @@ package body Exp_Ch11 is Force_Static_Allocation_Of_Referenced_Objects (Expression (N)); - -- Register_Exception (except'Unchecked_Access); + -- Register_Exception (except'Unrestricted_Access); if not No_Exception_Handlers_Set and then not Restriction_Active (No_Exception_Registration) @@ -1296,27 +1305,59 @@ package body Exp_Ch11 is Flag_Id := Make_Defining_Identifier (Loc, Chars => New_External_Name (Chars (Id), 'F')); - - Insert_Action (N, - Make_Object_Declaration (Loc, - Defining_Identifier => Flag_Id, - Object_Definition => - New_Occurrence_Of (Standard_Boolean, Loc), - Expression => - New_Occurrence_Of (Standard_True, Loc))); - Set_Is_Statically_Allocated (Flag_Id); - Append_To (L, - Make_Assignment_Statement (Loc, - Name => New_Occurrence_Of (Flag_Id, Loc), - Expression => New_Occurrence_Of (Standard_False, Loc))); + declare + Use_Test_And_Set_Flag : constant Boolean := + (not Global_No_Tasking) + and then RTE_Available (RE_Test_And_Set_Flag); + + Flag_Decl : Node_Id; + Condition : Node_Id; + begin + if Use_Test_And_Set_Flag then + Flag_Decl := + Make_Object_Declaration (Loc, + Defining_Identifier => Flag_Id, + Aliased_Present => True, + Object_Definition => + New_Occurrence_Of (RTE (RE_Test_And_Set_Flag), Loc), + Expression => + Make_Integer_Literal (Loc, 0)); + else + Flag_Decl := + Make_Object_Declaration (Loc, + Defining_Identifier => Flag_Id, + Object_Definition => + New_Occurrence_Of (Standard_Boolean, Loc), + Expression => + New_Occurrence_Of (Standard_True, Loc)); + end if; - Insert_After_And_Analyze (N, - Make_Implicit_If_Statement (N, - Condition => New_Occurrence_Of (Flag_Id, Loc), - Then_Statements => L)); + Insert_Action (N, Flag_Decl); + + if Use_Test_And_Set_Flag then + Condition := + Make_Op_Not (Loc, + Make_Function_Call (Loc, + Name => New_Occurrence_Of + (RTE (RE_Atomic_Test_And_Set), Loc), + Parameter_Associations => + New_List (New_Occurrence_Of (Flag_Id, Loc)))); + else + Condition := New_Occurrence_Of (Flag_Id, Loc); + + Append_To (L, + Make_Assignment_Statement (Loc, + Name => New_Occurrence_Of (Flag_Id, Loc), + Expression => New_Occurrence_Of (Standard_False, Loc))); + end if; + Insert_After_And_Analyze (N, + Make_Implicit_If_Statement (N, + Condition => Condition, + Then_Statements => L)); + end; else Insert_List_After_And_Analyze (N, L); end if; diff --git a/gcc/ada/rtsfind.adb b/gcc/ada/rtsfind.adb index 6fe6f85..5a89076 100644 --- a/gcc/ada/rtsfind.adb +++ b/gcc/ada/rtsfind.adb @@ -602,6 +602,10 @@ package body Rtsfind is subtype System_Descendant is RTU_Id range System_Address_Image .. System_Tasking_Stages; + subtype System_Atomic_Operations_Descendant is System_Descendant + range System_Atomic_Operations_Test_And_Set .. + System_Atomic_Operations_Test_And_Set; + subtype System_Dim_Descendant is System_Descendant range System_Dim_Float_IO .. System_Dim_Integer_IO; @@ -689,6 +693,10 @@ package body Rtsfind is elsif U_Id in System_Descendant then Name_Buffer (7) := '.'; + if U_Id in System_Atomic_Operations_Descendant then + Name_Buffer (25) := '.'; + end if; + if U_Id in System_Dim_Descendant then Name_Buffer (11) := '.'; end if; diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads index 6bec611..99f870a 100644 --- a/gcc/ada/rtsfind.ads +++ b/gcc/ada/rtsfind.ads @@ -195,6 +195,7 @@ package Rtsfind is System_Arith_128, System_AST_Handling, System_Assertions, + System_Atomic_Operations, System_Atomic_Primitives, System_Aux_DEC, System_Bignums, @@ -468,6 +469,10 @@ package Rtsfind is System_WWd_Enum, System_WWd_Wchar, + -- Children of System.Atomic_Operations + + System_Atomic_Operations_Test_And_Set, + -- Children of System.Dim System_Dim_Float_IO, @@ -800,6 +805,9 @@ package Rtsfind is RE_Uint32, -- System.Atomic_Primitives RE_Uint64, -- System.Atomic_Primitives + RE_Test_And_Set_Flag, -- System.Atomic_Operations.Test_And_Set + RE_Atomic_Test_And_Set, -- System.Atomic_Operations.Test_And_Set + RE_AST_Handler, -- System.Aux_DEC RE_Import_Address, -- System.Aux_DEC RE_Import_Value, -- System.Aux_DEC @@ -2482,6 +2490,9 @@ package Rtsfind is RE_Uint32 => System_Atomic_Primitives, RE_Uint64 => System_Atomic_Primitives, + RE_Test_And_Set_Flag => System_Atomic_Operations_Test_And_Set, + RE_Atomic_Test_And_Set => System_Atomic_Operations_Test_And_Set, + RE_AST_Handler => System_Aux_DEC, RE_Import_Address => System_Aux_DEC, RE_Import_Value => System_Aux_DEC, -- cgit v1.1 From 36fcfed88c7cbb3d55a59cdd077e8b26107148b9 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Wed, 19 May 2021 15:50:02 +0200 Subject: [Ada] Compute sizes when possible for packed array with Component_Size gcc/ada/ * layout.adb (Layout_Type): Special case when RM_Size and Esize can be computed for packed arrays. --- gcc/ada/layout.adb | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb index 6dc4d7f..cbc296a 100644 --- a/gcc/ada/layout.adb +++ b/gcc/ada/layout.adb @@ -487,6 +487,48 @@ package body Layout is then Set_Alignment (E, Alignment (Component_Type (E))); end if; + + -- If packing was requested, the one-dimensional array is constrained + -- with static bounds, the component size was set explicitly, and + -- the alignment is known, we can set (if not set explicitly) the + -- RM_Size and the Esize of the array type, as RM_Size is equal to + -- (arr'length * arr'component_size) and Esize is the same value + -- rounded to the next multiple of arr'alignment. This is not + -- applicable to packed arrays that are implemented specially + -- in GNAT, i.e. when Packed_Array_Impl_Type is set. + + if Is_Array_Type (E) + and then Number_Dimensions (E) = 1 + and then not Present (Packed_Array_Impl_Type (E)) + and then Has_Pragma_Pack (E) + and then Is_Constrained (E) + and then Compile_Time_Known_Bounds (E) + and then Known_Component_Size (E) + and then Known_Alignment (E) + then + declare + Abits : constant Int := UI_To_Int (Alignment (E)) * SSU; + Lo, Hi : Node_Id; + Siz : Uint; + + begin + Get_Index_Bounds (First_Index (E), Lo, Hi); + Siz := (Expr_Value (Hi) - Expr_Value (Lo) + 1) + * Component_Size (E); + + -- Do not overwrite a different value of 'Size specified + -- explicitly by the user. In that case, also do not set Esize. + + if Unknown_RM_Size (E) or else RM_Size (E) = Siz then + Set_RM_Size (E, Siz); + + if Unknown_Esize (E) then + Siz := ((Siz + (Abits - 1)) / Abits) * Abits; + Set_Esize (E, Siz); + end if; + end if; + end; + end if; end if; -- Even if the backend performs the layout, we still do a little in -- cgit v1.1 From 242c0f4772c6697ba0b27853f153a13970bbded9 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Wed, 26 May 2021 10:49:14 +0200 Subject: [Ada] Fix on computation of packed array size in case of error gcc/ada/ * layout.adb (Layout_Type): Add guard before calling Expr_Value. --- gcc/ada/layout.adb | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb index cbc296a..ee8e281 100644 --- a/gcc/ada/layout.adb +++ b/gcc/ada/layout.adb @@ -513,18 +513,28 @@ package body Layout is begin Get_Index_Bounds (First_Index (E), Lo, Hi); - Siz := (Expr_Value (Hi) - Expr_Value (Lo) + 1) - * Component_Size (E); - -- Do not overwrite a different value of 'Size specified - -- explicitly by the user. In that case, also do not set Esize. + -- Even if the bounds are known at compile time, they could + -- have been replaced by an error node. Check each bound + -- explicitly. - if Unknown_RM_Size (E) or else RM_Size (E) = Siz then - Set_RM_Size (E, Siz); + if Compile_Time_Known_Value (Lo) + and then Compile_Time_Known_Value (Hi) + then + Siz := (Expr_Value (Hi) - Expr_Value (Lo) + 1) + * Component_Size (E); + + -- Do not overwrite a different value of 'Size specified + -- explicitly by the user. In that case, also do not set + -- Esize. - if Unknown_Esize (E) then - Siz := ((Siz + (Abits - 1)) / Abits) * Abits; - Set_Esize (E, Siz); + if Unknown_RM_Size (E) or else RM_Size (E) = Siz then + Set_RM_Size (E, Siz); + + if Unknown_Esize (E) then + Siz := ((Siz + (Abits - 1)) / Abits) * Abits; + Set_Esize (E, Siz); + end if; end if; end if; end; -- cgit v1.1 From cd4341ef953bc5697917b3e6e43c59be03da0bee Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Tue, 25 May 2021 14:12:37 +0200 Subject: [Ada] Prevent crash on inspection point for unfrozen entity gcc/ada/ * exp_prag.adb (Expand_Pragma_Inspection_Point): After expansion of the Inspection_Point pragma, check if referenced entities that have a freeze node are already frozen. If they aren't, emit a warning and turn the pragma into a no-op. --- gcc/ada/exp_prag.adb | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/exp_prag.adb b/gcc/ada/exp_prag.adb index 2828f5a..f686395 100644 --- a/gcc/ada/exp_prag.adb +++ b/gcc/ada/exp_prag.adb @@ -2361,6 +2361,7 @@ package body Exp_Prag is S : Entity_Id; E : Entity_Id; + Remove_Inspection_Point : Boolean := False; begin if No (Pragma_Argument_Associations (N)) then A := New_List; @@ -2400,6 +2401,36 @@ package body Exp_Prag is Expand (Expression (Assoc)); Next (Assoc); end loop; + + -- If any of the references have a freeze node, it must appear before + -- pragma Inspection_Point, otherwise the entity won't be available when + -- Gigi processes Inspection_Point. + -- When this requirement isn't met, turn the pragma into a no-op. + + Assoc := First (Pragma_Argument_Associations (N)); + while Present (Assoc) loop + + if Present (Freeze_Node (Entity (Expression (Assoc)))) and then + not Is_Frozen (Entity (Expression (Assoc))) + then + Error_Msg_NE ("?inspection point references unfrozen object &", + Assoc, + Entity (Expression (Assoc))); + Remove_Inspection_Point := True; + end if; + + Next (Assoc); + end loop; + + if Remove_Inspection_Point then + Error_Msg_N ("\pragma will be ignored", N); + + -- We can't just remove the pragma from the tree as it might be + -- iterated over by the caller. Turn it into a null statement + -- instead. + + Rewrite (N, Make_Null_Statement (Sloc (N))); + end if; end Expand_Pragma_Inspection_Point; -------------------------------------- -- cgit v1.1 From 6cb2bcba3f31c6ec93fe76ff5e0f67db43556ef7 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Wed, 26 May 2021 14:54:02 +0200 Subject: [Ada] Skip types in error for test to compute array size gcc/ada/ * layout.adb (Layout_Type): Do not call Number_Dimensions if the type does not have First_Index set. --- gcc/ada/layout.adb | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb index ee8e281..de73193 100644 --- a/gcc/ada/layout.adb +++ b/gcc/ada/layout.adb @@ -498,6 +498,7 @@ package body Layout is -- in GNAT, i.e. when Packed_Array_Impl_Type is set. if Is_Array_Type (E) + and then Present (First_Index (E)) -- Skip types in error and then Number_Dimensions (E) = 1 and then not Present (Packed_Array_Impl_Type (E)) and then Has_Pragma_Pack (E) -- cgit v1.1 From 6105ebb782756b449ee2ebec01bd4dd2c256ff17 Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Wed, 26 May 2021 18:02:34 +0200 Subject: [Ada] Fix use of single question mark in error message gcc/ada/ * exp_prag.adb (Expand_Pragma_Inspection_Point): Fix error message. --- gcc/ada/exp_prag.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/exp_prag.adb b/gcc/ada/exp_prag.adb index f686395..43ecdcd 100644 --- a/gcc/ada/exp_prag.adb +++ b/gcc/ada/exp_prag.adb @@ -2413,7 +2413,7 @@ package body Exp_Prag is if Present (Freeze_Node (Entity (Expression (Assoc)))) and then not Is_Frozen (Entity (Expression (Assoc))) then - Error_Msg_NE ("?inspection point references unfrozen object &", + Error_Msg_NE ("??inspection point references unfrozen object &", Assoc, Entity (Expression (Assoc))); Remove_Inspection_Point := True; -- cgit v1.1 From 62aae315f680f2205d474ff3ebcb1756a707f715 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Wed, 26 May 2021 15:05:28 +0200 Subject: [Ada] Prevent infinite recursion when there is no expected unit gcc/ada/ * par-load.adb (Load): Don't remove unit, but flag it as erroneous and return. --- gcc/ada/par-load.adb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/par-load.adb b/gcc/ada/par-load.adb index 0773f36..6079fa4 100644 --- a/gcc/ada/par-load.adb +++ b/gcc/ada/par-load.adb @@ -234,9 +234,10 @@ begin Error_Msg ("\\found unit $!", Loc); end if; - -- In both cases, remove the unit so that it is out of the way later + -- In both cases, flag the fatal error and give up - Remove_Unit (Cur_Unum); + Set_Fatal_Error (Cur_Unum, Error_Detected); + return; end if; -- If current unit is a body, load its corresponding spec -- cgit v1.1 From 3711c2e5a06ac318fec2f7a5cfbd1f0267607a0f Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Wed, 26 May 2021 15:27:02 +0200 Subject: [Ada] Fix style in comments and code related to compilation units gcc/ada/ * lib-load.adb (Load_Unit): Fix style in comment. * par-load.adb (Load): Likewise. * scng.adb (Initialize_Scanner): Fix whitespace. --- gcc/ada/lib-load.adb | 4 ++-- gcc/ada/par-load.adb | 4 ++-- gcc/ada/scng.adb | 20 ++++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/lib-load.adb b/gcc/ada/lib-load.adb index 19afe26..f7534b6 100644 --- a/gcc/ada/lib-load.adb +++ b/gcc/ada/lib-load.adb @@ -823,7 +823,7 @@ package body Lib.Load is Units.Table (Calling_Unit).Fatal_Error := Error_Detected; -- If with'ed unit had an ignored error, then propagate it - -- but do not overide an existring setting. + -- but do not overide an existing setting. when Error_Ignored => if Units.Table (Calling_Unit).Fatal_Error = None then @@ -900,7 +900,7 @@ package body Lib.Load is Remove_Unit (Unum); -- If unit not required, remove load stack entry and the junk - -- file table entry, and return No_Unit to indicate not found, + -- file table entry, and return No_Unit to indicate not found. else Load_Stack.Decrement_Last; diff --git a/gcc/ada/par-load.adb b/gcc/ada/par-load.adb index 6079fa4..dcba6d5 100644 --- a/gcc/ada/par-load.adb +++ b/gcc/ada/par-load.adb @@ -129,8 +129,8 @@ begin Save_Style_Check_Options (Save_Style_Checks); Save_Style_Check := Opt.Style_Check; - -- If main unit, set Main_Unit_Entity (this will get overwritten if - -- the main unit has a separate spec, that happens later on in Load) + -- If main unit, set Main_Unit_Entity (this will get overwritten if the + -- main unit has a separate spec, that happens later on in Load). if Cur_Unum = Main_Unit then Main_Unit_Entity := Cunit_Entity (Main_Unit); diff --git a/gcc/ada/scng.adb b/gcc/ada/scng.adb index 66b1105..bf1307c 100644 --- a/gcc/ada/scng.adb +++ b/gcc/ada/scng.adb @@ -230,16 +230,16 @@ package body Scng is -- Initialize scan control variables - Current_Source_File := Index; - Source := Source_Text (Current_Source_File); - Scan_Ptr := Source_First (Current_Source_File); - Token := No_Token; - Token_Ptr := Scan_Ptr; - Current_Line_Start := Scan_Ptr; - Token_Node := Empty; - Token_Name := No_Name; - Start_Column := Set_Start_Column; - First_Non_Blank_Location := Scan_Ptr; + Current_Source_File := Index; + Source := Source_Text (Current_Source_File); + Scan_Ptr := Source_First (Current_Source_File); + Token := No_Token; + Token_Ptr := Scan_Ptr; + Current_Line_Start := Scan_Ptr; + Token_Node := Empty; + Token_Name := No_Name; + Start_Column := Set_Start_Column; + First_Non_Blank_Location := Scan_Ptr; Initialize_Checksum; Wide_Char_Byte_Count := 0; -- cgit v1.1 From df0783f81ca9aca026a1db3b81080a8756c6166e Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 25 May 2021 17:40:38 +0200 Subject: [Ada] Replace low-level condition with a high-level call gcc/ada/ * lib-writ.adb (Ensure_System_Dependency): Simplify condition. --- gcc/ada/lib-writ.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb index 1b2912a..738a91e 100644 --- a/gcc/ada/lib-writ.adb +++ b/gcc/ada/lib-writ.adb @@ -147,7 +147,7 @@ package body Lib.Writ is begin -- Nothing to do if we already compiled System - if Unit_Names.Get (System_Uname) /= No_Unit then + if Is_Loaded (System_Uname) then return; end if; -- cgit v1.1 From e581fbeab695838c3e36bf31072c1dad11d9f81b Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 25 May 2021 17:39:26 +0200 Subject: [Ada] Restore context on failure in loading of renamed child unit gcc/ada/ * lib-load.adb (Load): Replace early return with goto to properly restore context on failure. --- gcc/ada/lib-load.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/lib-load.adb b/gcc/ada/lib-load.adb index f7534b6..737762c 100644 --- a/gcc/ada/lib-load.adb +++ b/gcc/ada/lib-load.adb @@ -451,8 +451,8 @@ package body Lib.Load is With_Node => With_Node); if Unump = No_Unit then - Parsing_Main_Extended_Source := Save_PMES; - return No_Unit; + Unum := No_Unit; + goto Done; end if; -- If parent is a renaming, then we use the renamed package as -- cgit v1.1 From e959418a07c3753877aac9a3194d740c38e7058b Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 25 May 2021 20:41:55 +0200 Subject: [Ada] Remove redundant condition for listing compilation units gcc/ada/ * par-ch10.adb (Unit_Display): Remove redundant condition; fix whitespace. --- gcc/ada/par-ch10.adb | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/par-ch10.adb b/gcc/ada/par-ch10.adb index 9a49d45..f02934a 100644 --- a/gcc/ada/par-ch10.adb +++ b/gcc/ada/par-ch10.adb @@ -1162,24 +1162,22 @@ package body Ch10 is Loc : Source_Ptr; SR_Present : Boolean) is - Unum : constant Unit_Number_Type := Get_Cunit_Unit_Number (Cunit); - Sind : constant Source_File_Index := Source_Index (Unum); - Unam : constant Unit_Name_Type := Unit_Name (Unum); + Unum : constant Unit_Number_Type := Get_Cunit_Unit_Number (Cunit); + Sind : constant Source_File_Index := Source_Index (Unum); + Unam : constant Unit_Name_Type := Unit_Name (Unum); begin - if List_Units then - Write_Str ("Unit "); - Write_Unit_Name (Unit_Name (Unum)); - Unit_Location (Sind, Loc); + Write_Str ("Unit "); + Write_Unit_Name (Unit_Name (Unum)); + Unit_Location (Sind, Loc); - if SR_Present then - Write_Str (", SR"); - end if; - - Write_Str (", file name "); - Write_Name (Get_File_Name (Unam, Nkind (Unit (Cunit)) = N_Subunit)); - Write_Eol; + if SR_Present then + Write_Str (", SR"); end if; + + Write_Str (", file name "); + Write_Name (Get_File_Name (Unam, Nkind (Unit (Cunit)) = N_Subunit)); + Write_Eol; end Unit_Display; ------------------- -- cgit v1.1 From 73f841cfca82827a60b9a4da8400f6686c85d3ec Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Thu, 27 May 2021 17:16:34 +0200 Subject: [Ada] Simplify redundant checks for non-empty lists gcc/ada/ * sem_ch12.adb, sem_ch6.adb, sem_ch9.adb, sprint.adb: Simplify checks for non-empty lists. --- gcc/ada/sem_ch12.adb | 1 - gcc/ada/sem_ch6.adb | 1 - gcc/ada/sem_ch9.adb | 4 +--- gcc/ada/sprint.adb | 8 ++------ 4 files changed, 3 insertions(+), 11 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index bf51ce9..85c854f 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -9724,7 +9724,6 @@ package body Sem_Ch12 is if Nkind (Par_N) = N_Package_Specification and then Decls = Visible_Declarations (Par_N) - and then Present (Private_Declarations (Par_N)) and then not Is_Empty_List (Private_Declarations (Par_N)) then Decls := Private_Declarations (Par_N); diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 75e5a99..fbb2b55 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -549,7 +549,6 @@ package body Sem_Ch6 is else if Nkind (Par) = N_Package_Specification and then Decls = Visible_Declarations (Par) - and then Present (Private_Declarations (Par)) and then not Is_Empty_List (Private_Declarations (Par)) then Decls := Private_Declarations (Par); diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb index 65f48a7..ab25dd0 100644 --- a/gcc/ada/sem_ch9.adb +++ b/gcc/ada/sem_ch9.adb @@ -1955,9 +1955,7 @@ package body Sem_Ch9 is Tasking_Used := True; Analyze_Declarations (Visible_Declarations (N)); - if Present (Private_Declarations (N)) - and then not Is_Empty_List (Private_Declarations (N)) - then + if not Is_Empty_List (Private_Declarations (N)) then Last_Id := Last_Entity (Prot_Typ); Analyze_Declarations (Private_Declarations (N)); diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb index 4467929..c1f1ede 100644 --- a/gcc/ada/sprint.adb +++ b/gcc/ada/sprint.adb @@ -1065,16 +1065,12 @@ package body Sprint is if Present (Expressions (Node)) then Sprint_Comma_List (Expressions (Node)); - if Present (Component_Associations (Node)) - and then not Is_Empty_List (Component_Associations (Node)) - then + if not Is_Empty_List (Component_Associations (Node)) then Write_Str (", "); end if; end if; - if Present (Component_Associations (Node)) - and then not Is_Empty_List (Component_Associations (Node)) - then + if not Is_Empty_List (Component_Associations (Node)) then Indent_Begin; declare -- cgit v1.1 From a9c3a4975013a9c3e29c03af5a1d0772d81aba12 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 31 May 2021 16:32:14 +0200 Subject: [Ada] Fix violation of No_Implicit_Loops restriction for enumeration type gcc/ada/ * exp_imgv.adb: Add with and use clause for Restrict and Rident. (Build_Enumeration_Image_Tables): Do not generate the hash function if the No_Implicit_Loops restriction is active. --- gcc/ada/exp_imgv.adb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_imgv.adb b/gcc/ada/exp_imgv.adb index 6e17a5c..d2605fb 100644 --- a/gcc/ada/exp_imgv.adb +++ b/gcc/ada/exp_imgv.adb @@ -37,6 +37,8 @@ with Namet; use Namet; with Nmake; use Nmake; with Nlists; use Nlists; with Opt; use Opt; +with Restrict; use Restrict; +with Rident; use Rident; with Rtsfind; use Rtsfind; with Sem_Aux; use Sem_Aux; with Sem_Res; use Sem_Res; @@ -160,6 +162,8 @@ package body Exp_Imgv is Expression => Make_Aggregate (Loc, Expressions => V))); end Append_Table_To; + -- Start of Build_Enumeration_Image_Tables + begin -- Nothing to do for types other than a root enumeration type @@ -247,7 +251,7 @@ package body Exp_Imgv is Append_Table_To (Act, Eind, Nlit, Ityp, Ind); -- If the number of literals is not greater than Threshold, then we are - -- done. Otherwise we compute a (perfect) hash function for use by the + -- done. Otherwise we generate a (perfect) hash function for use by the -- Value attribute. if Nlit > Threshold then @@ -283,11 +287,12 @@ package body Exp_Imgv is -- If the unit where the type is declared is the main unit, and the -- number of literals is greater than Threshold_For_Size when we are - -- optimizing for size, and -gnatd_h is not specified, try to compute - -- the hash function. + -- optimizing for size, and the restriction No_Implicit_Loops is not + -- active, and -gnatd_h is not specified, generate the hash function. if In_Main_Unit and then (Optimize_Size = 0 or else Nlit > Threshold_For_Size) + and then not Restriction_Active (No_Implicit_Loops) and then not Debug_Flag_Underscore_H then declare -- cgit v1.1 From 629c82d729f1439718aa3759416cdb6cb03052f1 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Fri, 28 May 2021 10:25:39 -0400 Subject: [Ada] Spurious warning in generic instance gcc/ada/ * sem_util.ads, sem_util.adb (Apply_Compile_Time_Constraint_Error): New parameter Emit_Message. * sem_ch4.adb (Analyze_Selected_Component): Disable warning within an instance. --- gcc/ada/sem_ch4.adb | 4 +++- gcc/ada/sem_util.adb | 21 ++++++++++++--------- gcc/ada/sem_util.ads | 16 +++++++++------- 3 files changed, 24 insertions(+), 17 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index 1bfd222..c052022 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -5471,7 +5471,9 @@ package body Sem_Ch4 is Apply_Compile_Time_Constraint_Error (N, "component not present in }??", CE_Discriminant_Check_Failed, - Ent => Prefix_Type); + Ent => Prefix_Type, + Emit_Message => + SPARK_Mode = On or not In_Instance_Not_Visible); return; end if; diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index ba84029..6fdacdc 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -1510,13 +1510,14 @@ package body Sem_Util is ----------------------------------------- procedure Apply_Compile_Time_Constraint_Error - (N : Node_Id; - Msg : String; - Reason : RT_Exception_Code; - Ent : Entity_Id := Empty; - Typ : Entity_Id := Empty; - Loc : Source_Ptr := No_Location; - Warn : Boolean := False) + (N : Node_Id; + Msg : String; + Reason : RT_Exception_Code; + Ent : Entity_Id := Empty; + Typ : Entity_Id := Empty; + Loc : Source_Ptr := No_Location; + Warn : Boolean := False; + Emit_Message : Boolean := True) is Stat : constant Boolean := Is_Static_Expression (N); R_Stat : constant Node_Id := @@ -1530,8 +1531,10 @@ package body Sem_Util is Rtyp := Typ; end if; - Discard_Node - (Compile_Time_Constraint_Error (N, Msg, Ent, Loc, Warn => Warn)); + if Emit_Message then + Discard_Node + (Compile_Time_Constraint_Error (N, Msg, Ent, Loc, Warn => Warn)); + end if; -- Now we replace the node by an N_Raise_Constraint_Error node -- This does not need reanalyzing, so set it as analyzed now. diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index fb8309f..440ac80 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -161,13 +161,14 @@ package Sem_Util is -- part of the current package. procedure Apply_Compile_Time_Constraint_Error - (N : Node_Id; - Msg : String; - Reason : RT_Exception_Code; - Ent : Entity_Id := Empty; - Typ : Entity_Id := Empty; - Loc : Source_Ptr := No_Location; - Warn : Boolean := False); + (N : Node_Id; + Msg : String; + Reason : RT_Exception_Code; + Ent : Entity_Id := Empty; + Typ : Entity_Id := Empty; + Loc : Source_Ptr := No_Location; + Warn : Boolean := False; + Emit_Message : Boolean := True); -- N is a subexpression that will raise Constraint_Error when evaluated -- at run time. Msg is a message that explains the reason for raising the -- exception. The last character is ? if the message is always a warning, @@ -189,6 +190,7 @@ package Sem_Util is -- when the caller wants to parameterize whether an error or warning is -- given), or when the message should be treated as a warning even when -- SPARK_Mode is On (which otherwise would force an error). + -- If Emit_Message is False, then do not emit any message. function Async_Readers_Enabled (Id : Entity_Id) return Boolean; -- Id should be the entity of a state abstraction, an object, or a type. -- cgit v1.1 From 3c18e32037a4ab02afd22a535a96ac4cc3f88b16 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Mon, 31 May 2021 04:59:01 -0400 Subject: [Ada] AI12-0156 Use subtype indication in generalized iterators gcc/ada/ * par-ch5.adb (P_Iterator_Specification): Add support for access definition in loop parameter. * sem_ch5.adb (Check_Subtype_Indication): Renamed... (Check_Subtype_Definition): ... into this and check for conformance on access definitions, and improve error messages. (Analyze_Iterator_Specification): Add support for access definition in loop parameter. --- gcc/ada/par-ch5.adb | 12 ++++++-- gcc/ada/sem_ch5.adb | 83 ++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 80 insertions(+), 15 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/par-ch5.adb b/gcc/ada/par-ch5.adb index 608ebd0..1e55181 100644 --- a/gcc/ada/par-ch5.adb +++ b/gcc/ada/par-ch5.adb @@ -1741,7 +1741,15 @@ package body Ch5 is if Token = Tok_Colon then Scan; -- past : - Set_Subtype_Indication (Node1, P_Subtype_Indication); + + if Token = Tok_Access then + Error_Msg_Ada_2022_Feature + ("access definition in loop parameter", Token_Ptr); + Set_Subtype_Indication (Node1, P_Access_Definition (False)); + + else + Set_Subtype_Indication (Node1, P_Subtype_Indication); + end if; end if; if Token = Tok_Of then @@ -1761,7 +1769,7 @@ package body Ch5 is Set_Of_Present (Node1); Error_Msg_N ("subtype indication is only legal on an element iterator", - Subtype_Indication (Node1)); + Subtype_Indication (Node1)); else return Error; diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb index fbb6904..f9813a5 100644 --- a/gcc/ada/sem_ch5.adb +++ b/gcc/ada/sem_ch5.adb @@ -2176,9 +2176,11 @@ package body Sem_Ch5 is -- indicator, verify that the container type has an Iterate aspect that -- implements the reversible iterator interface. - procedure Check_Subtype_Indication (Comp_Type : Entity_Id); + procedure Check_Subtype_Definition (Comp_Type : Entity_Id); -- If a subtype indication is present, verify that it is consistent -- with the component type of the array or container name. + -- In Ada 2022, the subtype indication may be an access definition, + -- if the array or container has elements of an anonymous access type. function Get_Cursor_Type (Typ : Entity_Id) return Entity_Id; -- For containers with Iterator and related aspects, the cursor is @@ -2209,24 +2211,46 @@ package body Sem_Ch5 is end Check_Reverse_Iteration; ------------------------------- - -- Check_Subtype_Indication -- + -- Check_Subtype_Definition -- ------------------------------- - procedure Check_Subtype_Indication (Comp_Type : Entity_Id) is + procedure Check_Subtype_Definition (Comp_Type : Entity_Id) is begin - if Present (Subt) - and then (not Covers (Base_Type ((Bas)), Comp_Type) + if not Present (Subt) then + return; + end if; + + if Is_Anonymous_Access_Type (Entity (Subt)) then + if not Is_Anonymous_Access_Type (Comp_Type) then + Error_Msg_NE + ("component type& is not an anonymous access", + Subt, Comp_Type); + + elsif not Conforming_Types + (Designated_Type (Entity (Subt)), + Designated_Type (Comp_Type), + Fully_Conformant) + then + Error_Msg_NE + ("subtype indication does not match component type&", + Subt, Comp_Type); + end if; + + elsif Present (Subt) + and then (not Covers (Base_Type (Bas), Comp_Type) or else not Subtypes_Statically_Match (Bas, Comp_Type)) then if Is_Array_Type (Typ) then - Error_Msg_N - ("subtype indication does not match component type", Subt); + Error_Msg_NE + ("subtype indication does not match component type&", + Subt, Comp_Type); else - Error_Msg_N - ("subtype indication does not match element type", Subt); + Error_Msg_NE + ("subtype indication does not match element type&", + Subt, Comp_Type); end if; end if; - end Check_Subtype_Indication; + end Check_Subtype_Definition; --------------------- -- Get_Cursor_Type -- @@ -2288,6 +2312,39 @@ package body Sem_Ch5 is Analyze (Decl); Rewrite (Subt, New_Occurrence_Of (S, Sloc (Subt))); end; + + -- Ada 2022: the subtype definition may be for an anonymous + -- access type. + + elsif Nkind (Subt) = N_Access_Definition then + declare + S : constant Entity_Id := Make_Temporary (Sloc (Subt), 'S'); + Decl : Node_Id; + begin + if Present (Subtype_Mark (Subt)) then + Decl := + Make_Full_Type_Declaration (Loc, + Defining_Identifier => S, + Type_Definition => + Make_Access_To_Object_Definition (Loc, + All_Present => True, + Subtype_Indication => + New_Copy_Tree (Subtype_Mark (Subt)))); + + else + Decl := + Make_Full_Type_Declaration (Loc, + Defining_Identifier => S, + Type_Definition => + New_Copy_Tree + (Access_To_Subprogram_Definition (Subt))); + end if; + + Insert_Before (Parent (Parent (N)), Decl); + Analyze (Decl); + Freeze_Before (First (Statements (Parent (Parent (N)))), S); + Rewrite (Subt, New_Occurrence_Of (S, Sloc (Subt))); + end; else Analyze (Subt); end if; @@ -2565,7 +2622,7 @@ package body Sem_Ch5 is & "component of a mutable object", N); end if; - Check_Subtype_Indication (Component_Type (Typ)); + Check_Subtype_Definition (Component_Type (Typ)); -- Here we have a missing Range attribute @@ -2615,7 +2672,7 @@ package body Sem_Ch5 is end if; end; - Check_Subtype_Indication (Etype (Def_Id)); + Check_Subtype_Definition (Etype (Def_Id)); -- For a predefined container, the type of the loop variable is -- the Iterator_Element aspect of the container type. @@ -2642,7 +2699,7 @@ package body Sem_Ch5 is Cursor_Type := Get_Cursor_Type (Typ); pragma Assert (Present (Cursor_Type)); - Check_Subtype_Indication (Etype (Def_Id)); + Check_Subtype_Definition (Etype (Def_Id)); -- If the container has a variable indexing aspect, the -- element is a variable and is modifiable in the loop. -- cgit v1.1 From 99d6c1f8c29da41c33059024ff7494834b3bfbdc Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Sat, 29 May 2021 10:14:46 -0400 Subject: [Ada] Spurious style message on missing overriding indicator gcc/ada/ * style.adb (Missing_Overriding): Do not emit message when parent of subprogram is a full type declaration. --- gcc/ada/style.adb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/style.adb b/gcc/ada/style.adb index 1409cc6..c2bff83 100644 --- a/gcc/ada/style.adb +++ b/gcc/ada/style.adb @@ -265,11 +265,15 @@ package body Style is -- indicators were introduced in Ada 2005. We apply Comes_From_Source -- to Original_Node to catch the case of a procedure body declared with -- "is null" that has been rewritten as a normal empty body. + -- We do not emit a warning on an inherited operation that comes from + -- a type derivation. if Style_Check_Missing_Overriding and then (Comes_From_Source (Original_Node (N)) or else Is_Generic_Instance (E)) and then Ada_Version_Explicit >= Ada_2005 + and then Present (Parent (E)) + and then Nkind (Parent (E)) /= N_Full_Type_Declaration then -- If the subprogram is an instantiation, its declaration appears -- within a wrapper package that precedes the instance node. Place -- cgit v1.1 From d75dde1a7234c4ff556bd9e6ab55ca95baa00262 Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Thu, 27 May 2021 14:54:14 +0200 Subject: [Ada] Duplicated D lines in ali files gcc/ada/ * lib-writ.ads: Mention SCOs dependency as reason for duplicates. * lib.ads (Units): Update documentation to mention duplicated units. --- gcc/ada/lib-writ.ads | 3 +++ gcc/ada/lib.ads | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/lib-writ.ads b/gcc/ada/lib-writ.ads index b8370fa..ce5398b 100644 --- a/gcc/ada/lib-writ.ads +++ b/gcc/ada/lib-writ.ads @@ -1053,6 +1053,9 @@ package Lib.Writ is -- The Object parameter is true if an object file is created, and false -- otherwise. Note that the pseudo-object file generated in GNATprove mode -- does count as an object file from this point of view. + -- May output duplicate D lines caused by generic instantiations. This is + -- by design as GNATcoverage relies on them for its coverage of generic + -- instantiations, although this may be revisited in the future. procedure Add_Preprocessing_Dependency (S : Source_File_Index); -- Indicate that there is a dependency to be added on a preprocessing data diff --git a/gcc/ada/lib.ads b/gcc/ada/lib.ads index 1450124..f2c6ef3 100644 --- a/gcc/ada/lib.ads +++ b/gcc/ada/lib.ads @@ -926,7 +926,9 @@ private -- The following table records a mapping between a name and the entry in -- the units table whose Unit_Name is this name. It is used to speed up -- the Is_Loaded function, whose original implementation (linear search) - -- could account for 2% of the time spent in the front end. Note that, in + -- could account for 2% of the time spent in the front end. When the unit + -- is an instance of a generic, the unit might get duplicated in the unit + -- table - see Make_Instance_Unit for more information. Note that, in -- the case of source files containing multiple units, the units table may -- temporarily contain two entries with the same Unit_Name during parsing, -- which means that the mapping must be to the first entry in the table. -- cgit v1.1 From 6e8b502cb6c3e30ac59fc446b2e765e5b5a9d5a6 Mon Sep 17 00:00:00 2001 From: Doug Rupp Date: Thu, 3 Jun 2021 09:21:23 -0700 Subject: [Ada] Rename sigtramp-vxworks-target.inc to sigtramp-vxworks-target.h gcc/ada/ * sigtramp-vxworks-target.inc: Rename to... * sigtramp-vxworks-target.h: ... this. * sigtramp-vxworks.c, Makefile.rtl: Likewise. --- gcc/ada/Makefile.rtl | 2 +- gcc/ada/sigtramp-vxworks-target.h | 585 ++++++++++++++++++++++++++++++++++++ gcc/ada/sigtramp-vxworks-target.inc | 585 ------------------------------------ gcc/ada/sigtramp-vxworks.c | 2 +- 4 files changed, 587 insertions(+), 587 deletions(-) create mode 100644 gcc/ada/sigtramp-vxworks-target.h delete mode 100644 gcc/ada/sigtramp-vxworks-target.inc (limited to 'gcc') diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index e421c7c..fbd3993 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -1043,7 +1043,7 @@ EXTRA_GNATRTL_NONTASKING_OBJS= EXTRA_GNATRTL_TASKING_OBJS= # Subsets of extra libgnat sources that always go together -VX_SIGTRAMP_EXTRA_SRCS=sigtramp.h sigtramp-vxworks-target.inc +VX_SIGTRAMP_EXTRA_SRCS=sigtramp.h sigtramp-vxworks-target.h # Additional object files that should go in the same directory as libgnat, # aside the library itself. Typically useful for crtbegin/crtend kind of files. diff --git a/gcc/ada/sigtramp-vxworks-target.h b/gcc/ada/sigtramp-vxworks-target.h new file mode 100644 index 0000000..8c43451 --- /dev/null +++ b/gcc/ada/sigtramp-vxworks-target.h @@ -0,0 +1,585 @@ +/**************************************************************************** + * * + * GNAT COMPILER COMPONENTS * + * * + * S I G T R A M P - T A R G E T * + * * + * Asm Implementation Include File * + * * + * Copyright (C) 2011-2021, Free Software Foundation, Inc. * + * * + * GNAT is free software; you can redistribute it and/or modify it under * + * terms of the GNU General Public License as published by the Free Soft- * + * ware Foundation; either version 3, or (at your option) any later ver- * + * sion. GNAT is distributed in the hope that it will be useful, but WITH- * + * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. * + * * + * As a special exception under Section 7 of GPL version 3, you are granted * + * additional permissions described in the GCC Runtime Library Exception, * + * version 3.1, as published by the Free Software Foundation. * + * * + * In particular, you can freely distribute your programs built with the * + * GNAT Pro compiler, including any required library run-time units, using * + * any licensing terms of your choosing. See the AdaCore Software License * + * for full details. * + * * + * GNAT was originally developed by the GNAT team at New York University. * + * Extensive contributions were provided by Ada Core Technologies Inc. * + * * + ****************************************************************************/ + +/*************************************************************** + * VxWorks target specific part of the __gnat_sigtramp service * + ***************************************************************/ + +/* Note: This target specific part is kept in a separate file to avoid + duplication of its code for the vxworks and vxworks-vxsim asm + implementation files. */ + +/* --------------------------- + -- And now the asm stubs -- + --------------------------- + + They all have a common structure with blocks of asm sequences queued one + after the others. Typically: + + SYMBOL_START + + CFI_DIRECTIVES + CFI_DEF_CFA, + CFI_COMMON_REGISTERS, + ... + + STUB_BODY + asm code to establish frame, setup the cfa reg value, + call the real signal handler, ... + + SYMBOL_END +*/ + +/*-------------------------------- + -- Misc constants and helpers -- + -------------------------------- */ + +/* asm string construction helpers. */ + +#define STR(TEXT) #TEXT +/* stringify expanded TEXT, surrounding it with double quotes. */ + +#define S(E) STR(E) +/* stringify E, which will resolve as text but may contain macros + still to be expanded. */ + +/* asm (TEXT) outputs TEXT. These facilitate the output of + multine contents: */ +#define TAB(S) "\t" S +#define CR(S) S "\n" + +#undef TCR +#define TCR(S) TAB(CR(S)) + +/* REGNO constants, dwarf column numbers for registers of interest. */ + +#if defined (__PPC__) + +#define REGNO_LR 65 +#define REGNO_CTR 66 +#define REGNO_CR 70 +#define REGNO_XER 76 +#define REGNO_GR(N) (N) + +#define REGNO_PC 67 /* ARG_POINTER_REGNUM */ + +#define FUNCTION "@function" + +#elif defined (ARMEL) + +#define REGNO_G_REG_OFFSET(N) (N) + +#define FUNCTION "%function" + +#ifdef __aarch64__ +#define REGNO_PC_OFFSET 96 /* DWARF_ALT_FRAME_RETURN_COLUMN */ +#else +#define REGNO_PC_OFFSET 15 /* PC_REGNUM */ +#endif + +/* Mapping of CFI Column, Gcc Regno, Signal context offset for _LP64 + + Name CFI GCC SCTX + G0-G30 0-30 0-30 0-30 + SP 31 31 31 + PC 32 + V0-V31 64-95 32-63 N/A + +*/ + +#elif defined (i386) + +/* These are the cfi colunm numbers */ + +#define REGNO_EDI 7 +#define REGNO_ESI 6 +#define REGNO_EBP 5 +#define REGNO_ESP 4 +#define REGNO_EBX 3 +#define REGNO_EDX 2 +#define REGNO_ECX 1 +#define REGNO_EAX 0 +#define REGNO_EFLAGS 9 +#define REGNO_SET_PC 8 /* aka %eip */ + +#define FUNCTION "@function" + +/* Mapping of CFI Column, Gcc Regno, Signal context offset for 32bit + + Name CFI GCC SCTX + %eax 0 0 7 + %ecx 1 2 6 + %edx 2 1 5 + %ebx 3 3 4 + %esp 4 7 3 + %ebp 5 6 2 + %esi 6 4 1 + %edi 7 5 0 + %eflags 9 17 8 + %eip 8 n/a 9 + + + In general: + There is no unique numbering for the x86 architecture. It's parameterized + by DWARF_FRAME_REGNUM, which is DBX_REGISTER_NUMBER except for Windows, and + the latter depends on the platform. +*/ + +#elif defined (__x86_64__) + +/* These are the cfi colunm numbers */ + +#define REGNO_RAX 0 +#define REGNO_RDX 1 +#define REGNO_RCX 2 +#define REGNO_RBX 3 +#define REGNO_RSI 4 +#define REGNO_RDI 5 +#define REGNO_RBP 6 +#define REGNO_RSP 7 +#define REGNO_R8 8 +#define REGNO_R9 9 +#define REGNO_R10 10 +#define REGNO_R11 11 +#define REGNO_R12 12 +#define REGNO_R13 13 +#define REGNO_R14 14 +#define REGNO_R15 15 +#define REGNO_RPC 16 /* aka %rip */ +#define REGNO_EFLAGS 49 +#define REGNO_FS 54 + +#define FUNCTION "@function" + +#else +Not_implemented; +#endif /* REGNO constants */ + + +/*------------------------------ + -- Stub construction blocks -- + ------------------------------ */ + +/* CFA setup block + --------------- + Only non-volatile registers are suitable for a CFA base. These are the + only ones we can expect to be able retrieve from the unwinding context + while walking up the chain, saved by at least the bottom-most exception + propagation services. We set a non-volatile register to the value we + need in the stub body that follows. */ + +#if defined (__PPC__) + +/* Use r15 for PPC. Note that r14 is inappropriate here, even though it + is non-volatile according to the ABI, because GCC uses it as an extra + SCRATCH on SPE targets. */ + +#define CFA_REG 15 + +#elif defined (ARMEL) + +#ifdef __aarch64__ +#define CFA_REG 19 +#else +/* Use r8 for ARM. Any of r4-r8 should work. */ +#define CFA_REG 8 +#endif + +#elif defined (i386) + +#define CFA_REG 7 + +#elif defined (__x86_64__) + +/* R15 register */ +#define CFA_REG 15 + +#else +Not_implemented; +#endif /* CFA setup block */ + +#define CFI_DEF_CFA \ +CR(".cfi_def_cfa " S(CFA_REG) ", 0") + +/* Register location blocks + ------------------------ + Rules to find registers of interest from the CFA. This should comprise + all the non-volatile registers relevant to the interrupted context. + + Note that we include r1 in this set, unlike the libgcc unwinding + fallbacks. This is useful for fallbacks to allow the use of r1 in CFI + expressions and the absence of rule for r1 gets compensated by using the + target CFA instead. We don't need the expression facility here and + setup a fake CFA to allow very simple offset expressions, so having a + rule for r1 is the proper thing to do. We for sure have observed + crashes in some cases without it. */ + +#if defined (__PPC__) + +#define COMMON_CFI(REG) \ + ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG) + +#define CFI_COMMON_REGS \ +CR("# CFI for common registers\n") \ +TCR(COMMON_CFI(GR(0))) \ +TCR(COMMON_CFI(GR(1))) \ +TCR(COMMON_CFI(GR(2))) \ +TCR(COMMON_CFI(GR(3))) \ +TCR(COMMON_CFI(GR(4))) \ +TCR(COMMON_CFI(GR(5))) \ +TCR(COMMON_CFI(GR(6))) \ +TCR(COMMON_CFI(GR(7))) \ +TCR(COMMON_CFI(GR(8))) \ +TCR(COMMON_CFI(GR(9))) \ +TCR(COMMON_CFI(GR(10))) \ +TCR(COMMON_CFI(GR(11))) \ +TCR(COMMON_CFI(GR(12))) \ +TCR(COMMON_CFI(GR(13))) \ +TCR(COMMON_CFI(GR(14))) \ +TCR(COMMON_CFI(GR(15))) \ +TCR(COMMON_CFI(GR(16))) \ +TCR(COMMON_CFI(GR(17))) \ +TCR(COMMON_CFI(GR(18))) \ +TCR(COMMON_CFI(GR(19))) \ +TCR(COMMON_CFI(GR(20))) \ +TCR(COMMON_CFI(GR(21))) \ +TCR(COMMON_CFI(GR(22))) \ +TCR(COMMON_CFI(GR(23))) \ +TCR(COMMON_CFI(GR(24))) \ +TCR(COMMON_CFI(GR(25))) \ +TCR(COMMON_CFI(GR(26))) \ +TCR(COMMON_CFI(GR(27))) \ +TCR(COMMON_CFI(GR(28))) \ +TCR(COMMON_CFI(GR(29))) \ +TCR(COMMON_CFI(GR(30))) \ +TCR(COMMON_CFI(GR(31))) \ +TCR(COMMON_CFI(LR)) \ +TCR(COMMON_CFI(CR)) \ +TCR(COMMON_CFI(CTR)) \ +TCR(COMMON_CFI(XER)) \ +TCR(COMMON_CFI(PC)) \ +TCR(".cfi_return_column " S(REGNO_PC)) + +/* Trampoline body block + --------------------- */ + +#if !defined (__PPC64__) +#define SIGTRAMP_BODY \ +CR("") \ +TCR("# Allocate frame and save the non-volatile") \ +TCR("# registers we're going to modify") \ +TCR("stwu %r1,-16(%r1)") \ +TCR("mflr %r0") \ +TCR("stw %r0,20(%r1)") \ +TCR("stw %r" S(CFA_REG) ",8(%r1)") \ +TCR("") \ +TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ +TCR("mr %r" S(CFA_REG) ", %r7") \ +TCR("") \ +TCR("# Call the real handler. The signo, siginfo and sigcontext") \ +TCR("# arguments are the same as those we received in r3, r4 and r5") \ +TCR("mtctr %r6") \ +TCR("bctrl") \ +TCR("") \ +TCR("# Restore our callee-saved items, release our frame and return") \ +TCR("lwz %r" S(CFA_REG) ",8(%r1)") \ +TCR("lwz %r0,20(%r1)") \ +TCR("mtlr %r0") \ +TCR("") \ +TCR("addi %r1,%r1,16") \ +TCR("blr") +#else +#define SIGTRAMP_BODY \ +CR("") \ +TCR(".LOC_SIGTMP_COM_0:") \ +TCR("addis 2,12,.TOC.-.LOC_SIGTMP_COM_0@ha") \ +TCR("addi 2,2,.TOC.-.LOC_SIGTMP_COM_0@l") \ +TCR(".localentry __gnat_sigtramp_common,.-__gnat_sigtramp_common") \ +TCR("# Allocate frame and save the non-volatile") \ +TCR("# registers we're going to modify") \ +TCR("mflr %r0") \ +TCR("std %r0,16(%r1)") \ +TCR("stdu %r1,-32(%r1)") \ +TCR("std %r2,24(%r1)") \ +TCR("std %r" S(CFA_REG) ",8(%r1)") \ +TCR("") \ +TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ +TCR("mr %r" S(CFA_REG) ", %r7") \ +TCR("") \ +TCR("# Call the real handler. The signo, siginfo and sigcontext") \ +TCR("# arguments are the same as those we received in r3, r4 and r5") \ +TCR("mr %r12,%r6") \ +TCR("mtctr %r6") \ +TCR("bctrl") \ +TCR("") \ +TCR("# Restore our callee-saved items, release our frame and return") \ +TCR("ld %r" S(CFA_REG) ",8(%r1)") \ +TCR("ld %r2,24(%r1)") \ +TCR("addi %r1,%r1,32") \ +TCR("ld %r0,16(%r1)") \ +TCR("mtlr %r0") \ +TCR("blr") +#endif + +#elif defined (ARMEL) + +#define COMMON_CFI(REG) \ + ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG) + +#ifdef __aarch64__ +#define CFI_COMMON_REGS \ +CR("# CFI for common registers\n") \ +TCR(COMMON_CFI(G_REG_OFFSET(0))) \ +TCR(COMMON_CFI(G_REG_OFFSET(1))) \ +TCR(COMMON_CFI(G_REG_OFFSET(2))) \ +TCR(COMMON_CFI(G_REG_OFFSET(3))) \ +TCR(COMMON_CFI(G_REG_OFFSET(4))) \ +TCR(COMMON_CFI(G_REG_OFFSET(5))) \ +TCR(COMMON_CFI(G_REG_OFFSET(6))) \ +TCR(COMMON_CFI(G_REG_OFFSET(7))) \ +TCR(COMMON_CFI(G_REG_OFFSET(8))) \ +TCR(COMMON_CFI(G_REG_OFFSET(9))) \ +TCR(COMMON_CFI(G_REG_OFFSET(10))) \ +TCR(COMMON_CFI(G_REG_OFFSET(11))) \ +TCR(COMMON_CFI(G_REG_OFFSET(12))) \ +TCR(COMMON_CFI(G_REG_OFFSET(13))) \ +TCR(COMMON_CFI(G_REG_OFFSET(14))) \ +TCR(COMMON_CFI(G_REG_OFFSET(15))) \ +TCR(COMMON_CFI(G_REG_OFFSET(16))) \ +TCR(COMMON_CFI(G_REG_OFFSET(17))) \ +CR("# Leave alone R18, VxWorks reserved\n") \ +TCR(COMMON_CFI(G_REG_OFFSET(19))) \ +TCR(COMMON_CFI(G_REG_OFFSET(20))) \ +TCR(COMMON_CFI(G_REG_OFFSET(21))) \ +TCR(COMMON_CFI(G_REG_OFFSET(22))) \ +TCR(COMMON_CFI(G_REG_OFFSET(23))) \ +TCR(COMMON_CFI(G_REG_OFFSET(24))) \ +TCR(COMMON_CFI(G_REG_OFFSET(25))) \ +TCR(COMMON_CFI(G_REG_OFFSET(26))) \ +TCR(COMMON_CFI(G_REG_OFFSET(27))) \ +TCR(COMMON_CFI(G_REG_OFFSET(28))) \ +TCR(COMMON_CFI(G_REG_OFFSET(29))) \ +TCR(COMMON_CFI(G_REG_OFFSET(30))) \ +TCR(COMMON_CFI(G_REG_OFFSET(31))) \ +TCR(COMMON_CFI(PC_OFFSET)) \ +TCR(".cfi_return_column " S(REGNO_PC_OFFSET)) +#else +#define CFI_COMMON_REGS \ +CR("# CFI for common registers\n") \ +TCR(COMMON_CFI(G_REG_OFFSET(0))) \ +TCR(COMMON_CFI(G_REG_OFFSET(1))) \ +TCR(COMMON_CFI(G_REG_OFFSET(2))) \ +TCR(COMMON_CFI(G_REG_OFFSET(3))) \ +TCR(COMMON_CFI(G_REG_OFFSET(4))) \ +TCR(COMMON_CFI(G_REG_OFFSET(5))) \ +TCR(COMMON_CFI(G_REG_OFFSET(6))) \ +TCR(COMMON_CFI(G_REG_OFFSET(7))) \ +TCR(COMMON_CFI(G_REG_OFFSET(8))) \ +TCR(COMMON_CFI(G_REG_OFFSET(9))) \ +TCR(COMMON_CFI(G_REG_OFFSET(10))) \ +TCR(COMMON_CFI(G_REG_OFFSET(11))) \ +TCR(COMMON_CFI(G_REG_OFFSET(12))) \ +TCR(COMMON_CFI(G_REG_OFFSET(13))) \ +TCR(COMMON_CFI(G_REG_OFFSET(14))) \ +TCR(COMMON_CFI(PC_OFFSET)) \ +TCR(".cfi_return_column " S(REGNO_PC_OFFSET)) +#endif + +/* Trampoline body block + --------------------- */ +#ifdef __aarch64__ +#define SIGTRAMP_BODY \ +CR("") \ +TCR("# Allocate the frame (16bytes aligned) and push FP and LR") \ +TCR("stp x29, x30, [sp, #-32]!") \ +TCR("add x29, sp, 0") \ +TCR("# Store register used to hold the CFA on stack (pro forma)") \ +TCR("str x" S(CFA_REG) ", [sp, 16]") \ +TCR("# Set the CFA reg from the 5th arg") \ +TCR("mov x" S(CFA_REG) ", x4") \ +TCR("# Call the handler") \ +TCR("blr x3") \ +TCR("# Release our frame and return (should never get here!).") \ +TCR("ldr x" S(CFA_REG) ", [sp, 16]") \ +TCR("ldp x29, x30, [sp], 32") \ +TCR("ret") +#else +#define SIGTRAMP_BODY \ +CR("") \ +TCR("# Allocate frame and save the non-volatile") \ +TCR("# registers we're going to modify") \ +TCR("mov ip, sp") \ +TCR("stmfd sp!, {r"S(CFA_REG)", fp, ip, lr, pc}") \ +TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ +TCR("ldr r"S(CFA_REG)", [ip]") \ +TCR("") \ +TCR("# Call the real handler. The signo, siginfo and sigcontext") \ +TCR("# arguments are the same as those we received in r0, r1 and r2") \ +TCR("sub fp, ip, #4") \ +TCR("blx r3") \ +TCR("# Restore our callee-saved items, release our frame and return") \ +TCR("ldmfd sp, {r"S(CFA_REG)", fp, sp, pc}") +#endif + +#elif defined (i386) + +#if CPU == SIMNT || CPU == SIMPENTIUM || CPU == SIMLINUX +#define COMMON_CFI(REG) \ + ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG) +#else +#define COMMON_CFI(REG) \ + ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG) +#endif + +#define PC_CFI(REG) \ + ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG) + +#define CFI_COMMON_REGS \ +CR("# CFI for common registers\n") \ +TCR(COMMON_CFI(EDI)) \ +TCR(COMMON_CFI(ESI)) \ +TCR(COMMON_CFI(EBP)) \ +TCR(COMMON_CFI(ESP)) \ +TCR(COMMON_CFI(EBX)) \ +TCR(COMMON_CFI(EDX)) \ +TCR(COMMON_CFI(ECX)) \ +TCR(COMMON_CFI(EAX)) \ +TCR(COMMON_CFI(EFLAGS)) \ +TCR(PC_CFI(SET_PC)) \ +TCR(".cfi_return_column " S(REGNO_SET_PC)) + +/* Trampoline body block + --------------------- */ + +#define SIGTRAMP_BODY \ +CR("") \ +TCR("# Allocate frame and save the non-volatile") \ +TCR("# registers we're going to modify") \ +TCR("pushl %ebp") \ +TCR("movl %esp, %ebp") \ +TCR("pushl %edi") \ +TCR("subl $24, %esp") \ +TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ +TCR("movl 24(%ebp), %edi") \ +TCR("# Call the real handler. The signo, siginfo and sigcontext") \ +TCR("# arguments are the same as those we received") \ +TCR("movl 16(%ebp), %eax") \ +TCR("movl %eax, 8(%esp)") \ +TCR("movl 12(%ebp), %eax") \ +TCR("movl %eax, 4(%esp)") \ +TCR("movl 8(%ebp), %eax") \ +TCR("movl %eax, (%esp)") \ +TCR("call *20(%ebp)") \ +TCR("# Restore our callee-saved items, release our frame and return") \ +TCR("popl %edi") \ +TCR("leave") \ +TCR("ret") + +#elif defined (__x86_64__) + +#define COMMON_CFI(REG) \ + ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG) + +#define CFI_COMMON_REGS \ +CR("# CFI for common registers\n") \ +TCR(COMMON_CFI(R15)) \ +TCR(COMMON_CFI(R14)) \ +TCR(COMMON_CFI(R13)) \ +TCR(COMMON_CFI(R12)) \ +TCR(COMMON_CFI(R11)) \ +TCR(COMMON_CFI(R10)) \ +TCR(COMMON_CFI(R9)) \ +TCR(COMMON_CFI(R8)) \ +TCR(COMMON_CFI(RDI)) \ +TCR(COMMON_CFI(RSI)) \ +TCR(COMMON_CFI(RBP)) \ +TCR(COMMON_CFI(RSP)) \ +TCR(COMMON_CFI(RBX)) \ +TCR(COMMON_CFI(RDX)) \ +TCR(COMMON_CFI(RCX)) \ +TCR(COMMON_CFI(RAX)) \ +TCR(COMMON_CFI(RPC)) \ +TCR(".cfi_return_column " S(REGNO_RPC)) + +/* Trampoline body block + --------------------- */ + +#define SIGTRAMP_BODY \ +CR("") \ +TCR("# Allocate frame and save the non-volatile") \ +TCR("# registers we're going to modify") \ +TCR("subq $8, %rsp") \ +TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ +TCR("movq %r8, %r15") \ +TCR("# Call the real handler. The signo, siginfo and sigcontext") \ +TCR("# arguments are the same as those we received") \ +TCR("call *%rcx") \ +TCR("# This part should never be executed") \ +TCR("addq $8, %rsp") \ +TCR("ret") + +#else +Not_implemented; +#endif /* CFI_COMMON_REGS and SIGTRAMP_BODY */ + +/* Symbol definition block + ----------------------- */ + +#ifdef __x86_64__ +#define FUNC_ALIGN TCR(".p2align 4,,15") +#else +#define FUNC_ALIGN +#endif + +#define SIGTRAMP_START(SYM) \ +CR("# " S(SYM) " cfi trampoline") \ +TCR(".type " S(SYM) ", "FUNCTION) \ +CR("") \ +FUNC_ALIGN \ +CR(S(SYM) ":") \ +TCR(".cfi_startproc") \ +TCR(".cfi_signal_frame") + +/* Symbol termination block + ------------------------ */ + +#define SIGTRAMP_END(SYM) \ +CR(".cfi_endproc") \ +TCR(".size " S(SYM) ", .-" S(SYM)) + +/*---------------------------- + -- And now, the real code -- + ---------------------------- */ + +/* Text section start. The compiler isn't aware of that switch. */ + +asm (".text\n" + TCR(".align 2")); diff --git a/gcc/ada/sigtramp-vxworks-target.inc b/gcc/ada/sigtramp-vxworks-target.inc deleted file mode 100644 index 5a37b87..0000000 --- a/gcc/ada/sigtramp-vxworks-target.inc +++ /dev/null @@ -1,585 +0,0 @@ -/**************************************************************************** - * * - * GNAT COMPILER COMPONENTS * - * * - * S I G T R A M P - T A R G E T * - * * - * Asm Implementation Include File * - * * - * Copyright (C) 2011-2018, Free Software Foundation, Inc. * - * * - * GNAT is free software; you can redistribute it and/or modify it under * - * terms of the GNU General Public License as published by the Free Soft- * - * ware Foundation; either version 3, or (at your option) any later ver- * - * sion. GNAT is distributed in the hope that it will be useful, but WITH- * - * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. * - * * - * As a special exception under Section 7 of GPL version 3, you are granted * - * additional permissions described in the GCC Runtime Library Exception, * - * version 3.1, as published by the Free Software Foundation. * - * * - * In particular, you can freely distribute your programs built with the * - * GNAT Pro compiler, including any required library run-time units, using * - * any licensing terms of your choosing. See the AdaCore Software License * - * for full details. * - * * - * GNAT was originally developed by the GNAT team at New York University. * - * Extensive contributions were provided by Ada Core Technologies Inc. * - * * - ****************************************************************************/ - -/*************************************************************** - * VxWorks target specific part of the __gnat_sigtramp service * - ***************************************************************/ - -/* Note: This target specific part is kept in a separate file to avoid - duplication of its code for the vxworks and vxworks-vxsim asm - implementation files. */ - -/* --------------------------- - -- And now the asm stubs -- - --------------------------- - - They all have a common structure with blocks of asm sequences queued one - after the others. Typically: - - SYMBOL_START - - CFI_DIRECTIVES - CFI_DEF_CFA, - CFI_COMMON_REGISTERS, - ... - - STUB_BODY - asm code to establish frame, setup the cfa reg value, - call the real signal handler, ... - - SYMBOL_END -*/ - -/*-------------------------------- - -- Misc constants and helpers -- - -------------------------------- */ - -/* asm string construction helpers. */ - -#define STR(TEXT) #TEXT -/* stringify expanded TEXT, surrounding it with double quotes. */ - -#define S(E) STR(E) -/* stringify E, which will resolve as text but may contain macros - still to be expanded. */ - -/* asm (TEXT) outputs TEXT. These facilitate the output of - multine contents: */ -#define TAB(S) "\t" S -#define CR(S) S "\n" - -#undef TCR -#define TCR(S) TAB(CR(S)) - -/* REGNO constants, dwarf column numbers for registers of interest. */ - -#if defined (__PPC__) - -#define REGNO_LR 65 -#define REGNO_CTR 66 -#define REGNO_CR 70 -#define REGNO_XER 76 -#define REGNO_GR(N) (N) - -#define REGNO_PC 67 /* ARG_POINTER_REGNUM */ - -#define FUNCTION "@function" - -#elif defined (ARMEL) - -#define REGNO_G_REG_OFFSET(N) (N) - -#define FUNCTION "%function" - -#ifdef __aarch64__ -#define REGNO_PC_OFFSET 96 /* DWARF_ALT_FRAME_RETURN_COLUMN */ -#else -#define REGNO_PC_OFFSET 15 /* PC_REGNUM */ -#endif - -/* Mapping of CFI Column, Gcc Regno, Signal context offset for _LP64 - - Name CFI GCC SCTX - G0-G30 0-30 0-30 0-30 - SP 31 31 31 - PC 32 - V0-V31 64-95 32-63 N/A - -*/ - -#elif defined (i386) - -/* These are the cfi colunm numbers */ - -#define REGNO_EDI 7 -#define REGNO_ESI 6 -#define REGNO_EBP 5 -#define REGNO_ESP 4 -#define REGNO_EBX 3 -#define REGNO_EDX 2 -#define REGNO_ECX 1 -#define REGNO_EAX 0 -#define REGNO_EFLAGS 9 -#define REGNO_SET_PC 8 /* aka %eip */ - -#define FUNCTION "@function" - -/* Mapping of CFI Column, Gcc Regno, Signal context offset for 32bit - - Name CFI GCC SCTX - %eax 0 0 7 - %ecx 1 2 6 - %edx 2 1 5 - %ebx 3 3 4 - %esp 4 7 3 - %ebp 5 6 2 - %esi 6 4 1 - %edi 7 5 0 - %eflags 9 17 8 - %eip 8 n/a 9 - - - In general: - There is no unique numbering for the x86 architecture. It's parameterized - by DWARF_FRAME_REGNUM, which is DBX_REGISTER_NUMBER except for Windows, and - the latter depends on the platform. -*/ - -#elif defined (__x86_64__) - -/* These are the cfi colunm numbers */ - -#define REGNO_RAX 0 -#define REGNO_RDX 1 -#define REGNO_RCX 2 -#define REGNO_RBX 3 -#define REGNO_RSI 4 -#define REGNO_RDI 5 -#define REGNO_RBP 6 -#define REGNO_RSP 7 -#define REGNO_R8 8 -#define REGNO_R9 9 -#define REGNO_R10 10 -#define REGNO_R11 11 -#define REGNO_R12 12 -#define REGNO_R13 13 -#define REGNO_R14 14 -#define REGNO_R15 15 -#define REGNO_RPC 16 /* aka %rip */ -#define REGNO_EFLAGS 49 -#define REGNO_FS 54 - -#define FUNCTION "@function" - -#else -Not_implemented; -#endif /* REGNO constants */ - - -/*------------------------------ - -- Stub construction blocks -- - ------------------------------ */ - -/* CFA setup block - --------------- - Only non-volatile registers are suitable for a CFA base. These are the - only ones we can expect to be able retrieve from the unwinding context - while walking up the chain, saved by at least the bottom-most exception - propagation services. We set a non-volatile register to the value we - need in the stub body that follows. */ - -#if defined (__PPC__) - -/* Use r15 for PPC. Note that r14 is inappropriate here, even though it - is non-volatile according to the ABI, because GCC uses it as an extra - SCRATCH on SPE targets. */ - -#define CFA_REG 15 - -#elif defined (ARMEL) - -#ifdef __aarch64__ -#define CFA_REG 19 -#else -/* Use r8 for ARM. Any of r4-r8 should work. */ -#define CFA_REG 8 -#endif - -#elif defined (i386) - -#define CFA_REG 7 - -#elif defined (__x86_64__) - -/* R15 register */ -#define CFA_REG 15 - -#else -Not_implemented; -#endif /* CFA setup block */ - -#define CFI_DEF_CFA \ -CR(".cfi_def_cfa " S(CFA_REG) ", 0") - -/* Register location blocks - ------------------------ - Rules to find registers of interest from the CFA. This should comprise - all the non-volatile registers relevant to the interrupted context. - - Note that we include r1 in this set, unlike the libgcc unwinding - fallbacks. This is useful for fallbacks to allow the use of r1 in CFI - expressions and the absence of rule for r1 gets compensated by using the - target CFA instead. We don't need the expression facility here and - setup a fake CFA to allow very simple offset expressions, so having a - rule for r1 is the proper thing to do. We for sure have observed - crashes in some cases without it. */ - -#if defined (__PPC__) - -#define COMMON_CFI(REG) \ - ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG) - -#define CFI_COMMON_REGS \ -CR("# CFI for common registers\n") \ -TCR(COMMON_CFI(GR(0))) \ -TCR(COMMON_CFI(GR(1))) \ -TCR(COMMON_CFI(GR(2))) \ -TCR(COMMON_CFI(GR(3))) \ -TCR(COMMON_CFI(GR(4))) \ -TCR(COMMON_CFI(GR(5))) \ -TCR(COMMON_CFI(GR(6))) \ -TCR(COMMON_CFI(GR(7))) \ -TCR(COMMON_CFI(GR(8))) \ -TCR(COMMON_CFI(GR(9))) \ -TCR(COMMON_CFI(GR(10))) \ -TCR(COMMON_CFI(GR(11))) \ -TCR(COMMON_CFI(GR(12))) \ -TCR(COMMON_CFI(GR(13))) \ -TCR(COMMON_CFI(GR(14))) \ -TCR(COMMON_CFI(GR(15))) \ -TCR(COMMON_CFI(GR(16))) \ -TCR(COMMON_CFI(GR(17))) \ -TCR(COMMON_CFI(GR(18))) \ -TCR(COMMON_CFI(GR(19))) \ -TCR(COMMON_CFI(GR(20))) \ -TCR(COMMON_CFI(GR(21))) \ -TCR(COMMON_CFI(GR(22))) \ -TCR(COMMON_CFI(GR(23))) \ -TCR(COMMON_CFI(GR(24))) \ -TCR(COMMON_CFI(GR(25))) \ -TCR(COMMON_CFI(GR(26))) \ -TCR(COMMON_CFI(GR(27))) \ -TCR(COMMON_CFI(GR(28))) \ -TCR(COMMON_CFI(GR(29))) \ -TCR(COMMON_CFI(GR(30))) \ -TCR(COMMON_CFI(GR(31))) \ -TCR(COMMON_CFI(LR)) \ -TCR(COMMON_CFI(CR)) \ -TCR(COMMON_CFI(CTR)) \ -TCR(COMMON_CFI(XER)) \ -TCR(COMMON_CFI(PC)) \ -TCR(".cfi_return_column " S(REGNO_PC)) - -/* Trampoline body block - --------------------- */ - -#if !defined (__PPC64__) -#define SIGTRAMP_BODY \ -CR("") \ -TCR("# Allocate frame and save the non-volatile") \ -TCR("# registers we're going to modify") \ -TCR("stwu %r1,-16(%r1)") \ -TCR("mflr %r0") \ -TCR("stw %r0,20(%r1)") \ -TCR("stw %r" S(CFA_REG) ",8(%r1)") \ -TCR("") \ -TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ -TCR("mr %r" S(CFA_REG) ", %r7") \ -TCR("") \ -TCR("# Call the real handler. The signo, siginfo and sigcontext") \ -TCR("# arguments are the same as those we received in r3, r4 and r5") \ -TCR("mtctr %r6") \ -TCR("bctrl") \ -TCR("") \ -TCR("# Restore our callee-saved items, release our frame and return") \ -TCR("lwz %r" S(CFA_REG) ",8(%r1)") \ -TCR("lwz %r0,20(%r1)") \ -TCR("mtlr %r0") \ -TCR("") \ -TCR("addi %r1,%r1,16") \ -TCR("blr") -#else -#define SIGTRAMP_BODY \ -CR("") \ -TCR(".LOC_SIGTMP_COM_0:") \ -TCR("addis 2,12,.TOC.-.LOC_SIGTMP_COM_0@ha") \ -TCR("addi 2,2,.TOC.-.LOC_SIGTMP_COM_0@l") \ -TCR(".localentry __gnat_sigtramp_common,.-__gnat_sigtramp_common") \ -TCR("# Allocate frame and save the non-volatile") \ -TCR("# registers we're going to modify") \ -TCR("mflr %r0") \ -TCR("std %r0,16(%r1)") \ -TCR("stdu %r1,-32(%r1)") \ -TCR("std %r2,24(%r1)") \ -TCR("std %r" S(CFA_REG) ",8(%r1)") \ -TCR("") \ -TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ -TCR("mr %r" S(CFA_REG) ", %r7") \ -TCR("") \ -TCR("# Call the real handler. The signo, siginfo and sigcontext") \ -TCR("# arguments are the same as those we received in r3, r4 and r5") \ -TCR("mr %r12,%r6") \ -TCR("mtctr %r6") \ -TCR("bctrl") \ -TCR("") \ -TCR("# Restore our callee-saved items, release our frame and return") \ -TCR("ld %r" S(CFA_REG) ",8(%r1)") \ -TCR("ld %r2,24(%r1)") \ -TCR("addi %r1,%r1,32") \ -TCR("ld %r0,16(%r1)") \ -TCR("mtlr %r0") \ -TCR("blr") -#endif - -#elif defined (ARMEL) - -#define COMMON_CFI(REG) \ - ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG) - -#ifdef __aarch64__ -#define CFI_COMMON_REGS \ -CR("# CFI for common registers\n") \ -TCR(COMMON_CFI(G_REG_OFFSET(0))) \ -TCR(COMMON_CFI(G_REG_OFFSET(1))) \ -TCR(COMMON_CFI(G_REG_OFFSET(2))) \ -TCR(COMMON_CFI(G_REG_OFFSET(3))) \ -TCR(COMMON_CFI(G_REG_OFFSET(4))) \ -TCR(COMMON_CFI(G_REG_OFFSET(5))) \ -TCR(COMMON_CFI(G_REG_OFFSET(6))) \ -TCR(COMMON_CFI(G_REG_OFFSET(7))) \ -TCR(COMMON_CFI(G_REG_OFFSET(8))) \ -TCR(COMMON_CFI(G_REG_OFFSET(9))) \ -TCR(COMMON_CFI(G_REG_OFFSET(10))) \ -TCR(COMMON_CFI(G_REG_OFFSET(11))) \ -TCR(COMMON_CFI(G_REG_OFFSET(12))) \ -TCR(COMMON_CFI(G_REG_OFFSET(13))) \ -TCR(COMMON_CFI(G_REG_OFFSET(14))) \ -TCR(COMMON_CFI(G_REG_OFFSET(15))) \ -TCR(COMMON_CFI(G_REG_OFFSET(16))) \ -TCR(COMMON_CFI(G_REG_OFFSET(17))) \ -CR("# Leave alone R18, VxWorks reserved\n") \ -TCR(COMMON_CFI(G_REG_OFFSET(19))) \ -TCR(COMMON_CFI(G_REG_OFFSET(20))) \ -TCR(COMMON_CFI(G_REG_OFFSET(21))) \ -TCR(COMMON_CFI(G_REG_OFFSET(22))) \ -TCR(COMMON_CFI(G_REG_OFFSET(23))) \ -TCR(COMMON_CFI(G_REG_OFFSET(24))) \ -TCR(COMMON_CFI(G_REG_OFFSET(25))) \ -TCR(COMMON_CFI(G_REG_OFFSET(26))) \ -TCR(COMMON_CFI(G_REG_OFFSET(27))) \ -TCR(COMMON_CFI(G_REG_OFFSET(28))) \ -TCR(COMMON_CFI(G_REG_OFFSET(29))) \ -TCR(COMMON_CFI(G_REG_OFFSET(30))) \ -TCR(COMMON_CFI(G_REG_OFFSET(31))) \ -TCR(COMMON_CFI(PC_OFFSET)) \ -TCR(".cfi_return_column " S(REGNO_PC_OFFSET)) -#else -#define CFI_COMMON_REGS \ -CR("# CFI for common registers\n") \ -TCR(COMMON_CFI(G_REG_OFFSET(0))) \ -TCR(COMMON_CFI(G_REG_OFFSET(1))) \ -TCR(COMMON_CFI(G_REG_OFFSET(2))) \ -TCR(COMMON_CFI(G_REG_OFFSET(3))) \ -TCR(COMMON_CFI(G_REG_OFFSET(4))) \ -TCR(COMMON_CFI(G_REG_OFFSET(5))) \ -TCR(COMMON_CFI(G_REG_OFFSET(6))) \ -TCR(COMMON_CFI(G_REG_OFFSET(7))) \ -TCR(COMMON_CFI(G_REG_OFFSET(8))) \ -TCR(COMMON_CFI(G_REG_OFFSET(9))) \ -TCR(COMMON_CFI(G_REG_OFFSET(10))) \ -TCR(COMMON_CFI(G_REG_OFFSET(11))) \ -TCR(COMMON_CFI(G_REG_OFFSET(12))) \ -TCR(COMMON_CFI(G_REG_OFFSET(13))) \ -TCR(COMMON_CFI(G_REG_OFFSET(14))) \ -TCR(COMMON_CFI(PC_OFFSET)) \ -TCR(".cfi_return_column " S(REGNO_PC_OFFSET)) -#endif - -/* Trampoline body block - --------------------- */ -#ifdef __aarch64__ -#define SIGTRAMP_BODY \ -CR("") \ -TCR("# Allocate the frame (16bytes aligned) and push FP and LR") \ -TCR("stp x29, x30, [sp, #-32]!") \ -TCR("add x29, sp, 0") \ -TCR("# Store register used to hold the CFA on stack (pro forma)") \ -TCR("str x" S(CFA_REG) ", [sp, 16]") \ -TCR("# Set the CFA reg from the 5th arg") \ -TCR("mov x" S(CFA_REG) ", x4") \ -TCR("# Call the handler") \ -TCR("blr x3") \ -TCR("# Release our frame and return (should never get here!).") \ -TCR("ldr x" S(CFA_REG) ", [sp, 16]") \ -TCR("ldp x29, x30, [sp], 32") \ -TCR("ret") -#else -#define SIGTRAMP_BODY \ -CR("") \ -TCR("# Allocate frame and save the non-volatile") \ -TCR("# registers we're going to modify") \ -TCR("mov ip, sp") \ -TCR("stmfd sp!, {r"S(CFA_REG)", fp, ip, lr, pc}") \ -TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ -TCR("ldr r"S(CFA_REG)", [ip]") \ -TCR("") \ -TCR("# Call the real handler. The signo, siginfo and sigcontext") \ -TCR("# arguments are the same as those we received in r0, r1 and r2") \ -TCR("sub fp, ip, #4") \ -TCR("blx r3") \ -TCR("# Restore our callee-saved items, release our frame and return") \ -TCR("ldmfd sp, {r"S(CFA_REG)", fp, sp, pc}") -#endif - -#elif defined (i386) - -#if CPU == SIMNT || CPU == SIMPENTIUM || CPU == SIMLINUX -#define COMMON_CFI(REG) \ - ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG) -#else -#define COMMON_CFI(REG) \ - ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG) -#endif - -#define PC_CFI(REG) \ - ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG) - -#define CFI_COMMON_REGS \ -CR("# CFI for common registers\n") \ -TCR(COMMON_CFI(EDI)) \ -TCR(COMMON_CFI(ESI)) \ -TCR(COMMON_CFI(EBP)) \ -TCR(COMMON_CFI(ESP)) \ -TCR(COMMON_CFI(EBX)) \ -TCR(COMMON_CFI(EDX)) \ -TCR(COMMON_CFI(ECX)) \ -TCR(COMMON_CFI(EAX)) \ -TCR(COMMON_CFI(EFLAGS)) \ -TCR(PC_CFI(SET_PC)) \ -TCR(".cfi_return_column " S(REGNO_SET_PC)) - -/* Trampoline body block - --------------------- */ - -#define SIGTRAMP_BODY \ -CR("") \ -TCR("# Allocate frame and save the non-volatile") \ -TCR("# registers we're going to modify") \ -TCR("pushl %ebp") \ -TCR("movl %esp, %ebp") \ -TCR("pushl %edi") \ -TCR("subl $24, %esp") \ -TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ -TCR("movl 24(%ebp), %edi") \ -TCR("# Call the real handler. The signo, siginfo and sigcontext") \ -TCR("# arguments are the same as those we received") \ -TCR("movl 16(%ebp), %eax") \ -TCR("movl %eax, 8(%esp)") \ -TCR("movl 12(%ebp), %eax") \ -TCR("movl %eax, 4(%esp)") \ -TCR("movl 8(%ebp), %eax") \ -TCR("movl %eax, (%esp)") \ -TCR("call *20(%ebp)") \ -TCR("# Restore our callee-saved items, release our frame and return") \ -TCR("popl %edi") \ -TCR("leave") \ -TCR("ret") - -#elif defined (__x86_64__) - -#define COMMON_CFI(REG) \ - ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG) - -#define CFI_COMMON_REGS \ -CR("# CFI for common registers\n") \ -TCR(COMMON_CFI(R15)) \ -TCR(COMMON_CFI(R14)) \ -TCR(COMMON_CFI(R13)) \ -TCR(COMMON_CFI(R12)) \ -TCR(COMMON_CFI(R11)) \ -TCR(COMMON_CFI(R10)) \ -TCR(COMMON_CFI(R9)) \ -TCR(COMMON_CFI(R8)) \ -TCR(COMMON_CFI(RDI)) \ -TCR(COMMON_CFI(RSI)) \ -TCR(COMMON_CFI(RBP)) \ -TCR(COMMON_CFI(RSP)) \ -TCR(COMMON_CFI(RBX)) \ -TCR(COMMON_CFI(RDX)) \ -TCR(COMMON_CFI(RCX)) \ -TCR(COMMON_CFI(RAX)) \ -TCR(COMMON_CFI(RPC)) \ -TCR(".cfi_return_column " S(REGNO_RPC)) - -/* Trampoline body block - --------------------- */ - -#define SIGTRAMP_BODY \ -CR("") \ -TCR("# Allocate frame and save the non-volatile") \ -TCR("# registers we're going to modify") \ -TCR("subq $8, %rsp") \ -TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ -TCR("movq %r8, %r15") \ -TCR("# Call the real handler. The signo, siginfo and sigcontext") \ -TCR("# arguments are the same as those we received") \ -TCR("call *%rcx") \ -TCR("# This part should never be executed") \ -TCR("addq $8, %rsp") \ -TCR("ret") - -#else -Not_implemented; -#endif /* CFI_COMMON_REGS and SIGTRAMP_BODY */ - -/* Symbol definition block - ----------------------- */ - -#ifdef __x86_64__ -#define FUNC_ALIGN TCR(".p2align 4,,15") -#else -#define FUNC_ALIGN -#endif - -#define SIGTRAMP_START(SYM) \ -CR("# " S(SYM) " cfi trampoline") \ -TCR(".type " S(SYM) ", "FUNCTION) \ -CR("") \ -FUNC_ALIGN \ -CR(S(SYM) ":") \ -TCR(".cfi_startproc") \ -TCR(".cfi_signal_frame") - -/* Symbol termination block - ------------------------ */ - -#define SIGTRAMP_END(SYM) \ -CR(".cfi_endproc") \ -TCR(".size " S(SYM) ", .-" S(SYM)) - -/*---------------------------- - -- And now, the real code -- - ---------------------------- */ - -/* Text section start. The compiler isn't aware of that switch. */ - -asm (".text\n" - TCR(".align 2")); diff --git a/gcc/ada/sigtramp-vxworks.c b/gcc/ada/sigtramp-vxworks.c index b04d881..2455f6e 100644 --- a/gcc/ada/sigtramp-vxworks.c +++ b/gcc/ada/sigtramp-vxworks.c @@ -180,7 +180,7 @@ void __gnat_sigtramp (int signo, void *si, void *sc, } /* Include the target specific bits. */ -#include "sigtramp-vxworks-target.inc" +#include "sigtramp-vxworks-target.h" /* sigtramp stub for common registers. */ -- cgit v1.1 From 7c092960f0d116abdba7e13aaf38fbadfdefbeb0 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Thu, 3 Jun 2021 12:10:30 -0400 Subject: [Ada] Transient scope cleanup gcc/ada/ * comperr.adb (Compiler_Abort): Call Sinput.Unlock, because if this is called late, then Source_Dump would crash otherwise. * debug.adb: Correct documentation of the -gnatd.9 switch. * exp_ch4.adb (Expand_Allocator_Expression): Add a comment. * exp_ch6.adb: Minor comment fixes. Add assertion. * exp_ch6.ads (Is_Build_In_Place_Result_Type): Correct comment. * exp_ch7.adb, checks.ads: Minor comment fixes. --- gcc/ada/checks.ads | 2 +- gcc/ada/comperr.adb | 1 + gcc/ada/debug.adb | 2 +- gcc/ada/exp_ch4.adb | 3 +++ gcc/ada/exp_ch6.adb | 25 +++++++++++-------------- gcc/ada/exp_ch6.ads | 7 +++++-- gcc/ada/exp_ch7.adb | 4 ++-- 7 files changed, 24 insertions(+), 20 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads index a3835d9..3b97bd0 100644 --- a/gcc/ada/checks.ads +++ b/gcc/ada/checks.ads @@ -851,7 +851,7 @@ package Checks is -- are not following the flow graph (more properly the flow of actual -- processing only corresponds to the flow graph for local assignments). -- For non-local variables, we preserve the current setting, i.e. a - -- validity check is performed when assigning to a knonwn valid global. + -- validity check is performed when assigning to a known valid global. -- Note: no validity checking is required if range checks are suppressed -- regardless of the setting of the validity checking mode. diff --git a/gcc/ada/comperr.adb b/gcc/ada/comperr.adb index 1687038..300b523 100644 --- a/gcc/ada/comperr.adb +++ b/gcc/ada/comperr.adb @@ -404,6 +404,7 @@ package body Comperr is Set_Standard_Output; Tree_Dump; + Sinput.Unlock; -- so Source_Dump can modify it Source_Dump; raise Unrecoverable_Error; end if; diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index 599c9c9..5245feb3 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -1101,7 +1101,7 @@ package body Debug is -- issues (e.g., assuming that a low bound of an array parameter -- of an unconstrained subtype belongs to the index subtype). - -- d.9 Enable build-in-place for function calls returning some nonlimited + -- d.9 Disable build-in-place for function calls returning nonlimited -- types. ------------------------------------------ diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 0c5b3a2..16f513e 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -1166,6 +1166,9 @@ package body Exp_Ch4 is -- secondary stack). In that case, the object will be moved, so we do -- want to Adjust. However, if it's a nonlimited build-in-place -- function call, Adjust is not wanted. + -- + -- Needs_Finalization (DesigT) can differ from Needs_Finalization (T) + -- if one of the two types is class-wide, and the other is not. if Needs_Finalization (DesigT) and then Needs_Finalization (T) diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index dbae760..1c56cb8 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -4913,7 +4913,7 @@ package body Exp_Ch6 is -- Optimization, if the returned value (which is on the sec-stack) is -- returned again, no need to copy/readjust/finalize, we can just pass -- the value thru (see Expand_N_Simple_Return_Statement), and thus no - -- attachment is needed + -- attachment is needed. if Nkind (Parent (N)) = N_Simple_Return_Statement then return; @@ -7310,15 +7310,16 @@ package body Exp_Ch6 is Set_Enclosing_Sec_Stack_Return (N); - -- Optimize the case where the result is a function call. In this - -- case the result is already on the secondary stack and no further - -- processing is required except to set the By_Ref flag to ensure - -- that gigi does not attempt an extra unnecessary copy. (Actually - -- not just unnecessary but wrong in the case of a controlled type, - -- where gigi does not know how to do a copy.) + -- Optimize the case where the result is a function call that also + -- returns on the secondary stack. In this case the result is already + -- on the secondary stack and no further processing is required + -- except to set the By_Ref flag to ensure that gigi does not attempt + -- an extra unnecessary copy. (Actually not just unnecessary but + -- wrong in the case of a controlled type, where gigi does not know + -- how to do a copy.) - if Requires_Transient_Scope (Exp_Typ) - and then Exp_Is_Function_Call + pragma Assert (Requires_Transient_Scope (R_Type)); + if Exp_Is_Function_Call and then Requires_Transient_Scope (Exp_Typ) then Set_By_Ref (N); @@ -7849,7 +7850,7 @@ package body Exp_Ch6 is Compute_Returns_By_Ref (Subp); - -- Wnen freezing a null procedure, analyze its delayed aspects now + -- When freezing a null procedure, analyze its delayed aspects now -- because we may not have reached the end of the declarative list when -- delayed aspects are normally analyzed. This ensures that dispatching -- calls are properly rewritten when the generated _Postcondition @@ -8219,10 +8220,6 @@ package body Exp_Ch6 is return False; end if; - -- For now we test whether E denotes a function or access-to-function - -- type whose result subtype is inherently limited. Later this test - -- may be revised to allow composite nonlimited types. - if Ekind (E) in E_Function | E_Generic_Function or else (Ekind (E) = E_Subprogram_Type and then Etype (E) /= Standard_Void_Type) diff --git a/gcc/ada/exp_ch6.ads b/gcc/ada/exp_ch6.ads index 07a88c5..76cec4d 100644 --- a/gcc/ada/exp_ch6.ads +++ b/gcc/ada/exp_ch6.ads @@ -134,8 +134,11 @@ package Exp_Ch6 is -- -- For inherently limited types in Ada 2005, True means that calls will -- actually be build-in-place in all cases. For other types, build-in-place - -- will be used when possible, but we need to make a copy at the call site - -- in some cases, notably assignment statements. + -- will be used when possible, but we need to make a copy in some + -- cases. For example, for "X := F(...);" if F can see X, or if F can + -- propagate exceptions, we need to store its result in a temp in general, + -- and copy the temp into X. Also, for "return Global_Var;" Global_Var + -- needs to be copied into the function result object. function Is_Build_In_Place_Function (E : Entity_Id) return Boolean; -- Ada 2005 (AI-318-02): Returns True if E denotes a function, generic diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index b0374a3..f7807ac 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -480,7 +480,7 @@ package body Exp_Ch7 is Skip_Self : Boolean := False) return Node_Id; -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of -- routine [Deep_]Adjust or [Deep_]Finalize and an object parameter, create - -- an adjust or finalization call. Wnen flag Skip_Self is set, the related + -- an adjust or finalization call. When flag Skip_Self is set, the related -- action has an effect on the components only (if any). function Make_Deep_Proc @@ -8126,7 +8126,7 @@ package body Exp_Ch7 is -- end if; -- ... - -- When Deep_Adjust is invokes for field _parent, a value of False is + -- When Deep_Adjust is invoked for field _parent, a value of False is -- provided for the flag: -- Deep_Adjust (Obj._parent, False); -- cgit v1.1 From 4d743233ad29c03b5c65cfaf802d7c91f7fcc32c Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 4 Jun 2021 18:08:49 +0200 Subject: [Ada] Use encoded names only with -fgnat-encodings=all gcc/ada/ * exp_dbug.adb (Get_Encoded_Name): Do not encode names of discrete types with custom bounds, except with -fgnat-encodings=all. * exp_pakd.adb (Create_Packed_Array_Impl_Type): Adjust comment. --- gcc/ada/exp_dbug.adb | 11 +++++------ gcc/ada/exp_pakd.adb | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_dbug.adb b/gcc/ada/exp_dbug.adb index ed5ae43..bfc3b33 100644 --- a/gcc/ada/exp_dbug.adb +++ b/gcc/ada/exp_dbug.adb @@ -655,10 +655,10 @@ package body Exp_Dbug is Has_Suffix := True; - -- Fixed-point case: generate GNAT encodings when asked to + -- Generate GNAT encodings when asked to for fixed-point case - if Is_Fixed_Point_Type (E) - and then GNAT_Encodings = DWARF_GNAT_Encodings_All + if GNAT_Encodings = DWARF_GNAT_Encodings_All + and then Is_Fixed_Point_Type (E) then Get_External_Name (E, True, "XF_"); Add_Real_To_Buffer (Delta_Value (E)); @@ -668,10 +668,9 @@ package body Exp_Dbug is Add_Real_To_Buffer (Small_Value (E)); end if; - -- Discrete case where bounds do not match size. Not necessary if we can - -- emit standard DWARF. + -- Likewise for discrete case where bounds do not match size - elsif GNAT_Encodings /= DWARF_GNAT_Encodings_Minimal + elsif GNAT_Encodings = DWARF_GNAT_Encodings_All and then Is_Discrete_Type (E) and then not Bounds_Match_Size (E) then diff --git a/gcc/ada/exp_pakd.adb b/gcc/ada/exp_pakd.adb index 7e29502..3477bba 100644 --- a/gcc/ada/exp_pakd.adb +++ b/gcc/ada/exp_pakd.adb @@ -828,8 +828,8 @@ package body Exp_Pakd is elsif not Is_Constrained (Typ) then - -- When generating standard DWARF (i.e when GNAT_Encodings is - -- DWARF_GNAT_Encodings_Minimal), the ___XP suffix will be stripped + -- When generating standard DWARF (i.e when GNAT_Encodings is not + -- DWARF_GNAT_Encodings_All), the ___XP suffix will be stripped -- by the back-end but generate it anyway to ease compiler debugging. -- This will help to distinguish implementation types from original -- packed arrays. -- cgit v1.1 From 8de68eb37c7275735a8deb78f44fe6535b9462ec Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Fri, 4 Jun 2021 08:13:23 -0400 Subject: [Ada] Remove Unknown_ functions gcc/ada/ * einfo-utils.ads, einfo-utils.adb (Unknown_Alignment, Unknown_Component_Bit_Offset, Unknown_Component_Size, Unknown_Esize, Unknown_Normalized_First_Bit, Unknown_Normalized_Position, Unknown_Normalized_Position_Max, Unknown_RM_Size): Remove these functions. * exp_pakd.adb, exp_util.adb, fe.h, freeze.adb, layout.adb, repinfo.adb, sem_ch13.adb, sem_ch3.adb, sem_util.adb: Remove calls to these functions; do "not Known_..." instead. * gcc-interface/decl.c, gcc-interface/trans.c (Unknown_Alignment, Unknown_Component_Size, Unknown_Esize, Unknown_RM_Size): Remove calls to these functions; do "!Known_..." instead. --- gcc/ada/einfo-utils.adb | 40 ---------------------------------------- gcc/ada/einfo-utils.ads | 29 +++++------------------------ gcc/ada/exp_pakd.adb | 4 ++-- gcc/ada/exp_util.adb | 4 ++-- gcc/ada/fe.h | 24 ------------------------ gcc/ada/freeze.adb | 10 +++++----- gcc/ada/gcc-interface/decl.c | 24 ++++++++++++------------ gcc/ada/gcc-interface/trans.c | 6 +++--- gcc/ada/layout.adb | 28 ++++++++++++++-------------- gcc/ada/repinfo.adb | 6 +++--- gcc/ada/sem_ch13.adb | 2 +- gcc/ada/sem_ch3.adb | 2 +- gcc/ada/sem_util.adb | 4 ++-- 13 files changed, 50 insertions(+), 133 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/einfo-utils.adb b/gcc/ada/einfo-utils.adb index b2d8a84..21d7bfb 100644 --- a/gcc/ada/einfo-utils.adb +++ b/gcc/ada/einfo-utils.adb @@ -597,46 +597,6 @@ package body Einfo.Utils is and then not Is_Generic_Type (E); end Known_Static_RM_Size; - function Unknown_Alignment (E : Entity_Id) return B is - begin - return not Known_Alignment (E); - end Unknown_Alignment; - - function Unknown_Component_Bit_Offset (E : Entity_Id) return B is - begin - return not Known_Component_Bit_Offset (E); - end Unknown_Component_Bit_Offset; - - function Unknown_Component_Size (E : Entity_Id) return B is - begin - return not Known_Component_Size (E); - end Unknown_Component_Size; - - function Unknown_Esize (E : Entity_Id) return B is - begin - return not Known_Esize (E); - end Unknown_Esize; - - function Unknown_Normalized_First_Bit (E : Entity_Id) return B is - begin - return not Known_Normalized_First_Bit (E); - end Unknown_Normalized_First_Bit; - - function Unknown_Normalized_Position (E : Entity_Id) return B is - begin - return not Known_Normalized_Position (E); - end Unknown_Normalized_Position; - - function Unknown_Normalized_Position_Max (E : Entity_Id) return B is - begin - return not Known_Normalized_Position_Max (E); - end Unknown_Normalized_Position_Max; - - function Unknown_RM_Size (E : Entity_Id) return B is - begin - return not Known_RM_Size (E); - end Unknown_RM_Size; - -------------------- -- Address_Clause -- -------------------- diff --git a/gcc/ada/einfo-utils.ads b/gcc/ada/einfo-utils.ads index f65dbfa..dbf3ad6 100644 --- a/gcc/ada/einfo-utils.ads +++ b/gcc/ada/einfo-utils.ads @@ -314,12 +314,11 @@ package Einfo.Utils is -- Type Representation Attribute Predicates -- ---------------------------------------------- - -- These predicates test the setting of the indicated attribute. If the - -- value has been set, then Known is True, and Unknown is False. If no - -- value is set, then Known is False and Unknown is True. The Known_Static - -- predicate is true only if the value is set (Known) and is set to a - -- compile time known value. Note that in the case of Alignment and - -- Normalized_First_Bit, dynamic values are not possible, so we do not + -- These predicates test the setting of the indicated attribute. The + -- Known predicate is True if and only if the value has been set. The + -- Known_Static predicate is True only if the value is set (Known) and is + -- set to a compile time known value. Note that in the case of Alignment + -- and Normalized_First_Bit, dynamic values are not possible, so we do not -- need a separate Known_Static calls in these cases. The not set (unknown) -- values are as follows: @@ -364,15 +363,6 @@ package Einfo.Utils is function Known_Static_Normalized_Position_Max (E : Entity_Id) return B; function Known_Static_RM_Size (E : Entity_Id) return B; - function Unknown_Alignment (E : Entity_Id) return B; - function Unknown_Component_Bit_Offset (E : Entity_Id) return B; - function Unknown_Component_Size (E : Entity_Id) return B; - function Unknown_Esize (E : Entity_Id) return B; - function Unknown_Normalized_First_Bit (E : Entity_Id) return B; - function Unknown_Normalized_Position (E : Entity_Id) return B; - function Unknown_Normalized_Position_Max (E : Entity_Id) return B; - function Unknown_RM_Size (E : Entity_Id) return B; - pragma Inline (Known_Alignment); pragma Inline (Known_Component_Bit_Offset); pragma Inline (Known_Component_Size); @@ -390,15 +380,6 @@ package Einfo.Utils is pragma Inline (Known_Static_Normalized_Position_Max); pragma Inline (Known_Static_RM_Size); - pragma Inline (Unknown_Alignment); - pragma Inline (Unknown_Component_Bit_Offset); - pragma Inline (Unknown_Component_Size); - pragma Inline (Unknown_Esize); - pragma Inline (Unknown_Normalized_First_Bit); - pragma Inline (Unknown_Normalized_Position); - pragma Inline (Unknown_Normalized_Position_Max); - pragma Inline (Unknown_RM_Size); - --------------------------------------------------- -- Access to Subprograms in Subprograms_For_Type -- --------------------------------------------------- diff --git a/gcc/ada/exp_pakd.adb b/gcc/ada/exp_pakd.adb index 3477bba..47919fc 100644 --- a/gcc/ada/exp_pakd.adb +++ b/gcc/ada/exp_pakd.adb @@ -563,11 +563,11 @@ package body Exp_Pakd is -- Do not reset RM_Size if already set, as happens in the case of -- a modular type. - if Unknown_Esize (PAT) then + if not Known_Esize (PAT) then Set_Esize (PAT, PASize); end if; - if Unknown_RM_Size (PAT) then + if not Known_RM_Size (PAT) then Set_RM_Size (PAT, PASize); end if; diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 2ff1144..2584041 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -9048,7 +9048,7 @@ package body Exp_Util is if Target_Strict_Alignment and then Known_Alignment (Ptyp) - and then (Unknown_Alignment (Styp) + and then (not Known_Alignment (Styp) or else Alignment (Styp) > Alignment (Ptyp)) then return True; @@ -9072,7 +9072,7 @@ package body Exp_Util is begin if Present (Component_Clause (Field)) and then - (Unknown_Alignment (Styp) + (not Known_Alignment (Styp) or else (Component_Bit_Offset (Field) mod (System_Storage_Unit * Alignment (Styp))) /= 0) diff --git a/gcc/ada/fe.h b/gcc/ada/fe.h index 3e42f16..d7ab361b 100644 --- a/gcc/ada/fe.h +++ b/gcc/ada/fe.h @@ -636,30 +636,6 @@ B Known_Static_Normalized_Position_Max (Entity_Id E); #define Known_Static_RM_Size einfo__utils__known_static_rm_size B Known_Static_RM_Size (Entity_Id E); -#define Unknown_Alignment einfo__utils__unknown_alignment -B Unknown_Alignment (Entity_Id E); - -#define Unknown_Component_Bit_Offset einfo__utils__unknown_component_bit_offset -B Unknown_Component_Bit_Offset (Entity_Id E); - -#define Unknown_Component_Size einfo__utils__unknown_component_size -B Unknown_Component_Size (Entity_Id E); - -#define Unknown_Esize einfo__utils__unknown_esize -B Unknown_Esize (Entity_Id E); - -#define Unknown_Normalized_First_Bit einfo__utils__unknown_normalized_first_bit -B Unknown_Normalized_First_Bit (Entity_Id E); - -#define Unknown_Normalized_Position einfo__utils__unknown_normalized_position -B Unknown_Normalized_Position (Entity_Id E); - -#define Unknown_Normalized_Position_Max einfo__utils__unknown_normalized_position_max -B Unknown_Normalized_Position_Max (Entity_Id E); - -#define Unknown_RM_Size einfo__utils__unknown_rm_size -B Unknown_RM_Size (Entity_Id E); - #define Is_Discrete_Or_Fixed_Point_Type einfo__utils__is_discrete_or_fixed_point_type B Is_Discrete_Or_Fixed_Point_Type (E Id); diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 3796433..12d10ee 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -857,7 +857,7 @@ package body Freeze is -- Set size if not set already - elsif Unknown_RM_Size (T) then + elsif not Known_RM_Size (T) then Set_RM_Size (T, S); end if; end Set_Small_Size; @@ -1043,7 +1043,7 @@ package body Freeze is if not Is_Constrained (T) and then No (Discriminant_Default_Value (First_Discriminant (T))) - and then Unknown_RM_Size (T) + and then not Known_RM_Size (T) then return False; end if; @@ -3480,7 +3480,7 @@ package body Freeze is else -- Acquire alignment from base type - if Unknown_Alignment (Arr) then + if not Known_Alignment (Arr) then Set_Alignment (Arr, Alignment (Base_Type (Arr))); Adjust_Esize_Alignment (Arr); end if; @@ -8632,7 +8632,7 @@ package body Freeze is -- If Esize of a subtype has not previously been set, set it now - if Unknown_Esize (Typ) then + if not Known_Esize (Typ) then Atype := Ancestor_Subtype (Typ); if Present (Atype) then @@ -9127,7 +9127,7 @@ package body Freeze is -- Set Esize to calculated size if not set already - if Unknown_Esize (Typ) then + if not Known_Esize (Typ) then Init_Esize (Typ, Actual_Size); end if; diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 6fc94dd..b09e20d 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -444,7 +444,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) /* The RM size must be specified for all discrete and fixed-point types. */ gcc_assert (!(Is_In_Discrete_Or_Fixed_Point_Kind (kind) - && Unknown_RM_Size (gnat_entity))); + && !Known_RM_Size (gnat_entity))); /* If we get here, it means we have not yet done anything with this entity. If we are not defining it, it must be a type or an entity that is defined @@ -2324,7 +2324,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) /* If Component_Size is not already specified, annotate it with the size of the component. */ - if (Unknown_Component_Size (gnat_entity)) + if (!Known_Component_Size (gnat_entity)) Set_Component_Size (gnat_entity, annotate_value (TYPE_SIZE (comp_type))); @@ -4369,7 +4369,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) set_rm_size (RM_Size (gnat_entity), gnu_type, gnat_entity); /* Back-annotate the alignment of the type if not already set. */ - if (Unknown_Alignment (gnat_entity)) + if (!Known_Alignment (gnat_entity)) { unsigned int double_align, align; bool is_capped_double, align_clause; @@ -4395,7 +4395,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) } /* Likewise for the size, if any. */ - if (Unknown_Esize (gnat_entity) && TYPE_SIZE (gnu_type)) + if (!Known_Esize (gnat_entity) && TYPE_SIZE (gnu_type)) { tree gnu_size = TYPE_SIZE (gnu_type); @@ -4428,7 +4428,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) /* If there is neither size clause nor representation clause, the sizes need to be adjusted. */ - if (Unknown_RM_Size (gnat_entity) + if (!Known_RM_Size (gnat_entity) && !VOID_TYPE_P (gnu_type) && (!TYPE_FIELDS (gnu_type) || integer_zerop (bit_position (TYPE_FIELDS (gnu_type))))) @@ -4448,7 +4448,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) Set_Esize (gnat_entity, annotate_value (gnu_size)); /* Tagged types are Strict_Alignment so RM_Size = Esize. */ - if (Unknown_RM_Size (gnat_entity)) + if (!Known_RM_Size (gnat_entity)) Set_RM_Size (gnat_entity, Esize (gnat_entity)); } @@ -4458,7 +4458,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) } /* Likewise for the RM size, if any. */ - if (Unknown_RM_Size (gnat_entity) && TYPE_SIZE (gnu_type)) + if (!Known_RM_Size (gnat_entity) && TYPE_SIZE (gnu_type)) Set_RM_Size (gnat_entity, annotate_value (rm_size (gnu_type))); /* If we are at global level, GCC applied variable_size to the size but @@ -4723,11 +4723,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) && !TYPE_IS_DUMMY_P (TREE_TYPE (gnu_decl)) && Present (gnat_annotate_type)) { - if (Unknown_Alignment (gnat_entity)) + if (!Known_Alignment (gnat_entity)) Set_Alignment (gnat_entity, Alignment (gnat_annotate_type)); - if (Unknown_Esize (gnat_entity)) + if (!Known_Esize (gnat_entity)) Set_Esize (gnat_entity, Esize (gnat_annotate_type)); - if (Unknown_RM_Size (gnat_entity)) + if (!Known_RM_Size (gnat_entity)) Set_RM_Size (gnat_entity, RM_Size (gnat_annotate_type)); } @@ -8686,7 +8686,7 @@ annotate_object (Entity_Id gnat_entity, tree gnu_type, tree size, bool by_ref) gnu_type = TREE_TYPE (gnu_type); } - if (Unknown_Esize (gnat_entity)) + if (!Known_Esize (gnat_entity)) { if (TREE_CODE (gnu_type) == RECORD_TYPE && TYPE_CONTAINS_TEMPLATE_P (gnu_type)) @@ -8698,7 +8698,7 @@ annotate_object (Entity_Id gnat_entity, tree gnu_type, tree size, bool by_ref) Set_Esize (gnat_entity, annotate_value (size)); } - if (Unknown_Alignment (gnat_entity)) + if (!Known_Alignment (gnat_entity)) Set_Alignment (gnat_entity, UI_From_Int (TYPE_ALIGN (gnu_type) / BITS_PER_UNIT)); } diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 6a7424f..8f8bc70 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -9273,13 +9273,13 @@ process_freeze_entity (Node_Id gnat_node) gnu_new = gnat_to_gnu_entity (full_view, NULL_TREE, true); /* Propagate back-annotations from full view to partial view. */ - if (Unknown_Alignment (gnat_entity)) + if (!Known_Alignment (gnat_entity)) Set_Alignment (gnat_entity, Alignment (full_view)); - if (Unknown_Esize (gnat_entity)) + if (!Known_Esize (gnat_entity)) Set_Esize (gnat_entity, Esize (full_view)); - if (Unknown_RM_Size (gnat_entity)) + if (!Known_RM_Size (gnat_entity)) Set_RM_Size (gnat_entity, RM_Size (full_view)); /* The above call may have defined this entity (the simplest example diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb index de73193..f716488 100644 --- a/gcc/ada/layout.adb +++ b/gcc/ada/layout.adb @@ -77,7 +77,7 @@ package body Layout is begin -- Nothing to do if size unknown - if Unknown_Esize (E) then + if not Known_Esize (E) then return; end if; @@ -119,7 +119,7 @@ package body Layout is -- Now we have the size set, it must be a multiple of the alignment -- nothing more we can do here if the alignment is unknown here. - if Unknown_Alignment (E) then + if not Known_Alignment (E) then return; end if; @@ -404,7 +404,7 @@ package body Layout is -- it now to a copy of the Esize if the Esize is set. else - if Known_Esize (E) and then Unknown_RM_Size (E) then + if Known_Esize (E) and then not Known_RM_Size (E) then Set_RM_Size (E, Esize (E)); end if; end if; @@ -425,15 +425,15 @@ package body Layout is PAT : constant Entity_Id := Packed_Array_Impl_Type (E); begin - if Unknown_Esize (E) then + if not Known_Esize (E) then Set_Esize (E, Esize (PAT)); end if; - if Unknown_RM_Size (E) then + if not Known_RM_Size (E) then Set_RM_Size (E, RM_Size (PAT)); end if; - if Unknown_Alignment (E) then + if not Known_Alignment (E) then Set_Alignment (E, Alignment (PAT)); end if; end; @@ -446,7 +446,7 @@ package body Layout is -- gave up because, in this case, the object size is not a multiple -- of the alignment and, therefore, cannot be the component size. - if Ekind (E) = E_Array_Type and then Unknown_Component_Size (E) then + if Ekind (E) = E_Array_Type and then not Known_Component_Size (E) then declare CT : constant Entity_Id := Component_Type (E); @@ -478,7 +478,7 @@ package body Layout is if Is_Array_Type (E) and then not Is_Packed (E) - and then Unknown_Alignment (E) + and then not Known_Alignment (E) and then Known_Alignment (Component_Type (E)) and then Known_Static_Component_Size (E) and then Known_Static_Esize (Component_Type (E)) @@ -529,10 +529,10 @@ package body Layout is -- explicitly by the user. In that case, also do not set -- Esize. - if Unknown_RM_Size (E) or else RM_Size (E) = Siz then + if not Known_RM_Size (E) or else RM_Size (E) = Siz then Set_RM_Size (E, Siz); - if Unknown_Esize (E) then + if not Known_Esize (E) then Siz := ((Siz + (Abits - 1)) / Abits) * Abits; Set_Esize (E, Siz); end if; @@ -576,7 +576,7 @@ package body Layout is -- arrays when passed to subprogram parameters (see special test -- in Exp_Ch6.Expand_Actuals). - if not Is_Packed (E) and then Unknown_Alignment (E) then + if not Is_Packed (E) and then not Known_Alignment (E) then if Known_Static_Component_Size (E) and then Component_Size (E) = 1 then @@ -748,7 +748,7 @@ package body Layout is if Known_Static_Esize (E) then Siz := Esize (E); - elsif Unknown_Esize (E) and then Known_Static_RM_Size (E) then + elsif not Known_Esize (E) and then Known_Static_RM_Size (E) then Siz := RM_Size (E); else return; @@ -853,7 +853,7 @@ package body Layout is if Calign > Align and then - (Unknown_Esize (Comp) + (not Known_Esize (Comp) or else (Known_Static_Esize (Comp) and then Esize (Comp) = Calign * SSU)) @@ -1020,7 +1020,7 @@ package body Layout is -- If alignment is currently not set, then we can safely set it to -- this new calculated value. - if Unknown_Alignment (E) then + if not Known_Alignment (E) then Init_Alignment (E, A); -- Cases where we have inherited an alignment diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index 137c867..3cc1f93 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -1031,7 +1031,7 @@ package body Repinfo is -- whose position is not specified have starting normalized -- bit position of zero. - if Unknown_Normalized_First_Bit (Comp) + if not Known_Normalized_First_Bit (Comp) and then not Is_Packed (Ent) then Set_Normalized_First_Bit (Comp, Uint_0); @@ -1044,7 +1044,7 @@ package body Repinfo is -- Complete annotation in case not done - if Unknown_Normalized_First_Bit (Comp) then + if not Known_Normalized_First_Bit (Comp) then Set_Normalized_Position (Comp, Npos); Set_Normalized_First_Bit (Comp, Fbit); end if; @@ -1202,7 +1202,7 @@ package body Repinfo is -- No_Uint, not Uint_0. Really everyone should use No_Uint??? elsif List_Representation_Info < 3 - or else (Esize (Ent) /= Uint_0 and then Unknown_Esize (Ent)) + or else (Esize (Ent) /= Uint_0 and then not Known_Esize (Ent)) then Write_Unknown_Val; diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 92d5249..0359625 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -12370,7 +12370,7 @@ package body Sem_Ch13 is -- length (it may for example be appropriate to round up the size -- to some convenient boundary, based on alignment considerations, etc). - if Unknown_RM_Size (Rectype) + if not Known_RM_Size (Rectype) and then Hbit + 1 <= 32 and then not Strict_Alignment (Rectype) then diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 936852c..2966492 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -16824,7 +16824,7 @@ package body Sem_Ch3 is Set_Etype (Derived_Type, Implicit_Base); Set_Size_Info (Derived_Type, Parent_Type); - if Unknown_RM_Size (Derived_Type) then + if not Known_RM_Size (Derived_Type) then Set_RM_Size (Derived_Type, RM_Size (Parent_Type)); end if; diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 6fdacdc..9cd5d14 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -11825,7 +11825,7 @@ package body Sem_Util is if Default = Known_Compatible or else (Etype (Obj) = Etype (Expr) - and then (Unknown_Alignment (Obj) + and then (not Known_Alignment (Obj) or else Alignment (Obj) = Alignment (Etype (Obj)))) then @@ -12070,7 +12070,7 @@ package body Sem_Util is -- do it when there is an address clause since we can do more if the -- alignment is known. - if Unknown_Alignment (Obj) then + if not Known_Alignment (Obj) then Set_Alignment (Obj, Alignment (Etype (Obj))); end if; -- cgit v1.1 From d45ee636a8474217ed2ee2bc3305e7d1e715df96 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Sat, 5 Jun 2021 20:05:31 -0400 Subject: [Ada] Diagnose properly illegal uses of Target_Name gcc/ada/ * sem_ch5.adb (Analyze_Target_Name): Properly reject a Target_Name when it appears outside of an assignment statement, or within the left-hand side of one. --- gcc/ada/sem_ch5.adb | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb index f9813a5..82c33a2 100644 --- a/gcc/ada/sem_ch5.adb +++ b/gcc/ada/sem_ch5.adb @@ -4233,10 +4233,50 @@ package body Sem_Ch5 is ------------------------- procedure Analyze_Target_Name (N : Node_Id) is + procedure Report_Error; + + ------------------ + -- Report_Error -- + ------------------ + + procedure Report_Error is + begin + Error_Msg_N + ("must appear in the right-hand side of an assignment statement", + N); + Rewrite (N, New_Occurrence_Of (Any_Id, Sloc (N))); + end Report_Error; + begin -- A target name has the type of the left-hand side of the enclosing -- assignment. + -- First, verify that the context is the right-hand side of an + -- assignment statement. + + if No (Current_Assignment) then + Report_Error; + return; + + else + declare + P : Node_Id := N; + begin + while Present (P) + and then Nkind (Parent (P)) /= N_Assignment_Statement + loop + P := Parent (P); + end loop; + + if No (P) + or else P /= Expression (Parent (P)) + then + Report_Error; + return; + end if; + end; + end if; + Set_Etype (N, Etype (Name (Current_Assignment))); end Analyze_Target_Name; -- cgit v1.1 From 43931c97820a8ec9ad01784530ba61332fd87cc8 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Mon, 7 Jun 2021 10:18:29 +0200 Subject: [Ada] Tune detection of illegal occurrences of target_name gcc/ada/ * sem_ch5.adb (Analyze_Assignment): Clear Current_Assignment at exit. (Analyze_Target_Name): Prevent AST climbing from going too far. --- gcc/ada/sem_ch5.adb | 50 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb index 82c33a2..7a8d0cc 100644 --- a/gcc/ada/sem_ch5.adb +++ b/gcc/ada/sem_ch5.adb @@ -480,12 +480,11 @@ package body Sem_Ch5 is Mark_And_Set_Ghost_Assignment (N); if Has_Target_Names (N) then + pragma Assert (No (Current_Assignment)); Current_Assignment := N; Expander_Mode_Save_And_Set (False); Save_Full_Analysis := Full_Analysis; Full_Analysis := False; - else - Current_Assignment := Empty; end if; Analyze (Lhs); @@ -1302,6 +1301,7 @@ package body Sem_Ch5 is if Has_Target_Names (N) then Expander_Mode_Restore; Full_Analysis := Save_Full_Analysis; + Current_Assignment := Empty; end if; pragma Assert (not Should_Transform_BIP_Assignment (Typ => T1)); @@ -4234,6 +4234,8 @@ package body Sem_Ch5 is procedure Analyze_Target_Name (N : Node_Id) is procedure Report_Error; + -- Complain about illegal use of target_name and rewrite it into unknown + -- identifier. ------------------ -- Report_Error -- @@ -4247,6 +4249,8 @@ package body Sem_Ch5 is Rewrite (N, New_Occurrence_Of (Any_Id, Sloc (N))); end Report_Error; + -- Start of processing for Analyze_Target_Name + begin -- A target name has the type of the left-hand side of the enclosing -- assignment. @@ -4257,27 +4261,39 @@ package body Sem_Ch5 is if No (Current_Assignment) then Report_Error; return; + end if; - else - declare - P : Node_Id := N; - begin - while Present (P) - and then Nkind (Parent (P)) /= N_Assignment_Statement - loop - P := Parent (P); - end loop; + declare + Current : Node_Id := N; + Context : Node_Id := Parent (N); + begin + while Present (Context) loop - if No (P) - or else P /= Expression (Parent (P)) - then + -- Check if target_name appears in the expression of the enclosing + -- assignment. + + if Nkind (Context) = N_Assignment_Statement then + if Current = Expression (Context) then + pragma Assert (Context = Current_Assignment); + Set_Etype (N, Etype (Name (Current_Assignment))); + else + Report_Error; + end if; + return; + + -- Prevent the search from going too far + + elsif Is_Body_Or_Package_Declaration (Context) then Report_Error; return; end if; - end; - end if; - Set_Etype (N, Etype (Name (Current_Assignment))); + Current := Context; + Context := Parent (Context); + end loop; + + Report_Error; + end; end Analyze_Target_Name; ------------------------ -- cgit v1.1 From 1ca642d785c49e9e0b28651b190720267703f023 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Wed, 30 Jun 2021 13:47:07 +0000 Subject: testsuite: Add arm_arch_v7a_ok effective-target to pr57351.c I've noticed that overriding cpu/arch flags when running the testsuite can cause this test to fail rather than being skipped because of incompatible flags combination. Since the test forces -march=armv7-a, make sure it is accepted in combination with the current runtestflags. 2021-07-08 Christophe Lyon gcc/testsuite/ * gcc.dg/debug/pr57351.c: Require arm_arch_v7a_ok effective-target. --- gcc/testsuite/gcc.dg/debug/pr57351.c | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/debug/pr57351.c b/gcc/testsuite/gcc.dg/debug/pr57351.c index 972f3e9..236d74d 100644 --- a/gcc/testsuite/gcc.dg/debug/pr57351.c +++ b/gcc/testsuite/gcc.dg/debug/pr57351.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target arm_neon } */ +/* { dg-require-effective-target arm_arch_v7a_ok } */ /* { dg-options "-std=c99 -Os -g -march=armv7-a" } */ /* { dg-add-options arm_neon } */ -- cgit v1.1 From 9bf9f27ac6db4823628c435da9b242fd82bf8d68 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 8 Jul 2021 11:34:27 -0600 Subject: Use Object Size Type zero for -Warray-bounds [PR101374]. Resolves: PR bootstrap/101374 - -Warray-bounds accessing a member subobject as derived gcc/cp/ChangeLog: PR bootstrap/101374 * module.cc (module_state::read_macro_maps): Temporarily disable -Warray-bounds. (module_state::install_macros): Same. gcc/ChangeLog: PR bootstrap/101374 * gimple-array-bounds.cc (array_bounds_checker::check_mem_ref): Use Object Size Type 0 instead of 1. gcc/testsuite/ChangeLog: PR bootstrap/101374 * c-c++-common/Warray-bounds-3.c: Xfail assertion. * c-c++-common/Warray-bounds-4.c: Same. --- gcc/cp/module.cc | 13 +++++++++++++ gcc/gimple-array-bounds.cc | 2 +- gcc/testsuite/c-c++-common/Warray-bounds-3.c | 2 +- gcc/testsuite/c-c++-common/Warray-bounds-4.c | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index f259515..8a890c1 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -16301,11 +16301,18 @@ module_state::read_macro_maps () } if (count) sec.set_overrun (); + + /* FIXME: Re-enable or fix after root causing. */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + dump (dumper::LOCATION) && dump ("Macro:%u %I %u/%u*2 locations [%u,%u)", ix, identifier (node), runs, n_tokens, MAP_START_LOCATION (macro), MAP_START_LOCATION (macro) + n_tokens); + +#pragma GCC diagnostic pop } location_t lwm = sec.u (); macro_locs.first = lwm - slurp->loc_deltas.second; @@ -16911,6 +16918,10 @@ module_state::install_macros () macro_import::slot &slot = imp.append (mod, flags); slot.offset = sec.u (); + /* FIXME: Re-enable or fix after root causing. */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + dump (dumper::MACRO) && dump ("Read %s macro %s%s%s %I at %u", imp.length () > 1 ? "add" : "new", @@ -16931,6 +16942,8 @@ module_state::install_macros () exp.def = cur; dump (dumper::MACRO) && dump ("Saving current #define %I", identifier (node)); + +#pragma GCC diagnostic pop } } diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc index 83b8db9..8dfd6f9 100644 --- a/gcc/gimple-array-bounds.cc +++ b/gcc/gimple-array-bounds.cc @@ -427,7 +427,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref, axssize = wi::to_offset (access_size); access_ref aref; - if (!compute_objsize (ref, 1, &aref, ranges)) + if (!compute_objsize (ref, 0, &aref, ranges)) return false; if (aref.offset_in_range (axssize)) diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-3.c b/gcc/testsuite/c-c++-common/Warray-bounds-3.c index 3d7c768..75f9a49 100644 --- a/gcc/testsuite/c-c++-common/Warray-bounds-3.c +++ b/gcc/testsuite/c-c++-common/Warray-bounds-3.c @@ -178,7 +178,7 @@ void test_memcpy_bounds_memarray_range (void) TM (ma.a5, ma.a5 + i, ma.a5, 1); TM (ma.a5, ma.a5 + i, ma.a5, 3); - TM (ma.a5, ma.a5 + i, ma.a5, 5); /* { dg-warning "\\\[-Warray-bounds" } */ + TM (ma.a5, ma.a5 + i, ma.a5, 5); /* { dg-warning "\\\[-Warray-bounds" "pr101374" { xfail *-*-* } } */ TM (ma.a5, ma.a5 + i, ma.a5, 7); /* diagnosed with -Warray-bounds=2 */ } diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-4.c b/gcc/testsuite/c-c++-common/Warray-bounds-4.c index 1f73f119..835c634 100644 --- a/gcc/testsuite/c-c++-common/Warray-bounds-4.c +++ b/gcc/testsuite/c-c++-common/Warray-bounds-4.c @@ -52,7 +52,7 @@ void test_memcpy_bounds_memarray_range (void) = MEM [(char * {ref-all})&ma]; and could be improved. Just verify that one is issued but not its full text. */ - TM (ma.a5, ma.a5 + j, ma.a5, 5); /* { dg-warning "\\\[-Warray-bounds" } */ + TM (ma.a5, ma.a5 + j, ma.a5, 5); /* { dg-warning "\\\[-Warray-bounds" "pr101374" { xfail *-*-* } } */ TM (ma.a5, ma.a5 + j, ma.a5, 7); /* { dg-warning "offset \\\[5, 7] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]. at offset 0" } */ TM (ma.a5, ma.a5 + j, ma.a5, 9); /* { dg-warning "offset \\\[5, 9] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]. at offset 0" } */ -- cgit v1.1 From 763121ccd908f52bc666f277ea2cf42110b3aad9 Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Thu, 8 Jul 2021 19:44:41 +0200 Subject: ipa-sra: Fix thinko when overriding safe_to_import_accesses (PR 101066) The "new" IPA-SRA has a more difficult job than the previous not-truly-IPA version when identifying situations in which a parameter passed by reference can be passed into a third function and only thee converted to one passed by value (and possibly "split" at the same time). In order to allow this, two conditions must be fulfilled. First the call to the third function must happen before any modifications of memory, because it could change the value passed by reference. Second, in order to make sure we do not introduce new (invalid) dereferences, the call must postdominate the entry BB. The second condition is actually not necessary if the caller function is also certain to dereference the pointer but the first one must still hold. Unfortunately, the code making this overriding decision also happen to trigger when the first condition is not fulfilled. This is fixed in the following patch. gcc/ChangeLog: 2021-06-16 Martin Jambor PR ipa/101066 * ipa-sra.c (class isra_call_summary): New member m_before_any_store, initialize it in the constructor. (isra_call_summary::dump): Dump the new field. (ipa_sra_call_summaries::duplicate): Copy it. (process_scan_results): Set it. (isra_write_edge_summary): Stream it. (isra_read_edge_summary): Likewise. (param_splitting_across_edge): Only override safe_to_import_accesses if m_before_any_store is set. gcc/testsuite/ChangeLog: 2021-06-16 Martin Jambor PR ipa/101066 * gcc.dg/ipa/pr101066.c: New test. --- gcc/ipa-sra.c | 15 +++++++++++++-- gcc/testsuite/gcc.dg/ipa/pr101066.c | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/ipa/pr101066.c (limited to 'gcc') diff --git a/gcc/ipa-sra.c b/gcc/ipa-sra.c index 3272daf..965e246 100644 --- a/gcc/ipa-sra.c +++ b/gcc/ipa-sra.c @@ -343,7 +343,7 @@ class isra_call_summary public: isra_call_summary () : m_arg_flow (), m_return_ignored (false), m_return_returned (false), - m_bit_aligned_arg (false) + m_bit_aligned_arg (false), m_before_any_store (false) {} void init_inputs (unsigned arg_count); @@ -362,6 +362,10 @@ public: /* Set when any of the call arguments are not byte-aligned. */ unsigned m_bit_aligned_arg : 1; + + /* Set to true if the call happend before any (other) store to memory in the + caller. */ + unsigned m_before_any_store : 1; }; /* Class to manage function summaries. */ @@ -491,6 +495,8 @@ isra_call_summary::dump (FILE *f) fprintf (f, " return value ignored\n"); if (m_return_returned) fprintf (f, " return value used only to compute caller return value\n"); + if (m_before_any_store) + fprintf (f, " happens before any store to memory\n"); for (unsigned i = 0; i < m_arg_flow.length (); i++) { fprintf (f, " Parameter %u:\n", i); @@ -535,6 +541,7 @@ ipa_sra_call_summaries::duplicate (cgraph_edge *, cgraph_edge *, new_sum->m_return_ignored = old_sum->m_return_ignored; new_sum->m_return_returned = old_sum->m_return_returned; new_sum->m_bit_aligned_arg = old_sum->m_bit_aligned_arg; + new_sum->m_before_any_store = old_sum->m_before_any_store; } @@ -2374,6 +2381,7 @@ process_scan_results (cgraph_node *node, struct function *fun, unsigned count = gimple_call_num_args (call_stmt); isra_call_summary *csum = call_sums->get_create (cs); csum->init_inputs (count); + csum->m_before_any_store = uses_memory_as_obtained; for (unsigned argidx = 0; argidx < count; argidx++) { if (!csum->m_arg_flow[argidx].pointer_pass_through) @@ -2546,6 +2554,7 @@ isra_write_edge_summary (output_block *ob, cgraph_edge *e) bp_pack_value (&bp, csum->m_return_ignored, 1); bp_pack_value (&bp, csum->m_return_returned, 1); bp_pack_value (&bp, csum->m_bit_aligned_arg, 1); + bp_pack_value (&bp, csum->m_before_any_store, 1); streamer_write_bitpack (&bp); } @@ -2664,6 +2673,7 @@ isra_read_edge_summary (struct lto_input_block *ib, cgraph_edge *cs) csum->m_return_ignored = bp_unpack_value (&bp, 1); csum->m_return_returned = bp_unpack_value (&bp, 1); csum->m_bit_aligned_arg = bp_unpack_value (&bp, 1); + csum->m_before_any_store = bp_unpack_value (&bp, 1); } /* Read intraprocedural analysis information about NODE and all of its outgoing @@ -3420,7 +3430,8 @@ param_splitting_across_edge (cgraph_edge *cs) } else if (!ipf->safe_to_import_accesses) { - if (!all_callee_accesses_present_p (param_desc, arg_desc)) + if (!csum->m_before_any_store + || !all_callee_accesses_present_p (param_desc, arg_desc)) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " %u->%u: cannot import accesses.\n", diff --git a/gcc/testsuite/gcc.dg/ipa/pr101066.c b/gcc/testsuite/gcc.dg/ipa/pr101066.c new file mode 100644 index 0000000..1ceb6e4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr101066.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-options "-Os -fno-ipa-cp -fno-inline" } */ + +int a = 1, c, d, e; +int *b = &a; +static int g(int *h) { + c = *h; + return d; +} +static void f(int *h) { + e = *h; + *b = 0; + g(h); +} +int main() { + f(b); + if (c) + __builtin_abort(); + return 0; +} -- cgit v1.1 From b14ac7b29c9a05c94f62fe065c219bbaa83653db Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Thu, 8 Jul 2021 17:09:36 -0400 Subject: Further improvements to H8 variable shift patterns gcc/ * config/h8300/shiftrotate.md (variable shifts): Expose condition code handling for the test before the loop. --- gcc/config/h8300/shiftrotate.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/config/h8300/shiftrotate.md b/gcc/config/h8300/shiftrotate.md index 485303c..d3aa6be 100644 --- a/gcc/config/h8300/shiftrotate.md +++ b/gcc/config/h8300/shiftrotate.md @@ -377,8 +377,10 @@ (clobber (reg:CC CC_REG))] "epilogue_completed && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" - [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) + [(set (reg:CCZN CC_REG) + (compare:CCZN (match_dup 1) (const_int 0))) + (set (pc) + (if_then_else (le (reg:CCZN CC_REG) (const_int 0)) (label_ref (match_dup 5)) (pc))) (match_dup 4) @@ -411,10 +413,12 @@ (clobber (reg:CC CC_REG))] "epilogue_completed && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" - [(set (match_dup 3) - (match_dup 1)) + [(parallel + [(set (reg:CCZN CC_REG) + (compare:CCZN (match_dup 1) (const_int 0))) + (set (match_dup 3) (match_dup 1))]) (set (pc) - (if_then_else (le (match_dup 3) (const_int 0)) + (if_then_else (le (reg:CCZN CC_REG) (const_int 0)) (label_ref (match_dup 5)) (pc))) (match_dup 4) -- cgit v1.1 From dee00bf6894be0cabb8f263c993357a6f8444f8b Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 7 Jul 2021 20:02:18 -0400 Subject: c++: Fix noexcept with unevaluated operand [PR101087] It sounds plausible that this assert int f(); static_assert(noexcept(sizeof(f()))); should pass: sizeof produces a std::size_t and its operand is not evaluated, so it can't throw. noexcept should only evaluate to false for potentially evaluated operands. Therefore I think that check_noexcept_r shouldn't walk into operands of sizeof/decltype/ alignof/typeof. PR c++/101087 gcc/cp/ChangeLog: * cp-tree.h (unevaluated_p): New. * except.c (check_noexcept_r): Use it. Don't walk into unevaluated operands. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/noexcept70.C: New test. --- gcc/cp/cp-tree.h | 13 +++++++++++++ gcc/cp/except.c | 9 ++++++--- gcc/testsuite/g++.dg/cpp0x/noexcept70.C | 5 +++++ 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept70.C (limited to 'gcc') diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b450157..d4810c0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -8465,6 +8465,19 @@ is_constrained_auto (const_tree t) return is_auto (t) && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t); } +/* True if CODE, a tree code, denotes a tree whose operand is not evaluated + as per [expr.context], i.e., an operand to sizeof, typeof, decltype, or + alignof. */ + +inline bool +unevaluated_p (tree_code code) +{ + return (code == DECLTYPE_TYPE + || code == ALIGNOF_EXPR + || code == SIZEOF_EXPR + || code == NOEXCEPT_EXPR); +} + /* RAII class to push/pop the access scope for T. */ struct push_access_scope_guard diff --git a/gcc/cp/except.c b/gcc/cp/except.c index a8cea53..a8acbc4 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1033,12 +1033,15 @@ check_handlers (tree handlers) expression whose type is a polymorphic class type (10.3). */ static tree -check_noexcept_r (tree *tp, int * /*walk_subtrees*/, void * /*data*/) +check_noexcept_r (tree *tp, int *walk_subtrees, void *) { tree t = *tp; enum tree_code code = TREE_CODE (t); - if ((code == CALL_EXPR && CALL_EXPR_FN (t)) - || code == AGGR_INIT_EXPR) + + if (unevaluated_p (code)) + *walk_subtrees = false; + else if ((code == CALL_EXPR && CALL_EXPR_FN (t)) + || code == AGGR_INIT_EXPR) { /* We can only use the exception specification of the called function for determining the value of a noexcept expression; we can't use diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept70.C b/gcc/testsuite/g++.dg/cpp0x/noexcept70.C new file mode 100644 index 0000000..45a6137 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept70.C @@ -0,0 +1,5 @@ +// PR c++/101087 +// { dg-do compile { target c++11 } } + +int f(); +static_assert(noexcept(sizeof(f())), ""); -- cgit v1.1 From c68cac900ab4ccaf6b1a31168bc9a302ebc46428 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 8 Jul 2021 16:02:01 -0600 Subject: Avoid including to make cross-compiler testing easy. gcc/testsuite/ChangeLog: * g++.dg/warn/Warray-bounds-11.C: Avoid including . * g++.dg/warn/Warray-bounds-13.C: Same. --- gcc/testsuite/g++.dg/warn/Warray-bounds-11.C | 19 ++++++++++++++++++- gcc/testsuite/g++.dg/warn/Warray-bounds-13.C | 19 ++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C index 70b3912..9670898 100644 --- a/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C @@ -4,7 +4,24 @@ { dg-do compile } { dg-options "-O2 -Wall -Warray-bounds -ftrack-macro-expansion=0" } */ -#include +#if 0 +// Avoid including to make cross-compiler testing easy. +// #include +#else +namespace std { + +typedef __SIZE_TYPE__ size_t; +struct nothrow_t { }; +extern const nothrow_t nothrow; + +} + +void* operator new (std::size_t, const std::nothrow_t &) throw () + __attribute__ ((__alloc_size__ (1), __malloc__)); +void* operator new[] (std::size_t, const std::nothrow_t &) throw () + __attribute__ ((__alloc_size__ (1), __malloc__)); + +#endif typedef __INT32_TYPE__ int32_t; diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C index 2d3e9dc..449324a 100644 --- a/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C @@ -4,7 +4,24 @@ { dg-do compile } { dg-options "-O2 -Wall -Warray-bounds -ftrack-macro-expansion=0" } */ -#include +#if 0 +// Avoid including to make cross-compiler testing easy. +// #include +#else +namespace std { + +typedef __SIZE_TYPE__ size_t; +struct nothrow_t { }; +extern const nothrow_t nothrow; + +} + +void* operator new (std::size_t, const std::nothrow_t &) throw () + __attribute__ ((__alloc_size__ (1), __malloc__)); +void* operator new[] (std::size_t, const std::nothrow_t &) throw () + __attribute__ ((__alloc_size__ (1), __malloc__)); + +#endif typedef __INT32_TYPE__ int32_t; -- cgit v1.1 From c232f07b931e3e4cb7cbd96e47b161f1c390f21d Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 8 Jul 2021 16:08:20 -0600 Subject: Adjust expected output for LP32 [PR100451]. gcc/testsuite/ChangeLog: PR testsuite/100451 * g++.dg/warn/Warray-bounds-20.C: Adjust expected output for LP32. --- gcc/testsuite/g++.dg/warn/Warray-bounds-20.C | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C index a65b29e..f4876d8 100644 --- a/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C @@ -27,7 +27,7 @@ struct D1: virtual B, virtual C to the opening brace. */ D1 () { // { dg-warning "\\\[-Warray-bounds" "brace" } - ci = 0; // { dg-warning "\\\[-Warray-bounds" "assign" { xfail *-*-* } } + ci = 0; // { dg-warning "\\\[-Warray-bounds" "assign" { xfail lp64 } } } }; @@ -35,7 +35,8 @@ void sink (void*); void warn_derived_ctor_access_new_decl () { - char a[sizeof (D1)]; // { dg-message "at offset 1 into object 'a' of size 40" "note" } + char a[sizeof (D1)]; // { dg-message "at offset 1 into object 'a' of size 40" "LP64 note" { target lp64} } + // { dg-message "at offset 1 into object 'a' of size 20" "LP64 note" { target ilp32} .-1 } char *p = a; ++p; D1 *q = new (p) D1; @@ -52,7 +53,8 @@ void warn_derived_ctor_access_new_alloc () void warn_derived_ctor_access_new_array_decl () { - char b[sizeof (D1) * 2]; // { dg-message "at offset \\d+ into object 'b' of size 80" "note" } + char b[sizeof (D1) * 2]; // { dg-message "at offset \\d+ into object 'b' of size 80" "LP64 note" { target lp64 } } + // { dg-message "at offset \\d+ into object 'b' of size 40" "LP64 note" { target ilp32 } .-1 } char *p = b; ++p; D1 *q = new (p) D1[2]; -- cgit v1.1 From 68b938fada4c728c0b850b44125d9a173c01c8fb Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 8 Jul 2021 16:22:25 -0600 Subject: testsuite: Remove an xfail. gcc/testsuite/ChangeLog: * gcc.dg/Wstringop-overflow-43.c: Remove an xfail. --- gcc/testsuite/gcc.dg/Wstringop-overflow-43.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-43.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-43.c index 14ab925..6d045c5 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-43.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-43.c @@ -167,9 +167,7 @@ void warn_memset_reversed_range (void) /* The following are represented as ordinary ranges with reversed bounds and those are handled. */ T1 (p, SAR (INT_MIN, 11), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" } - /* In ILP32 the offset in the following has no range info associated - with it. */ - T1 (p, SAR (INT_MIN, 1), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" "pr?????" { xfail ilp32 } } + T1 (p, SAR (INT_MIN, 1), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" } T1 (p, SAR (INT_MIN, 0), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" } /* Also represented as a true anti-range. */ T1 (p, SAR ( -12, -11), n11); // { dg-warning "writing 11 or more bytes into a region of size \\d+" } -- cgit v1.1 From 79d3378c7d73814442eb468c562ab8aa572f9c43 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 8 Jul 2021 16:36:15 -0600 Subject: Move warning suppression to the ultimate callee. Resolves: PR bootstrap/101372 - -Warray-bounds in gcc/cp/module.cc causing bootstrap failure gcc/cp/ChangeLog: PR bootstrap/101372 * module.cc (identifier): Suppress warning. (module_state::read_macro_maps): Remove warning suppression. (module_state::install_macros): Ditto. --- gcc/cp/module.cc | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 8a890c1..ccbde29 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -274,7 +274,14 @@ static inline cpp_hashnode *cpp_node (tree id) static inline tree identifier (const cpp_hashnode *node) { + /* HT_NODE() expands to node->ident that HT_IDENT_TO_GCC_IDENT() + then subtracts a nonzero constant, deriving a pointer to + a different member than ident. That's strictly undefined + and detected by -Warray-bounds. Suppress it. See PR 101372. */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" return HT_IDENT_TO_GCC_IDENT (HT_NODE (const_cast (node))); +#pragma GCC diagnostic pop } /* Id for dumping module information. */ @@ -16301,18 +16308,11 @@ module_state::read_macro_maps () } if (count) sec.set_overrun (); - - /* FIXME: Re-enable or fix after root causing. */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warray-bounds" - dump (dumper::LOCATION) && dump ("Macro:%u %I %u/%u*2 locations [%u,%u)", ix, identifier (node), runs, n_tokens, MAP_START_LOCATION (macro), MAP_START_LOCATION (macro) + n_tokens); - -#pragma GCC diagnostic pop } location_t lwm = sec.u (); macro_locs.first = lwm - slurp->loc_deltas.second; @@ -16918,10 +16918,6 @@ module_state::install_macros () macro_import::slot &slot = imp.append (mod, flags); slot.offset = sec.u (); - /* FIXME: Re-enable or fix after root causing. */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warray-bounds" - dump (dumper::MACRO) && dump ("Read %s macro %s%s%s %I at %u", imp.length () > 1 ? "add" : "new", @@ -16942,8 +16938,6 @@ module_state::install_macros () exp.def = cur; dump (dumper::MACRO) && dump ("Saving current #define %I", identifier (node)); - -#pragma GCC diagnostic pop } } -- cgit v1.1 From fdc4d2a516d042bc9a6936fad3f887aff353a296 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 9 Jul 2021 00:16:27 +0000 Subject: Daily bump. --- gcc/ChangeLog | 70 +++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/ada/ChangeLog | 201 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/cp/ChangeLog | 21 +++++ gcc/testsuite/ChangeLog | 51 ++++++++++++ 5 files changed, 344 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8f06b05..48bb23c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,73 @@ +2021-07-08 Jeff Law + + * config/h8300/shiftrotate.md (variable shifts): Expose condition + code handling for the test before the loop. + +2021-07-08 Martin Jambor + + PR ipa/101066 + * ipa-sra.c (class isra_call_summary): New member + m_before_any_store, initialize it in the constructor. + (isra_call_summary::dump): Dump the new field. + (ipa_sra_call_summaries::duplicate): Copy it. + (process_scan_results): Set it. + (isra_write_edge_summary): Stream it. + (isra_read_edge_summary): Likewise. + (param_splitting_across_edge): Only override + safe_to_import_accesses if m_before_any_store is set. + +2021-07-08 Martin Sebor + + PR bootstrap/101374 + * gimple-array-bounds.cc (array_bounds_checker::check_mem_ref): + Use Object Size Type 0 instead of 1. + +2021-07-08 Richard Sandiford + + * tree-vect-loop.c (vectorizable_reduction): Remove always-true + if condition. + +2021-07-08 Richard Sandiford + + * match.pd: Simplify an extend-operate-truncate sequence involving + a POLY_INT_CST. + +2021-07-08 Roger Sayle + Richard Biener + + PR tree-optimization/40210 + * match.pd (bswap optimizations): Simplify (bswap(x)>>C1)&C2 as + (x>>C3)&C2 when possible. Simplify bswap(x)>>C1 as ((T)x)>>C2 + when possible. Simplify bswap(x)&C1 as (x>>C2)&C1 when 0<=C1<=255. + +2021-07-08 Uroš Bizjak + + PR target/100637 + * config/i386/i386-expand.c (ix86_expand_sse_unpack): + Handle V4QI mode. + * config/i386/mmx.md (V_32): New mode iterator. + (mov): Use V_32 mode iterator. + (*mov_internal): Ditto. + (*push2_rex64): Ditto. + (*push2): Ditto. + (movmisalign): Ditto. + (mmx_v1si3): New insn pattern. + (sse4_1_v2qiv2hi2): Ditto. + (vec_unpacks_lo_v4qi): New expander. + (vec_unpacks_hi_v4qi): Ditto. + (vec_unpacku_lo_v4qi): Ditto. + (vec_unpacku_hi_v4qi): Ditto. + * config/i386/i386.h (VALID_SSE2_REG_MODE): Add V1SImode. + (VALID_INT_MODE_P): Ditto. + +2021-07-08 Michael Meissner + + PR target/100809 + * config/rs6000/rs6000.md (udivti3): New insn. + (divti3): New insn. + (umodti3): New insn. + (modti3): New insn. + 2021-07-07 Martin Sebor PR tree-optimization/100137 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d944002..23a1b25 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210708 +20210709 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f04e184..e513e5b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,204 @@ +2021-07-08 Piotr Trojanek + + * sem_ch5.adb (Analyze_Assignment): Clear Current_Assignment at + exit. + (Analyze_Target_Name): Prevent AST climbing from going too far. + +2021-07-08 Ed Schonberg + + * sem_ch5.adb (Analyze_Target_Name): Properly reject a + Target_Name when it appears outside of an assignment statement, + or within the left-hand side of one. + +2021-07-08 Bob Duff + + * einfo-utils.ads, einfo-utils.adb (Unknown_Alignment, + Unknown_Component_Bit_Offset, Unknown_Component_Size, + Unknown_Esize, Unknown_Normalized_First_Bit, + Unknown_Normalized_Position, Unknown_Normalized_Position_Max, + Unknown_RM_Size): Remove these functions. + * exp_pakd.adb, exp_util.adb, fe.h, freeze.adb, layout.adb, + repinfo.adb, sem_ch13.adb, sem_ch3.adb, sem_util.adb: Remove + calls to these functions; do "not Known_..." instead. + * gcc-interface/decl.c, gcc-interface/trans.c + (Unknown_Alignment, Unknown_Component_Size, Unknown_Esize, + Unknown_RM_Size): Remove calls to these functions; do + "!Known_..." instead. + +2021-07-08 Eric Botcazou + + * exp_dbug.adb (Get_Encoded_Name): Do not encode names of discrete + types with custom bounds, except with -fgnat-encodings=all. + * exp_pakd.adb (Create_Packed_Array_Impl_Type): Adjust comment. + +2021-07-08 Bob Duff + + * comperr.adb (Compiler_Abort): Call Sinput.Unlock, because if + this is called late, then Source_Dump would crash otherwise. + * debug.adb: Correct documentation of the -gnatd.9 switch. + * exp_ch4.adb (Expand_Allocator_Expression): Add a comment. + * exp_ch6.adb: Minor comment fixes. Add assertion. + * exp_ch6.ads (Is_Build_In_Place_Result_Type): Correct comment. + * exp_ch7.adb, checks.ads: Minor comment fixes. + +2021-07-08 Doug Rupp + + * sigtramp-vxworks-target.inc: Rename to... + * sigtramp-vxworks-target.h: ... this. + * sigtramp-vxworks.c, Makefile.rtl: Likewise. + +2021-07-08 Ghjuvan Lacambre + + * lib-writ.ads: Mention SCOs dependency as reason for duplicates. + * lib.ads (Units): Update documentation to mention duplicated + units. + +2021-07-08 Ed Schonberg + + * style.adb (Missing_Overriding): Do not emit message when + parent of subprogram is a full type declaration. + +2021-07-08 Arnaud Charlet + + * par-ch5.adb (P_Iterator_Specification): Add support for access + definition in loop parameter. + * sem_ch5.adb (Check_Subtype_Indication): Renamed... + (Check_Subtype_Definition): ... into this and check for conformance + on access definitions, and improve error messages. + (Analyze_Iterator_Specification): Add support for access definition + in loop parameter. + +2021-07-08 Arnaud Charlet + + * sem_util.ads, sem_util.adb + (Apply_Compile_Time_Constraint_Error): New parameter + Emit_Message. + * sem_ch4.adb (Analyze_Selected_Component): Disable warning + within an instance. + +2021-07-08 Eric Botcazou + + * exp_imgv.adb: Add with and use clause for Restrict and Rident. + (Build_Enumeration_Image_Tables): Do not generate the hash function + if the No_Implicit_Loops restriction is active. + +2021-07-08 Piotr Trojanek + + * sem_ch12.adb, sem_ch6.adb, sem_ch9.adb, sprint.adb: Simplify + checks for non-empty lists. + +2021-07-08 Piotr Trojanek + + * par-ch10.adb (Unit_Display): Remove redundant condition; fix + whitespace. + +2021-07-08 Piotr Trojanek + + * lib-load.adb (Load): Replace early return with goto to properly + restore context on failure. + +2021-07-08 Piotr Trojanek + + * lib-writ.adb (Ensure_System_Dependency): Simplify condition. + +2021-07-08 Piotr Trojanek + + * lib-load.adb (Load_Unit): Fix style in comment. + * par-load.adb (Load): Likewise. + * scng.adb (Initialize_Scanner): Fix whitespace. + +2021-07-08 Piotr Trojanek + + * par-load.adb (Load): Don't remove unit, but flag it as + erroneous and return. + +2021-07-08 Ghjuvan Lacambre + + * exp_prag.adb (Expand_Pragma_Inspection_Point): Fix error + message. + +2021-07-08 Yannick Moy + + * layout.adb (Layout_Type): Do not call Number_Dimensions if the + type does not have First_Index set. + +2021-07-08 Ghjuvan Lacambre + + * exp_prag.adb (Expand_Pragma_Inspection_Point): After expansion + of the Inspection_Point pragma, check if referenced entities + that have a freeze node are already frozen. If they aren't, emit + a warning and turn the pragma into a no-op. + +2021-07-08 Yannick Moy + + * layout.adb (Layout_Type): Add guard before calling Expr_Value. + +2021-07-08 Yannick Moy + + * layout.adb (Layout_Type): Special case when RM_Size and Esize + can be computed for packed arrays. + +2021-07-08 Steve Baird + + * rtsfind.ads, rtsfind.adb: Add support for finding the packages + System.Atomic_Operations and + System.Atomic_Operations.Test_And_Set and the declarations + within that latter package of the type Test_And_Set_Flag and the + function Atomic_Test_And_Set. + * exp_ch11.adb (Expand_N_Exception_Declaration): If an exception + is declared other than at library level, then we need to call + Register_Exception the first time (and only the first time) the + declaration is elaborated. In order to decide whether to + perform this call for a given elaboration of the declaration, we + used to unconditionally use a (library-level) Boolean variable. + Now we instead use a variable of type + System.Atomic_Operations.Test_And_Set.Test_And_Set_Flag unless + either that type is unavailable or a No_Tasking restriction is + in effect (in which case we use a Boolean variable as before). + +2021-07-08 Arnaud Charlet + + * gcc-interface/system.ads: Add No_Tasking restriction. + +2021-07-08 Ed Schonberg + + * libgnat/a-cohama.ads: Introduce an equality operator over + cursors. + * libgnat/a-cohase.ads: Ditto. + * libgnat/a-cohama.adb: Add body for "=" over cursors. + (Insert): Do not set the Position component of the cursor that + denotes the inserted element. + * libgnat/a-cohase.adb: Ditto. + +2021-07-08 Arnaud Charlet + + * libgnat/a-cbdlli.adb, libgnat/a-cbhama.adb, + libgnat/a-cbhase.adb, libgnat/a-cbmutr.adb, + libgnat/a-cborma.adb, libgnat/a-cborse.adb, + libgnat/a-cobove.adb, libgnat/a-textio.adb, + libgnat/a-witeio.adb, libgnat/a-ztexio.adb: Make code compatible + with No_Dynamic_Accessibility_Checks restriction. + +2021-07-08 Arnaud Charlet + + * debug.adb, sem_util.adb: Revert meaning of -gnatd_b. + * sem_res.adb: Minor reformatting. + +2021-07-08 Arnaud Charlet + + * make.adb, osint.adb: Make code compatible with + No_Dynamic_Accessibility_Checks restriction. + +2021-07-08 Piotr Trojanek + + * lib-writ.adb (Ensure_System_Dependency): Replace search in + Lib.Units with a search in Lib.Unit_Names. + +2021-07-08 Piotr Trojanek + + * sinput-l.adb (Load_File): Simplify foreword manipulation with + concatenation; similar for filename with preprocessed output. + 2021-07-07 Dmitriy Anisimkov * s-oscons-tmplt.c (MSG_WAITALL): Remove wrong #ifdef diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 31deb04..4386e5d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,24 @@ +2021-07-08 Martin Sebor + + PR bootstrap/101372 + * module.cc (identifier): Suppress warning. + (module_state::read_macro_maps): Remove warning suppression. + (module_state::install_macros): Ditto. + +2021-07-08 Marek Polacek + + PR c++/101087 + * cp-tree.h (unevaluated_p): New. + * except.c (check_noexcept_r): Use it. Don't walk into + unevaluated operands. + +2021-07-08 Martin Sebor + + PR bootstrap/101374 + * module.cc (module_state::read_macro_maps): Temporarily disable + -Warray-bounds. + (module_state::install_macros): Same. + 2021-07-06 Martin Sebor * error.c (cp_printer): Remove support for %G and %K. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5543edb..cdd3376 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,54 @@ +2021-07-08 Martin Sebor + + * gcc.dg/Wstringop-overflow-43.c: Remove an xfail. + +2021-07-08 Martin Sebor + + PR testsuite/100451 + * g++.dg/warn/Warray-bounds-20.C: Adjust expected output for LP32. + +2021-07-08 Martin Sebor + + * g++.dg/warn/Warray-bounds-11.C: Avoid including . + * g++.dg/warn/Warray-bounds-13.C: Same. + +2021-07-08 Marek Polacek + + PR c++/101087 + * g++.dg/cpp0x/noexcept70.C: New test. + +2021-07-08 Martin Jambor + + PR ipa/101066 + * gcc.dg/ipa/pr101066.c: New test. + +2021-07-08 Martin Sebor + + PR bootstrap/101374 + * c-c++-common/Warray-bounds-3.c: Xfail assertion. + * c-c++-common/Warray-bounds-4.c: Same. + +2021-07-08 Christophe Lyon + + * gcc.dg/debug/pr57351.c: Require arm_arch_v7a_ok + effective-target. + +2021-07-08 Richard Sandiford + + * gcc.target/aarch64/sve/acle/general/cntb_1.c: New test. + +2021-07-08 Roger Sayle + Richard Biener + + PR tree-optimization/40210 + * gcc.dg/builtin-bswap-13.c: New test. + * gcc.dg/builtin-bswap-14.c: New test. + +2021-07-08 Michael Meissner + + PR target/100809 + * gcc.target/powerpc/p10-vdivq-vmodq.c: New test. + 2021-07-07 David Malcolm * gcc.dg/analyzer/pattern-test-2.c: Update expected results. -- cgit v1.1 From c3d1aa891cbc4d78408481d528d8f0927c2a0379 Mon Sep 17 00:00:00 2001 From: Kewen Lin Date: Thu, 8 Jul 2021 21:59:50 -0500 Subject: test/rs6000: Add cases to cover vector multiply This patch is to add test cases to check if vectorizer can exploit vector multiply instrutions on Power, some of them are supported since Power8, the others are newly introduced by Power10. gcc/testsuite/ChangeLog: * gcc.target/powerpc/mul-vectorize-1.c: New test. * gcc.target/powerpc/mul-vectorize-2.c: New test. --- gcc/testsuite/gcc.target/powerpc/mul-vectorize-1.c | 27 ++++++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/mul-vectorize-2.c | 27 ++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 gcc/testsuite/gcc.target/powerpc/mul-vectorize-1.c create mode 100644 gcc/testsuite/gcc.target/powerpc/mul-vectorize-2.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/powerpc/mul-vectorize-1.c b/gcc/testsuite/gcc.target/powerpc/mul-vectorize-1.c new file mode 100644 index 0000000..ba01d5c --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mul-vectorize-1.c @@ -0,0 +1,27 @@ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-options "-mdejagnu-cpu=power8 -O2 -ftree-vectorize -fno-vect-cost-model -fno-unroll-loops -fdump-tree-vect-details" } */ + +/* Test vectorizer can exploit ISA 2.07 instruction vmuluwm (Vector Multiply + Unsigned Word Modulo) for both signed and unsigned word multiplication. */ + +#define N 128 + +extern signed int si_a[N], si_b[N], si_c[N]; +extern unsigned int ui_a[N], ui_b[N], ui_c[N]; + +__attribute__ ((noipa)) void +test_si () +{ + for (int i = 0; i < N; i++) + si_c[i] = si_a[i] * si_b[i]; +} + +__attribute__ ((noipa)) void +test_ui () +{ + for (int i = 0; i < N; i++) + ui_c[i] = ui_a[i] * ui_b[i]; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */ +/* { dg-final { scan-assembler-times {\mvmuluwm\M} 2 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/mul-vectorize-2.c b/gcc/testsuite/gcc.target/powerpc/mul-vectorize-2.c new file mode 100644 index 0000000..12ca97a --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mul-vectorize-2.c @@ -0,0 +1,27 @@ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2 -ftree-vectorize -fno-vect-cost-model -fno-unroll-loops -fdump-tree-vect-details" } */ + +/* Test vectorizer can exploit ISA 3.1 instruction vmulld (Vector Multiply + Low Doubleword) for both signed and unsigned doubleword multiplication. */ + +#define N 128 + +extern signed long long sd_a[N], sd_b[N], sd_c[N]; +extern unsigned long long ud_a[N], ud_b[N], ud_c[N]; + +__attribute__ ((noipa)) void +test_sd () +{ + for (int i = 0; i < N; i++) + sd_c[i] = sd_a[i] * sd_b[i]; +} + +__attribute__ ((noipa)) void +test_ud () +{ + for (int i = 0; i < N; i++) + ud_c[i] = ud_a[i] * ud_b[i]; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */ +/* { dg-final { scan-assembler-times {\mvmulld\M} 2 } } */ -- cgit v1.1 From df85baa5687170cbca8450a59cf17f3157b1d61d Mon Sep 17 00:00:00 2001 From: Kewen Lin Date: Thu, 8 Jul 2021 22:00:18 -0500 Subject: test/rs6000: Add case to cover vector division This patch is to add one test case to check if vectorizer can exploit vector division instrutions newly introduced by Power10. gcc/testsuite/ChangeLog: * gcc.target/powerpc/div-vectorize-1.c: New test. --- gcc/testsuite/gcc.target/powerpc/div-vectorize-1.c | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 gcc/testsuite/gcc.target/powerpc/div-vectorize-1.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/powerpc/div-vectorize-1.c b/gcc/testsuite/gcc.target/powerpc/div-vectorize-1.c new file mode 100644 index 0000000..6208b2d --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/div-vectorize-1.c @@ -0,0 +1,46 @@ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2 -ftree-vectorize -fno-vect-cost-model -fno-unroll-loops -fdump-tree-vect-details" } */ + +/* Test vectorizer can exploit ISA 3.1 instructions Vector Divide + Signed/Unsigned Word/Doubleword for word/doubleword division. */ + +#define N 128 + +extern signed int si_a[N], si_b[N], si_c[N]; +extern unsigned int ui_a[N], ui_b[N], ui_c[N]; +extern signed long long sd_a[N], sd_b[N], sd_c[N]; +extern unsigned long long ud_a[N], ud_b[N], ud_c[N]; + +__attribute__ ((noipa)) void +test_si () +{ + for (int i = 0; i < N; i++) + si_c[i] = si_a[i] / si_b[i]; +} + +__attribute__ ((noipa)) void +test_ui () +{ + for (int i = 0; i < N; i++) + ui_c[i] = ui_a[i] / ui_b[i]; +} + +__attribute__ ((noipa)) void +test_sd () +{ + for (int i = 0; i < N; i++) + sd_c[i] = sd_a[i] / sd_b[i]; +} + +__attribute__ ((noipa)) void +test_ud () +{ + for (int i = 0; i < N; i++) + ud_c[i] = ud_a[i] / ud_b[i]; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 4 "vect" } } */ +/* { dg-final { scan-assembler-times {\mvdivsw\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvdivuw\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvdivsd\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvdivud\M} 1 } } */ -- cgit v1.1 From 062c762ef264dca89d01ebca2ef023ea91f31d50 Mon Sep 17 00:00:00 2001 From: Kewen Lin Date: Thu, 8 Jul 2021 22:00:24 -0500 Subject: rs6000: Support [u]mod3 for vector modulo insns This patch is to make Power10 newly introduced vector modulo instructions exploited in vectorized loops, it just simply renames existing define_insns as standard pattern names. gcc/ChangeLog: * config/rs6000/vsx.md (mods_): Rename to... (mod3): ... this. (modu_): Rename to... (umod3): ... this. * config/rs6000/rs6000-builtin.def (MODS_V2DI, MODS_V4SI, MODU_V2DI, MODU_V4SI): Adjust. gcc/testsuite/ChangeLog: * gcc.target/powerpc/mod-vectorize.c: New test. --- gcc/config/rs6000/rs6000-builtin.def | 8 ++--- gcc/config/rs6000/vsx.md | 4 +-- gcc/testsuite/gcc.target/powerpc/mod-vectorize.c | 46 ++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/mod-vectorize.c (limited to 'gcc') diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def index 6270444..a0dfefc 100644 --- a/gcc/config/rs6000/rs6000-builtin.def +++ b/gcc/config/rs6000/rs6000-builtin.def @@ -3031,10 +3031,10 @@ BU_P10V_AV_2 (DIVS_V4SI, "vdivsw", CONST, divv4si3) BU_P10V_AV_2 (DIVS_V2DI, "vdivsd", CONST, divv2di3) BU_P10V_AV_2 (DIVU_V4SI, "vdivuw", CONST, udivv4si3) BU_P10V_AV_2 (DIVU_V2DI, "vdivud", CONST, udivv2di3) -BU_P10V_AV_2 (MODS_V2DI, "vmodsd", CONST, mods_v2di) -BU_P10V_AV_2 (MODS_V4SI, "vmodsw", CONST, mods_v4si) -BU_P10V_AV_2 (MODU_V2DI, "vmodud", CONST, modu_v2di) -BU_P10V_AV_2 (MODU_V4SI, "vmoduw", CONST, modu_v4si) +BU_P10V_AV_2 (MODS_V2DI, "vmodsd", CONST, modv2di3) +BU_P10V_AV_2 (MODS_V4SI, "vmodsw", CONST, modv4si3) +BU_P10V_AV_2 (MODU_V2DI, "vmodud", CONST, umodv2di3) +BU_P10V_AV_2 (MODU_V4SI, "vmoduw", CONST, umodv4si3) BU_P10V_AV_2 (MULHS_V2DI, "vmulhsd", CONST, mulhs_v2di) BU_P10V_AV_2 (MULHS_V4SI, "vmulhsw", CONST, mulhs_v4si) BU_P10V_AV_2 (MULHU_V2DI, "vmulhud", CONST, mulhu_v2di) diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index f2260ba..f622873 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -6333,7 +6333,7 @@ [(set_attr "type" "vecdiv") (set_attr "size" "")]) -(define_insn "mods_" +(define_insn "mod3" [(set (match_operand:VIlong 0 "vsx_register_operand" "=v") (mod:VIlong (match_operand:VIlong 1 "vsx_register_operand" "v") (match_operand:VIlong 2 "vsx_register_operand" "v")))] @@ -6342,7 +6342,7 @@ [(set_attr "type" "vecdiv") (set_attr "size" "")]) -(define_insn "modu_" +(define_insn "umod3" [(set (match_operand:VIlong 0 "vsx_register_operand" "=v") (umod:VIlong (match_operand:VIlong 1 "vsx_register_operand" "v") (match_operand:VIlong 2 "vsx_register_operand" "v")))] diff --git a/gcc/testsuite/gcc.target/powerpc/mod-vectorize.c b/gcc/testsuite/gcc.target/powerpc/mod-vectorize.c new file mode 100644 index 0000000..4d4f5cd --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mod-vectorize.c @@ -0,0 +1,46 @@ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2 -ftree-vectorize -fno-vect-cost-model -fno-unroll-loops -fdump-tree-vect-details" } */ + +/* Test vectorizer can exploit ISA 3.1 instructions Vector Modulo + Signed/Unsigned Word/Doubleword for word/doubleword modulo operations. */ + +#define N 128 + +extern signed int si_a[N], si_b[N], si_c[N]; +extern unsigned int ui_a[N], ui_b[N], ui_c[N]; +extern signed long long sd_a[N], sd_b[N], sd_c[N]; +extern unsigned long long ud_a[N], ud_b[N], ud_c[N]; + +__attribute__ ((noipa)) void +test_si () +{ + for (int i = 0; i < N; i++) + si_c[i] = si_a[i] % si_b[i]; +} + +__attribute__ ((noipa)) void +test_ui () +{ + for (int i = 0; i < N; i++) + ui_c[i] = ui_a[i] % ui_b[i]; +} + +__attribute__ ((noipa)) void +test_sd () +{ + for (int i = 0; i < N; i++) + sd_c[i] = sd_a[i] % sd_b[i]; +} + +__attribute__ ((noipa)) void +test_ud () +{ + for (int i = 0; i < N; i++) + ud_c[i] = ud_a[i] % ud_b[i]; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 4 "vect" } } */ +/* { dg-final { scan-assembler-times {\mvmodsw\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvmoduw\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvmodsd\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvmodud\M} 1 } } */ -- cgit v1.1 From 82625a42e652d52fc6bbe6070f8d0589d5e0c8ad Mon Sep 17 00:00:00 2001 From: Xi Ruoyao Date: Fri, 18 Jun 2021 20:11:42 +0800 Subject: mips: check MSA support for vector modes [PR100760,PR100761,PR100762] Check if the vector mode is really supported by MSA in certain cases, instead of testing ISA_HAS_MSA. Simply testing ISA_HAS_MSA can cause ICE when MSA is enabled besides other MIPS SIMD extensions (notably, Loongson MMI). gcc/ PR target/100760 PR target/100761 PR target/100762 * config/mips/mips.c (mips_const_insns): Use MSA_SUPPORTED_MODE_P instead of ISA_HAS_MSA. (mips_expand_vec_unpack): Likewise. (mips_expand_vector_init): Likewise. gcc/testsuite/ PR target/100760 PR target/100761 PR target/100762 * gcc.target/mips/pr100760.c: New test. * gcc.target/mips/pr100761.c: New test. * gcc.target/mips/pr100762.c: New test. --- gcc/config/mips/mips.c | 6 +++--- gcc/testsuite/gcc.target/mips/pr100760.c | 10 ++++++++++ gcc/testsuite/gcc.target/mips/pr100761.c | 17 +++++++++++++++++ gcc/testsuite/gcc.target/mips/pr100762.c | 25 +++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.target/mips/pr100760.c create mode 100644 gcc/testsuite/gcc.target/mips/pr100761.c create mode 100644 gcc/testsuite/gcc.target/mips/pr100762.c (limited to 'gcc') diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 1f1475c..00a8eef 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -2879,7 +2879,7 @@ mips_const_insns (rtx x) return mips_build_integer (codes, INTVAL (x)); case CONST_VECTOR: - if (ISA_HAS_MSA + if (MSA_SUPPORTED_MODE_P (GET_MODE (x)) && mips_const_vector_same_int_p (x, GET_MODE (x), -512, 511)) return 1; /* Fall through. */ @@ -21732,7 +21732,7 @@ mips_expand_vec_unpack (rtx operands[2], bool unsigned_p, bool high_p) rtx (*cmpFunc) (rtx, rtx, rtx); rtx tmp, dest, zero; - if (ISA_HAS_MSA) + if (MSA_SUPPORTED_MODE_P (imode)) { switch (imode) { @@ -21994,7 +21994,7 @@ mips_expand_vector_init (rtx target, rtx vals) all_same = false; } - if (ISA_HAS_MSA) + if (MSA_SUPPORTED_MODE_P (vmode)) { if (all_same) { diff --git a/gcc/testsuite/gcc.target/mips/pr100760.c b/gcc/testsuite/gcc.target/mips/pr100760.c new file mode 100644 index 0000000..d715b85 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/pr100760.c @@ -0,0 +1,10 @@ +/* PR target/100760 + This was triggering an ICE with "maximum number of generated reload + insns per insn achieved (90)" when compiled with -mmsa -mloongson-mmi. */ + +/* { dg-do compile } */ +/* { dg-options "-mmsa -mloongson-mmi" } */ + +typedef __INT32_TYPE__ int32_t; +typedef int32_t a __attribute__((__vector_size__(8))); +void b() { a x = (a){1, 1}; } diff --git a/gcc/testsuite/gcc.target/mips/pr100761.c b/gcc/testsuite/gcc.target/mips/pr100761.c new file mode 100644 index 0000000..cc2598e --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/pr100761.c @@ -0,0 +1,17 @@ +/* PR target/100761 + This was triggering an ICE in mips_expand_vec_unpack when compiled with + -mmsa -mloongson-mmi. */ + +/* { dg-do compile } */ +/* { dg-options "-mmsa -mloongson-mmi" } */ + +typedef __INT8_TYPE__ int8_t; +typedef __INT16_TYPE__ int16_t; +typedef int8_t i8x8 __attribute__((__vector_size__(8))); +typedef int16_t i16x8 __attribute__((__vector_size__(16))); + +i8x8 a; + +void f() { + i16x8 b = __builtin_convertvector (a, i16x8); +} diff --git a/gcc/testsuite/gcc.target/mips/pr100762.c b/gcc/testsuite/gcc.target/mips/pr100762.c new file mode 100644 index 0000000..89c1185 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/pr100762.c @@ -0,0 +1,25 @@ +/* PR target/100762 + This was triggering an ICE in mips_expand_vector_init when compiled with + -mmsa -mloongson-mmi. */ + +/* { dg-do compile } */ +/* { dg-options "-mmsa -mloongson-mmi" } */ + +typedef __INT32_TYPE__ int32_t; +typedef int32_t i32x2 __attribute__((__vector_size__(8))); + +i32x2 cmp(i32x2 a, i32x2 b) { + return a >= b; +} + +i32x2 shift(i32x2 a, i32x2 b) { + return a >> b; +} + +i32x2 mul(i32x2 a, i32x2 b) { + return a * b; +} + +i32x2 div(i32x2 a, i32x2 b) { + return a / b; +} -- cgit v1.1 From 3b33b1136d5ba1903a56fa601a848accc3db46ef Mon Sep 17 00:00:00 2001 From: Xi Ruoyao Date: Tue, 22 Jun 2021 14:15:45 +0800 Subject: testsuite: mips: use noinline attribute instead of -fno-inline mips.exp does not support -fno-inline, causing the tests return "ERROR: Unrecognised option: -fno-inline for dg-options ... ". Use noinline attribute like other mips target tests, to workaround it. gcc/testsuite/ * gcc.target/mips/cfgcleanup-jalr2.c: Remove -fno-inline and add __attribute__((noinline)). * gcc.target/mips/cfgcleanup-jalr3.c: Likewise. --- gcc/testsuite/gcc.target/mips/cfgcleanup-jalr2.c | 11 ++++++++--- gcc/testsuite/gcc.target/mips/cfgcleanup-jalr3.c | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr2.c b/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr2.c index bf22f06..6a9f86a 100644 --- a/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr2.c +++ b/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr2.c @@ -1,10 +1,15 @@ /* { dg-do compile } */ -/* { dg-options "-mabicalls -fpic -mno-mips16 -mno-micromips -fno-inline -fipa-ra -mcompact-branches=never" } */ +/* { dg-options "-mabicalls -fpic -mno-mips16 -mno-micromips -fipa-ra -mcompact-branches=never" } */ /* { dg-skip-if "needs codesize optimization" { *-*-* } { "-O0" "-O1" "-O2" "-O3" } { "" } } */ -static int foo (void* p) { __asm__ (""::"r"(p):"$t0"); return 0; } +static int __attribute__((noinline)) +foo (void* p) +{ + __asm__ (""::"r"(p):"$t0"); + return 0; +} -static int bar (void* p) { return 1; } +__attribute__((noinline)) static int bar (void* p) { return 1; } int test (void* p) diff --git a/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr3.c b/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr3.c index 805b31a..5093741 100644 --- a/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr3.c +++ b/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr3.c @@ -1,10 +1,10 @@ /* { dg-do compile } */ -/* { dg-options "-mabicalls -fpic -mno-mips16 -mno-micromips -fno-inline -fipa-ra -mcompact-branches=never" } */ +/* { dg-options "-mabicalls -fpic -mno-mips16 -mno-micromips -fipa-ra -mcompact-branches=never" } */ /* { dg-skip-if "needs codesize optimization" { *-*-* } { "-O0" "-O1" "-O2" "-O3" } { "" } } */ -static int foo (void* p) { return 0; } +__attribute__((noinline)) static int foo (void* p) { return 0; } -static int bar (void* p) { return 1; } +__attribute__((noinline)) static int bar (void* p) { return 1; } int test (void* p) -- cgit v1.1 From 5f2d3ff4e5e2ecd92f78467209ff266a8932acd7 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Mon, 5 Jul 2021 20:13:48 -0700 Subject: Improve early simplify and match for phiopt Previously the idea was gimple_simplify_phiopt would call resimplify with a NULL sequence but that sometimes fails even if there was only one statement produced. The cases where it fails is when there are two simplifications happen. In the case of the min/max production, the first simplifcation produces: (convert (min @1 @2)) And then the convert is removed by a second one. The Min statement will be in the sequence while the op will be a SSA name. This was rejected before as could not produce something in the sequence. So this patch changes the way resimplify is called to always passing a pointer to the sequence and then decide based on if op is a SSA_NAME or not. OK? Bootstrapped and tested on x86_64-linux-gnu. gcc/ChangeLog: * tree-ssa-phiopt.c (phiopt_early_allow): Change arguments to take sequence and gimple_match_op. Accept the case where op is a SSA_NAME and one statement in the sequence. Also allow constants. (gimple_simplify_phiopt): Always pass a sequence to resimplify. Update call to phiopt_early_allow. Discard the sequence if not used. --- gcc/tree-ssa-phiopt.c | 62 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 13 deletions(-) (limited to 'gcc') diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 8b60ee8..7a98b7a 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -812,11 +812,33 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb, return true; } -/* Return TRUE if CODE should be allowed during early phiopt. - Currently this is to allow MIN/MAX and ABS/NEGATE. */ +/* Return TRUE if SEQ/OP pair should be allowed during early phiopt. + Currently this is to allow MIN/MAX and ABS/NEGATE and constants. */ static bool -phiopt_early_allow (enum tree_code code) +phiopt_early_allow (gimple_seq &seq, gimple_match_op &op) { + /* Don't allow functions. */ + if (!op.code.is_tree_code ()) + return false; + tree_code code = (tree_code)op.code; + + /* For non-empty sequence, only allow one statement. */ + if (!gimple_seq_empty_p (seq)) + { + /* Check to make sure op was already a SSA_NAME. */ + if (code != SSA_NAME) + return false; + if (!gimple_seq_singleton_p (seq)) + return false; + gimple *stmt = gimple_seq_first_stmt (seq); + /* Only allow assignments. */ + if (!is_gimple_assign (stmt)) + return false; + if (gimple_assign_lhs (stmt) != op.ops[0]) + return false; + code = gimple_assign_rhs_code (stmt); + } + switch (code) { case MIN_EXPR: @@ -826,6 +848,11 @@ phiopt_early_allow (enum tree_code code) case NEGATE_EXPR: case SSA_NAME: return true; + case INTEGER_CST: + case REAL_CST: + case VECTOR_CST: + case FIXED_CST: + return true; default: return false; } @@ -844,6 +871,7 @@ gimple_simplify_phiopt (bool early_p, tree type, gimple *comp_stmt, gimple_seq *seq) { tree result; + gimple_seq seq1 = NULL; enum tree_code comp_code = gimple_cond_code (comp_stmt); location_t loc = gimple_location (comp_stmt); tree cmp0 = gimple_cond_lhs (comp_stmt); @@ -858,18 +886,23 @@ gimple_simplify_phiopt (bool early_p, tree type, gimple *comp_stmt, gimple_match_op op (gimple_match_cond::UNCOND, COND_EXPR, type, cond, arg0, arg1); - if (op.resimplify (early_p ? NULL : seq, follow_all_ssa_edges)) + if (op.resimplify (&seq1, follow_all_ssa_edges)) { /* Early we want only to allow some generated tree codes. */ if (!early_p - || op.code.is_tree_code () - || phiopt_early_allow ((tree_code)op.code)) + || phiopt_early_allow (seq1, op)) { - result = maybe_push_res_to_seq (&op, seq); + result = maybe_push_res_to_seq (&op, &seq1); if (result) - return result; + { + gimple_seq_add_seq_without_update (seq, seq1); + return result; + } } } + gimple_seq_discard (seq1); + seq1 = NULL; + /* Try the inverted comparison, that is !COMP ? ARG1 : ARG0. */ comp_code = invert_tree_comparison (comp_code, HONOR_NANS (cmp0)); @@ -882,18 +915,21 @@ gimple_simplify_phiopt (bool early_p, tree type, gimple *comp_stmt, gimple_match_op op1 (gimple_match_cond::UNCOND, COND_EXPR, type, cond, arg1, arg0); - if (op1.resimplify (early_p ? NULL : seq, follow_all_ssa_edges)) + if (op1.resimplify (&seq1, follow_all_ssa_edges)) { /* Early we want only to allow some generated tree codes. */ if (!early_p - || op1.code.is_tree_code () - || phiopt_early_allow ((tree_code)op1.code)) + || phiopt_early_allow (seq1, op1)) { - result = maybe_push_res_to_seq (&op1, seq); + result = maybe_push_res_to_seq (&op1, &seq1); if (result) - return result; + { + gimple_seq_add_seq_without_update (seq, seq1); + return result; + } } } + gimple_seq_discard (seq1); return NULL; } -- cgit v1.1 From b5405babd82b84a65efab4e59ffbf22c8c93ff53 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Fri, 9 Jul 2021 08:19:37 +0100 Subject: docs: add missing 'see' word gcc/ChangeLog: * doc/md.texi: Add missing 'see' word. --- gcc/doc/md.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index cc92ebd..7a4d24e 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -9937,7 +9937,7 @@ Lengths are measured in addressable storage units (bytes). Note that it is possible to call functions via the @code{symbol_ref} mechanism to compute the length of an insn. However, if you use this mechanism you must provide dummy clauses to express the maximum length -without using the function call. You can an example of this in the +without using the function call. You can see an example of this in the @code{pa} machine description for the @code{call_symref} pattern. The following macros can be used to refine the length computation: -- cgit v1.1 From 840fabd8e0cd002c744adf219c64a672b0fa83b3 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Fri, 9 Jul 2021 08:26:15 +0100 Subject: docs: don't split @smallexample in multiple @groups Noticed multiple groups split in HTML documentation where example was written in two columns: "" " (define_expand "addsi3" { [(match_operand:SI 0 "register_operand" "") handle_add (... (match_operand:SI 1 "register_operand" "") DONE; (match_operand:SI 2 "register_operand" "")] }") The change uses single @group/@endgroup to prevent such break. gcc/ChangeLog: * doc/md.texi: Don't split @smallexample in multiple @groups. --- gcc/doc/md.texi | 9 --------- 1 file changed, 9 deletions(-) (limited to 'gcc') diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 7a4d24e..0fe70b7 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -8455,8 +8455,6 @@ list of operands, such as this example: [(match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" "")] -@end group -@group "" " @{ @@ -8473,17 +8471,10 @@ Here is an example, the definition of left-shift for the SPUR chip: (define_expand "ashlsi3" [(set (match_operand:SI 0 "register_operand" "") (ashift:SI -@end group -@group (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "nonmemory_operand" "")))] "" " -@end group -@end smallexample - -@smallexample -@group @{ if (GET_CODE (operands[2]) != CONST_INT || (unsigned) INTVAL (operands[2]) > 3) -- cgit v1.1 From 10722fb36de944c2385a275bb2b270727f7c93a4 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Fri, 9 Jul 2021 11:45:54 +0200 Subject: i386: Fix *udivmodsi4_pow2_zext_? patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In addition to the obvious cut-n-pasto where *udivmodsi4_pow2_zext_2 never matches, limit the range of the immediate operand to prevent out of range immediate operand of AND instruction. Found by inspection, the patterns rarely match (if at all), since tree optimizers do the transformation before RTL is generated. But according to the comment above *udivmod4_pow2, the constant can materialize after expansion, so leave these patterns around for now. 2021-07-09 Uroš Bizjak gcc/ * config/i386/i386.md (*udivmodsi4_pow2_zext_1): Limit the log2 range of operands[3] to [1,31]. (*udivmodsi4_pow2_zext_2): Ditto. Correct insn RTX pattern. --- gcc/config/i386/i386.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 156c6a9..26fb81b 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -8518,7 +8518,7 @@ (umod:SI (match_dup 2) (match_dup 3))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT - && exact_log2 (UINTVAL (operands[3])) > 0" + && IN_RANGE (exact_log2 (UINTVAL (operands[3])), 1, 31)" "#" "&& reload_completed" [(set (match_dup 1) (match_dup 2)) @@ -8599,10 +8599,10 @@ (umod:SI (match_operand:SI 2 "register_operand" "0") (match_operand:SI 3 "const_int_operand" "n")))) (set (match_operand:SI 0 "register_operand" "=r") - (umod:SI (match_dup 2) (match_dup 3))) + (udiv:SI (match_dup 2) (match_dup 3))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT - && exact_log2 (UINTVAL (operands[3])) > 0" + && IN_RANGE (exact_log2 (UINTVAL (operands[3])), 1, 31)" "#" "&& reload_completed" [(set (match_dup 1) (match_dup 2)) -- cgit v1.1 From e37e175e7dc3376244eb7705269ada6755616831 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 9 Jul 2021 12:08:52 +0200 Subject: Fix build failure on Windows with older binutils This is the build failure on Windows with binutils for which GNU as accepts the --gdwarf-5 switch but GNU ld generates broken binaries with DWARF 5. We already have the HAVE_LD_BROKEN_PE_DWARF5 kludge to disable DWARF 5 in this case but it only tames the DWARF version in the compiler, so the driver still passes --gdwarf-5 when invoked on an assembly file with -g. gcc/ PR target/101377 * gcc.c (ASM_DEBUG_DWARF_OPTION): Set again to --gdwarf2 in the case where HAVE_AS_WORKING_DWARF_N_FLAG is not defined and HAVE_LD_BROKEN_PE_DWARF5 is defined. --- gcc/gcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/gcc.c b/gcc/gcc.c index 36a88fc..f086dd4 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -916,7 +916,7 @@ proper position among the other output files. */ than in ASM_DEBUG_SPEC, so that it applies to both .s and .c etc. compilations. */ # define ASM_DEBUG_DWARF_OPTION "" -# elif defined(HAVE_AS_GDWARF_5_DEBUG_FLAG) +# elif defined(HAVE_AS_GDWARF_5_DEBUG_FLAG) && !defined(HAVE_LD_BROKEN_PE_DWARF5) # define ASM_DEBUG_DWARF_OPTION "%{%:dwarf-version-gt(4):--gdwarf-5;" \ "%:dwarf-version-gt(3):--gdwarf-4;" \ "%:dwarf-version-gt(2):--gdwarf-3;" \ -- cgit v1.1 From 7e12d491ceff898275074486d6927b0d44a4b8c8 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 28 May 2021 14:54:01 +0200 Subject: [Ada] Avoid unnecessary call in preanalysis without freezing gcc/ada/ * sem_res.adb (Preanalyze_And_Resolve): Only call Set_Must_Not_Freeze when it is necessary to restore the previous value. --- gcc/ada/sem_res.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 26e4a07..e2c069c 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -1886,9 +1886,9 @@ package body Sem_Res is Expander_Mode_Restore; Full_Analysis := Save_Full_Analysis; - Set_Must_Not_Freeze (N, Save_Must_Not_Freeze); if not With_Freezing then + Set_Must_Not_Freeze (N, Save_Must_Not_Freeze); Inside_Preanalysis_Without_Freezing := Inside_Preanalysis_Without_Freezing - 1; end if; -- cgit v1.1 From 48096ca4ac832a7b596b89ed6750a2777f47afa6 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 28 May 2021 12:53:05 +0200 Subject: [Ada] Remove an unnecessary local constant gcc/ada/ * sem_ch6.adb (Analyze_Expression_Function): A local Expr constant was shadowing a global constant with the same name and the same value. --- gcc/ada/sem_ch6.adb | 1 - 1 file changed, 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index fbb2b55..aeb1cad 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -532,7 +532,6 @@ package body Sem_Ch6 is declare Decls : List_Id := List_Containing (N); - Expr : constant Node_Id := Expression (Ret); Par : constant Node_Id := Parent (Decls); Typ : constant Entity_Id := Etype (Def_Id); -- cgit v1.1 From 8bab88ba7bec025ef9db7ed5cb8d525fceab8636 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 28 May 2021 14:51:43 +0200 Subject: [Ada] Refine types of local variables in analysis of expression functions gcc/ada/ * sem_ch6.adb (Analyze_Expression_Function): Change types local variables from Entity_Id to Node_Id. --- gcc/ada/sem_ch6.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index aeb1cad..6bc72d6 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -640,9 +640,9 @@ package body Sem_Ch6 is if Present (Parameter_Specifications (New_Spec)) then declare Form_New_Def : Entity_Id; - Form_New_Spec : Entity_Id; + Form_New_Spec : Node_Id; Form_Old_Def : Entity_Id; - Form_Old_Spec : Entity_Id; + Form_Old_Spec : Node_Id; begin Form_New_Spec := First (Parameter_Specifications (New_Spec)); -- cgit v1.1 From 8a13a0017e52979c4b55f4c6294f4794882a9ce7 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 28 May 2021 14:53:21 +0200 Subject: [Ada] Avoid repeated calls in analysis of expression functions gcc/ada/ * sem_ch6.adb (Analyze_Expression_Function): Use Orig_N variable instead of repeated calls to Original_Node. --- gcc/ada/sem_ch6.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 6bc72d6..ed76808 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -561,7 +561,7 @@ package body Sem_Ch6 is Push_Scope (Def_Id); Install_Formals (Def_Id); Preanalyze_Formal_Expression (Expr, Typ); - Check_Limited_Return (Original_Node (N), Expr, Typ); + Check_Limited_Return (Orig_N, Expr, Typ); End_Scope; end if; @@ -630,7 +630,7 @@ package body Sem_Ch6 is Check_Dynamically_Tagged_Expression (Expr => Expr, Typ => Etype (Def_Id), - Related_Nod => Original_Node (N)); + Related_Nod => Orig_N); end if; -- We must enforce checks for unreferenced formals in our newly -- cgit v1.1 From e437dd45e78c810b4ebf6bab1e5f3751a59338e3 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 28 May 2021 14:56:32 +0200 Subject: [Ada] Fix comment related to analysis of expression functions gcc/ada/ * sem_ch6.adb (Analyze_Expression_Function): Fix comment. --- gcc/ada/sem_ch6.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index ed76808..a0680b7 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -536,7 +536,7 @@ package body Sem_Ch6 is Typ : constant Entity_Id := Etype (Def_Id); begin - -- If this is a wrapper created for in an instance for a formal + -- If this is a wrapper created in an instance for a formal -- subprogram, insert body after declaration, to be analyzed when -- the enclosing instance is analyzed. -- cgit v1.1 From 640ba4c1a33cb7e4ad854985f7d95882f8ed2260 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 28 May 2021 15:01:18 +0200 Subject: [Ada] Avoid repeated computing of type of expression functions gcc/ada/ * sem_ch6.adb (Analyze_Expression_Function): Add variable to avoid repeated calls to Etype. --- gcc/ada/sem_ch6.adb | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index a0680b7..a324014 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -300,6 +300,7 @@ package body Sem_Ch6 is New_Spec : Node_Id; Orig_N : Node_Id; Ret : Node_Id; + Typ : Entity_Id; Def_Id : Entity_Id := Empty; Prev : Entity_Id; @@ -333,6 +334,8 @@ package body Sem_Ch6 is Def_Id := Analyze_Subprogram_Specification (Spec); Prev := Find_Corresponding_Spec (N); + Typ := Etype (Def_Id); + -- The previous entity may be an expression function as well, in -- which case the redeclaration is illegal. @@ -406,7 +409,7 @@ package body Sem_Ch6 is if not Inside_A_Generic then Freeze_Expr_Types (Def_Id => Def_Id, - Typ => Etype (Def_Id), + Typ => Typ, Expr => Expr, N => N); end if; @@ -496,6 +499,8 @@ package body Sem_Ch6 is Def_Id := Defining_Entity (N); Set_Is_Inlined (Def_Id); + Typ := Etype (Def_Id); + -- Establish the linkages between the spec and the body. These are -- used when the expression function acts as the prefix of attribute -- 'Access in order to freeze the original expression which has been @@ -517,7 +522,7 @@ package body Sem_Ch6 is Set_Has_Completion (Def_Id, not Is_Ignored_Ghost_Entity (Def_Id)); Push_Scope (Def_Id); Install_Formals (Def_Id); - Preanalyze_Spec_Expression (Expr, Etype (Def_Id)); + Preanalyze_Spec_Expression (Expr, Typ); End_Scope; end if; @@ -531,9 +536,8 @@ package body Sem_Ch6 is -- place at the point of declaration. declare - Decls : List_Id := List_Containing (N); - Par : constant Node_Id := Parent (Decls); - Typ : constant Entity_Id := Etype (Def_Id); + Decls : List_Id := List_Containing (N); + Par : constant Node_Id := Parent (Decls); begin -- If this is a wrapper created in an instance for a formal @@ -624,12 +628,11 @@ package body Sem_Ch6 is -- nodes that don't come from source. if Present (Def_Id) - and then Nkind (Def_Id) in N_Has_Etype - and then Is_Tagged_Type (Etype (Def_Id)) + and then Is_Tagged_Type (Typ) then Check_Dynamically_Tagged_Expression (Expr => Expr, - Typ => Etype (Def_Id), + Typ => Typ, Related_Nod => Orig_N); end if; -- cgit v1.1 From e40f4ab46364c3e16c35c4d96c89187e8cae5a65 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 28 May 2021 15:11:03 +0200 Subject: [Ada] Decouple analysis of static expression functions from GNATprove gcc/ada/ * sem_ch6.adb (Analyze_Expression_Function): Reorder code. --- gcc/ada/sem_ch6.adb | 137 ++++++++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 69 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index a324014..0ecac3f 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -526,30 +526,30 @@ package body Sem_Ch6 is End_Scope; end if; + -- If this is a wrapper created in an instance for a formal + -- subprogram, insert body after declaration, to be analyzed when the + -- enclosing instance is analyzed. + + if GNATprove_Mode + and then Is_Generic_Actual_Subprogram (Def_Id) + then + Insert_After (N, New_Body); + -- To prevent premature freeze action, insert the new body at the end -- of the current declarations, or at the end of the package spec. -- However, resolve usage names now, to prevent spurious visibility -- on later entities. Note that the function can now be called in - -- the current declarative part, which will appear to be prior to - -- the presence of the body in the code. There are nevertheless no - -- order of elaboration issues because all name resolution has taken - -- place at the point of declaration. - - declare - Decls : List_Id := List_Containing (N); - Par : constant Node_Id := Parent (Decls); + -- the current declarative part, which will appear to be prior to the + -- presence of the body in the code. There are nevertheless no order + -- of elaboration issues because all name resolution has taken place + -- at the point of declaration. - begin - -- If this is a wrapper created in an instance for a formal - -- subprogram, insert body after declaration, to be analyzed when - -- the enclosing instance is analyzed. - - if GNATprove_Mode - and then Is_Generic_Actual_Subprogram (Def_Id) - then - Insert_After (N, New_Body); + else + declare + Decls : List_Id := List_Containing (N); + Par : constant Node_Id := Parent (Decls); - else + begin if Nkind (Par) = N_Package_Specification and then Decls = Visible_Declarations (Par) and then not Is_Empty_List (Private_Declarations (Par)) @@ -558,68 +558,67 @@ package body Sem_Ch6 is end if; Insert_After (Last (Decls), New_Body); + end; + end if; - -- Preanalyze the expression if not already done above + -- Preanalyze the expression if not already done above - if not Inside_A_Generic then - Push_Scope (Def_Id); - Install_Formals (Def_Id); - Preanalyze_Formal_Expression (Expr, Typ); - Check_Limited_Return (Orig_N, Expr, Typ); - End_Scope; - end if; + if not Inside_A_Generic then + Push_Scope (Def_Id); + Install_Formals (Def_Id); + Preanalyze_Formal_Expression (Expr, Typ); + Check_Limited_Return (Orig_N, Expr, Typ); + End_Scope; + end if; - -- In the case of an expression function marked with the - -- aspect Static, we need to check the requirement that the - -- function's expression is a potentially static expression. - -- This is done by making a full copy of the expression tree - -- and performing a special preanalysis on that tree with - -- the global flag Checking_Potentially_Static_Expression - -- enabled. If the resulting expression is static, then it's - -- OK, but if not, that means the expression violates the - -- requirements of the Ada 2022 RM in 4.9(3.2/5-3.4/5) and - -- we flag an error. - - if Is_Static_Function (Def_Id) then - if not Is_Static_Expression (Expr) then - declare - Exp_Copy : constant Node_Id := New_Copy_Tree (Expr); - begin - Set_Checking_Potentially_Static_Expression (True); + -- In the case of an expression function marked with the aspect + -- Static, we need to check the requirement that the function's + -- expression is a potentially static expression. This is done + -- by making a full copy of the expression tree and performing + -- a special preanalysis on that tree with the global flag + -- Checking_Potentially_Static_Expression enabled. If the + -- resulting expression is static, then it's OK, but if not, that + -- means the expression violates the requirements of the Ada 2022 + -- RM in 4.9(3.2/5-3.4/5) and we flag an error. - Preanalyze_Formal_Expression (Exp_Copy, Typ); + if Is_Static_Function (Def_Id) then + if not Is_Static_Expression (Expr) then + declare + Exp_Copy : constant Node_Id := New_Copy_Tree (Expr); + begin + Set_Checking_Potentially_Static_Expression (True); - if not Is_Static_Expression (Exp_Copy) then - Error_Msg_N - ("static expression function requires " - & "potentially static expression", Expr); - end if; + Preanalyze_Formal_Expression (Exp_Copy, Typ); - Set_Checking_Potentially_Static_Expression (False); - end; + if not Is_Static_Expression (Exp_Copy) then + Error_Msg_N + ("static expression function requires " + & "potentially static expression", Expr); end if; - -- We also make an additional copy of the expression and - -- replace the expression of the expression function with - -- this copy, because the currently present expression is - -- now associated with the body created for the static - -- expression function, which will later be analyzed and - -- possibly rewritten, and we need to have the separate - -- unanalyzed copy available for use with later static - -- calls. + Set_Checking_Potentially_Static_Expression (False); + end; + end if; - Set_Expression - (Original_Node (Subprogram_Spec (Def_Id)), - New_Copy_Tree (Expr)); + -- We also make an additional copy of the expression and + -- replace the expression of the expression function with + -- this copy, because the currently present expression is + -- now associated with the body created for the static + -- expression function, which will later be analyzed and + -- possibly rewritten, and we need to have the separate + -- unanalyzed copy available for use with later static + -- calls. - -- Mark static expression functions as inlined, to ensure - -- that even calls with nonstatic actuals will be inlined. + Set_Expression + (Original_Node (Subprogram_Spec (Def_Id)), + New_Copy_Tree (Expr)); - Set_Has_Pragma_Inline (Def_Id); - Set_Is_Inlined (Def_Id); - end if; - end if; - end; + -- Mark static expression functions as inlined, to ensure + -- that even calls with nonstatic actuals will be inlined. + + Set_Has_Pragma_Inline (Def_Id); + Set_Is_Inlined (Def_Id); + end if; end if; -- Check incorrect use of dynamically tagged expression. This doesn't -- cgit v1.1 From 81956c08f74be83aa61cba6c112b92cdc0198a66 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 28 May 2021 15:32:16 +0200 Subject: [Ada] Reorder preanalysis of static expression functions gcc/ada/ * sem_ch6.adb (Analyze_Expression_Function): Reorder code. --- gcc/ada/sem_ch6.adb | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 0ecac3f..d543253 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -524,6 +524,12 @@ package body Sem_Ch6 is Install_Formals (Def_Id); Preanalyze_Spec_Expression (Expr, Typ); End_Scope; + else + Push_Scope (Def_Id); + Install_Formals (Def_Id); + Preanalyze_Formal_Expression (Expr, Typ); + Check_Limited_Return (Orig_N, Expr, Typ); + End_Scope; end if; -- If this is a wrapper created in an instance for a formal @@ -561,16 +567,6 @@ package body Sem_Ch6 is end; end if; - -- Preanalyze the expression if not already done above - - if not Inside_A_Generic then - Push_Scope (Def_Id); - Install_Formals (Def_Id); - Preanalyze_Formal_Expression (Expr, Typ); - Check_Limited_Return (Orig_N, Expr, Typ); - End_Scope; - end if; - -- In the case of an expression function marked with the aspect -- Static, we need to check the requirement that the function's -- expression is a potentially static expression. This is done -- cgit v1.1 From d80c73318785edec642b04dfe00db2e61503bf20 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 8 Jun 2021 13:24:46 +0200 Subject: [Ada] Update internal documentation of debugging information gcc/ada/ * exp_dbug.ads: Update documentation of various items. --- gcc/ada/exp_dbug.ads | 409 ++++++++++++++++++++++++--------------------------- 1 file changed, 191 insertions(+), 218 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_dbug.ads b/gcc/ada/exp_dbug.ads index 5e1bc91..09921f0 100644 --- a/gcc/ada/exp_dbug.ads +++ b/gcc/ada/exp_dbug.ads @@ -23,9 +23,11 @@ -- -- ------------------------------------------------------------------------------ --- Expand routines for generation of special declarations used by the --- debugger. In accordance with the Dwarf 2.2 specification, certain --- type names are encoded to provide information to the debugger. +-- Expand routines for the generation of special declarations used by the +-- debugger. In accordance with the DWARF specification, certain type names +-- may also be encoded to provide additional information to the debugger, but +-- this practice is being deprecated and some encodings described below are no +-- longer generated by default (they are marked OBSOLETE). with Namet; use Namet; with Types; use Types; @@ -496,53 +498,104 @@ package Exp_Dbug is -- corresponding positive value followed by a lower case m for minus to -- indicate that the value is negative (e.g. 2m for -2). - ------------------------- - -- Type Name Encodings -- - ------------------------- + ------------------------ + -- Encapsulated Types -- + ------------------------ + + -- In some cases, the compiler may encapsulate a type by wrapping it in a + -- record. For example, this is used when a size or alignment specification + -- requires a larger type. Consider: + + -- type x is mod 2 ** 64; + -- for x'size use 256; + + -- In this case, the compiler generates a record type x___PAD, which has + -- a single field whose name is F. This single field is 64-bit long and + -- contains the actual value. This kind of padding is used when the logical + -- value to be stored is shorter than the object in which it is allocated. + + -- A similar encapsulation is done for some packed array types, in which + -- case the record type is x___JM and the field name is OBJECT. This is + -- used in the case of a packed array stored using modular representation + -- (see the section on representation of packed array objects). In this + -- case the wrapping is used to achieve correct positioning of the packed + -- array value (left/right justified in its field depending on endianness). + + -- When the debugger sees an object of a type whose name has a suffix of + -- ___PAD or ___JM, the type will be a record containing a single field, + -- and the name of that field will be all upper case. In this case, it + -- should look inside to get the value of the inner field, and neither + -- the outer structure name, nor the field name should appear when the + -- value is printed. + + -- Similarly, when the debugger sees a record named REP being the type of + -- a field inside another record type, it should treat the fields inside + -- REP as being part of the outer record (this REP field is only present + -- for code generation purposes). The REP record should not appear in the + -- values printed by the debugger. + + -------------------- + -- Implicit Types -- + -------------------- + + -- The compiler creates implicit type names in many situations where a + -- type is present semantically, but no specific name is present. For + -- example: + + -- S : Integer range M .. N; + + -- Here the subtype of S is not integer, but rather an anonymous subtype + -- of Integer. Where possible, the compiler generates names for such + -- anonymous types that are related to the type from which the subtype + -- is obtained as follows: + + -- T name suffix + + -- where name is the name from which the subtype is obtained, using + -- lower case letters and underscores, and suffix starts with an upper + -- case letter. For example the name for the above declaration might be: + + -- TintegerS4b + + -- If the debugger is asked to give the type of an entity and the type + -- has the form T name suffix, it is probably appropriate to just use + -- "name" in the response since this is what is meaningful to the + -- programmer. + + ------------------- + -- Modular Types -- + ------------------- + + -- A type declared + + -- type x is mod N; + + -- is encoded as a subrange of an unsigned base type with lower bound zero + -- and upper bound N - 1. Thus we give these types a somewhat nonstandard + -- interpretation: the standard interpretation would not, in general, imply + -- that arithmetic operations on type x are performed modulo N (especially + -- not when N is not a power of 2). + + -------------------------------------- + -- Tagged Types and Type Extensions -- + -------------------------------------- + + -- A type D derived from a tagged type P has a field named "_parent" of + -- type P that contains its inherited fields. The type of this field is + -- usually P, but may be a more distant ancestor, if P is a null extension + -- of that type. + + -- The type tag of a tagged type is a field named "_tag" of a pointer type. + -- If the type is derived from another tagged type, its _tag field is found + -- in its _parent field. + + ------------------------------------ + -- Type Name Encodings (OBSOLETE) -- + ------------------------------------ -- In the following typ is the name of the type as normally encoded by the -- debugger rules, i.e. a non-qualified name, all in lower case, with - -- standard encoding of upper half and wide characters - - ------------------------ - -- Encapsulated Types -- - ------------------------ - - -- In some cases, the compiler encapsulates a type by wrapping it in a - -- structure. For example, this is used when a size or alignment - -- specification requires a larger type. Consider: - - -- type y is mod 2 ** 64; - -- for y'size use 256; - - -- In this case the compile generates a structure type y___PAD, which - -- has a single field whose name is F. This single field is 64 bits - -- long and contains the actual value. This kind of padding is used - -- when the logical value to be stored is shorter than the object in - -- which it is allocated. For example if a size clause is used to set - -- a size of 256 for a signed integer value, then a typical choice is - -- to wrap a 64-bit integer in a 256 bit PAD structure. - - -- A similar encapsulation is done for some packed array types, in which - -- case the structure type is y___JM and the field name is OBJECT. - -- This is used in the case of a packed array stored using modular - -- representation (see section on representation of packed array - -- objects). In this case the JM wrapping is used to achieve correct - -- positioning of the packed array value (left or right justified in its - -- field depending on endianness. - - -- When the debugger sees an object of a type whose name has a suffix of - -- ___PAD or ___JM, the type will be a record containing a single field, - -- and the name of that field will be all upper case. In this case, it - -- should look inside to get the value of the inner field, and neither - -- the outer structure name, nor the field name should appear when the - -- value is printed. - - -- When the debugger sees a record named REP being a field inside - -- another record, it should treat the fields inside REP as being part - -- of the outer record (this REP field is only present for code - -- generation purposes). The REP record should not appear in the values - -- printed by the debugger. + -- standard encoding of upper half and wide characters. ----------------------- -- Fixed-Point Types -- @@ -613,22 +666,6 @@ package Exp_Dbug is -- or compile time known values, with the encoding first for the lower -- bound, then for the upper bound, as previously described. - ------------------- - -- Modular Types -- - ------------------- - - -- A type declared - - -- type x is mod N; - - -- Is encoded as a subrange of an unsigned base type with lower bound - -- zero and upper bound N. That is, there is no name encoding. We use - -- the standard encodings provided by the debugging format. Thus we - -- give these types a non-standard interpretation: the standard - -- interpretation of our encoding would not, in general, imply that - -- arithmetic on type x was to be performed modulo N (especially not - -- when N is not a power of 2). - ------------------ -- Biased Types -- ------------------ @@ -887,34 +924,6 @@ package Exp_Dbug is -- redundantly, particularly in the fixed-point case, but this -- information can in any case be ignored by the debugger. - ---------------------------- - -- Note on Implicit Types -- - ---------------------------- - - -- The compiler creates implicit type names in many situations where a - -- type is present semantically, but no specific name is present. For - -- example: - - -- S : Integer range M .. N; - - -- Here the subtype of S is not integer, but rather an anonymous subtype - -- of Integer. Where possible, the compiler generates names for such - -- anonymous types that are related to the type from which the subtype - -- is obtained as follows: - - -- T name suffix - - -- where name is the name from which the subtype is obtained, using - -- lower case letters and underscores, and suffix starts with an upper - -- case letter. For example the name for the above declaration might be: - - -- TintegerS4b - - -- If the debugger is asked to give the type of an entity and the type - -- has the form T name suffix, it is probably appropriate to just use - -- "name" in the response since this is what is meaningful to the - -- programmer. - ------------------------------------------------- -- Subprograms for Handling Encoded Type Names -- ------------------------------------------------- @@ -1062,51 +1071,6 @@ package Exp_Dbug is -- debug declaration, then Empty is returned. This function also takes care -- of setting Materialize_Entity on the renamed entity where required. - --------------------------- - -- Packed Array Encoding -- - --------------------------- - - -- For every constrained packed array, two types are created, and both - -- appear in the debugging output: - - -- The original declared array type is a perfectly normal array type, and - -- its index bounds indicate the original bounds of the array. - - -- The corresponding packed array type, which may be a modular type, or - -- may be an array of bytes type (see Exp_Pakd for full details). This is - -- the type that is actually used in the generated code and for debugging - -- information for all objects of the packed type. - - -- The name of the corresponding packed array type is: - - -- ttt___XPnnn - - -- where - - -- ttt is the name of the original declared array - -- nnn is the component size in bits (1-31) - - -- Note that if the packed array is not bit-packed, the name will simply - -- be tttP. - - -- When the debugger sees that an object is of a type that is encoded in - -- this manner, it can use the original type to determine the bounds and - -- the component type, and the component size to determine the packing - -- details. - - -- For an unconstrained packed array, the corresponding packed array type - -- is neither used in the generated code nor for debugging information, - -- only the original type is used. In order to convey the packing in the - -- debugging information, the compiler generates the associated fat- and - -- thin-pointer types (see the Pointers to Unconstrained Array section - -- below) using the name of the corresponding packed array type as the - -- base name, i.e. ttt___XPnnn___XUP and ttt___XPnnn___XUT respectively. - - -- When the debugger sees that an object is of a type that is encoded in - -- this manner, it can use the type of the fields to determine the bounds - -- and the component type, and the component size to determine the packing - -- details. - ------------------------------------------- -- Packed Array Representation in Memory -- ------------------------------------------- @@ -1204,6 +1168,51 @@ package Exp_Dbug is -- would mean that an assignment such as a := above would require shifts -- when one value is in a register and the other value is in memory. + ------------------------------------------- + -- Packed Array Name Encoding (OBSOLETE) -- + ------------------------------------------- + + -- For every constrained packed array, two types are created, and both + -- appear in the debugging output: + + -- The original declared array type is a perfectly normal array type, and + -- its index bounds indicate the original bounds of the array. + + -- The corresponding packed array type, which may be a modular type, or + -- may be an array of bytes type (see Exp_Pakd for full details). This is + -- the type that is actually used in the generated code and for debugging + -- information for all objects of the packed type. + + -- The name of the corresponding packed array type is: + + -- ttt___XPnnn + + -- where + + -- ttt is the name of the original declared array + -- nnn is the component size in bits (1-31) + + -- Note that if the packed array is not bit-packed, the name will simply + -- be tttP. + + -- When the debugger sees that an object is of a type that is encoded in + -- this manner, it can use the original type to determine the bounds and + -- the component type, and the component size to determine the packing + -- details. + + -- For an unconstrained packed array, the corresponding packed array type + -- is neither used in the generated code nor for debugging information, + -- only the original type is used. In order to convey the packing in the + -- debugging information, the compiler generates the associated fat- and + -- thin-pointer types (see the Pointers to Unconstrained Array section + -- below) using the name of the corresponding packed array type as the + -- base name, i.e. ttt___XPnnn___XUP and ttt___XPnnn___XUT respectively. + + -- When the debugger sees that an object is of a type that is encoded in + -- this manner, it can use the type of the fields to determine the bounds + -- and the component type, and the component size to determine the packing + -- details. + ------------------------------------------------------ -- Subprograms for Handling Packed Array Type Names -- ------------------------------------------------------ @@ -1219,58 +1228,67 @@ package Exp_Dbug is -- Pointers to Unconstrained Arrays -- -------------------------------------- - -- There are two kinds of pointers to arrays. The debugger can tell which - -- format is in use by the form of the type of the pointer. + -- There are two kinds of pointer to unconstrained arrays. The debugger can + -- tell which format is in use by the form of the type of the pointer. -- Fat Pointers - -- Fat pointers are represented as a struct with two fields. This - -- struct has two distinguished field names: + -- Fat pointers are represented as a structure with two fields. This + -- structure has two distinguished field names: -- P_ARRAY is a pointer to the array type. The name of this type is - -- the unconstrained type followed by "___XUA". This array will have - -- bounds which are the discriminants, and hence are unparsable, but - -- will give the number of subscripts and the component type. + -- the unconstrained type followed by "___XUA". The bounds of this + -- array will be obtained through dereferences of P_BOUNDS below. - -- P_BOUNDS is a pointer to a struct, the name of whose type is the - -- unconstrained array name followed by "___XUB" and which has - -- fields of the form + -- P_BOUNDS is a pointer to a structure. The name of this type is + -- the unconstrained array name followed by "___XUB" and it has + -- fields of the form: -- LBn (n a decimal integer) lower bound of n'th dimension -- UBn (n a decimal integer) upper bound of n'th dimension - -- The bounds may be any integral type. In the case of an enumeration - -- type, Enum_Rep values are used. + -- The bounds may be of any integral type. In the case of enumeration + -- types, Enum_Rep values are used. + + -- For a given unconstrained array type, the compiler will generate a + -- fat pointer type whose name is the name of the array type, and use + -- it to represent the array type itself in the debugging information. - -- For a given unconstrained array type, the compiler will generate one - -- fat-pointer type whose name is "arr___XUP", where "arr" is the name - -- of the array type, and use it to represent the array type itself in - -- the debugging information. + -- This name was historically followed by "___XUP" (OBSOLETE). -- For each pointer to this unconstrained array type, the compiler will - -- generate a typedef that points to the above "arr___XUP" fat-pointer - -- type. As a consequence, when it comes to fat-pointer types: + -- generate a typedef that points to the above fat pointer type. As a + -- consequence, when it comes to fat pointer types: - -- 1. The type name is given by the typedef + -- 1. The type name is given by the typedef, if any -- 2. If the debugger is asked to output the type, the appropriate - -- form is "access arr", except if the type name is "arr___XUP" - -- for which it is the array definition. + -- form is "access arr" if there is the typedef, otherwise it is + -- the array definition. -- Thin Pointers -- The value of a thin pointer is a pointer to the second field of a + -- structure with two fields. The first field of the structure is of + -- the type ___XUB described for fat pointer types above. The second + -- field of the structure contains the actual array. + + -- Thin pointers are represented as a regular pointer to array in the + -- debugging information. The bounds of this array will be the contents + -- of the first field above obtained through (shifted) dereferences. + + -- Thin Pointers (OBSOLETE) + + -- The value of a thin pointer is a pointer to the second field of a -- structure with two fields. The name of this structure's type is -- "arr___XUT", where "arr" is the name of the unconstrained array - -- type. Even though it actually points into middle of this structure, - -- the thin pointer's type in debugging information is - -- pointer-to-arr___XUT. + -- type. Even though it points into the middle of this structure, + -- the type in the debugging information is pointer to structure. - -- The first field of arr___XUT is named BOUNDS, and has a type named - -- arr___XUB, with the structure described for such types in fat - -- pointers, as described above. + -- The first field of the structure is named BOUNDS and is of the type + -- ___XUB described for fat pointer types above. - -- The second field of arr___XUT is named ARRAY, and contains the + -- The second field of the structure is named ARRAY, and contains the -- actual array. Because this array has a dynamic size, determined by -- the BOUNDS field that precedes it, all of the information about -- arr___XUT is encoded in a parallel type named arr___XUT___XVE, with @@ -1279,19 +1297,6 @@ package Exp_Dbug is -- type in this case is named arr___XUA and only its element type is -- meaningful, just as described for fat pointers. - -------------------------------------- - -- Tagged Types and Type Extensions -- - -------------------------------------- - - -- A type C derived from a tagged type P has a field named "_parent" of - -- type P that contains its inherited fields. The type of this field is - -- usually P (encoded as usual if it has a dynamic size), but may be a more - -- distant ancestor, if P is a null extension of that type. - - -- The type tag of a tagged type is a field named _tag, of type void*. If - -- the type is derived from another tagged type, its _tag field is found in - -- its _parent field. - ----------------------------- -- Variant Record Encoding -- ----------------------------- @@ -1311,8 +1316,7 @@ package Exp_Dbug is -- union, in which each member of the union corresponds to one variant. -- However, unlike a C union, the size of the type may be variable even if -- each of the components are fixed size, since it includes a computation - -- of which variant is present. In that case, it will be encoded as above - -- and a type with the suffix "___XVN___XVU" will be present. + -- of which variant is present. -- The name of the union member is encoded to indicate the choices, and -- is a string given by the following grammar: @@ -1335,9 +1339,7 @@ package Exp_Dbug is -- to the use of the Enum_Rep attribute). -- The type of the inner record is given by the name of the union type (as - -- above) concatenated with the above string. Since that type may itself be - -- variable-sized, it may also be encoded as above with a new type with a - -- further suffix of "___XVU". + -- above) concatenated with the above string. -- As an example, consider: @@ -1375,9 +1377,7 @@ package Exp_Dbug is -- be encoded, as in ordinary C unions, as a single field of the -- enclosing union type named "x" of type "T", dispensing with the -- enclosing struct. In this case, of course, the discriminant values - -- corresponding to the variant are unavailable. As for normal - -- variants, the field name "x" may be suffixed with ___XVL if it - -- has dynamic size. + -- corresponding to the variant are unavailable. -- For example, the type Var in the preceding section, if followed by -- "pragma Unchecked_Union (Var);" may be encoded as a struct with two @@ -1549,46 +1549,19 @@ package Exp_Dbug is -- are missing and deal as best as it can with the limited information -- available. - --------------------------------- - -- GNAT Extensions to DWARF2/3 -- - --------------------------------- - - -- If the compiler switch "-gdwarf+" is specified, GNAT Vendor extensions - -- to DWARF2/3 are generated, with the following variations from the above - -- specification. - - -- Change in the contents of the DW_AT_name attribute - - -- The operators are represented in their natural form. (for example, - -- the addition operator is written as "+" instead of "Oadd"). The - -- component separator is "." instead of "__" + ----------------------------------------- + -- GNAT Extensions to DWARF (OBSOLETE) -- + ----------------------------------------- - -- Introduction of DW_AT_GNAT_encoding, encoded with value 0x2301 + -- DW_AT_use_GNAT_descriptive_type, encoded with value 0x2301 - -- Any debugging information entry representing a program entity, named - -- or implicit, may have a DW_AT_GNAT_encoding attribute. The value of - -- this attribute is a string representing the suffix internally added - -- by GNAT for various purposes, mainly for representing debug - -- information compatible with other formats. In particular this is - -- useful for IDEs which need to filter out information internal to - -- GNAT from their graphical interfaces. + -- This extension has never been implemented in the compiler. - -- If a debugging information entry has multiple encodings, all of them - -- will be listed in DW_AT_GNAT_encoding using the list separator ':'. - - -- Introduction of DW_AT_GNAT_descriptive_type, encoded with value 0x2302 + -- DW_AT_GNAT_descriptive_type, encoded with value 0x2302 -- Any debugging information entry representing a type may have a -- DW_AT_GNAT_descriptive_type attribute whose value is a reference, -- pointing to a debugging information entry representing another type -- associated to the type. - -- Modification of the contents of the DW_AT_producer string - - -- When emitting full GNAT Vendor extensions to DWARF2/3, "-gdwarf+" - -- is appended to the DW_AT_producer string. - -- - -- When emitting only DW_AT_GNAT_descriptive_type, "-gdwarf+-" is - -- appended to the DW_AT_producer string. - end Exp_Dbug; -- cgit v1.1 From 9b1647a50dda833a0640e66bb0bedb6c477b7561 Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Thu, 3 Jun 2021 17:15:51 -0400 Subject: [Ada] Incremental patch for restriction No_Dynamic_Accessibility_Checks gcc/ada/ * sem_util.ads (Type_Access_Level): Add new optional parameter Assoc_Ent. * sem_util.adb (Accessibility_Level): Treat access discriminants the same as components when the restriction No_Dynamic_Accessibility_Checks is enabled. (Deepest_Type_Access_Level): Remove exception for Debug_Flag_Underscore_B when returning the result of Type_Access_Level in the case where No_Dynamic_Accessibility_Checks is active. (Function_Call_Or_Allocator_Level): Correctly calculate the level of Expr based on its containing subprogram instead of using Current_Subprogram. * sem_res.adb (Valid_Conversion): Add actual for new parameter Assoc_Ent in call to Type_Access_Level, and add test of No_Dynamic_Accessibility_Checks_Enabled to ensure that static accessibility checks are performed for all anonymous access type conversions. --- gcc/ada/sem_res.adb | 15 ++++++++++----- gcc/ada/sem_util.adb | 34 ++++++++++++++++++++++++++++------ gcc/ada/sem_util.ads | 7 ++++++- 3 files changed, 44 insertions(+), 12 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index e2c069c..03d747e 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -13734,11 +13734,16 @@ package body Sem_Res is -- the target type is anonymous access as well - see RM 3.10.2 -- (10.3/3). - elsif Type_Access_Level (Opnd_Type) > - Deepest_Type_Access_Level (Target_Type) - and then (Nkind (Associated_Node_For_Itype (Opnd_Type)) /= - N_Function_Specification - or else Ekind (Target_Type) in Anonymous_Access_Kind) + -- Note that when the restriction No_Dynamic_Accessibility_Checks + -- is in effect wei also want to proceed with the conversion check + -- described above. + + elsif Type_Access_Level (Opnd_Type, Assoc_Ent => Operand) + > Deepest_Type_Access_Level (Target_Type) + and then (Nkind (Associated_Node_For_Itype (Opnd_Type)) + /= N_Function_Specification + or else Ekind (Target_Type) in Anonymous_Access_Kind + or else No_Dynamic_Accessibility_Checks_Enabled (N)) -- Check we are not in a return value ??? diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 9cd5d14..5d0aa49 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -420,7 +420,7 @@ package body Sem_Util is else return Make_Level_Literal - (Subprogram_Access_Level (Current_Subprogram)); + (Subprogram_Access_Level (Entity (Name (N)))); end if; end if; @@ -791,12 +791,22 @@ package body Sem_Util is -- is an anonymous access type means that its associated -- level is that of the containing type - see RM 3.10.2 (16). + -- Note that when restriction No_Dynamic_Accessibility_Checks is + -- in effect we treat discriminant components as regular + -- components. + elsif Nkind (E) = N_Selected_Component and then Ekind (Etype (E)) = E_Anonymous_Access_Type and then Ekind (Etype (Pre)) /= E_Anonymous_Access_Type - and then not (Nkind (Selector_Name (E)) in N_Has_Entity - and then Ekind (Entity (Selector_Name (E))) - = E_Discriminant) + and then (not (Nkind (Selector_Name (E)) in N_Has_Entity + and then Ekind (Entity (Selector_Name (E))) + = E_Discriminant) + + -- The alternative accessibility models both treat + -- discriminants as regular components. + + or else (No_Dynamic_Accessibility_Checks_Enabled (E) + and then Allow_Alt_Model)) then -- When restriction No_Dynamic_Accessibility_Checks is active -- and -gnatd_b set, the level is that of the designated type. @@ -7215,7 +7225,6 @@ package body Sem_Util is if Allow_Alt_Model and then No_Dynamic_Accessibility_Checks_Enabled (Typ) - and then not Debug_Flag_Underscore_B then return Type_Access_Level (Typ, Allow_Alt_Model); end if; @@ -29157,7 +29166,8 @@ package body Sem_Util is function Type_Access_Level (Typ : Entity_Id; - Allow_Alt_Model : Boolean := True) return Uint + Allow_Alt_Model : Boolean := True; + Assoc_Ent : Entity_Id := Empty) return Uint is Btyp : Entity_Id := Base_Type (Typ); Def_Ent : Entity_Id; @@ -29187,6 +29197,18 @@ package body Sem_Util is (Designated_Type (Btyp), Allow_Alt_Model); end if; + -- When an anonymous access type's Assoc_Ent is specifiedi, + -- calculate the result based on the general accessibility + -- level routine. + + -- We would like to use Associated_Node_For_Itype here instead, + -- but in some cases it is not fine grained enough ??? + + if Present (Assoc_Ent) then + return Static_Accessibility_Level + (Assoc_Ent, Object_Decl_Level); + end if; + -- Otherwise take the context of the anonymous access type into -- account. diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index 440ac80..b0d6a2a 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -3267,12 +3267,17 @@ package Sem_Util is function Type_Access_Level (Typ : Entity_Id; - Allow_Alt_Model : Boolean := True) return Uint; + Allow_Alt_Model : Boolean := True; + Assoc_Ent : Entity_Id := Empty) return Uint; -- Return the accessibility level of Typ -- The Allow_Alt_Model parameter allows the alternative level calculation -- under the restriction No_Dynamic_Accessibility_Checks to be performed. + -- Assoc_Ent allows for the optional specification of the entity associated + -- with Typ. This gets utilized mostly for anonymous access type + -- processing, where context matters in interpreting Typ's level. + function Type_Without_Stream_Operation (T : Entity_Id; Op : TSS_Name_Type := TSS_Null) return Entity_Id; -- cgit v1.1 From e347e6c92769196408720a027618bc67450abe61 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Mon, 10 May 2021 11:29:08 -0400 Subject: [Ada] Inconsistency between declaration and body of predicate functions gcc/ada/ * sem_ch13.adb (Resolve_Aspect_Expressions): Use the same processing for Predicate, Static_Predicate and Dynamic_Predicate. Do not build the predicate function spec. Update comments. (Resolve_Name): Only reset Entity when necessary to avoid spurious visibility errors. (Check_Aspect_At_End_Of_Declarations): Handle consistently all Predicate aspects. * sem_ch3.adb (Analyze_Subtype_Declaration): Fix handling of private types with predicates. --- gcc/ada/sem_ch13.adb | 43 ++++++++++++++++++++++++++----------------- gcc/ada/sem_ch3.adb | 11 ++++++++++- 2 files changed, 36 insertions(+), 18 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 0359625..f0962ca0 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -10114,11 +10114,11 @@ package body Sem_Ch13 is then return; - -- Do not generate predicate bodies within a generic unit. The - -- expressions have been analyzed already, and the bodies play - -- no role if not within an executable unit. However, if a static - -- predicate is present it must be processed for legality checks - -- such as case coverage in an expression. + -- Do not generate predicate bodies within a generic unit. The + -- expressions have been analyzed already, and the bodies play no role + -- if not within an executable unit. However, if a static predicate is + -- present it must be processed for legality checks such as case + -- coverage in an expression. elsif Inside_A_Generic and then not Has_Static_Predicate_Aspect (Typ) @@ -10782,7 +10782,9 @@ package body Sem_Ch13 is -- also make its potential components accessible. if not Analyzed (Freeze_Expr) and then Inside_A_Generic then - if A_Id in Aspect_Dynamic_Predicate | Aspect_Predicate then + if A_Id in Aspect_Dynamic_Predicate | Aspect_Predicate | + Aspect_Static_Predicate + then Push_Type (Ent); Preanalyze_Spec_Expression (Freeze_Expr, Standard_Boolean); Pop_Type (Ent); @@ -10813,6 +10815,7 @@ package body Sem_Ch13 is if A_Id in Aspect_Dynamic_Predicate | Aspect_Predicate | Aspect_Priority + | Aspect_Static_Predicate then Push_Type (Ent); Check_Aspect_At_Freeze_Point (ASN); @@ -10840,6 +10843,7 @@ package body Sem_Ch13 is | Aspect_Dynamic_Predicate | Aspect_Predicate | Aspect_Priority + | Aspect_Static_Predicate then Push_Type (Ent); Preanalyze_Spec_Expression (End_Decl_Expr, T); @@ -15042,9 +15046,15 @@ package body Sem_Ch13 is or else N /= Selector_Name (Parent (N))) then Find_Direct_Name (N); - Set_Entity (N, Empty); - -- The name is component association needs no resolution + -- Reset the Entity if N is overloaded since the entity may not + -- be the correct one. + + if Is_Overloaded (N) then + Set_Entity (N, Empty); + end if; + + -- The name in a component association needs no resolution elsif Nkind (N) = N_Component_Association then Dummy := Resolve_Name (Expression (N)); @@ -15087,24 +15097,23 @@ package body Sem_Ch13 is -- types. These will require special handling???. when Aspect_Invariant - | Aspect_Predicate | Aspect_Predicate_Failure => null; when Aspect_Dynamic_Predicate | Aspect_Static_Predicate + | Aspect_Predicate => - -- Build predicate function specification and preanalyze - -- expression after type replacement. The function - -- declaration must be analyzed in the scope of the type, - -- but the expression can reference components and - -- discriminants of the type. + -- Preanalyze expression after type replacement to catch + -- name resolution errors if the predicate function has + -- not been built yet. + -- Note that we cannot use Preanalyze_Spec_Expression + -- because of the special handling required for + -- quantifiers, see comments on Resolve_Aspect_Expression + -- above. if No (Predicate_Function (E)) then - Discard_Node - (Build_Predicate_Function_Declaration (E)); - Push_Type (E); Resolve_Aspect_Expression (Expr); Pop_Type (E); diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 2966492..e9b4456 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -5779,7 +5779,16 @@ package body Sem_Ch3 is ((In_Instance and then not Comes_From_Source (N)) or else No (Aspect_Specifications (N))) then - Set_Subprograms_For_Type (Id, Subprograms_For_Type (T)); + -- Inherit Subprograms_For_Type from the full view, if present + + if Present (Full_View (T)) + and then Subprograms_For_Type (Full_View (T)) /= No_Elist + then + Set_Subprograms_For_Type + (Id, Subprograms_For_Type (Full_View (T))); + else + Set_Subprograms_For_Type (Id, Subprograms_For_Type (T)); + end if; -- If the current declaration created both a private and a full view, -- then propagate Predicate_Function to the latter as well. -- cgit v1.1 From 1f72ec808b2a6f95f969bc9a1a13af1f310e1678 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Wed, 9 Jun 2021 01:04:35 +0200 Subject: [Ada] Initialize local variables related to static expression functions gcc/ada/ * sem_ch6.adb (Analyze_Expression_Function): Initialize Orig_N and Typ variables. --- gcc/ada/sem_ch6.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index d543253..78a076c 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -298,9 +298,9 @@ package body Sem_Ch6 is Asp : Node_Id; New_Body : Node_Id; New_Spec : Node_Id; - Orig_N : Node_Id; + Orig_N : Node_Id := Empty; Ret : Node_Id; - Typ : Entity_Id; + Typ : Entity_Id := Empty; Def_Id : Entity_Id := Empty; Prev : Entity_Id; -- cgit v1.1 From f1b4b3d75cd4552211fb683d1e1e3dd1e9ef6267 Mon Sep 17 00:00:00 2001 From: Frederic Konrad Date: Tue, 13 Apr 2021 10:55:52 +0200 Subject: [Ada] aarch64-rtems6: use wraplf variant for a-nallfl gcc/ada/ * Makefile.rtl (LIBGNAT_TARGET_PAIRS) : Use the wraplf variant of Aux_Long_Long_Float. --- gcc/ada/Makefile.rtl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index fbd3993..5475d0d 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -2193,7 +2193,7 @@ ifeq ($(strip $(filter-out rtems%,$(target_os))),) EH_MECHANISM=-gcc endif - ifeq ($(strip $(filter-out riscv%,$(target_cpu))),) + ifeq ($(strip $(filter-out aarch64% riscv%,$(target_cpu))),) LIBGNAT_TARGET_PAIRS += a-nallfl.ads Date: Thu, 10 Jun 2021 10:21:46 +0200 Subject: [Ada] Add paragraph about representation changes and Scalar_Storage_Order gcc/ada/ * doc/gnat_rm/implementation_defined_attributes.rst (Scalar_Storage_Order): Add paragraph about representation changes. * gnat_rm.texi: Regenerate. --- .../gnat_rm/implementation_defined_attributes.rst | 40 ++++++++++++++++++++++ gcc/ada/gnat_rm.texi | 40 ++++++++++++++++++++++ 2 files changed, 80 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst index 0df103b..665170c 100644 --- a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst +++ b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst @@ -1057,6 +1057,46 @@ If a component of ``T`` is itself of a record or array type, the specfied attribute definition clause must be provided for the component type as well if desired. +Representation changes that explicitly or implicitly toggle the scalar storage +order are not supported and may result in erroneous execution of the program, +except when performed by means of an instance of ``Ada.Unchecked_Conversion``. + +In particular, overlays are not supported and a warning is given for them: + +.. code-block:: ada + + type Rec_LE is record + I : Integer; + end record; + + for Rec_LE use record + I at 0 range 0 .. 31; + end record; + + for Rec_LE'Bit_Order use System.Low_Order_First; + for Rec_LE'Scalar_Storage_Order use System.Low_Order_First; + + type Rec_BE is record + I : Integer; + end record; + + for Rec_BE use record + I at 0 range 0 .. 31; + end record; + + for Rec_BE'Bit_Order use System.High_Order_First; + for Rec_BE'Scalar_Storage_Order use System.High_Order_First; + + R_LE : Rec_LE; + + R_BE : Rec_BE; + for R_BE'Address use R_LE'Address; + +``warning: overlay changes scalar storage order [enabled by default]`` + +In most cases, such representation changes ought to be replaced by an +instantiation of a function or procedure provided by ``GNAT.Byte_Swapping``. + Note that the scalar storage order only affects the in-memory data representation. It has no effect on the representation used by stream attributes. diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 19d6f33..c0ccfe4 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -11442,6 +11442,46 @@ If a component of @code{T} is itself of a record or array type, the specfied attribute definition clause must be provided for the component type as well if desired. +Representation changes that explicitly or implicitly toggle the scalar storage +order are not supported and may result in erroneous execution of the program, +except when performed by means of an instance of @code{Ada.Unchecked_Conversion}. + +In particular, overlays are not supported and a warning is given for them: + +@example +type Rec_LE is record + I : Integer; +end record; + +for Rec_LE use record + I at 0 range 0 .. 31; +end record; + +for Rec_LE'Bit_Order use System.Low_Order_First; +for Rec_LE'Scalar_Storage_Order use System.Low_Order_First; + +type Rec_BE is record + I : Integer; +end record; + +for Rec_BE use record + I at 0 range 0 .. 31; +end record; + +for Rec_BE'Bit_Order use System.High_Order_First; +for Rec_BE'Scalar_Storage_Order use System.High_Order_First; + +R_LE : Rec_LE; + +R_BE : Rec_BE; +for R_BE'Address use R_LE'Address; +@end example + +@code{warning: overlay changes scalar storage order [enabled by default]} + +In most cases, such representation changes ought to be replaced by an +instantiation of a function or procedure provided by @code{GNAT.Byte_Swapping}. + Note that the scalar storage order only affects the in-memory data representation. It has no effect on the representation used by stream attributes. -- cgit v1.1 From e4a6acd67ef7ab110b7f575b22019554819af0cc Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Wed, 9 Jun 2021 11:58:47 -0400 Subject: [Ada] Code cleanups in a-strfix.adb gcc/ada/ * libgnat/a-strfix.adb: Take advantage of extended returns. --- gcc/ada/libgnat/a-strfix.adb | 138 +++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 84 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/a-strfix.adb b/gcc/ada/libgnat/a-strfix.adb index 8b7f043..ee72b6b 100644 --- a/gcc/ada/libgnat/a-strfix.adb +++ b/gcc/ada/libgnat/a-strfix.adb @@ -145,30 +145,26 @@ package body Ada.Strings.Fixed is (Left : Natural; Right : Character) return String is - Result : String (1 .. Left); - begin - for J in Result'Range loop - Result (J) := Right; - end loop; - - return Result; + return Result : String (1 .. Left) do + for J in Result'Range loop + Result (J) := Right; + end loop; + end return; end "*"; function "*" (Left : Natural; Right : String) return String is - Result : String (1 .. Left * Right'Length); Ptr : Integer := 1; - begin - for J in 1 .. Left loop - Result (Ptr .. Ptr + Right'Length - 1) := Right; - Ptr := Ptr + Right'Length; - end loop; - - return Result; + return Result : String (1 .. Left * Right'Length) do + for J in 1 .. Left loop + Result (Ptr .. Ptr + Right'Length - 1) := Right; + Ptr := Ptr + Right'Length; + end loop; + end return; end "*"; ------------ @@ -180,6 +176,7 @@ package body Ada.Strings.Fixed is From : Positive; Through : Natural) return String is + Front : Integer; begin if From > Through then declare @@ -207,18 +204,13 @@ package body Ada.Strings.Fixed is end if; else - declare - Front : constant Integer := From - Source'First; - Result : String (1 .. Source'Length - (Through - From + 1)); - - begin + Front := From - Source'First; + return Result : String (1 .. Source'Length - (Through - From + 1)) do Result (1 .. Front) := Source (Source'First .. From - 1); Result (Front + 1 .. Result'Last) := Source (Through + 1 .. Source'Last); - - return Result; - end; + end return; end if; end Delete; @@ -253,18 +245,13 @@ package body Ada.Strings.Fixed is Result_Type (Source (Source'First .. Source'First + Count - 1)); else - declare - Result : Result_Type; - - begin + return Result : Result_Type do Result (1 .. Source'Length) := Source; for J in Source'Length + 1 .. Count loop Result (J) := Pad; end loop; - - return Result; - end; + end return; end if; end Head; @@ -291,7 +278,6 @@ package body Ada.Strings.Fixed is Before : Positive; New_Item : String) return String is - Result : String (1 .. Source'Length + New_Item'Length); Front : constant Integer := Before - Source'First; begin @@ -299,14 +285,14 @@ package body Ada.Strings.Fixed is raise Index_Error; end if; - Result (1 .. Front) := - Source (Source'First .. Before - 1); - Result (Front + 1 .. Front + New_Item'Length) := - New_Item; - Result (Front + New_Item'Length + 1 .. Result'Last) := - Source (Before .. Source'Last); - - return Result; + return Result : String (1 .. Source'Length + New_Item'Length) do + Result (1 .. Front) := + Source (Source'First .. Before - 1); + Result (Front + 1 .. Front + New_Item'Length) := + New_Item; + Result (Front + New_Item'Length + 1 .. Result'Last) := + Source (Before .. Source'Last); + end return; end Insert; procedure Insert @@ -435,8 +421,7 @@ package body Ada.Strings.Fixed is function Overwrite (Source : String; Position : Positive; - New_Item : String) return String - is + New_Item : String) return String is begin if Position not in Source'First .. Source'Last + 1 then raise Index_Error; @@ -444,21 +429,17 @@ package body Ada.Strings.Fixed is declare Result_Length : constant Natural := - Integer'Max - (Source'Length, - Position - Source'First + New_Item'Length); - - Result : String (1 .. Result_Length); - Front : constant Integer := Position - Source'First; + Integer'Max (Source'Length, + Position - Source'First + New_Item'Length); + Front : constant Integer := Position - Source'First; begin - Result (1 .. Front) := - Source (Source'First .. Position - 1); - Result (Front + 1 .. Front + New_Item'Length) := - New_Item; - Result (Front + New_Item'Length + 1 .. Result'Length) := - Source (Position + New_Item'Length .. Source'Last); - return Result; + return Result : String (1 .. Result_Length) do + Result (1 .. Front) := Source (Source'First .. Position - 1); + Result (Front + 1 .. Front + New_Item'Length) := New_Item; + Result (Front + New_Item'Length + 1 .. Result'Length) := + Source (Position + New_Item'Length .. Source'Last); + end return; end; end Overwrite; @@ -495,24 +476,21 @@ package body Ada.Strings.Fixed is Integer'Max (0, Low - Source'First); -- Length of prefix of Source copied to result - Back_Len : constant Integer := - Integer'Max (0, Source'Last - High); + Back_Len : constant Integer := Integer'Max (0, Source'Last - High); -- Length of suffix of Source copied to result Result_Length : constant Integer := Front_Len + By'Length + Back_Len; -- Length of result - Result : String (1 .. Result_Length); - begin - Result (1 .. Front_Len) := Source (Source'First .. Low - 1); - Result (Front_Len + 1 .. Front_Len + By'Length) := By; - Result (Front_Len + By'Length + 1 .. Result'Length) := - Source (High + 1 .. Source'Last); - return Result; + return Result : String (1 .. Result_Length) do + Result (1 .. Front_Len) := Source (Source'First .. Low - 1); + Result (Front_Len + 1 .. Front_Len + By'Length) := By; + Result (Front_Len + By'Length + 1 .. Result'Length) := + Source (High + 1 .. Source'Last); + end return; end; - else return Insert (Source, Before => Low, New_Item => By); end if; @@ -549,17 +527,13 @@ package body Ada.Strings.Fixed is -- Pad on left else - declare - Result : Result_Type; - - begin + return Result : Result_Type do for J in 1 .. Count - Source'Length loop Result (J) := Pad; end loop; Result (Count - Source'Length + 1 .. Count) := Source; - return Result; - end; + end return; end if; end Tail; @@ -585,14 +559,12 @@ package body Ada.Strings.Fixed is (Source : String; Mapping : Maps.Character_Mapping) return String is - Result : String (1 .. Source'Length); - begin - for J in Source'Range loop - Result (J - (Source'First - 1)) := Value (Mapping, Source (J)); - end loop; - - return Result; + return Result : String (1 .. Source'Length) do + for J in Source'Range loop + Result (J - (Source'First - 1)) := Value (Mapping, Source (J)); + end loop; + end return; end Translate; procedure Translate @@ -609,15 +581,13 @@ package body Ada.Strings.Fixed is (Source : String; Mapping : Maps.Character_Mapping_Function) return String is - Result : String (1 .. Source'Length); pragma Unsuppress (Access_Check); - begin - for J in Source'Range loop - Result (J - (Source'First - 1)) := Mapping.all (Source (J)); - end loop; - - return Result; + return Result : String (1 .. Source'Length) do + for J in Source'Range loop + Result (J - (Source'First - 1)) := Mapping.all (Source (J)); + end loop; + end return; end Translate; procedure Translate -- cgit v1.1 From 90635a37c2d0e0468c3599398c5f8eeecf596f93 Mon Sep 17 00:00:00 2001 From: Fedor Rybin Date: Fri, 4 Jun 2021 21:01:27 +0300 Subject: [Ada] Fix index range violations in krunch gcc/ada/ * krunch.adb: Add safeguards against index range violations. --- gcc/ada/krunch.adb | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/krunch.adb b/gcc/ada/krunch.adb index 4cff3ca..f698d88 100644 --- a/gcc/ada/krunch.adb +++ b/gcc/ada/krunch.adb @@ -92,15 +92,16 @@ begin Startloc := 3; Buffer (2 .. Len - 5) := Buffer (7 .. Len); Curlen := Len - 5; - if Buffer (Curlen - 2 .. Curlen) = "128" - or else Buffer (3 .. 9) = "exn_lll" - or else Buffer (3 .. 9) = "exp_lll" - or else Buffer (3 .. 9) = "img_lll" - or else Buffer (3 .. 9) = "val_lll" - or else Buffer (3 .. 9) = "wid_lll" - or else (Buffer (3 .. 6) = "pack" and then Curlen = 10) + if (Curlen >= 3 and then Buffer (Curlen - 2 .. Curlen) = "128") + or else (Len >= 9 and then + (Buffer (3 .. 9) = "exn_lll" + or else Buffer (3 .. 9) = "exp_lll" + or else Buffer (3 .. 9) = "img_lll" + or else Buffer (3 .. 9) = "val_lll" + or else Buffer (3 .. 9) = "wid_lll")) + or else (Curlen = 10 and then Buffer (3 .. 6) = "pack") then - if Buffer (3 .. 15) = "compare_array" then + if Len >= 15 and then Buffer (3 .. 15) = "compare_array" then Buffer (3 .. 4) := "ca"; Buffer (5 .. Curlen - 11) := Buffer (16 .. Curlen); Curlen := Curlen - 11; -- cgit v1.1 From 06fd120d19d2636a812c9ffe4b8871f3733ae213 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 11 Jun 2021 16:01:36 +0200 Subject: [Ada] Fix typo in comment related to derived discriminated types gcc/ada/ * exp_util.ads (Map_Types): Fix typo. --- gcc/ada/exp_util.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads index 3be0166..5c931c9 100644 --- a/gcc/ada/exp_util.ads +++ b/gcc/ada/exp_util.ads @@ -915,7 +915,7 @@ package Exp_Util is -- Establish the following mapping between the attributes of tagged parent -- type Parent_Type and tagged derived type Derived_Type. -- - -- * Map each discriminant of Parent_Type to ether the corresponding + -- * Map each discriminant of Parent_Type to either the corresponding -- discriminant of Derived_Type or come constraint. -- * Map each primitive operation of Parent_Type to the corresponding -- cgit v1.1 From 2390451ede49fa09bc0d9692802651aff66ae8a6 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 11 Jun 2021 09:11:13 +0200 Subject: [Ada] Fix invalid JSON for derived variant record with -gnatRj gcc/ada/ * repinfo.ads (JSON output format): Document adjusted key name. * repinfo.adb (List_Record_Layout): Use Original_Record_Component if the normalized position of the component is not known. (List_Structural_Record_Layout): Rename Outer_Ent parameter into Ext_End and add Ext_Level parameter. In an extension, if the parent subtype has static discriminants, call List_Record_Layout on it. Output "parent_" prefixes before "variant" according to Ext_Level. Adjust recursive calls throughout the procedure. --- gcc/ada/repinfo.adb | 55 ++++++++++++++++++++++++++++++++++++++--------------- gcc/ada/repinfo.ads | 7 ++++--- 2 files changed, 44 insertions(+), 18 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index 3cc1f93..25b5237 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -963,10 +963,15 @@ package body Repinfo is procedure List_Structural_Record_Layout (Ent : Entity_Id; - Outer_Ent : Entity_Id; + Ext_Ent : Entity_Id; + Ext_Level : Nat := 0; Variant : Node_Id := Empty; Indent : Natural := 0); - -- Internal recursive procedure to display the structural layout + -- Internal recursive procedure to display the structural layout. + -- If Ext_Ent is not equal to Ent, it is an extension of Ent and + -- Ext_Level is the number of successive extensions between them. + -- If Variant is present, it's for a variant in the variant part + -- instead of the common part of Ent. Indent is the indentation. Incomplete_Layout : exception; -- Exception raised if the layout is incomplete in -gnatc mode @@ -1319,7 +1324,12 @@ package body Repinfo is end if; end if; - List_Component_Layout (Comp, + -- The Parent_Subtype in an extension is not back-annotated + + List_Component_Layout ( + (if Known_Normalized_Position (Comp) + then Comp + else Original_Record_Component (Comp)), Starting_Position, Starting_First_Bit, Prefix); end; @@ -1334,15 +1344,16 @@ package body Repinfo is procedure List_Structural_Record_Layout (Ent : Entity_Id; - Outer_Ent : Entity_Id; + Ext_Ent : Entity_Id; + Ext_Level : Nat := 0; Variant : Node_Id := Empty; Indent : Natural := 0) is function Derived_Discriminant (Disc : Entity_Id) return Entity_Id; - -- This function assumes that Outer_Ent is an extension of Ent. + -- This function assumes that Ext_Ent is an extension of Ent. -- Disc is a discriminant of Ent that does not itself constrain a -- discriminant of the parent type of Ent. Return the discriminant - -- of Outer_Ent that ultimately constrains Disc, if any. + -- of Ext_Ent that ultimately constrains Disc, if any. ---------------------------- -- Derived_Discriminant -- @@ -1353,7 +1364,7 @@ package body Repinfo is Derived_Disc : Entity_Id; begin - Derived_Disc := First_Discriminant (Outer_Ent); + Derived_Disc := First_Discriminant (Ext_Ent); -- Loop over the discriminants of the extension @@ -1380,7 +1391,7 @@ package body Repinfo is Next_Discriminant (Derived_Disc); end loop; - -- Disc is not constrained by a discriminant of Outer_Ent + -- Disc is not constrained by a discriminant of Ext_Ent return Empty; end Derived_Discriminant; @@ -1432,12 +1443,21 @@ package body Repinfo is pragma Assert (Present (Parent_Type)); end if; - Parent_Type := Base_Type (Parent_Type); - if not In_Extended_Main_Source_Unit (Parent_Type) then - raise Not_In_Extended_Main; + -- Do not list variants if one of them has been selected + + if Has_Static_Discriminants (Parent_Type) then + List_Record_Layout (Parent_Type); + + else + Parent_Type := Base_Type (Parent_Type); + if not In_Extended_Main_Source_Unit (Parent_Type) then + raise Not_In_Extended_Main; + end if; + + List_Structural_Record_Layout + (Parent_Type, Ext_Ent, Ext_Level + 1); end if; - List_Structural_Record_Layout (Parent_Type, Outer_Ent); First := False; if Present (Record_Extension_Part (Definition)) then @@ -1467,7 +1487,7 @@ package body Repinfo is -- If this is the parent type of an extension, retrieve -- the derived discriminant from the extension, if any. - if Ent /= Outer_Ent then + if Ent /= Ext_Ent then Listed_Disc := Derived_Discriminant (Disc); if No (Listed_Disc) then @@ -1544,7 +1564,11 @@ package body Repinfo is Spaces (Indent); Write_Line (" ],"); Spaces (Indent); - Write_Str (" ""variant"" : ["); + Write_Str (" """); + for J in 1 .. Ext_Level loop + Write_Str ("parent_"); + end loop; + Write_Str ("variant"" : ["); -- Otherwise we recurse on each variant @@ -1567,7 +1591,8 @@ package body Repinfo is Spaces (Indent); Write_Str (" ""record"": ["); - List_Structural_Record_Layout (Ent, Outer_Ent, Var, Indent + 4); + List_Structural_Record_Layout + (Ent, Ext_Ent, Ext_Level, Var, Indent + 4); Write_Eol; Spaces (Indent); diff --git a/gcc/ada/repinfo.ads b/gcc/ada/repinfo.ads index 45eb0ab..606bba4 100644 --- a/gcc/ada/repinfo.ads +++ b/gcc/ada/repinfo.ads @@ -189,7 +189,7 @@ package Repinfo is -- "name" : string -- "location" : string -- "record" : array of components - -- "variant" : array of variants + -- "[parent_]*variant" : array of variants -- "formal" : array of formal parameters -- "mechanism" : string -- "Size" : numerical expression @@ -209,8 +209,9 @@ package Repinfo is -- fully qualified Ada name. The value of "location" is the expanded -- chain of instantiation locations that contains the entity. -- "record" is present for every record type and its value is the list of - -- components. "variant" is present only if the record type has a variant - -- part and its value is the list of variants. + -- components. "[parent_]*variant" is present only if the record type, or + -- one of its ancestors (parent, grand-parent, etc) if it's an extension, + -- has a variant part and its value is the list of variants. -- "formal" is present for every subprogram and entry, and its value is -- the list of formal parameters. "mechanism" is present for functions -- only and its value is the return mechanim. -- cgit v1.1 From 021cf768fba5724f6d419fbbd574ca12c76c616c Mon Sep 17 00:00:00 2001 From: Joffrey Huguet Date: Thu, 10 Jun 2021 11:39:01 +0200 Subject: [Ada] Fix layout of contracts gcc/ada/ * libgnat/a-strunb.ads, libgnat/a-strunb__shared.ads: Fix layout in contracts. --- gcc/ada/libgnat/a-strunb.ads | 29 ++++++++++++++--------------- gcc/ada/libgnat/a-strunb__shared.ads | 11 ++++------- 2 files changed, 18 insertions(+), 22 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/a-strunb.ads b/gcc/ada/libgnat/a-strunb.ads index 89c8339..13c7612 100644 --- a/gcc/ada/libgnat/a-strunb.ads +++ b/gcc/ada/libgnat/a-strunb.ads @@ -81,7 +81,7 @@ is -------------------------------------------------------- function To_Unbounded_String - (Source : String) return Unbounded_String + (Source : String) return Unbounded_String with Post => Length (To_Unbounded_String'Result) = Source'Length, Global => null; @@ -91,8 +91,7 @@ is (Length : Natural) return Unbounded_String with Post => - Ada.Strings.Unbounded.Length (To_Unbounded_String'Result) - = Length, + Ada.Strings.Unbounded.Length (To_Unbounded_String'Result) = Length, Global => null; -- Returns an Unbounded_String that represents an uninitialized String -- whose length is Length. @@ -524,11 +523,11 @@ is with Pre => Low - 1 <= Length (Source) - and then (if High >= Low - then Low - 1 - <= Natural'Last - By'Length - - Natural'Max (Length (Source) - High, 0) - else Length (Source) <= Natural'Last - By'Length), + and then (if High >= Low + then Low - 1 + <= Natural'Last - By'Length + - Natural'Max (Length (Source) - High, 0) + else Length (Source) <= Natural'Last - By'Length), Contract_Cases => (High >= Low => Length (Replace_Slice'Result) @@ -545,11 +544,11 @@ is with Pre => Low - 1 <= Length (Source) - and then (if High >= Low - then Low - 1 - <= Natural'Last - By'Length - - Natural'Max (Length (Source) - High, 0) - else Length (Source) <= Natural'Last - By'Length), + and then (if High >= Low + then Low - 1 + <= Natural'Last - By'Length + - Natural'Max (Length (Source) - High, 0) + else Length (Source) <= Natural'Last - By'Length), Contract_Cases => (High >= Low => Length (Source) @@ -586,7 +585,7 @@ is Pre => Position - 1 <= Length (Source) and then (if New_Item'Length /= 0 then - New_Item'Length <= Natural'Last - (Position - 1)), + New_Item'Length <= Natural'Last - (Position - 1)), Post => Length (Overwrite'Result) = Natural'Max (Length (Source), Position - 1 + New_Item'Length), @@ -600,7 +599,7 @@ is Pre => Position - 1 <= Length (Source) and then (if New_Item'Length /= 0 then - New_Item'Length <= Natural'Last - (Position - 1)), + New_Item'Length <= Natural'Last - (Position - 1)), Post => Length (Source) = Natural'Max (Length (Source)'Old, Position - 1 + New_Item'Length), diff --git a/gcc/ada/libgnat/a-strunb__shared.ads b/gcc/ada/libgnat/a-strunb__shared.ads index 6382252..2091bde 100644 --- a/gcc/ada/libgnat/a-strunb__shared.ads +++ b/gcc/ada/libgnat/a-strunb__shared.ads @@ -363,9 +363,8 @@ is Going : Direction := Forward; Mapping : Maps.Character_Mapping := Maps.Identity) return Natural with - Pre => (if Length (Source) /= 0 - then From <= Length (Source)) - and then Pattern'Length /= 0, + Pre => (if Length (Source) /= 0 then From <= Length (Source)) + and then Pattern'Length /= 0, Global => null; pragma Ada_05 (Index); @@ -376,11 +375,9 @@ is Going : Direction := Forward; Mapping : Maps.Character_Mapping_Function) return Natural with - Pre => (if Length (Source) /= 0 - then From <= Length (Source)) - and then Pattern'Length /= 0, + Pre => (if Length (Source) /= 0 then From <= Length (Source)) + and then Pattern'Length /= 0, Global => null; - pragma Ada_05 (Index); function Index -- cgit v1.1 From fbc72d0b4ac841fdf7d3ea15851f3be39361a86c Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Mon, 14 Jun 2021 09:37:24 -0400 Subject: [Ada] Add source file name to gnat bug box gcc/ada/ * comperr.adb (Compiler_Abort): Print source file name. --- gcc/ada/comperr.adb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/comperr.adb b/gcc/ada/comperr.adb index 300b523..064fae0 100644 --- a/gcc/ada/comperr.adb +++ b/gcc/ada/comperr.adb @@ -244,12 +244,17 @@ package body Comperr is end if; End_Line; + else Write_Str ("| Error detected at "); Write_Location (Sloc (Current_Error_Node)); End_Line; end if; + Write_Str ("| Compiling "); + Write_Str (Get_First_Main_File_Name); + End_Line; + -- There are two cases now. If the file gnat_bug.box exists, -- we use the contents of this file at this point. -- cgit v1.1 From 175c2f98ea85004f23acc4b40f0e4264420116fc Mon Sep 17 00:00:00 2001 From: Doug Rupp Date: Sat, 5 Jun 2021 12:58:35 -0700 Subject: [Ada] Declare time_t uniformly based on a system parameter gcc/ada/ * Makefile.rtl: Add translations for s-parame__posix2008.ads * libgnarl/s-linux.ads: Import System.Parameters. (time_t): Declare using System.Parameters.time_t_bits. * libgnarl/s-linux__alpha.ads: Likewise. * libgnarl/s-linux__android.ads: Likewise. * libgnarl/s-linux__hppa.ads: Likewise. * libgnarl/s-linux__mips.ads: Likewise. * libgnarl/s-linux__riscv.ads: Likewise. * libgnarl/s-linux__sparc.ads: Likewise. * libgnarl/s-linux__x32.ads: Likewise. * libgnarl/s-qnx.ads: Likewise. * libgnarl/s-osinte__aix.ads: Likewise. * libgnarl/s-osinte__android.ads: Likewise. * libgnarl/s-osinte__darwin.ads: Likewise. * libgnarl/s-osinte__dragonfly.ads: Likewise. * libgnarl/s-osinte__freebsd.ads: Likewise. * libgnarl/s-osinte__gnu.ads: Likewise. * libgnarl/s-osinte__hpux-dce.ads: Likewise. * libgnarl/s-osinte__hpux.ads: Likewise. * libgnarl/s-osinte__kfreebsd-gnu.ads: Likewise. * libgnarl/s-osinte__lynxos178e.ads: Likewise. * libgnarl/s-osinte__qnx.ads: Likewise. * libgnarl/s-osinte__rtems.ads: Likewise. * libgnarl/s-osinte__solaris.ads: Likewise. * libgnarl/s-osinte__vxworks.ads: Likewise. * libgnat/g-sothco.ads: Likewise. * libgnat/s-osprim__darwin.adb: Likewise. * libgnat/s-osprim__posix.adb: Likewise. * libgnat/s-osprim__posix2008.adb: Likewise. * libgnat/s-osprim__rtems.adb: Likewise. * libgnat/s-osprim__x32.adb: Likewise. * libgnarl/s-osinte__linux.ads: use type System.Linux.time_t. * libgnat/s-os_lib.ads (time_t): Declare as subtype of Long_Long_Integer. * libgnat/s-parame.ads (time_t_bits): New constant. * libgnat/s-parame__ae653.ads (time_t_bits): Likewise. * libgnat/s-parame__hpux.ads (time_t_bits): Likewise. * libgnat/s-parame__vxworks.ads (time_t_bits): Likewise. * libgnat/s-parame__posix2008.ads: New file for 64 bit time_t. --- gcc/ada/Makefile.rtl | 3 + gcc/ada/libgnarl/s-linux.ads | 4 +- gcc/ada/libgnarl/s-linux__alpha.ads | 4 +- gcc/ada/libgnarl/s-linux__android.ads | 4 +- gcc/ada/libgnarl/s-linux__hppa.ads | 4 +- gcc/ada/libgnarl/s-linux__mips.ads | 4 +- gcc/ada/libgnarl/s-linux__riscv.ads | 4 +- gcc/ada/libgnarl/s-linux__sparc.ads | 4 +- gcc/ada/libgnarl/s-linux__x32.ads | 7 +- gcc/ada/libgnarl/s-osinte__aix.ads | 5 +- gcc/ada/libgnarl/s-osinte__android.ads | 4 +- gcc/ada/libgnarl/s-osinte__darwin.ads | 4 +- gcc/ada/libgnarl/s-osinte__dragonfly.ads | 5 +- gcc/ada/libgnarl/s-osinte__freebsd.ads | 5 +- gcc/ada/libgnarl/s-osinte__gnu.ads | 4 +- gcc/ada/libgnarl/s-osinte__hpux-dce.ads | 5 +- gcc/ada/libgnarl/s-osinte__hpux.ads | 5 +- gcc/ada/libgnarl/s-osinte__kfreebsd-gnu.ads | 4 +- gcc/ada/libgnarl/s-osinte__linux.ads | 2 + gcc/ada/libgnarl/s-osinte__lynxos178e.ads | 4 +- gcc/ada/libgnarl/s-osinte__qnx.ads | 4 +- gcc/ada/libgnarl/s-osinte__rtems.ads | 4 +- gcc/ada/libgnarl/s-osinte__solaris.ads | 5 +- gcc/ada/libgnarl/s-osinte__vxworks.ads | 7 +- gcc/ada/libgnarl/s-qnx.ads | 5 +- gcc/ada/libgnat/g-sothco.ads | 7 +- gcc/ada/libgnat/s-os_lib.ads | 10 +- gcc/ada/libgnat/s-osprim__darwin.adb | 4 +- gcc/ada/libgnat/s-osprim__posix.adb | 4 +- gcc/ada/libgnat/s-osprim__posix2008.adb | 4 +- gcc/ada/libgnat/s-osprim__rtems.adb | 4 +- gcc/ada/libgnat/s-osprim__x32.adb | 3 +- gcc/ada/libgnat/s-parame.ads | 7 + gcc/ada/libgnat/s-parame__ae653.ads | 7 + gcc/ada/libgnat/s-parame__hpux.ads | 7 + gcc/ada/libgnat/s-parame__posix2008.ads | 193 ++++++++++++++++++++++++++++ gcc/ada/libgnat/s-parame__vxworks.ads | 15 +++ 37 files changed, 342 insertions(+), 33 deletions(-) create mode 100644 gcc/ada/libgnat/s-parame__posix2008.ads (limited to 'gcc') diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 5475d0d..fb851a6 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -2162,6 +2162,7 @@ ifeq ($(strip $(filter-out lynxos178%,$(target_os))),) ifeq ($(strip $(filter-out lynxos178e,$(target_os))),) LIBGNAT_TARGET_PAIRS += \ + s-parame.ads. -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +-- This is the Posix 2008 version for 64 bit time_t. + +-- This package defines some system dependent parameters for GNAT. These +-- are values that are referenced by the runtime library and are therefore +-- relevant to the target machine. + +-- The parameters whose value is defined in the spec are not generally +-- expected to be changed. If they are changed, it will be necessary to +-- recompile the run-time library. + +-- The parameters which are defined by functions can be changed by modifying +-- the body of System.Parameters in file s-parame.adb. A change to this body +-- requires only rebinding and relinking of the application. + +-- Note: do not introduce any pragma Inline statements into this unit, since +-- otherwise the relinking and rebinding capability would be deactivated. + +pragma Compiler_Unit_Warning; + +package System.Parameters is + pragma Pure; + + --------------------------------------- + -- Task And Stack Allocation Control -- + --------------------------------------- + + type Size_Type is range + -(2 ** (Integer'(Standard'Address_Size) - 1)) .. + +(2 ** (Integer'(Standard'Address_Size) - 1)) - 1; + -- Type used to provide task stack sizes to the runtime. Sized to permit + -- stack sizes of up to half the total addressable memory space. This may + -- seem excessively large (even for 32-bit systems), however there are many + -- instances of users requiring large stack sizes (for example string + -- processing). + + Unspecified_Size : constant Size_Type := Size_Type'First; + -- Value used to indicate that no size type is set + + function Default_Stack_Size return Size_Type; + -- Default task stack size used if none is specified + + function Minimum_Stack_Size return Size_Type; + -- Minimum task stack size permitted + + function Adjust_Storage_Size (Size : Size_Type) return Size_Type; + -- Given the storage size stored in the TCB, return the Storage_Size + -- value required by the RM for the Storage_Size attribute. The + -- required adjustment is as follows: + -- + -- when Size = Unspecified_Size, return Default_Stack_Size + -- when Size < Minimum_Stack_Size, return Minimum_Stack_Size + -- otherwise return given Size + + Default_Env_Stack_Size : constant Size_Type := 8_192_000; + -- Assumed size of the environment task, if no other information is + -- available. This value is used when stack checking is enabled and + -- no GNAT_STACK_LIMIT environment variable is set. + + Stack_Grows_Down : constant Boolean := True; + -- This constant indicates whether the stack grows up (False) or + -- down (True) in memory as functions are called. It is used for + -- proper implementation of the stack overflow check. + + Runtime_Default_Sec_Stack_Size : constant Size_Type := 10 * 1024; + -- The run-time chosen default size for secondary stacks that may be + -- overridden by the user with the use of binder -D switch. + + Sec_Stack_Dynamic : constant Boolean := True; + -- Indicates if secondary stacks can grow and shrink at run-time. If False, + -- the size of a secondary stack is fixed at the point of its creation. + + ------------------------------------ + -- Characteristics of time_t type -- + ------------------------------------ + + time_t_bits : constant := Long_Long_Integer'Size; + -- Number of bits in type time_t. Use for targets that are Posix 2008 + -- compliant (fixes the year 2038 time_t overflow). + + ---------------------------------------------- + -- Characteristics of types in Interfaces.C -- + ---------------------------------------------- + + long_bits : constant := Long_Integer'Size; + -- Number of bits in type long and unsigned_long. The normal convention + -- is that this is the same as type Long_Integer, but this may not be true + -- of all targets. + + ptr_bits : constant := Standard'Address_Size; + subtype C_Address is System.Address; + -- Number of bits in Interfaces.C pointers, normally a standard address + + C_Malloc_Linkname : constant String := "__gnat_malloc"; + -- Name of runtime function used to allocate such a pointer + + ---------------------------------------------- + -- Behavior of Pragma Finalize_Storage_Only -- + ---------------------------------------------- + + -- Garbage_Collected is a Boolean constant whose value indicates the + -- effect of the pragma Finalize_Storage_Entry on a controlled type. + + -- Garbage_Collected = False + + -- The system releases all storage on program termination only, + -- but not other garbage collection occurs, so finalization calls + -- are omitted only for outer level objects can be omitted if + -- pragma Finalize_Storage_Only is used. + + -- Garbage_Collected = True + + -- The system provides full garbage collection, so it is never + -- necessary to release storage for controlled objects for which + -- a pragma Finalize_Storage_Only is used. + + Garbage_Collected : constant Boolean := False; + -- The storage mode for this system (release on program exit) + + --------------------- + -- Tasking Profile -- + --------------------- + + -- In the following sections, constant parameters are defined to + -- allow some optimizations and fine tuning within the tasking run time + -- based on restrictions on the tasking features. + + ------------------- + -- Task Abortion -- + ------------------- + + No_Abort : constant Boolean := False; + -- This constant indicates whether abort statements and asynchronous + -- transfer of control (ATC) are disallowed. If set to True, it is + -- assumed that neither construct is used, and the run time does not + -- need to defer/undefer abort and check for pending actions at + -- completion points. A value of True for No_Abort corresponds to: + -- pragma Restrictions (No_Abort_Statements); + -- pragma Restrictions (Max_Asynchronous_Select_Nesting => 0); + + --------------------- + -- Task Attributes -- + --------------------- + + Max_Attribute_Count : constant := 32; + -- Number of task attributes stored in the task control block + + ----------------------- + -- Task Image Length -- + ----------------------- + + Max_Task_Image_Length : constant := 256; + -- This constant specifies the maximum length of a task's image + + ------------------------------ + -- Exception Message Length -- + ------------------------------ + + Default_Exception_Msg_Max_Length : constant := 200; + -- This constant specifies the default number of characters to allow + -- in an exception message (200 is minimum required by RM 11.4.1(18)). + +end System.Parameters; diff --git a/gcc/ada/libgnat/s-parame__vxworks.ads b/gcc/ada/libgnat/s-parame__vxworks.ads index 8598a43..11b408b 100644 --- a/gcc/ada/libgnat/s-parame__vxworks.ads +++ b/gcc/ada/libgnat/s-parame__vxworks.ads @@ -100,6 +100,21 @@ package System.Parameters is -- Indicates if secondary stacks can grow and shrink at run-time. If False, -- the size of a secondary stack is fixed at the point of its creation. + ------------------------------------ + -- Characteristics of time_t type -- + ------------------------------------ + + -- IMPORTANT NOTE: + -- Select the appropriate time_t_bits for the VSB in use, then rebuild + -- the runtime using instructions in adainclude/libada.gpr. + + time_t_bits : constant := Long_Integer'Size; + -- Number of bits in type time_t for SR0650 and before and SR0660 with + -- non-default configuration. + + -- time_t_bits : constant := Long_Long_Integer'Size; + -- Number of bits in type time_t for SR0660 with default configuration. + ---------------------------------------------- -- Characteristics of types in Interfaces.C -- ---------------------------------------------- -- cgit v1.1 From 765ca22b1792b613d2801b6d2ef9986e18bba3ab Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Sun, 13 Jun 2021 12:52:18 -0400 Subject: [Ada] Crash on inlined separate subprogram gcc/ada/ * sem_ch6.adb (Check_Pragma_Inline): Correctly use Corresponding_Spec_Of_Stub when dealing subprogram body stubs. --- gcc/ada/sem_ch6.adb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 78a076c..304dc19 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -3454,7 +3454,12 @@ package body Sem_Ch6 is -- Link the body and the generated spec Set_Corresponding_Body (Decl, Body_Id); - Set_Corresponding_Spec (N, Subp); + + if Nkind (N) = N_Subprogram_Body_Stub then + Set_Corresponding_Spec_Of_Stub (N, Subp); + else + Set_Corresponding_Spec (N, Subp); + end if; Set_Defining_Unit_Name (Specification (Decl), Subp); -- cgit v1.1 From e4de29f4677e81e71c60eb2b9f247eaa12ea1353 Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Thu, 10 Jun 2021 11:20:27 -0700 Subject: [Ada] Add -gnatX support for casing on discriminated values gcc/ada/ * exp_ch5.adb (Expand_General_Case_Statement): Add new function Else_Statements to handle the case of invalid data analogously to how it is handled when casing on a discrete value. * sem_case.adb (Has_Static_Discriminant_Constraint): A new Boolean-valued function. (Composite_Case_Ops.Scalar_Part_Count): Include discriminants when traversing components. (Composite_Case_Ops.Choice_Analysis.Traverse_Discrete_Parts): Include discriminants when traversing components; the component range for a constrained discriminant is a single value. (Composite_Case_Ops.Choice_Analysis.Parse_Choice): Eliminate Done variable and modify how Next_Part is computed so that it is always correct (as opposed to being incorrect when Done is True). This includes changes in Update_Result (a local procedure). Add new local procedure Update_Result_For_Box_Component and call it not just for box components but also for "missing" components (components associated with an inactive variant). (Check_Choices.Check_Composite_Case_Selector.Check_Component_Subtype): Instead of disallowing all discriminated component types, allow those that are unconstrained or statically constrained. Check discriminant subtypes along with other component subtypes. * doc/gnat_rm/implementation_defined_pragmas.rst: Update documentation to reflect current implementation status. * gnat_rm.texi: Regenerate. --- .../doc/gnat_rm/implementation_defined_pragmas.rst | 11 +- gcc/ada/exp_ch5.adb | 27 +- gcc/ada/gnat_rm.texi | 11 +- gcc/ada/sem_case.adb | 285 +++++++++++++++------ 4 files changed, 241 insertions(+), 93 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst index c82658d..6c81ca7 100644 --- a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst +++ b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst @@ -2237,8 +2237,7 @@ of GNAT specific extensions are recognized as follows: some restrictions (described below). Aggregate syntax is used for choices of such a case statement; however, in cases where a "normal" aggregate would require a discrete value, a discrete subtype may be used instead; box - notation can also be used to match all values (but currently only - for discrete subcomponents). + notation can also be used to match all values. Consider this example: @@ -2269,10 +2268,10 @@ of GNAT specific extensions are recognized as follows: set shall be a proper subset of the second (and the later alternative will not be executed if the earlier alternative "matches"). All possible values of the composite type shall be covered. The composite type of the - selector shall be a nonlimited untagged undiscriminated record type, all - of whose subcomponent subtypes are either static discrete subtypes or - record types that meet the same restrictions. Support for arrays is - planned, but not yet implemented. + selector shall be a nonlimited untagged (but possibly discriminated) + record type, all of whose subcomponent subtypes are either static discrete + subtypes or record types that meet the same restrictions. Support for arrays + is planned, but not yet implemented. In addition, pattern bindings are supported. This is a mechanism for binding a name to a component of a matching value for use within diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 2559e56..8ac9662 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -3641,16 +3641,37 @@ package body Exp_Ch5 is return Result; end Elsif_Parts; + function Else_Statements return List_Id; + -- Returns a "raise Constraint_Error" statement if + -- exception propagate is permitted and No_List otherwise. + + --------------------- + -- Else_Statements -- + --------------------- + + function Else_Statements return List_Id is + begin + if Restriction_Active (No_Exception_Propagation) then + return No_List; + else + return New_List (Make_Raise_Constraint_Error (Loc, + Reason => CE_Invalid_Data)); + end if; + end Else_Statements; + + -- Local constants + If_Stmt : constant Node_Id := Make_If_Statement (Loc, Condition => Top_Level_Pattern_Match_Condition (First_Alt), Then_Statements => Statements (First_Alt), - Elsif_Parts => Elsif_Parts); - -- Do we want an implicit "else raise Program_Error" here??? - -- Perhaps only if Exception-related restrictions are not in effect. + Elsif_Parts => Elsif_Parts, + Else_Statements => Else_Statements); Declarations : constant List_Id := New_List (Selector_Decl); + -- Start of processing for Expand_General_Case_Statment + begin if Present (Choice_Index_Decl) then Append_To (Declarations, Choice_Index_Decl); diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index c0ccfe4..349586e 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -3665,8 +3665,7 @@ The selector for a case statement may be of a composite type, subject to some restrictions (described below). Aggregate syntax is used for choices of such a case statement; however, in cases where a “normal” aggregate would require a discrete value, a discrete subtype may be used instead; box -notation can also be used to match all values (but currently only -for discrete subcomponents). +notation can also be used to match all values. Consider this example: @@ -3697,10 +3696,10 @@ overlaps the corresponding set of a later alternative, then the first set shall be a proper subset of the second (and the later alternative will not be executed if the earlier alternative “matches”). All possible values of the composite type shall be covered. The composite type of the -selector shall be a nonlimited untagged undiscriminated record type, all -of whose subcomponent subtypes are either static discrete subtypes or -record types that meet the same restrictions. Support for arrays is -planned, but not yet implemented. +selector shall be a nonlimited untagged (but possibly discriminated) +record type, all of whose subcomponent subtypes are either static discrete +subtypes or record types that meet the same restrictions. Support for arrays +is planned, but not yet implemented. In addition, pattern bindings are supported. This is a mechanism for binding a name to a component of a matching value for use within diff --git a/gcc/ada/sem_case.adb b/gcc/ada/sem_case.adb index 9ff2564..7d08da5 100644 --- a/gcc/ada/sem_case.adb +++ b/gcc/ada/sem_case.adb @@ -27,6 +27,7 @@ with Atree; use Atree; with Einfo; use Einfo; with Einfo.Entities; use Einfo.Entities; with Einfo.Utils; use Einfo.Utils; +with Elists; use Elists; with Errout; use Errout; with Namet; use Namet; with Nlists; use Nlists; @@ -90,13 +91,18 @@ package body Sem_Case is -- -- Bounds_Type is the type whose range must be covered by the alternatives -- - -- Subtyp is the subtype of the expression. If its bounds are non-static + -- Subtyp is the subtype of the expression. If its bounds are nonstatic -- the alternatives must cover its base type. function Choice_Image (Value : Uint; Ctype : Entity_Id) return Name_Id; -- Given a Pos value of enumeration type Ctype, returns the name -- ID of an appropriate string to be used in error message output. + function Has_Static_Discriminant_Constraint + (Subtyp : Entity_Id) return Boolean; + -- Returns True if the given subtype is subject to a discriminant + -- constraint and at least one of the constraint values is nonstatic. + package Composite_Case_Ops is function Scalar_Part_Count (Subtyp : Entity_Id) return Nat; @@ -255,9 +261,9 @@ package body Sem_Case is -- is posted at location C. Caller sets Error_Msg_Sloc for xx. procedure Explain_Non_Static_Bound; - -- Called when we find a non-static bound, requiring the base type to + -- Called when we find a nonstatic bound, requiring the base type to -- be covered. Provides where possible a helpful explanation of why the - -- bounds are non-static, since this is not always obvious. + -- bounds are nonstatic, since this is not always obvious. function Lt_Choice (C1, C2 : Natural) return Boolean; -- Comparison routine for comparing Choice_Table entries. Use the lower @@ -734,7 +740,7 @@ package body Sem_Case is ("bounds of & are not static, " & "alternatives must cover base type!", Expr, Expr); - -- If this is a case statement, the expression may be non-static + -- If this is a case statement, the expression may be nonstatic -- or else the subtype may be at fault. elsif Is_Entity_Name (Expr) then @@ -1124,14 +1130,14 @@ package body Sem_Case is return Static_Array_Length (Subtyp) * Scalar_Part_Count (Component_Type (Subtyp)); elsif Is_Record_Type (Subtyp) then - pragma Assert (not Has_Discriminants (Subtyp)); declare Result : Nat := 0; - Comp : Entity_Id := First_Component (Subtyp); + Comp : Entity_Id := First_Component_Or_Discriminant + (Base_Type (Subtyp)); begin while Present (Comp) loop Result := Result + Scalar_Part_Count (Etype (Comp)); - Next_Component (Comp); + Next_Component_Or_Discriminant (Comp); end loop; return Result; end; @@ -1218,15 +1224,47 @@ package body Sem_Case is Traverse_Discrete_Parts (Component_Type (Subtyp)); end loop; elsif Is_Record_Type (Subtyp) then - pragma Assert (not Has_Discriminants (Subtyp)); - declare - Comp : Entity_Id := First_Component (Subtyp); - begin - while Present (Comp) loop - Traverse_Discrete_Parts (Etype (Comp)); - Next_Component (Comp); - end loop; - end; + if Has_Static_Discriminant_Constraint (Subtyp) then + + -- The component range for a constrained discriminant + -- is a single value. + declare + Dc_Elmt : Elmt_Id := + First_Elmt (Discriminant_Constraint (Subtyp)); + Dc_Value : Uint; + begin + while Present (Dc_Elmt) loop + Dc_Value := Expr_Value (Node (Dc_Elmt)); + Update_Result ((Low => Dc_Value, + High => Dc_Value)); + + Next_Elmt (Dc_Elmt); + end loop; + end; + + -- Generate ranges for nondiscriminant components. + declare + Comp : Entity_Id := First_Component + (Base_Type (Subtyp)); + begin + while Present (Comp) loop + Traverse_Discrete_Parts (Etype (Comp)); + Next_Component (Comp); + end loop; + end; + else + -- Generate ranges for all components + declare + Comp : Entity_Id := + First_Component_Or_Discriminant + (Base_Type (Subtyp)); + begin + while Present (Comp) loop + Traverse_Discrete_Parts (Etype (Comp)); + Next_Component_Or_Discriminant (Comp); + end loop; + end; + end if; else Error_Msg_N ("case selector type having a non-discrete non-record" @@ -1234,6 +1272,7 @@ package body Sem_Case is Expression (Case_Statement)); end if; end Traverse_Discrete_Parts; + begin Traverse_Discrete_Parts (Etype (Expression (Case_Statement))); pragma Assert (Done or else Serious_Errors_Detected > 0); @@ -1338,12 +1377,23 @@ package body Sem_Case is is Result : Choice_Range_Info (Is_Others => False); Ranges : Composite_Range_Info renames Result.Ranges; - Next_Part : Part_Id := 1; - Done : Boolean := False; + Next_Part : Part_Id'Base range 1 .. Part_Id'Last + 1 := 1; + + procedure Traverse_Choice (Expr : Node_Id); + -- Traverse a legal choice expression, looking for + -- values/ranges of discrete parts. Call Update_Result + -- for each. procedure Update_Result (Discrete_Range : Discrete_Range_Info); -- Initialize first remaining uninitialized element of Ranges. - -- Also set Next_Part and Done. + -- Also set Next_Part. + + procedure Update_Result_For_Full_Coverage (Comp_Type : Entity_Id); + -- For each scalar part of the given component type, call + -- Update_Result with the full range for that scalar part. + -- This is used for both box components in aggregates and + -- for any inactive-variant components that do not appear in + -- a given aggregate. ------------------- -- Update_Result -- @@ -1351,19 +1401,21 @@ package body Sem_Case is procedure Update_Result (Discrete_Range : Discrete_Range_Info) is begin - pragma Assert (not Done); Ranges (Next_Part) := Discrete_Range; - if Next_Part = Part_Id'Last then - Done := True; - else - Next_Part := Next_Part + 1; - end if; + Next_Part := Next_Part + 1; end Update_Result; - procedure Traverse_Choice (Expr : Node_Id); - -- Traverse a legal choice expression, looking for - -- values/ranges of discrete parts. Call Update_Result - -- for each. + ------------------------------------- + -- Update_Result_For_Full_Coverage -- + ------------------------------------- + + procedure Update_Result_For_Full_Coverage (Comp_Type : Entity_Id) + is + begin + for Counter in 1 .. Scalar_Part_Count (Comp_Type) loop + Update_Result (Component_Bounds (Next_Part)); + end loop; + end Update_Result_For_Full_Coverage; --------------------- -- Traverse_Choice -- @@ -1388,52 +1440,89 @@ package body Sem_Case is Refresh_Binding_Info (Aggr => Expr); declare - Comp : Node_Id := + Comp_Assoc : Node_Id := First (Component_Associations (Expr)); - -- Ok to assume that components are in order here? + -- Aggregate has been normalized (components in + -- order, only one component per choice, etc.). + + Comp_From_Type : Node_Id := + First_Component_Or_Discriminant + (Base_Type (Etype (Expr))); + + Saved_Next_Part : constant Part_Id := Next_Part; begin - while Present (Comp) loop - pragma Assert (List_Length (Choices (Comp)) = 1); - if Box_Present (Comp) then - declare - Comp_Type : constant Entity_Id := - Etype (First (Choices (Comp))); - begin - if Is_Discrete_Type (Comp_Type) then - declare - Low : constant Node_Id := - Type_Low_Bound (Comp_Type); - High : constant Node_Id := - Type_High_Bound (Comp_Type); - begin - Update_Result - ((Low => Expr_Value (Low), - High => Expr_Value (High))); - end; - else - -- Need to recursively traverse type - -- here, calling Update_Result for - -- each discrete subcomponent. + while Present (Comp_Assoc) loop + pragma Assert + (List_Length (Choices (Comp_Assoc)) = 1); - Error_Msg_N - ("box values for nondiscrete pattern " - & "subcomponents unimplemented", Comp); + declare + Comp : constant Node_Id := + Entity (First (Choices (Comp_Assoc))); + Comp_Seen : Boolean := False; + begin + loop + if Original_Record_Component (Comp) = + Original_Record_Component (Comp_From_Type) + then + Comp_Seen := True; + else + -- We have an aggregate of a type that + -- has a variant part (or has a + -- subcomponent type that has a variant + -- part) and we have to deal with a + -- component that is present in the type + -- but not in the aggregate (because the + -- component is in an inactive variant). + -- + Update_Result_For_Full_Coverage + (Comp_Type => Etype (Comp_From_Type)); end if; - end; + + Comp_From_Type := + Next_Component_Or_Discriminant + (Comp_From_Type); + + exit when Comp_Seen; + end loop; + end; + + if Box_Present (Comp_Assoc) then + -- Box matches all values + Update_Result_For_Full_Coverage + (Etype (First (Choices (Comp_Assoc)))); else - Traverse_Choice (Expression (Comp)); + Traverse_Choice (Expression (Comp_Assoc)); end if; - if Binding_Chars (Comp) /= No_Name + if Binding_Chars (Comp_Assoc) /= No_Name then Case_Bindings.Note_Binding - (Comp_Assoc => Comp, + (Comp_Assoc => Comp_Assoc, Choice => Choice, Alt => Alt); end if; - Next (Comp); + Next (Comp_Assoc); end loop; + + while Present (Comp_From_Type) loop + -- Deal with any trailing inactive-variant + -- components. + -- + -- See earlier commment about calling + -- Update_Result_For_Full_Coverage for such + -- components. + + Update_Result_For_Full_Coverage + (Comp_Type => Etype (Comp_From_Type)); + + Comp_From_Type := + Next_Component_Or_Discriminant (Comp_From_Type); + end loop; + + pragma Assert + (Nat (Next_Part - Saved_Next_Part) + = Scalar_Part_Count (Etype (Expr))); end; elsif Is_Array_Type (Etype (Expr)) then if Is_Non_Empty_List (Component_Associations (Expr)) then @@ -1477,6 +1566,8 @@ package body Sem_Case is end if; end Traverse_Choice; + -- Start of processing for Parse_Choice + begin if Nkind (Choice) = N_Others_Choice then return (Is_Others => True); @@ -1484,7 +1575,7 @@ package body Sem_Case is Traverse_Choice (Choice); -- Avoid returning uninitialized garbage in error case - if not Done then + if Next_Part /= Part_Id'Last + 1 then pragma Assert (Serious_Errors_Detected > 0); Result.Ranges := (others => (Low => Uint_1, High => Uint_0)); end if; @@ -2936,20 +3027,34 @@ package body Sem_Case is end if; Check_Component_Subtype (Component_Type (Subtyp)); elsif Is_Record_Type (Subtyp) then - if Has_Discriminants (Subtyp) then - Error_Msg_N - ("type of case selector (or subcomponent thereof) " & - "is discriminated", N); - else - declare - Comp : Entity_Id := First_Component (Subtyp); - begin - while Present (Comp) loop - Check_Component_Subtype (Etype (Comp)); - Next_Component (Comp); - end loop; - end; + + if Has_Discriminants (Subtyp) + and then Is_Constrained (Subtyp) + and then not Has_Static_Discriminant_Constraint (Subtyp) + then + -- We are only disallowing nonstatic constraints for + -- subcomponent subtypes, not for the subtype of the + -- expression we are casing on. This test could be + -- implemented via an Is_Recursive_Call parameter if + -- that seems preferable. + + if Subtyp /= Check_Choices.Subtyp then + Error_Msg_N + ("constrained discriminated subtype of case " & + "selector subcomponent has nonstatic " & + "constraint", N); + end if; end if; + + declare + Comp : Entity_Id := + First_Component_Or_Discriminant (Base_Type (Subtyp)); + begin + while Present (Comp) loop + Check_Component_Subtype (Etype (Comp)); + Next_Component_Or_Discriminant (Comp); + end loop; + end; else Error_Msg_N ("type of case selector (or subcomponent thereof) is " & @@ -3058,7 +3163,7 @@ package body Sem_Case is -- bounds of its base type to determine the values covered by the -- discrete choices. - -- In Ada 2012, if the subtype has a non-static predicate the full + -- In Ada 2012, if the subtype has a nonstatic predicate the full -- range of the base type must be covered as well. if Is_OK_Static_Subtype (Subtyp) then @@ -3075,7 +3180,7 @@ package body Sem_Case is end if; -- Obtain static bounds of type, unless this is a generic formal - -- discrete type for which all choices will be non-static. + -- discrete type for which all choices will be nonstatic. if not Is_Generic_Type (Root_Type (Bounds_Type)) or else Ekind (Bounds_Type) /= E_Enumeration_Type @@ -3137,7 +3242,7 @@ package body Sem_Case is if Has_Predicates (E) then - -- Use of non-static predicate is an error + -- Use of nonstatic predicate is an error if not Is_Discrete_Type (E) or else not Has_Static_Predicate (E) @@ -3298,6 +3403,30 @@ package body Sem_Case is end Generic_Check_Choices; + ----------------------------------------- + -- Has_Static_Discriminant_Constraint -- + ----------------------------------------- + + function Has_Static_Discriminant_Constraint + (Subtyp : Entity_Id) return Boolean + is + begin + if Has_Discriminants (Subtyp) and then Is_Constrained (Subtyp) then + declare + DC_Elmt : Elmt_Id := First_Elmt (Discriminant_Constraint (Subtyp)); + begin + while Present (DC_Elmt) loop + if not All_Composite_Constraints_Static (Node (DC_Elmt)) then + return False; + end if; + Next_Elmt (DC_Elmt); + end loop; + return True; + end; + end if; + return False; + end Has_Static_Discriminant_Constraint; + ---------------------------- -- Is_Case_Choice_Pattern -- ---------------------------- -- cgit v1.1 From 79b87fcf29cd100f15ae68bd74bf94830bf41564 Mon Sep 17 00:00:00 2001 From: Gary Dismukes Date: Mon, 14 Jun 2021 15:37:49 -0400 Subject: [Ada] Typo corrections and minor reformatting gcc/ada/ * libgnarl/s-osinte__vxworks.ads: Fix typo ("release" => "releases") plus comment reformatting. * libgnat/s-os_lib.ads: In a comment, fix typo ("indended" => "intended"), add a hyphen and semicolon, plus reformatting. In comment for subtype time_t, fix typo ("effect" => "affect"), add hyphens, plus reformatting. * libgnat/s-parame.ads, libgnat/s-parame__ae653.ads, libgnat/s-parame__hpux.ads: Remove period from one-line comment. --- gcc/ada/libgnarl/s-osinte__vxworks.ads | 6 +++--- gcc/ada/libgnat/s-os_lib.ads | 19 +++++++++---------- gcc/ada/libgnat/s-parame.ads | 2 +- gcc/ada/libgnat/s-parame__ae653.ads | 2 +- gcc/ada/libgnat/s-parame__hpux.ads | 2 +- 5 files changed, 15 insertions(+), 16 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnarl/s-osinte__vxworks.ads b/gcc/ada/libgnarl/s-osinte__vxworks.ads index 8b9c5bf..a2d5620 100644 --- a/gcc/ada/libgnarl/s-osinte__vxworks.ads +++ b/gcc/ada/libgnarl/s-osinte__vxworks.ads @@ -242,9 +242,9 @@ package System.OS_Interface is type time_t is range -2 ** (System.Parameters.time_t_bits - 1) .. 2 ** (System.Parameters.time_t_bits - 1) - 1; - -- Time_t here used to be unsigned to match the VxWorks header - -- declaration. The header declaration has changed in newer release - -- and is now signed for applications. + -- Time_t here used to be unsigned to match the VxWorks header declaration. + -- The header declaration has changed in newer releases and is now signed + -- for applications. type timespec is record ts_sec : time_t; diff --git a/gcc/ada/libgnat/s-os_lib.ads b/gcc/ada/libgnat/s-os_lib.ads index 4c279d5..2049e38 100644 --- a/gcc/ada/libgnat/s-os_lib.ads +++ b/gcc/ada/libgnat/s-os_lib.ads @@ -168,18 +168,17 @@ package System.OS_Lib is -- Time_t Stuff -- ------------------ - -- Note: Do not use time_t in the compiler and host based tools, - -- instead use OS_Time. These 3 declarations are indended for use only - -- by consumers of the GNAT.OS_Lib renaming of this package. + -- Note: Do not use time_t in the compiler and host-based tools; instead + -- use OS_Time. These 3 declarations are intended for use only by consumers + -- of the GNAT.OS_Lib renaming of this package. subtype time_t is Long_Long_Integer; - -- C time_t can be either long or long long, but this is a subtype - -- not used in the compiler or tools, but only for user - -- applications, so we choose the Ada equivalent of the latter - -- because eventually that will be the type used out of necessity. - -- This may effect some user code on 32 bit targets that have not yet - -- migrated to the Posix 2008 standard, particularly pre version 5 - -- 32 bit Linux. + -- C time_t can be either long or long long, but this is a subtype not used + -- in the compiler or tools, but only for user applications, so we choose + -- the Ada equivalent of the latter because eventually that will be the + -- type used out of necessity. This may affect some user code on 32-bit + -- targets that have not yet migrated to the Posix 2008 standard, + -- particularly pre version 5 32-bit Linux. function To_C (Time : OS_Time) return time_t; -- Convert OS_Time to C time_t type diff --git a/gcc/ada/libgnat/s-parame.ads b/gcc/ada/libgnat/s-parame.ads index 178bd7c..0f76a65 100644 --- a/gcc/ada/libgnat/s-parame.ads +++ b/gcc/ada/libgnat/s-parame.ads @@ -105,7 +105,7 @@ package System.Parameters is ------------------------------------ time_t_bits : constant := Long_Integer'Size; - -- Number of bits in type time_t. + -- Number of bits in type time_t ---------------------------------------------- -- Characteristics of types in Interfaces.C -- diff --git a/gcc/ada/libgnat/s-parame__ae653.ads b/gcc/ada/libgnat/s-parame__ae653.ads index 7682435..f838b41 100644 --- a/gcc/ada/libgnat/s-parame__ae653.ads +++ b/gcc/ada/libgnat/s-parame__ae653.ads @@ -105,7 +105,7 @@ package System.Parameters is ------------------------------------ time_t_bits : constant := Long_Integer'Size; - -- Number of bits in type time_t. + -- Number of bits in type time_t ---------------------------------------------- -- Characteristics of types in Interfaces.C -- diff --git a/gcc/ada/libgnat/s-parame__hpux.ads b/gcc/ada/libgnat/s-parame__hpux.ads index 053cd76..d6d4e10 100644 --- a/gcc/ada/libgnat/s-parame__hpux.ads +++ b/gcc/ada/libgnat/s-parame__hpux.ads @@ -103,7 +103,7 @@ package System.Parameters is ------------------------------------ time_t_bits : constant := Long_Integer'Size; - -- Number of bits in type time_t. + -- Number of bits in type time_t ---------------------------------------------- -- Characteristics of Types in Interfaces.C -- -- cgit v1.1 From 66d43665bc9c8a8f38531a8b9a02cfcfe129cc88 Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Tue, 15 Jun 2021 12:54:12 -0400 Subject: [Ada] Crash on expansion of BIP construct in -gnatf mode gcc/ada/ * exp_ch6.adb (Is_Build_In_Place_Function_Call): Add check to verify the Selector_Name of Exp_Node has been analyzed before obtaining its entity. --- gcc/ada/exp_ch6.adb | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 1c56cb8..59704a4 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -8275,6 +8275,15 @@ package body Exp_Ch6 is -- This may be a call to a protected function. elsif Nkind (Name (Exp_Node)) = N_Selected_Component then + -- The selector in question might not have been analyzed due to a + -- previous error, so analyze it here to output the appropriate + -- error message instead of crashing when attempting to fetch its + -- entity. + + if not Analyzed (Selector_Name (Name (Exp_Node))) then + Analyze (Selector_Name (Name (Exp_Node))); + end if; + Function_Id := Etype (Entity (Selector_Name (Name (Exp_Node)))); else -- cgit v1.1 From d206399a97bc0111cff30c66c535ce0884228b77 Mon Sep 17 00:00:00 2001 From: Steve Baird Date: Wed, 9 Jun 2021 07:29:11 -0700 Subject: [Ada] Improve performance of Ada.Containers.Doubly_Linked_Lists.Generic_Sorting.Sort gcc/ada/ * libgnat/a-cdlili.adb: Reimplement Ada.Containers.Doubly_Linked_Lists.Generic_Sorting.Sort using Mergesort instead of the previous Quicksort variant. --- gcc/ada/libgnat/a-cdlili.adb | 219 +++++++++++++++++++++++++++++++------------ 1 file changed, 161 insertions(+), 58 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/libgnat/a-cdlili.adb b/gcc/ada/libgnat/a-cdlili.adb index 75961a2..d989751 100644 --- a/gcc/ada/libgnat/a-cdlili.adb +++ b/gcc/ada/libgnat/a-cdlili.adb @@ -675,68 +675,152 @@ is procedure Sort (Container : in out List) is - procedure Partition (Pivot : Node_Access; Back : Node_Access); - - procedure Sort (Front, Back : Node_Access); - - --------------- - -- Partition -- - --------------- + type List_Descriptor is + record + First, Last : Node_Access; + Length : Count_Type; + end record; + + function Merge_Sort (Arg : List_Descriptor) return List_Descriptor; + -- Sort list of given length using MergeSort; length must be >= 2. + -- As required by RM, the sort is stable. + + ---------------- + -- Merge_Sort -- + ---------------- + + function Merge_Sort (Arg : List_Descriptor) return List_Descriptor + is + procedure Split_List + (Unsplit : List_Descriptor; Part1, Part2 : out List_Descriptor); + -- Split list into two parts for divide-and-conquer. + -- Unsplit.Length must be >= 2. + + function Merge_Parts + (Part1, Part2 : List_Descriptor) return List_Descriptor; + -- Merge two sorted lists, preserving sorted property. + + ---------------- + -- Split_List -- + ---------------- + + procedure Split_List + (Unsplit : List_Descriptor; Part1, Part2 : out List_Descriptor) + is + Rover : Node_Access := Unsplit.First; + Bump_Count : constant Count_Type := (Unsplit.Length - 1) / 2; + begin + for Iter in 1 .. Bump_Count loop + Rover := Rover.Next; + end loop; + + Part1 := (First => Unsplit.First, + Last => Rover, + Length => Bump_Count + 1); + + Part2 := (First => Rover.Next, + Last => Unsplit.Last, + Length => Unsplit.Length - Part1.Length); + + -- Detach + Part1.Last.Next := null; + Part2.First.Prev := null; + end Split_List; + + ----------------- + -- Merge_Parts -- + ----------------- + + function Merge_Parts + (Part1, Part2 : List_Descriptor) return List_Descriptor + is + Empty : constant List_Descriptor := (null, null, 0); + + procedure Detach_First (Source : in out List_Descriptor; + Detached : out Node_Access); + -- Detach the first element from a non-empty list and + -- return the detached node via the Detached parameter. + + ------------------ + -- Detach_First -- + ------------------ + + procedure Detach_First (Source : in out List_Descriptor; + Detached : out Node_Access) is + begin + Detached := Source.First; + + if Source.Length = 1 then + Source := Empty; + else + Source := (Source.First.Next, + Source.Last, + Source.Length - 1); + + Detached.Next.Prev := null; + Detached.Next := null; + end if; + end Detach_First; + + P1 : List_Descriptor := Part1; + P2 : List_Descriptor := Part2; + Merged : List_Descriptor := Empty; + + Take_From_P2 : Boolean; + Detached : Node_Access; + + -- Start of processing for Merge_Parts - procedure Partition (Pivot : Node_Access; Back : Node_Access) is - Node : Node_Access; + begin + while (P1.Length /= 0) or (P2.Length /= 0) loop + if P1.Length = 0 then + Take_From_P2 := True; + elsif P2.Length = 0 then + Take_From_P2 := False; + else + -- If the compared elements are equal then Take_From_P2 + -- must be False in order to ensure stability. + + Take_From_P2 := P2.First.Element < P1.First.Element; + end if; + + if Take_From_P2 then + Detach_First (P2, Detached); + else + Detach_First (P1, Detached); + end if; + + if Merged.Length = 0 then + Merged := (First | Last => Detached, Length => 1); + else + Detached.Prev := Merged.Last; + Merged.Last.Next := Detached; + Merged.Last := Detached; + Merged.Length := Merged.Length + 1; + end if; + end loop; + return Merged; + end Merge_Parts; + + -- Start of processing for Merge_Sort begin - Node := Pivot.Next; - while Node /= Back loop - if Node.Element < Pivot.Element then - declare - Prev : constant Node_Access := Node.Prev; - Next : constant Node_Access := Node.Next; - - begin - Prev.Next := Next; - - if Next = null then - Container.Last := Prev; - else - Next.Prev := Prev; - end if; - - Node.Next := Pivot; - Node.Prev := Pivot.Prev; - - Pivot.Prev := Node; - - if Node.Prev = null then - Container.First := Node; - else - Node.Prev.Next := Node; - end if; - - Node := Next; - end; + if Arg.Length < 2 then + -- already sorted + return Arg; + end if; - else - Node := Node.Next; - end if; - end loop; - end Partition; + declare + Part1, Part2 : List_Descriptor; + begin + Split_List (Unsplit => Arg, Part1 => Part1, Part2 => Part2); - ---------- - -- Sort -- - ---------- + Part1 := Merge_Sort (Part1); + Part2 := Merge_Sort (Part2); - procedure Sort (Front, Back : Node_Access) is - Pivot : constant Node_Access := - (if Front = null then Container.First else Front.Next); - begin - if Pivot /= Back then - Partition (Pivot, Back); - Sort (Front, Pivot); - Sort (Pivot, Back); - end if; - end Sort; + return Merge_Parts (Part1, Part2); + end; + end Merge_Sort; -- Start of processing for Sort @@ -754,9 +838,28 @@ is -- element tampering by a generic actual subprogram. declare - Lock : With_Lock (Container.TC'Unchecked_Access); + Lock : With_Lock (Container.TC'Unchecked_Access); + + Unsorted : constant List_Descriptor := + (First => Container.First, + Last => Container.Last, + Length => Container.Length); + + Sorted : List_Descriptor; begin - Sort (Front => null, Back => null); + -- If a call to the formal < operator references the container + -- during sorting, seeing an empty container seems preferable + -- to seeing an internally inconsistent container. + -- + Container.First := null; + Container.Last := null; + Container.Length := 0; + + Sorted := Merge_Sort (Unsorted); + + Container.First := Sorted.First; + Container.Last := Sorted.Last; + Container.Length := Sorted.Length; end; pragma Assert (Container.First.Prev = null); -- cgit v1.1 From bb66a1021527ab68975a02cc3359c71c69ce443b Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Sun, 13 Jun 2021 08:42:54 +0600 Subject: [Ada] Add missed OS constant values gcc/ada/ * gsocket.h: Include net/if.h to get IF_NAMESIZE constant. * s-oscons-tmplt.c: Define IPV6_FLOWINFO for Linux. --- gcc/ada/gsocket.h | 1 + gcc/ada/s-oscons-tmplt.c | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/gsocket.h b/gcc/ada/gsocket.h index eb6e6d9..a987594 100644 --- a/gcc/ada/gsocket.h +++ b/gcc/ada/gsocket.h @@ -215,6 +215,7 @@ #if !(defined (VMS) || defined (__MINGW32__)) #include #include +#include #include #include #include diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c index f373c39..54fa2f1 100644 --- a/gcc/ada/s-oscons-tmplt.c +++ b/gcc/ada/s-oscons-tmplt.c @@ -1689,8 +1689,14 @@ CND(IPV6_DSTOPTS, "Set the destination options delivery") CND(IPV6_HOPOPTS, "Set the hop options delivery") #ifndef IPV6_FLOWINFO +#ifdef __linux__ +/* The IPV6_FLOWINFO is defined in linux/in6.h, but we can't include it because + * of conflicts with other headers. */ +# define IPV6_FLOWINFO 11 +#else # define IPV6_FLOWINFO -1 #endif +#endif CND(IPV6_FLOWINFO, "Set the flow ID delivery") #ifndef IPV6_HOPLIMIT -- cgit v1.1 From f377685e3d82193b0f69bb0742e7f470f63532b2 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Tue, 15 Jun 2021 15:36:34 -0400 Subject: [Ada] Fix crash on type extensions with discriminants gcc/ada/ * exp_put_image.adb (Make_Component_Attributes): Use Implementation_Base_Type to get the parent type. Otherwise, Parent_Type_Decl is actually an internally generated subtype declaration, so we blow up on Type_Definition (Parent_Type_Decl). --- gcc/ada/exp_put_image.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_put_image.adb b/gcc/ada/exp_put_image.adb index 082e08b..87f4b74 100644 --- a/gcc/ada/exp_put_image.adb +++ b/gcc/ada/exp_put_image.adb @@ -658,8 +658,8 @@ package body Exp_Put_Image is if Chars (Defining_Identifier (Item)) = Name_uParent then declare Parent_Type : constant Entity_Id := - Underlying_Type (Base_Type ( - (Etype (Defining_Identifier (Item))))); + Implementation_Base_Type + (Etype (Defining_Identifier (Item))); Parent_Aspect_Spec : constant Node_Id := Find_Aspect (Parent_Type, Aspect_Put_Image); -- cgit v1.1 From d35d546a7fcaf7e48e8d15abb8428d1e0b618948 Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Thu, 17 Jun 2021 10:01:33 +0200 Subject: [Ada] par-ch6: do not mark subprogram as missing "is" if imported gcc/ada/ * par-ch6.adb (Contains_Import_Aspect): New function. (P_Subprogram): Acknowledge `Import` aspects. --- gcc/ada/par-ch6.adb | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb index e3b3155..be85d09 100644 --- a/gcc/ada/par-ch6.adb +++ b/gcc/ada/par-ch6.adb @@ -201,6 +201,28 @@ package body Ch6 is -- Error recovery: cannot raise Error_Resync function P_Subprogram (Pf_Flags : Pf_Rec) return Node_Id is + + function Contains_Import_Aspect (Aspects : List_Id) return Boolean; + -- Return True if Aspects contains an Import aspect. + + ---------------------------- + -- Contains_Import_Aspect -- + ---------------------------- + + function Contains_Import_Aspect (Aspects : List_Id) return Boolean is + Aspect : Node_Id := First (Aspects); + begin + while Present (Aspect) loop + if Chars (Identifier (Aspect)) = Name_Import then + return True; + end if; + + Next (Aspect); + end loop; + + return False; + end Contains_Import_Aspect; + Specification_Node : Node_Id; Name_Node : Node_Id; Aspects : List_Id; @@ -982,10 +1004,12 @@ package body Ch6 is if Pf_Flags.Pbod -- Disconnect this processing if we have scanned a null procedure - -- because in this case the spec is complete anyway with no body. + -- or an Import aspect because in this case the spec is complete + -- anyway with no body. and then (Nkind (Specification_Node) /= N_Procedure_Specification or else not Null_Present (Specification_Node)) + and then not Contains_Import_Aspect (Aspects) then SIS_Labl := Scopes (Scope.Last).Labl; SIS_Sloc := Scopes (Scope.Last).Sloc; -- cgit v1.1 From 7802ee7b0181dcd4e4c40047d67a1b2a6cf06a57 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Thu, 17 Jun 2021 18:46:21 +0200 Subject: [Ada] Fix style in expansion of attribute Put_Image gcc/ada/ * exp_put_image.adb (Make_Put_Image_Name): Fix style. (Image_Should_Call_Put_Image): Likewise. (Build_Image_Call): Likewise. --- gcc/ada/exp_put_image.adb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/exp_put_image.adb b/gcc/ada/exp_put_image.adb index 87f4b74..90a542d 100644 --- a/gcc/ada/exp_put_image.adb +++ b/gcc/ada/exp_put_image.adb @@ -1005,9 +1005,9 @@ package body Exp_Put_Image is return True; end Enable_Put_Image; - --------------------------------- + ------------------------- -- Make_Put_Image_Name -- - --------------------------------- + ------------------------- function Make_Put_Image_Name (Loc : Source_Ptr; Typ : Entity_Id) return Entity_Id @@ -1028,6 +1028,10 @@ package body Exp_Put_Image is return Make_Defining_Identifier (Loc, Sname); end Make_Put_Image_Name; + --------------------------------- + -- Image_Should_Call_Put_Image -- + --------------------------------- + function Image_Should_Call_Put_Image (N : Node_Id) return Boolean is begin if Ada_Version < Ada_2022 then @@ -1049,6 +1053,10 @@ package body Exp_Put_Image is end; end Image_Should_Call_Put_Image; + ---------------------- + -- Build_Image_Call -- + ---------------------- + function Build_Image_Call (N : Node_Id) return Node_Id is -- For T'Image (X) Generate an Expression_With_Actions node: -- -- cgit v1.1 From f53e66019df819f55d424cc56f8b0ea81c074b55 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 9 Jul 2021 10:20:22 -0400 Subject: c++: find_template_parameters and TEMPLATE_DECLs [PR101247] r12-1989 fixed the testcase in the PR, but unfortunately the fix is buggy: it breaks the case where the common template between the TEMPLATE_DECL t and ctx_parms is the innermost template (as in concepts-memtmpl5.C below). This can be fixed by instead passing the TREE_TYPE of ctmpl to common_enclosing_class when ctmpl is a class template. But even after that's fixed, the analogous case where the innermost template is a partial specialization is still broken (as in concepts-memtmpl5a.C below), because ctmpl is always a primary template. So this patch instead takes a diferent approach that doesn't rely on ctx_parms at all: when looking for the template parameters of a TEMPLATE_DECL that are shared with the current template context, just walk its DECL_CONTEXT. As long as the template is not overly general (e.g. we didn't pass it through most_general_template), this should give us exactly what we want, since if a TEMPLATE_DECL can be referred to from some template context then the template parameters it uses must all be in-scope and contained in its DECL_CONTEXT. This effectively makes us treat TEMPLATE_DECLs more similarly to other _DECLs (whose DECL_CONTEXT we also walk). PR c++/101247 gcc/cp/ChangeLog: * pt.c (any_template_parm_r) : Just walk the DECL_CONTEXT. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-memtmpl4.C: Uncomment the commented out example, which we now handle correctly. * g++.dg/cpp2a/concepts-memtmpl5.C: New test. * g++.dg/cpp2a/concepts-memtmpl5a.C: New test. --- gcc/cp/pt.c | 14 +++++--------- gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl5.C | 11 +++++++++++ gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl5a.C | 15 +++++++++++++++ 4 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl5.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl5a.C (limited to 'gcc') diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7e56ccf..dc0f0b7 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10728,15 +10728,11 @@ any_template_parm_r (tree t, void *data) break; case TEMPLATE_DECL: - { - /* If T is a member template that shares template parameters with - ctx_parms, we need to mark all those parameters for mapping. */ - if (tree ctmpl = TREE_TYPE (INNERMOST_TEMPLATE_PARMS (ftpi->ctx_parms))) - if (tree com = common_enclosing_class (DECL_CONTEXT (t), - DECL_CONTEXT (ctmpl))) - if (tree ti = CLASSTYPE_TEMPLATE_INFO (com)) - WALK_SUBTREE (TI_ARGS (ti)); - } + /* If T is a member template that shares template parameters with + ctx_parms, we need to mark all those parameters for mapping. + To that end, it should suffice to just walk the DECL_CONTEXT of + the template (assuming the template is not overly general). */ + WALK_SUBTREE (DECL_CONTEXT (t)); break; case LAMBDA_EXPR: diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C index 625149e..f990ae1 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C @@ -24,5 +24,5 @@ int main() { A::B::f(0); A::C::f(0); - // A::C::g(); + A::C::g(); } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl5.C new file mode 100644 index 0000000..3c83bb8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl5.C @@ -0,0 +1,11 @@ +// PR c++/101247 +// { dg-do compile { target concepts } } + +template struct A { + template static constexpr bool d = true; + static void g() requires d; +}; + +int main() { + A::g(); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl5a.C b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl5a.C new file mode 100644 index 0000000..458f1cd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl5a.C @@ -0,0 +1,15 @@ +// PR c++/101247 +// { dg-do compile { target concepts } } +// A variant of concepts-memtmpl5.C that uses a partial specialization +// of A instead of the primary template. + +template struct A; + +template requires true struct A { + template static constexpr bool d = true; + static void g() requires d; +}; + +int main() { + A::g(); +} -- cgit v1.1 From 2c699fd29829cd6115f78238dab7cab74f0a5009 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 9 Jul 2021 10:20:25 -0400 Subject: c++: requires-expr with dependent extra args [PR101181] Here we're crashing ultimately because the mechanism for delaying substitution into a requires-expression (and constexpr if and pack expansions) doesn't expect to see dependent args. But we end up capturing dependent args here during substitution into the default template argument as part of coerce_template_parms for the dependent specialization p. This patch enables the commented out code in add_extra_args for handling this situation. This isn't needed for pack expansions (as the accompanying comment points out), and it doesn't seem strictly necessary for constexpr if either, but for requires-expressions delaying even dependent substitution is important for ensuring we don't evaluate requirements out of order. It turns out we also need to make a copy of the arguments when capturing them so that coerce_template_parms doesn't later add to them and form an unexpected cycle (REQUIRES_EXPR_EXTRA_ARGS (t) would indirectly point to t). We also need to make tsubst_template_args handle missing template arguments, since the arguments we capture from coerce_template_parms and are incomplete at that point. PR c++/101181 gcc/cp/ChangeLog: * constraint.cc (tsubst_requires_expr): Pass complain/in_decl to add_extra_args. * cp-tree.h (add_extra_args): Add complain/in_decl parameters. * pt.c (build_extra_args): Make a copy of args. (add_extra_args): Add complain/in_decl parameters. Enable the code for handling the case where the extra arguments are dependent. (tsubst_pack_expansion): Pass complain/in_decl to add_extra_args. (tsubst_template_args): Handle missing template arguments. (tsubst_expr) : Pass complain/in_decl to add_extra_args. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-requires26.C: New test. * g++.dg/cpp2a/lambda-uneval16.C: New test. --- gcc/cp/constraint.cc | 3 ++- gcc/cp/cp-tree.h | 2 +- gcc/cp/pt.c | 31 ++++++++++++------------ gcc/testsuite/g++.dg/cpp2a/concepts-requires26.C | 18 ++++++++++++++ gcc/testsuite/g++.dg/cpp2a/lambda-uneval16.C | 22 +++++++++++++++++ 5 files changed, 58 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-requires26.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval16.C (limited to 'gcc') diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 99d3ccc..4ee5215 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -2266,7 +2266,8 @@ tsubst_requires_expr (tree t, tree args, sat_info info) /* A requires-expression is an unevaluated context. */ cp_unevaluated u; - args = add_extra_args (REQUIRES_EXPR_EXTRA_ARGS (t), args); + args = add_extra_args (REQUIRES_EXPR_EXTRA_ARGS (t), args, + info.complain, info.in_decl); if (processing_template_decl) { /* We're partially instantiating a generic lambda. Substituting into diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d4810c0..b1cf44e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7291,7 +7291,7 @@ extern void add_mergeable_specialization (bool is_decl, bool is_alias, tree outer, unsigned); extern tree add_to_template_args (tree, tree); extern tree add_outermost_template_args (tree, tree); -extern tree add_extra_args (tree, tree); +extern tree add_extra_args (tree, tree, tsubst_flags_t, tree); extern tree build_extra_args (tree, tree, tsubst_flags_t); /* in rtti.c */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index dc0f0b7..cf0ce77 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12907,7 +12907,9 @@ extract_local_specs (tree pattern, tsubst_flags_t complain) tree build_extra_args (tree pattern, tree args, tsubst_flags_t complain) { - tree extra = args; + /* Make a copy of the extra arguments so that they won't get changed + out from under us. */ + tree extra = copy_template_args (args); if (local_specializations) if (tree locals = extract_local_specs (pattern, complain)) extra = tree_cons (NULL_TREE, extra, locals); @@ -12918,7 +12920,7 @@ build_extra_args (tree pattern, tree args, tsubst_flags_t complain) normal template args to ARGS. */ tree -add_extra_args (tree extra, tree args) +add_extra_args (tree extra, tree args, tsubst_flags_t complain, tree in_decl) { if (extra && TREE_CODE (extra) == TREE_LIST) { @@ -12938,20 +12940,14 @@ add_extra_args (tree extra, tree args) gcc_assert (!TREE_PURPOSE (extra)); extra = TREE_VALUE (extra); } -#if 1 - /* I think we should always be able to substitute dependent args into the - pattern. If that turns out to be incorrect in some cases, enable the - alternate code (and add complain/in_decl parms to this function). */ - gcc_checking_assert (!uses_template_parms (extra)); -#else - if (!uses_template_parms (extra)) + if (uses_template_parms (extra)) { - gcc_unreachable (); + /* This can happen after dependent substitution into a + requires-expr or a lambda that uses constexpr if. */ extra = tsubst_template_args (extra, args, complain, in_decl); args = add_outermost_template_args (args, extra); } else -#endif args = add_to_template_args (extra, args); return args; } @@ -12977,7 +12973,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, pattern = PACK_EXPANSION_PATTERN (t); /* Add in any args remembered from an earlier partial instantiation. */ - args = add_extra_args (PACK_EXPANSION_EXTRA_ARGS (t), args); + args = add_extra_args (PACK_EXPANSION_EXTRA_ARGS (t), args, complain, in_decl); levels = TMPL_ARGS_DEPTH (args); @@ -13349,7 +13345,9 @@ tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl) tree orig_arg = TREE_VEC_ELT (t, i); tree new_arg; - if (TREE_CODE (orig_arg) == TREE_VEC) + if (!orig_arg) + new_arg = NULL_TREE; + else if (TREE_CODE (orig_arg) == TREE_VEC) new_arg = tsubst_template_args (orig_arg, args, complain, in_decl); else if (PACK_EXPANSION_P (orig_arg)) { @@ -13399,8 +13397,9 @@ tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl) } for (i = 0, out = 0; i < len; i++) { - if ((PACK_EXPANSION_P (TREE_VEC_ELT (orig_t, i)) - || ARGUMENT_PACK_P (TREE_VEC_ELT (orig_t, i))) + tree orig_arg = TREE_VEC_ELT (orig_t, i); + if (orig_arg + && (PACK_EXPANSION_P (orig_arg) || ARGUMENT_PACK_P (orig_arg)) && TREE_CODE (elts[i]) == TREE_VEC) { int idx; @@ -18428,7 +18427,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, IF_STMT_CONSTEXPR_P (stmt) = IF_STMT_CONSTEXPR_P (t); IF_STMT_CONSTEVAL_P (stmt) = IF_STMT_CONSTEVAL_P (t); if (IF_STMT_CONSTEXPR_P (t)) - args = add_extra_args (IF_STMT_EXTRA_ARGS (t), args); + args = add_extra_args (IF_STMT_EXTRA_ARGS (t), args, complain, in_decl); tmp = RECUR (IF_COND (t)); tmp = finish_if_stmt_cond (tmp, stmt); if (IF_STMT_CONSTEXPR_P (t) diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires26.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires26.C new file mode 100644 index 0000000..824d234 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires26.C @@ -0,0 +1,18 @@ +// PR c++/101181 +// { dg-do compile { target c++20 } } + +template +struct p { using type = void; }; + +template +struct p { using type = typename T::type; }; + +template using P = typename p::type; + +using type1 = P; +using type1 = void; + +struct A { using type = char; }; +using type2 = P; +using type2 = char; diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval16.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval16.C new file mode 100644 index 0000000..1113c6f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval16.C @@ -0,0 +1,22 @@ +// PR c++/101181 +// { dg-do compile { target c++20 } } + +template bool { + if constexpr (requires { typename T::type; }) + return true; + return false; + }()> +struct p { using type = void; }; + +template +struct p { using type = typename T::type; }; + +template using P = typename p::type; + +using type1 = P; +using type = void; + +struct A { using type = char; }; +using type2 = P; +using type2 = char; -- cgit v1.1 From 37e65643d3e32d33bb6c9d15c678a627d1682626 Mon Sep 17 00:00:00 2001 From: Indu Bhagat Date: Fri, 9 Jul 2021 09:03:08 -0700 Subject: testsuite/101269: fix testcase when used with -m32 PR testsuite/101269 - new test case gcc.dg/debug/btf/btf-datasec-1.c fails with its introduction in r12-1852 BTF datasec records for .rodata/.data are expected for now for all targets. For powerpc based targets, use -msdata=none when ilp32 is enabled. 2021-07-09 Indu Bhagat gcc/testsuite/ChangeLog: PR testsuite/101269 * gcc.dg/debug/btf/btf-datasec-1.c: Force -msdata=none with ilp32 for powerpc based targets. --- gcc/testsuite/gcc.dg/debug/btf/btf-datasec-1.c | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-datasec-1.c b/gcc/testsuite/gcc.dg/debug/btf/btf-datasec-1.c index 88ae4c4..f809d93 100644 --- a/gcc/testsuite/gcc.dg/debug/btf/btf-datasec-1.c +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-datasec-1.c @@ -11,6 +11,7 @@ /* { dg-do compile ) */ /* { dg-options "-O0 -gbtf -dA" } */ +/* { dg-options "-O0 -gbtf -dA -msdata=none" { target { { powerpc*-*-* } && ilp32 } } } */ /* Check for two DATASEC entries with vlen 3, and one with vlen 1. */ /* { dg-final { scan-assembler-times "0xf000003\[\t \]+\[^\n\]*btt_info" 2 } } */ -- cgit v1.1 From 511cec029c6592ee553d9087d8b2bbf7719cf30d Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 9 Jul 2021 18:30:54 +0200 Subject: Missing piece in earlier change gcc/ada/ * gcc-interface/utils.c (finish_subprog_decl): Remove obsolete line. --- gcc/ada/gcc-interface/utils.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 982274c..535f4ca 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -3543,9 +3543,6 @@ finish_subprog_decl (tree decl, tree asm_name, tree type) DECL_BY_REFERENCE (result_decl) = TREE_ADDRESSABLE (type); DECL_RESULT (decl) = result_decl; - /* Propagate the "const" property. */ - TREE_READONLY (decl) = TYPE_READONLY (type); - /* Propagate the "pure" property. */ DECL_PURE_P (decl) = TYPE_RESTRICT (type); -- cgit v1.1 From 41bd1b190358fce213f5add8396faf14a32d5c23 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Mon, 3 May 2021 08:22:53 +0100 Subject: Darwin, X86: Adjust call clobbers to allow for lazy-binding [PR 100152]. We allow public functions defined in a TU to bind locally for PIC code (the default) on 64bit Mach-O. If such functions are not inlined, we cannot tell at compile-time if they might be called via the lazy symbol resolver (this can depend on options given at link-time). Therefore, we must assume that the lazy resolver could be used which clobbers R11 and R10. Signed-off-by: Iain Sandoe gcc/ChangeLog: PR target/100152 * config/i386/i386-expand.c (ix86_expand_call): If a call is to a non-local-binding, or local but to a public symbol, then assume that it might be indirected via the lazy symbol binder. Mark R10 and R10 as clobbered in that case. --- gcc/config/i386/i386-expand.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index 65764ad..69ea79e 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -8410,6 +8410,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, pop = NULL; gcc_assert (!TARGET_64BIT || !pop); + rtx addr = XEXP (fnaddr, 0); if (TARGET_MACHO && !TARGET_64BIT) { #if TARGET_MACHO @@ -8422,7 +8423,6 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, /* Static functions and indirect calls don't need the pic register. Also, check if PLT was explicitly avoided via no-plt or "noplt" attribute, making it an indirect call. */ - rtx addr = XEXP (fnaddr, 0); if (flag_pic && GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (addr)) @@ -8585,6 +8585,20 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, } } + if (TARGET_MACHO && TARGET_64BIT && !sibcall + && ((GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (addr)) + || !fndecl || TREE_PUBLIC (fndecl))) + { + /* We allow public functions defined in a TU to bind locally for PIC + code (the default) on 64bit Mach-O. + If such functions are not inlined, we cannot tell at compile-time if + they will be called via the lazy symbol resolver (this can depend on + options given at link-time). Therefore, we must assume that the lazy + resolver could be used which clobbers R11 and R10. */ + clobber_reg (&use, gen_rtx_REG (DImode, R11_REG)); + clobber_reg (&use, gen_rtx_REG (DImode, R10_REG)); + } + if (vec_len > 1) call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (vec_len, vec)); rtx_insn *call_insn = emit_call_insn (call); -- cgit v1.1 From 0d5db79a61af150cba48612c9fbc3267262adb93 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Wed, 23 Jun 2021 08:13:22 +0100 Subject: coroutines: Fix a typo in rewriting the function. When amending the function re-write code, I made a typo in the block connections. This has not shown up in any test fails (as far as can be seen) but is a regression in debug info. Fixed thus. Signed-off-by: Iain Sandoe gcc/cp/ChangeLog: * coroutines.cc (coro_rewrite_function_body): Connect the replacement function block to the block nest correctly. --- gcc/cp/coroutines.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index a1b0b31..f5ae2d6 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -4055,8 +4055,8 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig, BIND_EXPR_BLOCK (first) = replace_blk; /* The top block has one child, so far, and we have now got a superblock. */ - BLOCK_SUPERCONTEXT (block) = top_block; - BLOCK_SUBBLOCKS (top_block) = block; + BLOCK_SUPERCONTEXT (replace_blk) = top_block; + BLOCK_SUBBLOCKS (top_block) = replace_blk; } /* Wrap the function body in a try {} catch (...) {} block, if exceptions -- cgit v1.1 From 59045273cc648e354ba72f9188f69927f00802e2 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Fri, 9 Jul 2021 17:45:40 +0100 Subject: Improvement to signed division of integer constant on x86_64. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch tweaks the way GCC handles 32-bit integer division on x86_64, when the numerator is constant. Currently the function int foo (int x) { return 100/x; } generates the code: foo: movl $100, %eax cltd idivl %edi ret where the sign-extension instruction "cltd" creates a long dependency chain, as it depends on the "mov" before it, and is depended upon by "idivl" after it. With this patch, GCC now matches both icc and LLVM and uses an xor instead, generating: foo: xorl %edx, %edx movl $100, %eax idivl %edi ret Microbenchmarking confirms that this is faster on Intel processors (Kaby lake), and no worse on AMD processors (Zen2), which agrees with intuition, but oddly disagrees with the llvm-mca cycle count prediction on godbolt.org. The tricky bit is that this sign-extension instruction is only produced by late (postreload) splitting, and unfortunately none of the subsequent passes (e.g. cprop_hardreg) is able to propagate and simplify its constant argument. The solution here is to introduce a define_insn_and_split that allows the constant numerator operand to be captured (by combine) and then split into an optimal form after reload. The above microbenchmarking also shows that eliminating the sign extension of negative values (using movl $-1,%edx) is also a performance improvement, as performed by icc but not by LLVM. Both the xor and movl sign-extensions are larger than cltd, so this transformation is prevented for -Os. 2021-07-09 Roger Sayle Uroš Bizjak gcc/ChangeLog * config/i386/i386.md (*divmodsi4_const): Optimize SImode divmod of a constant numerator with new define_insn_and_split. gcc/testsuite/ChangeLog * gcc.target/i386/divmod-9.c: New test case. --- gcc/config/i386/i386.md | 27 ++++++++++++++++++++++++++- gcc/testsuite/gcc.target/i386/divmod-9.c | 14 ++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/divmod-9.c (limited to 'gcc') diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 26fb81b..8b809c4 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -8385,7 +8385,7 @@ (ashiftrt:SWIM248 (match_dup 4) (match_dup 5))) (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_dup 0) - (div:SWIM248 (match_dup 2) (match_dup 3))) + (div:SWIM248 (match_dup 2) (match_dup 3))) (set (match_dup 1) (mod:SWIM248 (match_dup 2) (match_dup 3))) (use (match_dup 1)) @@ -8661,6 +8661,31 @@ [(set_attr "type" "idiv") (set_attr "mode" "SI")]) +;; Avoid sign-extension (using cdq) for constant numerators. +(define_insn_and_split "*divmodsi4_const" + [(set (match_operand:SI 0 "register_operand" "=&a") + (div:SI (match_operand:SI 2 "const_int_operand" "n") + (match_operand:SI 3 "nonimmediate_operand" "rm"))) + (set (match_operand:SI 1 "register_operand" "=&d") + (mod:SI (match_dup 2) (match_dup 3))) + (clobber (reg:CC FLAGS_REG))] + "!optimize_function_for_size_p (cfun)" + "#" + "reload_completed" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 1) (match_dup 4)) + (parallel [(set (match_dup 0) + (div:SI (match_dup 0) (match_dup 3))) + (set (match_dup 1) + (mod:SI (match_dup 0) (match_dup 3))) + (use (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] +{ + operands[4] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx; +} + [(set_attr "type" "multi") + (set_attr "mode" "SI")]) + (define_expand "divmodqi4" [(parallel [(set (match_operand:QI 0 "register_operand") (div:QI diff --git a/gcc/testsuite/gcc.target/i386/divmod-9.c b/gcc/testsuite/gcc.target/i386/divmod-9.c new file mode 100644 index 0000000..1515e69 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/divmod-9.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int foo (int x) +{ + return 100/x; +} + +int bar(int x) +{ + return -100/x; +} +/* { dg-final { scan-assembler-not "(cltd|cdq)" } } */ + -- cgit v1.1 From d5b1bb0d197f9141a0f0e510f8d1b598c3df9552 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Wed, 7 Jul 2021 19:56:20 +0100 Subject: coroutines: Factor code. Match original source location in helpers [NFC]. This is primarily a source code refactoring, the only change is to ensure that the outlined functions are marked to begin at the same line as the original. Otherwise, they get the default (which seems to be input_location, which corresponds to the closing brace at the point that this is done). Having the source location point to that confuses some debuggers. This is a contributory fix to: PR c++/99215 - coroutines: debugging with gdb Signed-off-by: Iain Sandoe gcc/cp/ChangeLog: * coroutines.cc (build_actor_fn): Move common code to act_des_fn. (build_destroy_fn): Likewise. (act_des_fn): Build the void return here. Ensure that the source location matches the original function. --- gcc/cp/coroutines.cc | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index f5ae2d6..54ffdc8 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -2155,13 +2155,6 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody, /* One param, the coro frame pointer. */ tree actor_fp = DECL_ARGUMENTS (actor); - /* A void return. */ - tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node); - DECL_ARTIFICIAL (resdecl) = 1; - DECL_IGNORED_P (resdecl) = 1; - DECL_RESULT (actor) = resdecl; - DECL_COROUTINE_P (actor) = 1; - /* We have a definition here. */ TREE_STATIC (actor) = 1; @@ -2532,15 +2525,8 @@ build_destroy_fn (location_t loc, tree coro_frame_type, tree destroy, /* One param, the coro frame pointer. */ tree destr_fp = DECL_ARGUMENTS (destroy); - /* A void return. */ - tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node); - DECL_ARTIFICIAL (resdecl) = 1; - DECL_IGNORED_P (resdecl) = 1; - DECL_RESULT (destroy) = resdecl; - /* We have a definition here. */ TREE_STATIC (destroy) = 1; - DECL_COROUTINE_P (destroy) = 1; tree destr_outer = push_stmt_list (); current_stmt_tree ()->stmts_are_full_exprs_p = 1; @@ -4000,15 +3986,19 @@ static tree act_des_fn (tree orig, tree fn_type, tree coro_frame_ptr, const char* name) { tree fn_name = get_fn_local_identifier (orig, name); + location_t loc = DECL_SOURCE_LOCATION (orig); tree fn = build_lang_decl (FUNCTION_DECL, fn_name, fn_type); DECL_CONTEXT (fn) = DECL_CONTEXT (orig); + DECL_SOURCE_LOCATION (fn) = loc; DECL_ARTIFICIAL (fn) = true; DECL_INITIAL (fn) = error_mark_node; + tree id = get_identifier ("frame_ptr"); tree fp = build_lang_decl (PARM_DECL, id, coro_frame_ptr); DECL_CONTEXT (fp) = fn; DECL_ARG_TYPE (fp) = type_passed_as (coro_frame_ptr); DECL_ARGUMENTS (fn) = fp; + /* Copy selected attributes from the original function. */ TREE_USED (fn) = TREE_USED (orig); if (DECL_SECTION_NAME (orig)) @@ -4020,6 +4010,17 @@ act_des_fn (tree orig, tree fn_type, tree coro_frame_ptr, const char* name) DECL_USER_ALIGN (fn) = DECL_USER_ALIGN (orig); /* Apply attributes from the original fn. */ DECL_ATTRIBUTES (fn) = copy_list (DECL_ATTRIBUTES (orig)); + + /* A void return. */ + tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node); + DECL_CONTEXT (resdecl) = fn; + DECL_ARTIFICIAL (resdecl) = 1; + DECL_IGNORED_P (resdecl) = 1; + DECL_RESULT (fn) = resdecl; + + /* This is a coroutine component. */ + DECL_COROUTINE_P (fn) = 1; + return fn; } -- cgit v1.1 From ddd25bd1a7c8f456bc914e34b77d43f39a1062d4 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 9 Jul 2021 13:50:01 -0400 Subject: c++: concepts TS and explicit specialization [PR101098] duplicate_decls was not recognizing the explicit specialization as matching the implicit specialization of g because function_requirements_equivalent_p was seeing the C constraint on the implicit one and not on the explicit. PR c++/101098 gcc/cp/ChangeLog: * decl.c (function_requirements_equivalent_p): Only compare trailing requirements on a specialization. gcc/testsuite/ChangeLog: * g++.dg/concepts/explicit-spec1.C: New test. --- gcc/cp/decl.c | 4 +++- gcc/testsuite/g++.dg/concepts/explicit-spec1.C | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/concepts/explicit-spec1.C (limited to 'gcc') diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index ebe1318..0df689b 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -955,7 +955,9 @@ static bool function_requirements_equivalent_p (tree newfn, tree oldfn) { /* In the concepts TS, the combined constraints are compared. */ - if (cxx_dialect < cxx20) + if (cxx_dialect < cxx20 + && (DECL_TEMPLATE_SPECIALIZATION (newfn) + <= DECL_TEMPLATE_SPECIALIZATION (oldfn))) { tree ci1 = get_constraints (oldfn); tree ci2 = get_constraints (newfn); diff --git a/gcc/testsuite/g++.dg/concepts/explicit-spec1.C b/gcc/testsuite/g++.dg/concepts/explicit-spec1.C new file mode 100644 index 0000000..d9b6b3d --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/explicit-spec1.C @@ -0,0 +1,9 @@ +// PR c++/101098 +// { dg-do compile { target concepts } } + +template concept C = __is_class(T); +struct Y { int n; } y; +template void g(T) { } +int called; +template<> void g(Y) { called = 3; } +int main() { g(y); } -- cgit v1.1 From ef2ace642a1ba795235c542b728cb83c73dfce74 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 10 Jul 2021 00:16:53 +0000 Subject: Daily bump. --- gcc/ChangeLog | 64 ++++++++++++ gcc/DATESTAMP | 2 +- gcc/ada/ChangeLog | 251 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/cp/ChangeLog | 42 ++++++++ gcc/testsuite/ChangeLog | 58 +++++++++++ 5 files changed, 416 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 48bb23c..6e6aaf0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,67 @@ +2021-07-09 Roger Sayle + Uroš Bizjak + + * config/i386/i386.md (*divmodsi4_const): Optimize SImode + divmod of a constant numerator with new define_insn_and_split. + +2021-07-09 Iain Sandoe + + PR target/100152 + * config/i386/i386-expand.c (ix86_expand_call): If a call is + to a non-local-binding, or local but to a public symbol, then + assume that it might be indirected via the lazy symbol binder. + Mark R10 and R10 as clobbered in that case. + +2021-07-09 Eric Botcazou + + PR target/101377 + * gcc.c (ASM_DEBUG_DWARF_OPTION): Set again to --gdwarf2 in + the case where HAVE_AS_WORKING_DWARF_N_FLAG is not defined + and HAVE_LD_BROKEN_PE_DWARF5 is defined. + +2021-07-09 Uroš Bizjak + + * config/i386/i386.md (*udivmodsi4_pow2_zext_1): Limit the + log2 range of operands[3] to [1,31]. + (*udivmodsi4_pow2_zext_2): Ditto. Correct insn RTX pattern. + +2021-07-09 Sergei Trofimovich + + * doc/md.texi: Don't split @smallexample in multiple @groups. + +2021-07-09 Sergei Trofimovich + + * doc/md.texi: Add missing 'see' word. + +2021-07-09 Andrew Pinski + + * tree-ssa-phiopt.c (phiopt_early_allow): Change arguments + to take sequence and gimple_match_op. Accept the case where + op is a SSA_NAME and one statement in the sequence. + Also allow constants. + (gimple_simplify_phiopt): Always pass a sequence to resimplify. + Update call to phiopt_early_allow. Discard the sequence if not + used. + +2021-07-09 Xi Ruoyao + + PR target/100760 + PR target/100761 + PR target/100762 + * config/mips/mips.c (mips_const_insns): Use MSA_SUPPORTED_MODE_P + instead of ISA_HAS_MSA. + (mips_expand_vec_unpack): Likewise. + (mips_expand_vector_init): Likewise. + +2021-07-09 Kewen Lin + + * config/rs6000/vsx.md (mods_): Rename to... + (mod3): ... this. + (modu_): Rename to... + (umod3): ... this. + * config/rs6000/rs6000-builtin.def (MODS_V2DI, MODS_V4SI, MODU_V2DI, + MODU_V4SI): Adjust. + 2021-07-08 Jeff Law * config/h8300/shiftrotate.md (variable shifts): Expose condition diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 23a1b25..1d7b87f 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210709 +20210710 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e513e5b..9b5629c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,254 @@ +2021-07-09 Eric Botcazou + + * gcc-interface/utils.c (finish_subprog_decl): Remove obsolete line. + +2021-07-09 Piotr Trojanek + + * exp_put_image.adb (Make_Put_Image_Name): Fix style. + (Image_Should_Call_Put_Image): Likewise. + (Build_Image_Call): Likewise. + +2021-07-09 Ghjuvan Lacambre + + * par-ch6.adb (Contains_Import_Aspect): New function. + (P_Subprogram): Acknowledge `Import` aspects. + +2021-07-09 Bob Duff + + * exp_put_image.adb (Make_Component_Attributes): Use + Implementation_Base_Type to get the parent type. Otherwise, + Parent_Type_Decl is actually an internally generated subtype + declaration, so we blow up on + Type_Definition (Parent_Type_Decl). + +2021-07-09 Dmitriy Anisimkov + + * gsocket.h: Include net/if.h to get IF_NAMESIZE constant. + * s-oscons-tmplt.c: Define IPV6_FLOWINFO for Linux. + +2021-07-09 Steve Baird + + * libgnat/a-cdlili.adb: Reimplement + Ada.Containers.Doubly_Linked_Lists.Generic_Sorting.Sort using + Mergesort instead of the previous Quicksort variant. + +2021-07-09 Justin Squirek + + * exp_ch6.adb (Is_Build_In_Place_Function_Call): Add check to + verify the Selector_Name of Exp_Node has been analyzed before + obtaining its entity. + +2021-07-09 Gary Dismukes + + * libgnarl/s-osinte__vxworks.ads: Fix typo ("release" => + "releases") plus comment reformatting. + * libgnat/s-os_lib.ads: In a comment, fix typo ("indended" => + "intended"), add a hyphen and semicolon, plus reformatting. In + comment for subtype time_t, fix typo ("effect" => "affect"), add + hyphens, plus reformatting. + * libgnat/s-parame.ads, libgnat/s-parame__ae653.ads, + libgnat/s-parame__hpux.ads: Remove period from one-line comment. + +2021-07-09 Steve Baird + + * exp_ch5.adb (Expand_General_Case_Statement): Add new function + Else_Statements to handle the case of invalid data analogously + to how it is handled when casing on a discrete value. + * sem_case.adb (Has_Static_Discriminant_Constraint): A new + Boolean-valued function. + (Composite_Case_Ops.Scalar_Part_Count): Include discriminants + when traversing components. + (Composite_Case_Ops.Choice_Analysis.Traverse_Discrete_Parts): + Include discriminants when traversing components; the component + range for a constrained discriminant is a single value. + (Composite_Case_Ops.Choice_Analysis.Parse_Choice): Eliminate + Done variable and modify how Next_Part is computed so that it is + always correct (as opposed to being incorrect when Done is + True). This includes changes in Update_Result (a local + procedure). Add new local procedure + Update_Result_For_Box_Component and call it not just for box + components but also for "missing" components (components + associated with an inactive variant). + (Check_Choices.Check_Composite_Case_Selector.Check_Component_Subtype): + Instead of disallowing all discriminated component types, allow + those that are unconstrained or statically constrained. Check + discriminant subtypes along with other component subtypes. + * doc/gnat_rm/implementation_defined_pragmas.rst: Update + documentation to reflect current implementation status. + * gnat_rm.texi: Regenerate. + +2021-07-09 Justin Squirek + + * sem_ch6.adb (Check_Pragma_Inline): Correctly use + Corresponding_Spec_Of_Stub when dealing subprogram body stubs. + +2021-07-09 Doug Rupp + + * Makefile.rtl: Add translations for s-parame__posix2008.ads + * libgnarl/s-linux.ads: Import System.Parameters. + (time_t): Declare using System.Parameters.time_t_bits. + * libgnarl/s-linux__alpha.ads: Likewise. + * libgnarl/s-linux__android.ads: Likewise. + * libgnarl/s-linux__hppa.ads: Likewise. + * libgnarl/s-linux__mips.ads: Likewise. + * libgnarl/s-linux__riscv.ads: Likewise. + * libgnarl/s-linux__sparc.ads: Likewise. + * libgnarl/s-linux__x32.ads: Likewise. + * libgnarl/s-qnx.ads: Likewise. + * libgnarl/s-osinte__aix.ads: Likewise. + * libgnarl/s-osinte__android.ads: Likewise. + * libgnarl/s-osinte__darwin.ads: Likewise. + * libgnarl/s-osinte__dragonfly.ads: Likewise. + * libgnarl/s-osinte__freebsd.ads: Likewise. + * libgnarl/s-osinte__gnu.ads: Likewise. + * libgnarl/s-osinte__hpux-dce.ads: Likewise. + * libgnarl/s-osinte__hpux.ads: Likewise. + * libgnarl/s-osinte__kfreebsd-gnu.ads: Likewise. + * libgnarl/s-osinte__lynxos178e.ads: Likewise. + * libgnarl/s-osinte__qnx.ads: Likewise. + * libgnarl/s-osinte__rtems.ads: Likewise. + * libgnarl/s-osinte__solaris.ads: Likewise. + * libgnarl/s-osinte__vxworks.ads: Likewise. + * libgnat/g-sothco.ads: Likewise. + * libgnat/s-osprim__darwin.adb: Likewise. + * libgnat/s-osprim__posix.adb: Likewise. + * libgnat/s-osprim__posix2008.adb: Likewise. + * libgnat/s-osprim__rtems.adb: Likewise. + * libgnat/s-osprim__x32.adb: Likewise. + * libgnarl/s-osinte__linux.ads: use type System.Linux.time_t. + * libgnat/s-os_lib.ads (time_t): Declare as subtype of + Long_Long_Integer. + * libgnat/s-parame.ads (time_t_bits): New constant. + * libgnat/s-parame__ae653.ads (time_t_bits): Likewise. + * libgnat/s-parame__hpux.ads (time_t_bits): Likewise. + * libgnat/s-parame__vxworks.ads (time_t_bits): Likewise. + * libgnat/s-parame__posix2008.ads: New file for 64 bit time_t. + +2021-07-09 Bob Duff + + * comperr.adb (Compiler_Abort): Print source file name. + +2021-07-09 Joffrey Huguet + + * libgnat/a-strunb.ads, libgnat/a-strunb__shared.ads: Fix layout + in contracts. + +2021-07-09 Eric Botcazou + + * repinfo.ads (JSON output format): Document adjusted key name. + * repinfo.adb (List_Record_Layout): Use Original_Record_Component + if the normalized position of the component is not known. + (List_Structural_Record_Layout): Rename Outer_Ent parameter into + Ext_End and add Ext_Level parameter. In an extension, if the parent + subtype has static discriminants, call List_Record_Layout on it. + Output "parent_" prefixes before "variant" according to Ext_Level. + Adjust recursive calls throughout the procedure. + +2021-07-09 Piotr Trojanek + + * exp_util.ads (Map_Types): Fix typo. + +2021-07-09 Fedor Rybin + + * krunch.adb: Add safeguards against index range violations. + +2021-07-09 Arnaud Charlet + + * libgnat/a-strfix.adb: Take advantage of extended returns. + +2021-07-09 Eric Botcazou + + * doc/gnat_rm/implementation_defined_attributes.rst + (Scalar_Storage_Order): Add paragraph about representation + changes. + * gnat_rm.texi: Regenerate. + +2021-07-09 Frederic Konrad + + * Makefile.rtl (LIBGNAT_TARGET_PAIRS) : Use + the wraplf variant of Aux_Long_Long_Float. + +2021-07-09 Piotr Trojanek + + * sem_ch6.adb (Analyze_Expression_Function): Initialize Orig_N + and Typ variables. + +2021-07-09 Arnaud Charlet + + * sem_ch13.adb (Resolve_Aspect_Expressions): Use the same + processing for Predicate, Static_Predicate and + Dynamic_Predicate. Do not build the predicate function spec. + Update comments. + (Resolve_Name): Only reset Entity when necessary to avoid + spurious visibility errors. + (Check_Aspect_At_End_Of_Declarations): Handle consistently all + Predicate aspects. + * sem_ch3.adb (Analyze_Subtype_Declaration): Fix handling of + private types with predicates. + +2021-07-09 Justin Squirek + + * sem_util.ads (Type_Access_Level): Add new optional parameter + Assoc_Ent. + * sem_util.adb (Accessibility_Level): Treat access discriminants + the same as components when the restriction + No_Dynamic_Accessibility_Checks is enabled. + (Deepest_Type_Access_Level): Remove exception for + Debug_Flag_Underscore_B when returning the result of + Type_Access_Level in the case where + No_Dynamic_Accessibility_Checks is active. + (Function_Call_Or_Allocator_Level): Correctly calculate the + level of Expr based on its containing subprogram instead of + using Current_Subprogram. + * sem_res.adb (Valid_Conversion): Add actual for new parameter + Assoc_Ent in call to Type_Access_Level, and add test of + No_Dynamic_Accessibility_Checks_Enabled to ensure that static + accessibility checks are performed for all anonymous access type + conversions. + +2021-07-09 Eric Botcazou + + * exp_dbug.ads: Update documentation of various items. + +2021-07-09 Piotr Trojanek + + * sem_ch6.adb (Analyze_Expression_Function): Reorder code. + +2021-07-09 Piotr Trojanek + + * sem_ch6.adb (Analyze_Expression_Function): Reorder code. + +2021-07-09 Piotr Trojanek + + * sem_ch6.adb (Analyze_Expression_Function): Add variable to + avoid repeated calls to Etype. + +2021-07-09 Piotr Trojanek + + * sem_ch6.adb (Analyze_Expression_Function): Fix comment. + +2021-07-09 Piotr Trojanek + + * sem_ch6.adb (Analyze_Expression_Function): Use Orig_N variable + instead of repeated calls to Original_Node. + +2021-07-09 Piotr Trojanek + + * sem_ch6.adb (Analyze_Expression_Function): Change types local + variables from Entity_Id to Node_Id. + +2021-07-09 Piotr Trojanek + + * sem_ch6.adb (Analyze_Expression_Function): A local Expr + constant was shadowing a global constant with the same name and + the same value. + +2021-07-09 Piotr Trojanek + + * sem_res.adb (Preanalyze_And_Resolve): Only call + Set_Must_Not_Freeze when it is necessary to restore the previous + value. + 2021-07-08 Piotr Trojanek * sem_ch5.adb (Analyze_Assignment): Clear Current_Assignment at diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4386e5d..351476d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,45 @@ +2021-07-09 Jason Merrill + + PR c++/101098 + * decl.c (function_requirements_equivalent_p): Only compare + trailing requirements on a specialization. + +2021-07-09 Iain Sandoe + + * coroutines.cc (build_actor_fn): Move common code to + act_des_fn. + (build_destroy_fn): Likewise. + (act_des_fn): Build the void return here. Ensure that the + source location matches the original function. + +2021-07-09 Iain Sandoe + + * coroutines.cc + (coro_rewrite_function_body): Connect the replacement + function block to the block nest correctly. + +2021-07-09 Patrick Palka + + PR c++/101181 + * constraint.cc (tsubst_requires_expr): Pass complain/in_decl to + add_extra_args. + * cp-tree.h (add_extra_args): Add complain/in_decl parameters. + * pt.c (build_extra_args): Make a copy of args. + (add_extra_args): Add complain/in_decl parameters. Enable the + code for handling the case where the extra arguments are + dependent. + (tsubst_pack_expansion): Pass complain/in_decl to + add_extra_args. + (tsubst_template_args): Handle missing template arguments. + (tsubst_expr) : Pass complain/in_decl to + add_extra_args. + +2021-07-09 Patrick Palka + + PR c++/101247 + * pt.c (any_template_parm_r) : Just walk the + DECL_CONTEXT. + 2021-07-08 Martin Sebor PR bootstrap/101372 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cdd3376..9d203f5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,61 @@ +2021-07-09 Jason Merrill + + PR c++/101098 + * g++.dg/concepts/explicit-spec1.C: New test. + +2021-07-09 Roger Sayle + Uroš Bizjak + + * gcc.target/i386/divmod-9.c: New test case. + +2021-07-09 Indu Bhagat + + PR testsuite/101269 + * gcc.dg/debug/btf/btf-datasec-1.c: Force -msdata=none with ilp32 for + powerpc based targets. + +2021-07-09 Patrick Palka + + PR c++/101181 + * g++.dg/cpp2a/concepts-requires26.C: New test. + * g++.dg/cpp2a/lambda-uneval16.C: New test. + +2021-07-09 Patrick Palka + + PR c++/101247 + * g++.dg/cpp2a/concepts-memtmpl4.C: Uncomment the commented out + example, which we now handle correctly. + * g++.dg/cpp2a/concepts-memtmpl5.C: New test. + * g++.dg/cpp2a/concepts-memtmpl5a.C: New test. + +2021-07-09 Xi Ruoyao + + * gcc.target/mips/cfgcleanup-jalr2.c: Remove -fno-inline and add + __attribute__((noinline)). + * gcc.target/mips/cfgcleanup-jalr3.c: Likewise. + +2021-07-09 Xi Ruoyao + + PR target/100760 + PR target/100761 + PR target/100762 + * gcc.target/mips/pr100760.c: New test. + * gcc.target/mips/pr100761.c: New test. + * gcc.target/mips/pr100762.c: New test. + +2021-07-09 Kewen Lin + + * gcc.target/powerpc/mod-vectorize.c: New test. + +2021-07-09 Kewen Lin + + * gcc.target/powerpc/div-vectorize-1.c: New test. + +2021-07-09 Kewen Lin + + * gcc.target/powerpc/mul-vectorize-1.c: New test. + * gcc.target/powerpc/mul-vectorize-2.c: New test. + 2021-07-08 Martin Sebor * gcc.dg/Wstringop-overflow-43.c: Remove an xfail. -- cgit v1.1 From b9119edc09e4660d772dea771578715858f7fbdb Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 9 Jul 2021 22:40:07 -0400 Subject: c++: 'new T[N]' and SFINAE [PR82110] Here we're failing to treat 'new T[N]' as erroneous in a SFINAE context when T isn't default constructible because expand_aggr_init_1 doesn't communicate to build_aggr_init (its only SFINAE caller) whether the initialization was actually successful. To fix this, this patch makes expand_aggr_init_1 and its subroutine expand_default_init return true on success, false on failure so that build_aggr_init can properly return error_mark_node on failure. PR c++/82110 gcc/cp/ChangeLog: * init.c (build_aggr_init): Return error_mark_node if expand_aggr_init_1 returns false. (expand_default_init): Change return type to bool. Return false on error, true on success. (expand_aggr_init_1): Likewise. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/pr78765.C: Expect another conversion failure diagnostic. * g++.dg/template/sfinae14.C: Flip incorrect assertion. * g++.dg/cpp2a/concepts-requires27.C: New test. --- gcc/cp/init.c | 43 ++++++++++++++++-------- gcc/testsuite/g++.dg/cpp0x/pr78765.C | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C | 10 ++++++ gcc/testsuite/g++.dg/template/sfinae14.C | 2 +- 4 files changed, 41 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C (limited to 'gcc') diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 88f6f90..d47e405 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -39,8 +39,8 @@ along with GCC; see the file COPYING3. If not see static bool begin_init_stmts (tree *, tree *); static tree finish_init_stmts (bool, tree, tree); static void construct_virtual_base (tree, tree); -static void expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t); -static void expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t); +static bool expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t); +static bool expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t); static void perform_member_init (tree, tree); static int member_init_ok_or_else (tree, tree, tree); static void expand_virtual_init (tree, tree); @@ -1838,12 +1838,14 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) is_global = begin_init_stmts (&stmt_expr, &compound_stmt); destroy_temps = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = 0; - expand_aggr_init_1 (TYPE_BINFO (type), exp, exp, - init, LOOKUP_NORMAL|flags, complain); + bool ok = expand_aggr_init_1 (TYPE_BINFO (type), exp, exp, + init, LOOKUP_NORMAL|flags, complain); stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt); current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps; TREE_READONLY (exp) = was_const; TREE_THIS_VOLATILE (exp) = was_volatile; + if (!ok) + return error_mark_node; if ((VAR_P (exp) || TREE_CODE (exp) == PARM_DECL) && TREE_SIDE_EFFECTS (stmt_expr) @@ -1854,7 +1856,7 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) return stmt_expr; } -static void +static bool expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, tsubst_flags_t complain) { @@ -1889,6 +1891,9 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, happen for direct-initialization, too. */ init = digest_init (type, init, complain); + if (init == error_mark_node) + return false; + /* A CONSTRUCTOR of the target's type is a previously digested initializer, whether that happened just above or in cp_parser_late_parsing_nsdmi. @@ -1910,7 +1915,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); - return; + return true; } if (init && TREE_CODE (init) != TREE_LIST @@ -1927,8 +1932,12 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, have already built up the constructor call so we could wrap it in an exception region. */; else - init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, - flags, complain | tf_no_cleanup); + { + init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, + flags, complain | tf_no_cleanup); + if (init == error_mark_node) + return false; + } if (TREE_CODE (init) == MUST_NOT_THROW_EXPR) /* We need to protect the initialization of a catch parm with a @@ -1944,7 +1953,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); - return; + return true; } if (init == NULL_TREE) @@ -1982,6 +1991,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, &parms, binfo, flags, complain); base = fold_build_cleanup_point_expr (void_type_node, base); + if (complete == error_mark_node || base == error_mark_node) + return false; rval = build_if_in_charge (complete, base); } else @@ -1991,6 +2002,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags, complain); + if (rval == error_mark_node) + return false; } if (parms != NULL) @@ -2010,10 +2023,12 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, /* FIXME put back convert_to_void? */ if (TREE_SIDE_EFFECTS (rval)) finish_expr_stmt (rval); + + return true; } /* This function is responsible for initializing EXP with INIT - (if any). + (if any). Returns true on success, false on failure. BINFO is the binfo of the type for who we are performing the initialization. For example, if W is a virtual base class of A and B, @@ -2032,7 +2047,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, FLAGS is just passed to `build_new_method_call'. See that function for its description. */ -static void +static bool expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, tsubst_flags_t complain) { @@ -2058,7 +2073,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, if (init) finish_expr_stmt (init); gcc_assert (!cleanups); - return; + return true; } /* List-initialization from {} becomes value-initialization for non-aggregate @@ -2096,7 +2111,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, /* If we don't need to mess with the constructor at all, then we're done. */ if (! type_build_ctor_call (type)) - return; + return true; /* Otherwise fall through and call the constructor. */ init = NULL_TREE; @@ -2104,7 +2119,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, /* We know that expand_default_init can handle everything we want at this point. */ - expand_default_init (binfo, true_exp, exp, init, flags, complain); + return expand_default_init (binfo, true_exp, exp, init, flags, complain); } /* Report an error if TYPE is not a user-defined, class type. If diff --git a/gcc/testsuite/g++.dg/cpp0x/pr78765.C b/gcc/testsuite/g++.dg/cpp0x/pr78765.C index 6b66d26..4c63fdd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr78765.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr78765.C @@ -8,7 +8,7 @@ struct ValueType { int field; }; -static constexpr ValueType var = 0; // { dg-error "conversion" } +static constexpr ValueType var = 0; // { dg-error "conversion|convert" } template class ValueTypeInfo; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C new file mode 100644 index 0000000..99d4500 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C @@ -0,0 +1,10 @@ +// PR c++/82110 +// { dg-do compile { target c++20 } } + +struct X { X() = delete; }; + +template concept C = requires(T t) { new T; }; +template concept D = requires(T t) { new T[1]; }; + +static_assert(!C); +static_assert(!D); diff --git a/gcc/testsuite/g++.dg/template/sfinae14.C b/gcc/testsuite/g++.dg/template/sfinae14.C index 93eba43a..0c59dad 100644 --- a/gcc/testsuite/g++.dg/template/sfinae14.C +++ b/gcc/testsuite/g++.dg/template/sfinae14.C @@ -76,4 +76,4 @@ STATIC_ASSERT(!(has_new_one_arg::value)); STATIC_ASSERT((has_array_new::value)); STATIC_ASSERT(!(has_array_new::value)); -STATIC_ASSERT((has_array_new::value)); +STATIC_ASSERT(!(has_array_new::value)); -- cgit v1.1 From 1798cac7a8b3331a277da1f106752ce0a34f8937 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 8 Jul 2021 19:25:55 -0700 Subject: runtime: remove direct assignments to memory locations PR bootstrap/101374 They cause a warning with the updated GCC -Warray-bounds option. Replace them with calls to abort, which for our purposes is fine. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/333409 --- gcc/go/gofrontend/MERGE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index ab1384d..4d0f44f 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -01cb2b5e69a2d08ef3cc1ea023c22ed9b79f5114 +adcf10890833026437a94da54934ce50c0018309 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. -- cgit v1.1 From 7466a0a5d8d536ab15f9732ec0ca331df972b3ac Mon Sep 17 00:00:00 2001 From: John David Anglin Date: Sat, 10 Jul 2021 16:20:32 +0000 Subject: Require target lra for tests using asm goto gcc/testsuite/ChangeLog: * gcc.dg/torture/pr100329.c: Require target lra. * gcc.dg/torture/pr100519.c: Likewise. --- gcc/testsuite/gcc.dg/torture/pr100329.c | 2 +- gcc/testsuite/gcc.dg/torture/pr100519.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/torture/pr100329.c b/gcc/testsuite/gcc.dg/torture/pr100329.c index b90700d..2a4331b 100644 --- a/gcc/testsuite/gcc.dg/torture/pr100329.c +++ b/gcc/testsuite/gcc.dg/torture/pr100329.c @@ -1,4 +1,4 @@ -/* { dg-do compile } */ +/* { dg-do compile { target lra } } */ /* { dg-additional-options "--param tree-reassoc-width=2" } */ unsigned int a0; diff --git a/gcc/testsuite/gcc.dg/torture/pr100519.c b/gcc/testsuite/gcc.dg/torture/pr100519.c index faf6e24..89dff66 100644 --- a/gcc/testsuite/gcc.dg/torture/pr100519.c +++ b/gcc/testsuite/gcc.dg/torture/pr100519.c @@ -1,4 +1,4 @@ -/* { dg-do compile } */ +/* { dg-do compile { target lra } } */ /* { dg-additional-options "--param tree-reassoc-width=2" } */ unsigned int foo_a1, foo_a2; -- cgit v1.1 From 269256f33c51222167ad461f775d5468bb5ecaf5 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sun, 11 Jul 2021 00:16:35 +0000 Subject: Daily bump. --- gcc/DATESTAMP | 2 +- gcc/cp/ChangeLog | 9 +++++++++ gcc/testsuite/ChangeLog | 13 +++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 1d7b87f..e569510 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210710 +20210711 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 351476d..39e5ec3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2021-07-10 Patrick Palka + + PR c++/82110 + * init.c (build_aggr_init): Return error_mark_node if + expand_aggr_init_1 returns false. + (expand_default_init): Change return type to bool. Return false + on error, true on success. + (expand_aggr_init_1): Likewise. + 2021-07-09 Jason Merrill PR c++/101098 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9d203f5..cac4995 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2021-07-10 John David Anglin + + * gcc.dg/torture/pr100329.c: Require target lra. + * gcc.dg/torture/pr100519.c: Likewise. + +2021-07-10 Patrick Palka + + PR c++/82110 + * g++.dg/cpp0x/pr78765.C: Expect another conversion failure + diagnostic. + * g++.dg/template/sfinae14.C: Flip incorrect assertion. + * g++.dg/cpp2a/concepts-requires27.C: New test. + 2021-07-09 Jason Merrill PR c++/101098 -- cgit v1.1 From d55eee24a9f5e04d2b71e98b77347924a3cebd05 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Mon, 12 Jul 2021 00:16:29 +0000 Subject: Daily bump. --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e569510..d01e523 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210711 +20210712 -- cgit v1.1 From 5f5fbb550af7d9d6cb56ae8f607fea0eccaa9295 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Mon, 12 Jul 2021 08:24:27 +0100 Subject: PR tree-optimization/101403: Incorrect folding of ((T)bswap(x))>>C My sincere apologies for the breakage. My recent patch to fold bswapN(x)>>C where the constant C was large enough that the result only contains bits from the low byte, and can therefore avoid the byte swap contains a minor logic error. The pattern contains a convert? allowing an extension to occur between the bswap and the shift. The logic is correct if there's no extension, or the extension has the same sign as the shift, but I'd mistakenly convinced myself that these couldn't have different signedness. (T)bswap16(x)>>12 is (T)((unsigned char)x>>4) or (T)((signed char)x>>4). The bug is that for zero-extensions to signed type T, we need to use the unsigned char variant [the signedness of the byte shift is not (always) the same as the signedness of T and the original shift]. Then because I'm now paranoid, I've also added a clause to handle the hypothetical (but in practice impossible) sign-extension to an unsigned type T, which can implemented as (T)(x<<8)>>12. 2021-07-12 Roger Sayle gcc/ChangeLog PR tree-optimization/101403 * match.pd ((T)bswap(X)>>C): Correctly handle cases where signedness of the shift is not the same as the signedness of the type extension. gcc/testsuite/ChangeLog PR tree-optimization/101403 * gcc.dg/pr101403.c: New test case. --- gcc/match.pd | 36 ++++++++++++++++++++++++------------ gcc/testsuite/gcc.dg/pr101403.c | 17 +++++++++++++++++ 2 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr101403.c (limited to 'gcc') diff --git a/gcc/match.pd b/gcc/match.pd index 30680d4..beb8d27 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3659,19 +3659,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) { unsigned HOST_WIDE_INT prec = TYPE_PRECISION (TREE_TYPE (@2)); unsigned HOST_WIDE_INT bits = tree_to_uhwi (@1); + /* If the bswap was extended before the original shift, this + byte (shift) has the sign of the extension, not the sign of + the original shift. */ + tree st = TYPE_PRECISION (type) > prec ? TREE_TYPE (@2) : type; } - (if (bits + 8 == prec) - (if (TYPE_UNSIGNED (type)) - (convert (convert:unsigned_char_type_node @0)) - (convert (convert:signed_char_type_node @0))) - (if (bits < prec && bits + 8 > prec) - (with - { - tree nst = build_int_cst (integer_type_node, bits & 7); - tree bt = TYPE_UNSIGNED (type) ? unsigned_char_type_node - : signed_char_type_node; - } - (convert (rshift:bt (convert:bt @0) {nst;})))))))) + /* Special case: logical right shift of sign-extended bswap. + (unsigned)(short)bswap16(x)>>12 is (unsigned)((short)x<<8)>>12. */ + (if (TYPE_PRECISION (type) > prec + && !TYPE_UNSIGNED (TREE_TYPE (@2)) + && TYPE_UNSIGNED (type) + && bits < prec && bits + 8 >= prec) + (with { tree nst = build_int_cst (integer_type_node, prec - 8); } + (rshift (convert (lshift:st (convert:st @0) {nst;})) @1)) + (if (bits + 8 == prec) + (if (TYPE_UNSIGNED (st)) + (convert (convert:unsigned_char_type_node @0)) + (convert (convert:signed_char_type_node @0))) + (if (bits < prec && bits + 8 > prec) + (with + { + tree nst = build_int_cst (integer_type_node, bits & 7); + tree bt = TYPE_UNSIGNED (st) ? unsigned_char_type_node + : signed_char_type_node; + } + (convert (rshift:bt (convert:bt @0) {nst;}))))))))) /* bswap(x) & C1 can sometimes be simplified to (x >> C2) & C1. */ (simplify (bit_and (convert? (bswap@2 @0)) INTEGER_CST@1) diff --git a/gcc/testsuite/gcc.dg/pr101403.c b/gcc/testsuite/gcc.dg/pr101403.c new file mode 100644 index 0000000..ac5fa79 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101403.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +unsigned int foo (unsigned int a) +{ + unsigned int u; + unsigned short b = __builtin_bswap16 (a); + return b >> (u, 12); +} + +int main (void) +{ + unsigned int x = foo (0x80); + if (x != 0x0008) + __builtin_abort (); + return 0; +} + -- cgit v1.1 From 1e72c24d2f3b1427f5e117e371928e7af50d2036 Mon Sep 17 00:00:00 2001 From: "prathamesh.kulkarni" Date: Mon, 12 Jul 2021 13:23:06 +0530 Subject: arm/98435: Missed optimization in expanding vector constructor. The patch moves vec_init pattern from neon.md to vec-common.md, and adjusts the mode to VDQX to accomodate binary floats. Also, the pattern is additionally gated on VALID_MVE_MODE. gcc/ChangeLog: PR target/98435 * config/arm/neon.md (vec_init): Move to ... * config/arm/vec-common.md (vec_init): ... here. Change the pattern's mode to VDQX and gate it on VALID_MVE_MODE. gcc/testsuite/ChangeLog: PR target/98435 * gcc.target/arm/simd/pr98435.c: New test. --- gcc/config/arm/neon.md | 9 --------- gcc/config/arm/vec-common.md | 9 +++++++++ gcc/testsuite/gcc.target/arm/simd/pr98435.c | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/simd/pr98435.c (limited to 'gcc') diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index 81cc8d3..64365e0 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -458,15 +458,6 @@ [(set_attr "type" "neon_store1_one_lane_q,neon_to_gp_q")] ) -(define_expand "vec_init" - [(match_operand:VDQ 0 "s_register_operand") - (match_operand 1 "" "")] - "TARGET_NEON || TARGET_HAVE_MVE" -{ - neon_expand_vector_init (operands[0], operands[1]); - DONE; -}) - ;; Doubleword and quadword arithmetic. ;; NOTE: some other instructions also support 64-bit integer diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md index f90afa4..68de4f0 100644 --- a/gcc/config/arm/vec-common.md +++ b/gcc/config/arm/vec-common.md @@ -702,3 +702,12 @@ DONE; } ) + +(define_expand "vec_init" + [(match_operand:VDQX 0 "s_register_operand") + (match_operand 1 "" "")] + "TARGET_NEON || (TARGET_HAVE_MVE && VALID_MVE_MODE (mode))" +{ + neon_expand_vector_init (operands[0], operands[1]); + DONE; +}) diff --git a/gcc/testsuite/gcc.target/arm/simd/pr98435.c b/gcc/testsuite/gcc.target/arm/simd/pr98435.c new file mode 100644 index 0000000..0af8633 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/pr98435.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ffast-math" } */ +/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */ +/* { dg-add-options arm_v8_2a_bf16_neon } */ +/* { dg-additional-options "-mfloat-abi=softfp -march=armv8.2-a+bf16+fp16" } */ + +#include + +bfloat16x4_t f (bfloat16_t a) +{ + return (bfloat16x4_t) {a, a, a, a}; +} + +/* { dg-final { scan-assembler {\tvdup.16\td[0-9]+, r0} } } */ +/* { dg-final { scan-assembler {\tvmov\tr0, r1, d[0-9]+} } } */ -- cgit v1.1 From 9b8b37d1b6301855213b8d4860feaeb74d464c6b Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 12 Jul 2021 10:59:06 +0200 Subject: offloading: fix -foffload hinting PR sanitizer/101425 gcc/ChangeLog: * gcc.c (check_offload_target_name): Call candidates_list_and_hint only if we have a candidate. --- gcc/gcc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/gcc.c b/gcc/gcc.c index f086dd4..12b3440 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -4001,7 +4001,6 @@ check_offload_target_name (const char *target, ptrdiff_t len) } if (!c) { - char *s; auto_vec candidates; size_t olen = strlen (OFFLOAD_TARGETS) + 1; char *cand = XALLOCAVEC (char, olen); @@ -4015,15 +4014,19 @@ check_offload_target_name (const char *target, ptrdiff_t len) error ("GCC is not configured to support %qs as offload target", target2); - const char *hint = candidates_list_and_hint (target2, s, candidates); if (candidates.is_empty ()) inform (UNKNOWN_LOCATION, "no offloading targets configured"); - else if (hint) - inform (UNKNOWN_LOCATION, - "valid offload targets are: %s; did you mean %qs?", s, hint); else - inform (UNKNOWN_LOCATION, "valid offload targets are: %s", s); - XDELETEVEC (s); + { + char *s; + const char *hint = candidates_list_and_hint (target2, s, candidates); + if (hint) + inform (UNKNOWN_LOCATION, + "valid offload targets are: %s; did you mean %qs?", s, hint); + else + inform (UNKNOWN_LOCATION, "valid offload targets are: %s", s); + XDELETEVEC (s); + } return false; } return true; -- cgit v1.1