Compare commits
No commits in common. "c8" and "c9s-RHEL-105416" have entirely different histories.
c8
...
c9s-RHEL-1
1
.fmf/version
Normal file
1
.fmf/version
Normal file
@ -0,0 +1 @@
|
||||
1
|
||||
@ -1,3 +0,0 @@
|
||||
b7245af5eab1d4055b6590b6e4f5fb3b7f6c24bf SOURCES/gcc-8.5.0-20210514.tar.xz
|
||||
3bdb3cc01fa7690a0e20ea5cfffcbe690f7665eb SOURCES/nvptx-newlib-aadc8eb0ec43b7cd0dd2dfb484bae63c8b05ef24.tar.xz
|
||||
ce8eb83be0ac37fb5d5388df455a980fe37b4f13 SOURCES/nvptx-tools-c28050f60193b3b95a18866a96f03334e874e78f.tar.xz
|
||||
54
.gitignore
vendored
54
.gitignore
vendored
@ -1,3 +1,51 @@
|
||||
SOURCES/gcc-8.5.0-20210514.tar.xz
|
||||
SOURCES/nvptx-newlib-aadc8eb0ec43b7cd0dd2dfb484bae63c8b05ef24.tar.xz
|
||||
SOURCES/nvptx-tools-c28050f60193b3b95a18866a96f03334e874e78f.tar.xz
|
||||
/gcc-10.0.1-20200118.tar.xz
|
||||
/newlib-cygwin-50e2a63b04bdd018484605fbb954fd1bd5147fa0.tar.xz
|
||||
/nvptx-tools-5f6f343a302d620b0868edab376c00b15741e39e.tar.xz
|
||||
/gcc-10.0.1-20200121.tar.xz
|
||||
/gcc-10.0.1-20200123.tar.xz
|
||||
/gcc-10.0.1-20200126.tar.xz
|
||||
/gcc-10.0.1-20200130.tar.xz
|
||||
/gcc-10.0.1-20200216.tar.xz
|
||||
/gcc-10.0.1-20200311.tar.xz
|
||||
/gcc-10.0.1-20200325.tar.xz
|
||||
/gcc-10.0.1-20200328.tar.xz
|
||||
/gcc-10.0.1-20200420.tar.xz
|
||||
/gcc-10.0.1-20200501.tar.xz
|
||||
/gcc-10.1.1-20200507.tar.xz
|
||||
/gcc-10.1.1-20200618.tar.xz
|
||||
/gcc-10.2.1-20200723.tar.xz
|
||||
/gcc-10.2.1-20200804.tar.xz
|
||||
/gcc-10.2.1-20200826.tar.xz
|
||||
/gcc-10.2.1-20200916.tar.xz
|
||||
/gcc-10.2.1-20201005.tar.xz
|
||||
/gcc-10.2.1-20201016.tar.xz
|
||||
/gcc-10.2.1-20201102.tar.xz
|
||||
/gcc-10.2.1-20201112.tar.xz
|
||||
/gcc-10.2.1-20201125.tar.xz
|
||||
/gcc-11.0.0-20201204.tar.xz
|
||||
/gcc-11.0.0-20201216.tar.xz
|
||||
/gcc-11.0.0-20201217.tar.xz
|
||||
/gcc-11.0.0-20201223.tar.xz
|
||||
/gcc-11.0.0-20210109.tar.xz
|
||||
/gcc-11.0.0-20210113.tar.xz
|
||||
/gcc-11.0.0-20210116.tar.xz
|
||||
/gcc-11.0.0-20210119.tar.xz
|
||||
/gcc-11.0.0-20210123.tar.xz
|
||||
/gcc-11.0.0-20210130.tar.xz
|
||||
/gcc-11.0.0-20210210.tar.xz
|
||||
/gcc-11.0.0-20210225.tar.xz
|
||||
/gcc-11.0.1-20210307.tar.xz
|
||||
/gcc-11.0.1-20210319.tar.xz
|
||||
/isl-0.18.tar.bz2
|
||||
/gcc-11.0.1-20210324.tar.xz
|
||||
/gcc-11.1.1-20210617.tar.xz
|
||||
/gcc-11.1.1-20210623.tar.xz
|
||||
/gcc-11.2.1-20211019.tar.xz
|
||||
/gcc-11.2.1-20211203.tar.xz
|
||||
/gcc-11.2.1-20220127.tar.xz
|
||||
/gcc-11.2.1-20220401.tar.xz
|
||||
/gcc-11.3.1-20220421.tar.xz
|
||||
/gcc-11.3.1-20221121.tar.xz
|
||||
/gcc-11.4.1-20230605.tar.xz
|
||||
/gcc-11.4.1-20231218.tar.xz
|
||||
/gcc-11.5.0-20240719.tar.xz
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
2024-04-18 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* tree-vect-stmts.c (vectorizable_call): For j == 0 use
|
||||
vargs.safe_grow (nargs) rather than vargs.create (nargs), for j != 0
|
||||
remove vargs.truncate (0). Instead of vargs.quick_push store into
|
||||
vargs[i]. Use vargs[i] instead of gimple_call_arg (new_stmt, i)
|
||||
if j != 0.
|
||||
|
||||
* gcc.c-torture/compile/20240418.c: New test.
|
||||
|
||||
--- gcc/tree-vect-stmts.c.jj 2021-04-22 15:48:48.228178359 +0200
|
||||
+++ gcc/tree-vect-stmts.c 2024-04-18 13:21:46.104061529 +0200
|
||||
@@ -3242,9 +3242,7 @@ vectorizable_call (gimple *gs, gimple_st
|
||||
{
|
||||
/* Build argument list for the vectorized call. */
|
||||
if (j == 0)
|
||||
- vargs.create (nargs);
|
||||
- else
|
||||
- vargs.truncate (0);
|
||||
+ vargs.safe_grow (nargs);
|
||||
|
||||
if (slp_node)
|
||||
{
|
||||
@@ -3252,7 +3250,7 @@ vectorizable_call (gimple *gs, gimple_st
|
||||
vec<tree> vec_oprnds0;
|
||||
|
||||
for (i = 0; i < nargs; i++)
|
||||
- vargs.quick_push (gimple_call_arg (stmt, i));
|
||||
+ vargs[i] = gimple_call_arg (stmt, i);
|
||||
vect_get_slp_defs (vargs, slp_node, &vec_defs);
|
||||
vec_oprnds0 = vec_defs[0];
|
||||
|
||||
@@ -3314,13 +3312,10 @@ vectorizable_call (gimple *gs, gimple_st
|
||||
vec_oprnd0
|
||||
= vect_get_vec_def_for_operand (op, stmt);
|
||||
else
|
||||
- {
|
||||
- vec_oprnd0 = gimple_call_arg (new_stmt, i);
|
||||
- vec_oprnd0
|
||||
- = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
|
||||
- }
|
||||
+ vec_oprnd0
|
||||
+ = vect_get_vec_def_for_stmt_copy (dt[i], vargs[i]);
|
||||
|
||||
- vargs.quick_push (vec_oprnd0);
|
||||
+ vargs[i] = vec_oprnd0;
|
||||
}
|
||||
|
||||
if (gimple_call_internal_p (stmt)
|
||||
--- gcc/testsuite/gcc.c-torture/compile/20240418.c.jj 2024-04-18 13:24:10.180065661 +0200
|
||||
+++ gcc/testsuite/gcc.c-torture/compile/20240418.c 2024-04-18 13:19:12.166194018 +0200
|
||||
@@ -0,0 +1,7 @@
|
||||
+void
|
||||
+foo (signed char *p, unsigned long long *q)
|
||||
+{
|
||||
+ int i;
|
||||
+ for (i = 0; i <= 64; i++)
|
||||
+ *p++ = __builtin_popcountll (*q++);
|
||||
+}
|
||||
@ -1,105 +0,0 @@
|
||||
From 9c108bb84d3a2447dac730c455df658be0a2c751 Mon Sep 17 00:00:00 2001
|
||||
From: Richard Sandiford <richard.sandiford@arm.com>
|
||||
Date: Tue, 17 Aug 2021 15:15:27 +0100
|
||||
Subject: [PATCH] aarch64: Add -mtune=neoverse-512tvb
|
||||
To: gcc-patches@gcc.gnu.org
|
||||
|
||||
This patch adds an option to tune for Neoverse cores that have
|
||||
a total vector bandwidth of 512 bits (4x128 for Advanced SIMD
|
||||
and a vector-length-dependent equivalent for SVE). This is intended
|
||||
to be a compromise between tuning aggressively for a single core like
|
||||
Neoverse V1 (which can be too narrow) and tuning for AArch64 cores
|
||||
in general (which can be too wide).
|
||||
|
||||
-mcpu=neoverse-512tvb is equivalent to -mcpu=neoverse-v1
|
||||
-mtune=neoverse-512tvb.
|
||||
|
||||
gcc/
|
||||
* doc/invoke.texi: Document -mtune=neoverse-512tvb and
|
||||
-mcpu=neoverse-512tvb.
|
||||
* config/aarch64/aarch64-cores.def (neoverse-512tvb): New entry.
|
||||
* config/aarch64/aarch64-tune.md: Regenerate.
|
||||
|
||||
(cherry picked from commit 048039c49b96875144f67e7789fdea54abf7710b)
|
||||
---
|
||||
gcc/config/aarch64/aarch64-cores.def | 1 +
|
||||
gcc/config/aarch64/aarch64-tune.md | 2 +-
|
||||
gcc/doc/invoke.texi | 25 ++++++++++++++++++++++---
|
||||
3 files changed, 24 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
|
||||
index dfb839c01cc..f348d31e22e 100644
|
||||
--- a/gcc/config/aarch64/aarch64-cores.def
|
||||
+++ b/gcc/config/aarch64/aarch64-cores.def
|
||||
@@ -99,6 +99,7 @@ AARCH64_CORE("saphira", saphira, falkor, 8_3A, AARCH64_FL_FOR_ARCH8_3
|
||||
/* ARM ('A') cores. */
|
||||
AARCH64_CORE("zeus", zeus, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
|
||||
AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
|
||||
+AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversev1, INVALID_IMP, INVALID_CORE, -1)
|
||||
|
||||
/* Armv8.5-A Architecture Processors. */
|
||||
AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversen2, 0x41, 0xd49, -1)
|
||||
diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md
|
||||
index 2d7c9aa4740..09b76480f0b 100644
|
||||
--- a/gcc/config/aarch64/aarch64-tune.md
|
||||
+++ b/gcc/config/aarch64/aarch64-tune.md
|
||||
@@ -1,5 +1,5 @@
|
||||
;; -*- buffer-read-only: t -*-
|
||||
;; Generated automatically by gentune.sh from aarch64-cores.def
|
||||
(define_attr "tune"
|
||||
- "cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,thunderxt81,thunderxt83,xgene1,falkor,qdf24xx,exynosm1,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,ares,neoversen1,saphira,zeus,neoversev1,neoversen2,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55"
|
||||
+ "cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,thunderxt81,thunderxt83,xgene1,falkor,qdf24xx,exynosm1,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,ares,neoversen1,saphira,zeus,neoversev1,neoverse512tvb,neoversen2,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55"
|
||||
(const (symbol_ref "((enum attr_tune) aarch64_tune)")))
|
||||
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
|
||||
index 78ca7738df2..68fda03281a 100644
|
||||
--- a/gcc/doc/invoke.texi
|
||||
+++ b/gcc/doc/invoke.texi
|
||||
@@ -14772,9 +14772,9 @@ performance of the code. Permissible values for this option are:
|
||||
@samp{generic}, @samp{cortex-a35}, @samp{cortex-a53}, @samp{cortex-a55},
|
||||
@samp{cortex-a57}, @samp{cortex-a72}, @samp{cortex-a73}, @samp{cortex-a75},
|
||||
@samp{cortex-a76}, @samp{ares}, @samp{neoverse-n1}, @samp{neoverse-n2},
|
||||
-@samp{neoverse-v1}, @samp{zeus}, @samp{exynos-m1}, @samp{falkor},
|
||||
-@samp{qdf24xx}, @samp{saphira}, @samp{xgene1}, @samp{vulcan}, @samp{thunderx},
|
||||
-@samp{thunderxt88}, @samp{thunderxt88p1}, @samp{thunderxt81},
|
||||
+@samp{neoverse-v1}, @samp{zeus}, @samp{neoverse-512tvb}, @samp{exynos-m1},
|
||||
+@samp{falkor}, @samp{qdf24xx}, @samp{saphira}, @samp{xgene1}, @samp{vulcan},
|
||||
+@samp{thunderx}, @samp{thunderxt88}, @samp{thunderxt88p1}, @samp{thunderxt81},
|
||||
@samp{thunderxt83}, @samp{thunderx2t99}, @samp{cortex-a57.cortex-a53},
|
||||
@samp{cortex-a72.cortex-a53}, @samp{cortex-a73.cortex-a35},
|
||||
@samp{cortex-a73.cortex-a53}, @samp{cortex-a75.cortex-a55},
|
||||
@@ -14785,6 +14785,15 @@ The values @samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53},
|
||||
@samp{cortex-a75.cortex-a55} specify that GCC should tune for a
|
||||
big.LITTLE system.
|
||||
|
||||
+The value @samp{neoverse-512tvb} specifies that GCC should tune
|
||||
+for Neoverse cores that (a) implement SVE and (b) have a total vector
|
||||
+bandwidth of 512 bits per cycle. In other words, the option tells GCC to
|
||||
+tune for Neoverse cores that can execute 4 128-bit Advanced SIMD arithmetic
|
||||
+instructions a cycle and that can execute an equivalent number of SVE
|
||||
+arithmetic instructions per cycle (2 for 256-bit SVE, 4 for 128-bit SVE).
|
||||
+This is more general than tuning for a specific core like Neoverse V1
|
||||
+but is more specific than the default tuning described below.
|
||||
+
|
||||
Additionally on native AArch64 GNU/Linux systems the value
|
||||
@samp{native} tunes performance to the host system. This option has no effect
|
||||
if the compiler is unable to recognize the processor of the host system.
|
||||
@@ -14814,6 +14823,16 @@ by @option{-mtune}). Where this option is used in conjunction
|
||||
with @option{-march} or @option{-mtune}, those options take precedence
|
||||
over the appropriate part of this option.
|
||||
|
||||
+@option{-mcpu=neoverse-512tvb} is special in that it does not refer
|
||||
+to a specific core, but instead refers to all Neoverse cores that
|
||||
+(a) implement SVE and (b) have a total vector bandwidth of 512 bits
|
||||
+a cycle. Unless overridden by @option{-march},
|
||||
+@option{-mcpu=neoverse-512tvb} generates code that can run on a
|
||||
+Neoverse V1 core, since Neoverse V1 is the first Neoverse core with
|
||||
+these properties. Unless overridden by @option{-mtune},
|
||||
+@option{-mcpu=neoverse-512tvb} tunes code in the same way as for
|
||||
+@option{-mtune=neoverse-512tvb}.
|
||||
+
|
||||
@item -moverride=@var{string}
|
||||
@opindex moverride
|
||||
Override tuning decisions made by the back-end in response to a
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@ -1,294 +0,0 @@
|
||||
From 88bf1c3910e4cf97dcb85c6d32291c23e572a516 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Wed, 27 Oct 2021 07:48:54 -0700
|
||||
Subject: [PATCH 1/4] x86: Add -mharden-sls=[none|all|return|indirect-branch]
|
||||
|
||||
Add -mharden-sls= to mitigate against straight line speculation (SLS)
|
||||
for function return and indirect branch by adding an INT3 instruction
|
||||
after function return and indirect branch.
|
||||
|
||||
gcc/
|
||||
|
||||
PR target/102952
|
||||
* config/i386/i386-opts.h (harden_sls): New enum.
|
||||
* config/i386/i386.c (output_indirect_thunk): Mitigate against
|
||||
SLS for function return.
|
||||
(ix86_output_function_return): Likewise.
|
||||
(ix86_output_jmp_thunk_or_indirect): Mitigate against indirect
|
||||
branch.
|
||||
(ix86_output_indirect_jmp): Likewise.
|
||||
(ix86_output_call_insn): Likewise.
|
||||
* config/i386/i386.opt: Add -mharden-sls=.
|
||||
* doc/invoke.texi: Document -mharden-sls=.
|
||||
|
||||
gcc/testsuite/
|
||||
|
||||
PR target/102952
|
||||
* gcc.target/i386/harden-sls-1.c: New test.
|
||||
* gcc.target/i386/harden-sls-2.c: Likewise.
|
||||
* gcc.target/i386/harden-sls-3.c: Likewise.
|
||||
* gcc.target/i386/harden-sls-4.c: Likewise.
|
||||
* gcc.target/i386/harden-sls-5.c: Likewise.
|
||||
|
||||
(cherry picked from commit 53a643f8568067d7700a9f2facc8ba39974973d3)
|
||||
---
|
||||
gcc/config/i386/i386-opts.h | 7 +++++++
|
||||
gcc/config/i386/i386.c | 22 +++++++++++++++-----
|
||||
gcc/config/i386/i386.opt | 20 ++++++++++++++++++
|
||||
gcc/doc/invoke.texi | 10 ++++++++-
|
||||
gcc/testsuite/gcc.target/i386/harden-sls-1.c | 14 +++++++++++++
|
||||
gcc/testsuite/gcc.target/i386/harden-sls-2.c | 14 +++++++++++++
|
||||
gcc/testsuite/gcc.target/i386/harden-sls-3.c | 14 +++++++++++++
|
||||
gcc/testsuite/gcc.target/i386/harden-sls-4.c | 16 ++++++++++++++
|
||||
gcc/testsuite/gcc.target/i386/harden-sls-5.c | 17 +++++++++++++++
|
||||
9 files changed, 128 insertions(+), 6 deletions(-)
|
||||
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-1.c
|
||||
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-2.c
|
||||
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-3.c
|
||||
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-4.c
|
||||
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-5.c
|
||||
|
||||
diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
|
||||
index 46366cbfa72..34718b6d52c 100644
|
||||
--- a/gcc/config/i386/i386-opts.h
|
||||
+++ b/gcc/config/i386/i386-opts.h
|
||||
@@ -119,4 +119,11 @@ enum indirect_branch {
|
||||
indirect_branch_thunk_extern
|
||||
};
|
||||
|
||||
+enum harden_sls {
|
||||
+ harden_sls_none = 0,
|
||||
+ harden_sls_return = 1 << 0,
|
||||
+ harden_sls_indirect_branch = 1 << 1,
|
||||
+ harden_sls_all = harden_sls_return | harden_sls_indirect_branch
|
||||
+};
|
||||
+
|
||||
#endif
|
||||
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
|
||||
index 31502774ef3..eb9303f8742 100644
|
||||
--- a/gcc/config/i386/i386.c
|
||||
+++ b/gcc/config/i386/i386.c
|
||||
@@ -10977,6 +10977,9 @@ output_indirect_thunk (enum indirect_thunk_prefix need_prefix,
|
||||
fputs ("\tbnd ret\n", asm_out_file);
|
||||
else
|
||||
fputs ("\tret\n", asm_out_file);
|
||||
+
|
||||
+ if ((ix86_harden_sls & harden_sls_return))
|
||||
+ fputs ("\tint3\n", asm_out_file);
|
||||
}
|
||||
|
||||
/* Output a funtion with a call and return thunk for indirect branch.
|
||||
@@ -28728,6 +28731,8 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name,
|
||||
fprintf (asm_out_file, "\tjmp\t");
|
||||
assemble_name (asm_out_file, thunk_name);
|
||||
putc ('\n', asm_out_file);
|
||||
+ if ((ix86_harden_sls & harden_sls_indirect_branch))
|
||||
+ fputs ("\tint3\n", asm_out_file);
|
||||
}
|
||||
else
|
||||
output_indirect_thunk (need_prefix, regno);
|
||||
@@ -28973,10 +28978,10 @@ ix86_output_indirect_jmp (rtx call_op)
|
||||
gcc_unreachable ();
|
||||
|
||||
ix86_output_indirect_branch (call_op, "%0", true);
|
||||
- return "";
|
||||
}
|
||||
else
|
||||
- return "%!jmp\t%A0";
|
||||
+ output_asm_insn ("%!jmp\t%A0", &call_op);
|
||||
+ return (ix86_harden_sls & harden_sls_indirect_branch) ? "int3" : "";
|
||||
}
|
||||
|
||||
/* Output function return. CALL_OP is the jump target. Add a REP
|
||||
@@ -29018,9 +29023,11 @@ ix86_output_function_return (bool long_p)
|
||||
}
|
||||
|
||||
if (!long_p || ix86_bnd_prefixed_insn_p (current_output_insn))
|
||||
- return "%!ret";
|
||||
+ output_asm_insn ("%!ret", NULL);
|
||||
+ else
|
||||
+ output_asm_insn ("rep%; ret", NULL);
|
||||
|
||||
- return "rep%; ret";
|
||||
+ return (ix86_harden_sls & harden_sls_return) ? "int3" : "";
|
||||
}
|
||||
|
||||
/* Output indirect function return. RET_OP is the function return
|
||||
@@ -29158,7 +29165,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
|
||||
if (output_indirect_p && !direct_p)
|
||||
ix86_output_indirect_branch (call_op, xasm, true);
|
||||
else
|
||||
- output_asm_insn (xasm, &call_op);
|
||||
+ {
|
||||
+ output_asm_insn (xasm, &call_op);
|
||||
+ if (!direct_p
|
||||
+ && (ix86_harden_sls & harden_sls_indirect_branch))
|
||||
+ return "int3";
|
||||
+ }
|
||||
return "";
|
||||
}
|
||||
|
||||
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
|
||||
index d9bd909a885..3ae48609e25 100644
|
||||
--- a/gcc/config/i386/i386.opt
|
||||
+++ b/gcc/config/i386/i386.opt
|
||||
@@ -1055,3 +1055,23 @@ Support MOVDIRI built-in functions and code generation.
|
||||
mmovdir64b
|
||||
Target Report Mask(ISA_MOVDIR64B) Var(ix86_isa_flags2) Save
|
||||
Support MOVDIR64B built-in functions and code generation.
|
||||
+
|
||||
+mharden-sls=
|
||||
+Target RejectNegative Joined Enum(harden_sls) Var(ix86_harden_sls) Init(harden_sls_none)
|
||||
+Generate code to mitigate against straight line speculation.
|
||||
+
|
||||
+Enum
|
||||
+Name(harden_sls) Type(enum harden_sls)
|
||||
+Known choices for mitigation against straight line speculation with -mharden-sls=:
|
||||
+
|
||||
+EnumValue
|
||||
+Enum(harden_sls) String(none) Value(harden_sls_none)
|
||||
+
|
||||
+EnumValue
|
||||
+Enum(harden_sls) String(return) Value(harden_sls_return)
|
||||
+
|
||||
+EnumValue
|
||||
+Enum(harden_sls) String(indirect-branch) Value(harden_sls_indirect_branch)
|
||||
+
|
||||
+EnumValue
|
||||
+Enum(harden_sls) String(all) Value(harden_sls_all)
|
||||
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
|
||||
index 78ca7738df2..1e20efd6969 100644
|
||||
--- a/gcc/doc/invoke.texi
|
||||
+++ b/gcc/doc/invoke.texi
|
||||
@@ -1284,7 +1284,7 @@ See RS/6000 and PowerPC Options.
|
||||
-mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol
|
||||
-mgeneral-regs-only -mcall-ms2sysv-xlogues @gol
|
||||
-mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol
|
||||
--mindirect-branch-register}
|
||||
+-mindirect-branch-register -mharden-sls=@var{choice}}
|
||||
|
||||
@emph{x86 Windows Options}
|
||||
@gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
|
||||
@@ -28036,6 +28036,14 @@ not be reachable in the large code model.
|
||||
@opindex -mindirect-branch-register
|
||||
Force indirect call and jump via register.
|
||||
|
||||
+@item -mharden-sls=@var{choice}
|
||||
+@opindex mharden-sls
|
||||
+Generate code to mitigate against straight line speculation (SLS) with
|
||||
+@var{choice}. The default is @samp{none} which disables all SLS
|
||||
+hardening. @samp{return} enables SLS hardening for function return.
|
||||
+@samp{indirect-branch} enables SLS hardening for indirect branch.
|
||||
+@samp{all} enables all SLS hardening.
|
||||
+
|
||||
@end table
|
||||
|
||||
These @samp{-m} switches are supported in addition to the above
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-1.c b/gcc/testsuite/gcc.target/i386/harden-sls-1.c
|
||||
new file mode 100644
|
||||
index 00000000000..6f70dc94a23
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-1.c
|
||||
@@ -0,0 +1,14 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */
|
||||
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
|
||||
+
|
||||
+extern void foo (void);
|
||||
+
|
||||
+void
|
||||
+bar (void)
|
||||
+{
|
||||
+ foo ();
|
||||
+}
|
||||
+
|
||||
+/* { dg-final { scan-assembler "jmp\[ \t\]+_?foo" } } */
|
||||
+/* { dg-final { scan-assembler-not {int3} } } */
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-2.c b/gcc/testsuite/gcc.target/i386/harden-sls-2.c
|
||||
new file mode 100644
|
||||
index 00000000000..a7c59078d03
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-2.c
|
||||
@@ -0,0 +1,14 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */
|
||||
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
|
||||
+
|
||||
+extern void (*fptr) (void);
|
||||
+
|
||||
+void
|
||||
+foo (void)
|
||||
+{
|
||||
+ fptr ();
|
||||
+}
|
||||
+
|
||||
+/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */
|
||||
+/* { dg-final { scan-assembler-times "int3" 1 } } */
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-3.c b/gcc/testsuite/gcc.target/i386/harden-sls-3.c
|
||||
new file mode 100644
|
||||
index 00000000000..1a6056b6d7b
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-3.c
|
||||
@@ -0,0 +1,14 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -mindirect-branch=thunk -mharden-sls=all" } */
|
||||
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
|
||||
+
|
||||
+extern void (*fptr) (void);
|
||||
+
|
||||
+void
|
||||
+foo (void)
|
||||
+{
|
||||
+ fptr ();
|
||||
+}
|
||||
+
|
||||
+/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */
|
||||
+/* { dg-final { scan-assembler-times "int3" 2 } } */
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-4.c b/gcc/testsuite/gcc.target/i386/harden-sls-4.c
|
||||
new file mode 100644
|
||||
index 00000000000..f70dd1379d3
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-4.c
|
||||
@@ -0,0 +1,16 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -mindirect-branch=keep -mharden-sls=all" } */
|
||||
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
|
||||
+
|
||||
+extern void (*fptr) (void);
|
||||
+
|
||||
+void
|
||||
+foo (void)
|
||||
+{
|
||||
+ fptr ();
|
||||
+}
|
||||
+
|
||||
+/* { dg-final { scan-assembler "jmp\[ \t\]+\\*_?fptr" { target { ! x32 } } } } */
|
||||
+/* { dg-final { scan-assembler "movl\[ \t\]+fptr\\(%rip\\), %eax" { target x32 } } } */
|
||||
+/* { dg-final { scan-assembler "jmp\[ \t\]+\\*%rax" { target x32 } } } */
|
||||
+/* { dg-final { scan-assembler-times "int3" 1 } } */
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-5.c b/gcc/testsuite/gcc.target/i386/harden-sls-5.c
|
||||
new file mode 100644
|
||||
index 00000000000..613c44c6f82
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-5.c
|
||||
@@ -0,0 +1,17 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -mharden-sls=return" } */
|
||||
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
|
||||
+
|
||||
+typedef void (*dispatch_t)(long offset);
|
||||
+
|
||||
+dispatch_t dispatch;
|
||||
+
|
||||
+int
|
||||
+male_indirect_jump (long offset)
|
||||
+{
|
||||
+ dispatch(offset);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* { dg-final { scan-assembler-times "ret" 1 } } */
|
||||
+/* { dg-final { scan-assembler-times "int3" 1 } } */
|
||||
--
|
||||
2.36.1
|
||||
|
||||
@ -1,155 +0,0 @@
|
||||
From 0df8313a0a5d8533f2487e21d7b42e9adee28f18 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Wed, 27 Oct 2021 06:27:15 -0700
|
||||
Subject: [PATCH 2/4] x86: Add -mindirect-branch-cs-prefix
|
||||
|
||||
Add -mindirect-branch-cs-prefix to add CS prefix to call and jmp to
|
||||
indirect thunk with branch target in r8-r15 registers so that the call
|
||||
and jmp instruction length is 6 bytes to allow them to be replaced with
|
||||
"lfence; call *%r8-r15" or "lfence; jmp *%r8-r15" at run-time.
|
||||
|
||||
gcc/
|
||||
|
||||
PR target/102952
|
||||
* config/i386/i386.c (ix86_output_jmp_thunk_or_indirect): Emit
|
||||
CS prefix for -mindirect-branch-cs-prefix.
|
||||
(ix86_output_indirect_branch_via_reg): Likewise.
|
||||
* config/i386/i386.opt: Add -mindirect-branch-cs-prefix.
|
||||
* doc/invoke.texi: Document -mindirect-branch-cs-prefix.
|
||||
|
||||
gcc/testsuite/
|
||||
|
||||
PR target/102952
|
||||
* gcc.target/i386/indirect-thunk-cs-prefix-1.c: New test.
|
||||
* gcc.target/i386/indirect-thunk-cs-prefix-2.c: Likewise.
|
||||
|
||||
(cherry picked from commit 2196a681d7810ad8b227bf983f38ba716620545e)
|
||||
---
|
||||
gcc/config/i386/i386.c | 14 ++++++++++++--
|
||||
gcc/config/i386/i386.opt | 4 ++++
|
||||
gcc/doc/invoke.texi | 10 +++++++++-
|
||||
.../gcc.target/i386/indirect-thunk-cs-prefix-1.c | 14 ++++++++++++++
|
||||
.../gcc.target/i386/indirect-thunk-cs-prefix-2.c | 15 +++++++++++++++
|
||||
5 files changed, 54 insertions(+), 3 deletions(-)
|
||||
create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c
|
||||
create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c
|
||||
|
||||
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
|
||||
index eb9303f8742..8442dd0daea 100644
|
||||
--- a/gcc/config/i386/i386.c
|
||||
+++ b/gcc/config/i386/i386.c
|
||||
@@ -28728,7 +28728,12 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name,
|
||||
if (need_prefix == indirect_thunk_prefix_bnd)
|
||||
fprintf (asm_out_file, "\tbnd jmp\t");
|
||||
else
|
||||
- fprintf (asm_out_file, "\tjmp\t");
|
||||
+ {
|
||||
+ if (REX_INT_REGNO_P (regno)
|
||||
+ && ix86_indirect_branch_cs_prefix)
|
||||
+ fprintf (asm_out_file, "\tcs\n");
|
||||
+ fprintf (asm_out_file, "\tjmp\t");
|
||||
+ }
|
||||
assemble_name (asm_out_file, thunk_name);
|
||||
putc ('\n', asm_out_file);
|
||||
if ((ix86_harden_sls & harden_sls_indirect_branch))
|
||||
@@ -28787,7 +28792,12 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
|
||||
if (need_prefix == indirect_thunk_prefix_bnd)
|
||||
fprintf (asm_out_file, "\tbnd call\t");
|
||||
else
|
||||
- fprintf (asm_out_file, "\tcall\t");
|
||||
+ {
|
||||
+ if (REX_INT_REGNO_P (regno)
|
||||
+ && ix86_indirect_branch_cs_prefix)
|
||||
+ fprintf (asm_out_file, "\tcs\n");
|
||||
+ fprintf (asm_out_file, "\tcall\t");
|
||||
+ }
|
||||
assemble_name (asm_out_file, thunk_name);
|
||||
putc ('\n', asm_out_file);
|
||||
return;
|
||||
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
|
||||
index 3ae48609e25..9f67ef558dc 100644
|
||||
--- a/gcc/config/i386/i386.opt
|
||||
+++ b/gcc/config/i386/i386.opt
|
||||
@@ -1044,6 +1044,10 @@ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
|
||||
EnumValue
|
||||
Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
|
||||
|
||||
+mindirect-branch-cs-prefix
|
||||
+Target Var(ix86_indirect_branch_cs_prefix) Init(0)
|
||||
+Add CS prefix to call and jmp to indirect thunk with branch target in r8-r15 registers.
|
||||
+
|
||||
mindirect-branch-register
|
||||
Target Report Var(ix86_indirect_branch_register) Init(0)
|
||||
Force indirect call and jump via register.
|
||||
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
|
||||
index 1e20efd6969..605cd4b93f1 100644
|
||||
--- a/gcc/doc/invoke.texi
|
||||
+++ b/gcc/doc/invoke.texi
|
||||
@@ -1284,7 +1284,8 @@ See RS/6000 and PowerPC Options.
|
||||
-mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol
|
||||
-mgeneral-regs-only -mcall-ms2sysv-xlogues @gol
|
||||
-mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol
|
||||
--mindirect-branch-register -mharden-sls=@var{choice}}
|
||||
+-mindirect-branch-register -mharden-sls=@var{choice} @gol
|
||||
+-mindirect-branch-cs-prefix}
|
||||
|
||||
@emph{x86 Windows Options}
|
||||
@gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
|
||||
@@ -28044,6 +28045,13 @@ hardening. @samp{return} enables SLS hardening for function return.
|
||||
@samp{indirect-branch} enables SLS hardening for indirect branch.
|
||||
@samp{all} enables all SLS hardening.
|
||||
|
||||
+@item -mindirect-branch-cs-prefix
|
||||
+@opindex mindirect-branch-cs-prefix
|
||||
+Add CS prefix to call and jmp to indirect thunk with branch target in
|
||||
+r8-r15 registers so that the call and jmp instruction length is 6 bytes
|
||||
+to allow them to be replaced with @samp{lfence; call *%r8-r15} or
|
||||
+@samp{lfence; jmp *%r8-r15} at run-time.
|
||||
+
|
||||
@end table
|
||||
|
||||
These @samp{-m} switches are supported in addition to the above
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c
|
||||
new file mode 100644
|
||||
index 00000000000..db2f3416823
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c
|
||||
@@ -0,0 +1,14 @@
|
||||
+/* { dg-do compile { target { ! ia32 } } } */
|
||||
+/* { dg-options "-O2 -ffixed-rax -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rdi -ffixed-rsi -mindirect-branch-cs-prefix -mindirect-branch=thunk-extern" } */
|
||||
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
|
||||
+
|
||||
+extern void (*fptr) (void);
|
||||
+
|
||||
+void
|
||||
+foo (void)
|
||||
+{
|
||||
+ fptr ();
|
||||
+}
|
||||
+
|
||||
+/* { dg-final { scan-assembler-times "jmp\[ \t\]+_?__x86_indirect_thunk_r\[0-9\]+" 1 } } */
|
||||
+/* { dg-final { scan-assembler-times "\tcs" 1 } } */
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c
|
||||
new file mode 100644
|
||||
index 00000000000..adfc39a49d4
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c
|
||||
@@ -0,0 +1,15 @@
|
||||
+/* { dg-do compile { target { ! ia32 } } } */
|
||||
+/* { dg-options "-O2 -ffixed-rax -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rdi -ffixed-rsi -mindirect-branch-cs-prefix -mindirect-branch=thunk-extern" } */
|
||||
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
|
||||
+
|
||||
+extern void (*bar) (void);
|
||||
+
|
||||
+int
|
||||
+foo (void)
|
||||
+{
|
||||
+ bar ();
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* { dg-final { scan-assembler-times "call\[ \t\]+_?__x86_indirect_thunk_r\[0-9\]+" 1 } } */
|
||||
+/* { dg-final { scan-assembler-times "\tcs" 1 } } */
|
||||
--
|
||||
2.36.1
|
||||
|
||||
@ -1,108 +0,0 @@
|
||||
From 621de498ee19e1f2642eebde707430254c0459c0 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Wed, 5 Jan 2022 16:33:16 -0800
|
||||
Subject: [PATCH 3/4] x86: Rename -harden-sls=indirect-branch to
|
||||
-harden-sls=indirect-jmp
|
||||
|
||||
Indirect branch also includes indirect call instructions. Rename
|
||||
-harden-sls=indirect-branch to -harden-sls=indirect-jmp to match its
|
||||
intended behavior.
|
||||
|
||||
PR target/102952
|
||||
* config/i386/i386-opts.h (harden_sls): Replace
|
||||
harden_sls_indirect_branch with harden_sls_indirect_jmp.
|
||||
* config/i386/i386.c (ix86_output_jmp_thunk_or_indirect):
|
||||
Likewise.
|
||||
(ix86_output_indirect_jmp): Likewise.
|
||||
(ix86_output_call_insn): Likewise.
|
||||
* config/i386/i386.opt: Replace indirect-branch with
|
||||
indirect-jmp. Replace harden_sls_indirect_branch with
|
||||
harden_sls_indirect_jmp.
|
||||
* doc/invoke.texi (-harden-sls=): Replace indirect-branch with
|
||||
indirect-jmp.
|
||||
|
||||
(cherry picked from commit ed8060950c64f2e449aaf90e438aa26d0d9d0b31)
|
||||
---
|
||||
gcc/config/i386/i386-opts.h | 4 ++--
|
||||
gcc/config/i386/i386.c | 6 +++---
|
||||
gcc/config/i386/i386.opt | 2 +-
|
||||
gcc/doc/invoke.texi | 4 ++--
|
||||
4 files changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
|
||||
index 34718b6d52c..47facc254cd 100644
|
||||
--- a/gcc/config/i386/i386-opts.h
|
||||
+++ b/gcc/config/i386/i386-opts.h
|
||||
@@ -122,8 +122,8 @@ enum indirect_branch {
|
||||
enum harden_sls {
|
||||
harden_sls_none = 0,
|
||||
harden_sls_return = 1 << 0,
|
||||
- harden_sls_indirect_branch = 1 << 1,
|
||||
- harden_sls_all = harden_sls_return | harden_sls_indirect_branch
|
||||
+ harden_sls_indirect_jmp = 1 << 1,
|
||||
+ harden_sls_all = harden_sls_return | harden_sls_indirect_jmp
|
||||
};
|
||||
|
||||
#endif
|
||||
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
|
||||
index 8442dd0daea..3bc14e20105 100644
|
||||
--- a/gcc/config/i386/i386.c
|
||||
+++ b/gcc/config/i386/i386.c
|
||||
@@ -28736,7 +28736,7 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name,
|
||||
}
|
||||
assemble_name (asm_out_file, thunk_name);
|
||||
putc ('\n', asm_out_file);
|
||||
- if ((ix86_harden_sls & harden_sls_indirect_branch))
|
||||
+ if ((ix86_harden_sls & harden_sls_indirect_jmp))
|
||||
fputs ("\tint3\n", asm_out_file);
|
||||
}
|
||||
else
|
||||
@@ -28991,7 +28991,7 @@ ix86_output_indirect_jmp (rtx call_op)
|
||||
}
|
||||
else
|
||||
output_asm_insn ("%!jmp\t%A0", &call_op);
|
||||
- return (ix86_harden_sls & harden_sls_indirect_branch) ? "int3" : "";
|
||||
+ return (ix86_harden_sls & harden_sls_indirect_jmp) ? "int3" : "";
|
||||
}
|
||||
|
||||
/* Output function return. CALL_OP is the jump target. Add a REP
|
||||
@@ -29178,7 +29178,7 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
|
||||
{
|
||||
output_asm_insn (xasm, &call_op);
|
||||
if (!direct_p
|
||||
- && (ix86_harden_sls & harden_sls_indirect_branch))
|
||||
+ && (ix86_harden_sls & harden_sls_indirect_jmp))
|
||||
return "int3";
|
||||
}
|
||||
return "";
|
||||
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
|
||||
index 9f67ef558dc..7a5c7b9369a 100644
|
||||
--- a/gcc/config/i386/i386.opt
|
||||
+++ b/gcc/config/i386/i386.opt
|
||||
@@ -1075,7 +1075,7 @@ EnumValue
|
||||
Enum(harden_sls) String(return) Value(harden_sls_return)
|
||||
|
||||
EnumValue
|
||||
-Enum(harden_sls) String(indirect-branch) Value(harden_sls_indirect_branch)
|
||||
+Enum(harden_sls) String(indirect-jmp) Value(harden_sls_indirect_jmp)
|
||||
|
||||
EnumValue
|
||||
Enum(harden_sls) String(all) Value(harden_sls_all)
|
||||
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
|
||||
index 605cd4b93f1..20d8e3fd782 100644
|
||||
--- a/gcc/doc/invoke.texi
|
||||
+++ b/gcc/doc/invoke.texi
|
||||
@@ -28041,8 +28041,8 @@ Force indirect call and jump via register.
|
||||
@opindex mharden-sls
|
||||
Generate code to mitigate against straight line speculation (SLS) with
|
||||
@var{choice}. The default is @samp{none} which disables all SLS
|
||||
-hardening. @samp{return} enables SLS hardening for function return.
|
||||
-@samp{indirect-branch} enables SLS hardening for indirect branch.
|
||||
+hardening. @samp{return} enables SLS hardening for function returns.
|
||||
+@samp{indirect-jmp} enables SLS hardening for indirect jumps.
|
||||
@samp{all} enables all SLS hardening.
|
||||
|
||||
@item -mindirect-branch-cs-prefix
|
||||
--
|
||||
2.36.1
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
From 5a5e7890cefa112e95e1de9800d8081c2a38a1da Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Wed, 5 Jan 2022 18:04:21 -0800
|
||||
Subject: [PATCH 4/4] x86: Generate INT3 for __builtin_eh_return
|
||||
|
||||
Generate INT3 after indirect jmp in exception return for -fcf-protection
|
||||
with -mharden-sls=indirect-jmp.
|
||||
|
||||
gcc/
|
||||
|
||||
PR target/103925
|
||||
* config/i386/i386.c (ix86_output_indirect_function_return):
|
||||
Generate INT3 after indirect jmp for -mharden-sls=indirect-jmp.
|
||||
|
||||
gcc/testsuite/
|
||||
|
||||
PR target/103925
|
||||
* gcc.target/i386/harden-sls-6.c: New test.
|
||||
|
||||
(cherry picked from commit c2e5c4feed32c808591b5278f680bbabe63eb225)
|
||||
---
|
||||
gcc/config/i386/i386.c | 9 ++++++---
|
||||
gcc/testsuite/gcc.target/i386/harden-sls-6.c | 18 ++++++++++++++++++
|
||||
2 files changed, 24 insertions(+), 3 deletions(-)
|
||||
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-6.c
|
||||
|
||||
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
|
||||
index 3bc14e20105..dbc3d462fda 100644
|
||||
--- a/gcc/config/i386/i386.c
|
||||
+++ b/gcc/config/i386/i386.c
|
||||
@@ -29083,11 +29083,14 @@ ix86_output_indirect_function_return (rtx ret_op)
|
||||
}
|
||||
else
|
||||
output_indirect_thunk (need_prefix, regno);
|
||||
-
|
||||
- return "";
|
||||
}
|
||||
else
|
||||
- return "%!jmp\t%A0";
|
||||
+ {
|
||||
+ output_asm_insn ("%!jmp\t%A0", &ret_op);
|
||||
+ if (ix86_harden_sls & harden_sls_indirect_jmp)
|
||||
+ fputs ("\tint3\n", asm_out_file);
|
||||
+ }
|
||||
+ return "";
|
||||
}
|
||||
|
||||
/* Split simple return with popping POPC bytes from stack to indirect
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-6.c b/gcc/testsuite/gcc.target/i386/harden-sls-6.c
|
||||
new file mode 100644
|
||||
index 00000000000..9068eb64008
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-6.c
|
||||
@@ -0,0 +1,18 @@
|
||||
+/* { dg-do compile { target { ! ia32 } } } */
|
||||
+/* { dg-options "-O2 -fcf-protection -mharden-sls=indirect-jmp" } */
|
||||
+
|
||||
+struct _Unwind_Context _Unwind_Resume_or_Rethrow_this_context;
|
||||
+
|
||||
+void offset (int);
|
||||
+
|
||||
+struct _Unwind_Context {
|
||||
+ void *reg[7];
|
||||
+} _Unwind_Resume_or_Rethrow() {
|
||||
+ struct _Unwind_Context cur_contextcur_context =
|
||||
+ _Unwind_Resume_or_Rethrow_this_context;
|
||||
+ offset(0);
|
||||
+ __builtin_eh_return ((long) offset, 0);
|
||||
+}
|
||||
+
|
||||
+/* { dg-final { scan-assembler "jmp\[ \t\]+\\*%rcx" } } */
|
||||
+/* { dg-final { scan-assembler-times "int3" 1 } } */
|
||||
--
|
||||
2.36.1
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
--- libgomp/configure.tgt.jj 2008-01-10 20:53:48.000000000 +0100
|
||||
+++ libgomp/configure.tgt 2008-03-27 12:44:51.000000000 +0100
|
||||
@@ -67,7 +67,7 @@ if test $enable_linux_futex = yes; then
|
||||
;;
|
||||
*)
|
||||
if test -z "$with_arch"; then
|
||||
- XCFLAGS="${XCFLAGS} -march=i486 -mtune=${target_cpu}"
|
||||
+ XCFLAGS="${XCFLAGS} -march=i486 -mtune=generic"
|
||||
fi
|
||||
esac
|
||||
;;
|
||||
@ -1,14 +0,0 @@
|
||||
--- libgcc/config/t-slibgcc.mp 2018-10-03 16:07:00.336990246 -0400
|
||||
+++ libgcc/config/t-slibgcc 2018-10-03 16:06:26.719946740 -0400
|
||||
@@ -30,9 +30,10 @@ SHLIB_LC = -lc
|
||||
SHLIB_MAKE_SOLINK = $(LN_S) $(SHLIB_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
|
||||
SHLIB_INSTALL_SOLINK = $(LN_S) $(SHLIB_SONAME) \
|
||||
$(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
|
||||
+SHLIB_EXTRA_LDFLAGS = -Wl,-z,relro -Wl,-z,now
|
||||
|
||||
SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
|
||||
- $(SHLIB_LDFLAGS) \
|
||||
+ $(SHLIB_LDFLAGS) $(SHLIB_EXTRA_LDFLAGS) \
|
||||
-o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
|
||||
$(SHLIB_OBJS) $(SHLIB_LC) && \
|
||||
rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \
|
||||
@ -1,516 +0,0 @@
|
||||
diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c
|
||||
index d93dcfa..f47565c 100644
|
||||
--- a/gcc/fortran/io.c
|
||||
+++ b/gcc/fortran/io.c
|
||||
@@ -909,6 +909,13 @@ data_desc:
|
||||
|
||||
if (u != FMT_POSINT)
|
||||
{
|
||||
+ if (flag_dec)
|
||||
+ {
|
||||
+ /* Assume a default width based on the variable size. */
|
||||
+ saved_token = u;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
format_locus.nextc += format_string_pos;
|
||||
gfc_error ("Positive width required in format "
|
||||
"specifier %s at %L", token_to_string (t),
|
||||
@@ -1030,6 +1037,13 @@ data_desc:
|
||||
goto fail;
|
||||
if (t != FMT_ZERO && t != FMT_POSINT)
|
||||
{
|
||||
+ if (flag_dec)
|
||||
+ {
|
||||
+ /* Assume the default width is expected here and continue lexing. */
|
||||
+ value = 0; /* It doesn't matter what we set the value to here. */
|
||||
+ saved_token = t;
|
||||
+ break;
|
||||
+ }
|
||||
error = nonneg_required;
|
||||
goto syntax;
|
||||
}
|
||||
@@ -1099,8 +1113,17 @@ data_desc:
|
||||
goto fail;
|
||||
if (t != FMT_ZERO && t != FMT_POSINT)
|
||||
{
|
||||
- error = nonneg_required;
|
||||
- goto syntax;
|
||||
+ if (flag_dec)
|
||||
+ {
|
||||
+ /* Assume the default width is expected here and continue lexing. */
|
||||
+ value = 0; /* It doesn't matter what we set the value to here. */
|
||||
+ saved_token = t;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ error = nonneg_required;
|
||||
+ goto syntax;
|
||||
+ }
|
||||
}
|
||||
else if (is_input && t == FMT_ZERO)
|
||||
{
|
||||
diff --git a/gcc/testsuite/gfortran.dg/fmt_f_default_field_width.f90 b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width.f90
|
||||
new file mode 100644
|
||||
index 0000000..b087b8f
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width.f90
|
||||
@@ -0,0 +1,43 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options -fdec }
|
||||
+!
|
||||
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
|
||||
+!
|
||||
+! This feature is not part of any Fortran standard, but it is supported by the
|
||||
+! Oracle Fortran compiler and others.
|
||||
+!
|
||||
+! libgfortran uses printf() internally to implement FORMAT. If you print float
|
||||
+! values to a higher precision than the type can actually store, the results
|
||||
+! are implementation dependent: some platforms print zeros, others print random
|
||||
+! numbers. Don't depend on this behaviour in tests because they will not be
|
||||
+! portable.
|
||||
+
|
||||
+ character(50) :: buffer
|
||||
+
|
||||
+ real*4 :: real_4
|
||||
+ real*8 :: real_8
|
||||
+ real*16 :: real_16
|
||||
+ integer :: len
|
||||
+
|
||||
+ real_4 = 4.18
|
||||
+ write(buffer, '(A, F, A)') ':',real_4,':'
|
||||
+ print *,buffer
|
||||
+ if (buffer.ne.": 4.1799998:") call abort
|
||||
+
|
||||
+ real_4 = 0.00000018
|
||||
+ write(buffer, '(A, F, A)') ':',real_4,':'
|
||||
+ print *,buffer
|
||||
+ if (buffer.ne.": 0.0000002:") call abort
|
||||
+
|
||||
+ real_8 = 4.18
|
||||
+ write(buffer, '(A, F, A)') ':',real_8,':'
|
||||
+ print *,buffer
|
||||
+ len = len_trim(buffer)
|
||||
+ if (len /= 27) call abort
|
||||
+
|
||||
+ real_16 = 4.18
|
||||
+ write(buffer, '(A, F, A)') ':',real_16,':'
|
||||
+ print *,buffer
|
||||
+ len = len_trim(buffer)
|
||||
+ if (len /= 44) call abort
|
||||
+end
|
||||
diff --git a/gcc/testsuite/gfortran.dg/fmt_g_default_field_width.f90 b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width.f90
|
||||
new file mode 100644
|
||||
index 0000000..3d3a476
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width.f90
|
||||
@@ -0,0 +1,48 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options -fdec }
|
||||
+!
|
||||
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
|
||||
+!
|
||||
+! This feature is not part of any Fortran standard, but it is supported by the
|
||||
+! Oracle Fortran compiler and others.
|
||||
+!
|
||||
+! libgfortran uses printf() internally to implement FORMAT. If you print float
|
||||
+! values to a higher precision than the type can actually store, the results
|
||||
+! are implementation dependent: some platforms print zeros, others print random
|
||||
+! numbers. Don't depend on this behaviour in tests because they will not be
|
||||
+! portable.
|
||||
+
|
||||
+ character(50) :: buffer
|
||||
+
|
||||
+ real*4 :: real_4
|
||||
+ real*8 :: real_8
|
||||
+ real*16 :: real_16
|
||||
+ integer :: len
|
||||
+
|
||||
+ real_4 = 4.18
|
||||
+ write(buffer, '(A, G, A)') ':',real_4,':'
|
||||
+ print *,buffer
|
||||
+ if (buffer.ne.": 4.180000 :") call abort
|
||||
+
|
||||
+ real_4 = 0.00000018
|
||||
+ write(buffer, '(A, G, A)') ':',real_4,':'
|
||||
+ print *,buffer
|
||||
+ if (buffer.ne.": 0.1800000E-06:") call abort
|
||||
+
|
||||
+ real_4 = 18000000.4
|
||||
+ write(buffer, '(A, G, A)') ':',real_4,':'
|
||||
+ print *,buffer
|
||||
+ if (buffer.ne.": 0.1800000E+08:") call abort
|
||||
+
|
||||
+ real_8 = 4.18
|
||||
+ write(buffer, '(A, G, A)') ':',real_8,':'
|
||||
+ print *,buffer
|
||||
+ len = len_trim(buffer)
|
||||
+ if (len /= 27) call abort
|
||||
+
|
||||
+ real_16 = 4.18
|
||||
+ write(buffer, '(A, G, A)') ':',real_16,':'
|
||||
+ print *,buffer
|
||||
+ len = len_trim(buffer)
|
||||
+ if (len /= 44) call abort
|
||||
+end
|
||||
diff --git a/gcc/testsuite/gfortran.dg/fmt_i_default_field_width.f90 b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width.f90
|
||||
new file mode 100644
|
||||
index 0000000..ac4e165
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width.f90
|
||||
@@ -0,0 +1,38 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options -fdec }
|
||||
+!
|
||||
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
|
||||
+!
|
||||
+! This feature is not part of any Fortran standard, but it is supported by the
|
||||
+! Oracle Fortran compiler and others.
|
||||
+
|
||||
+ character(50) :: buffer
|
||||
+ character(1) :: colon
|
||||
+
|
||||
+ integer*2 :: integer_2
|
||||
+ integer*4 :: integer_4
|
||||
+ integer*8 :: integer_8
|
||||
+
|
||||
+ write(buffer, '(A, I, A)') ':',12340,':'
|
||||
+ print *,buffer
|
||||
+ if (buffer.ne.": 12340:") call abort
|
||||
+
|
||||
+ read(buffer, '(A1, I, A1)') colon, integer_4, colon
|
||||
+ if (integer_4.ne.12340) call abort
|
||||
+
|
||||
+ integer_2 = -99
|
||||
+ write(buffer, '(A, I, A)') ':',integer_2,':'
|
||||
+ print *,buffer
|
||||
+ if (buffer.ne.": -99:") call abort
|
||||
+
|
||||
+ integer_8 = -11112222
|
||||
+ write(buffer, '(A, I, A)') ':',integer_8,':'
|
||||
+ print *,buffer
|
||||
+ if (buffer.ne.": -11112222:") call abort
|
||||
+
|
||||
+! If the width is 7 and there are 7 leading zeroes, the result should be zero.
|
||||
+ integer_2 = 789
|
||||
+ buffer = '0000000789'
|
||||
+ read(buffer, '(I)') integer_2
|
||||
+ if (integer_2.ne.0) call abort
|
||||
+end
|
||||
diff --git a/libgfortran/io/format.c b/libgfortran/io/format.c
|
||||
index c2abdd7..692b1ff 100644
|
||||
--- a/libgfortran/io/format.c
|
||||
+++ b/libgfortran/io/format.c
|
||||
@@ -956,12 +956,33 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd)
|
||||
*seen_dd = true;
|
||||
if (u != FMT_POSINT && u != FMT_ZERO)
|
||||
{
|
||||
+ if (dtp->common.flags & IOPARM_DT_DEC_EXT)
|
||||
+ {
|
||||
+ tail->u.real.w = DEFAULT_WIDTH;
|
||||
+ tail->u.real.d = 0;
|
||||
+ tail->u.real.e = -1;
|
||||
+ fmt->saved_token = u;
|
||||
+ break;
|
||||
+ }
|
||||
fmt->error = nonneg_required;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
+ else if (u == FMT_ZERO)
|
||||
+ {
|
||||
+ fmt->error = posint_required;
|
||||
+ goto finished;
|
||||
+ }
|
||||
else if (u != FMT_POSINT)
|
||||
{
|
||||
+ if (dtp->common.flags & IOPARM_DT_DEC_EXT)
|
||||
+ {
|
||||
+ tail->u.real.w = DEFAULT_WIDTH;
|
||||
+ tail->u.real.d = 0;
|
||||
+ tail->u.real.e = -1;
|
||||
+ fmt->saved_token = u;
|
||||
+ break;
|
||||
+ }
|
||||
fmt->error = posint_required;
|
||||
goto finished;
|
||||
}
|
||||
@@ -1099,6 +1120,13 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd)
|
||||
{
|
||||
if (t != FMT_POSINT)
|
||||
{
|
||||
+ if (dtp->common.flags & IOPARM_DT_DEC_EXT)
|
||||
+ {
|
||||
+ tail->u.integer.w = DEFAULT_WIDTH;
|
||||
+ tail->u.integer.m = -1;
|
||||
+ fmt->saved_token = t;
|
||||
+ break;
|
||||
+ }
|
||||
fmt->error = posint_required;
|
||||
goto finished;
|
||||
}
|
||||
@@ -1107,6 +1135,13 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd)
|
||||
{
|
||||
if (t != FMT_ZERO && t != FMT_POSINT)
|
||||
{
|
||||
+ if (dtp->common.flags & IOPARM_DT_DEC_EXT)
|
||||
+ {
|
||||
+ tail->u.integer.w = DEFAULT_WIDTH;
|
||||
+ tail->u.integer.m = -1;
|
||||
+ fmt->saved_token = t;
|
||||
+ break;
|
||||
+ }
|
||||
fmt->error = nonneg_required;
|
||||
goto finished;
|
||||
}
|
||||
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
|
||||
index 5583183..d1d08e8 100644
|
||||
--- a/libgfortran/io/io.h
|
||||
+++ b/libgfortran/io/io.h
|
||||
@@ -981,5 +981,55 @@ memset4 (gfc_char4_t *p, gfc_char4_t c, int k)
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
+/* Used in width fields to indicate that the default should be used */
|
||||
+#define DEFAULT_WIDTH -1
|
||||
+
|
||||
+/* Defaults for certain format field descriptors. These are decided based on
|
||||
+ * the type of the value being formatted.
|
||||
+ *
|
||||
+ * The behaviour here is modelled on the Oracle Fortran compiler. At the time
|
||||
+ * of writing, the details were available at this URL:
|
||||
+ *
|
||||
+ * https://docs.oracle.com/cd/E19957-01/805-4939/6j4m0vnc3/index.html#z4000743746d
|
||||
+ */
|
||||
+
|
||||
+static inline int
|
||||
+default_width_for_integer (int kind)
|
||||
+{
|
||||
+ switch (kind)
|
||||
+ {
|
||||
+ case 1:
|
||||
+ case 2: return 7;
|
||||
+ case 4: return 12;
|
||||
+ case 8: return 23;
|
||||
+ case 16: return 44;
|
||||
+ default: return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static inline int
|
||||
+default_width_for_float (int kind)
|
||||
+{
|
||||
+ switch (kind)
|
||||
+ {
|
||||
+ case 4: return 15;
|
||||
+ case 8: return 25;
|
||||
+ case 16: return 42;
|
||||
+ default: return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static inline int
|
||||
+default_precision_for_float (int kind)
|
||||
+{
|
||||
+ switch (kind)
|
||||
+ {
|
||||
+ case 4: return 7;
|
||||
+ case 8: return 16;
|
||||
+ case 16: return 33;
|
||||
+ default: return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#endif
|
||||
|
||||
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c
|
||||
index 2c9de48..e911e35 100644
|
||||
--- a/libgfortran/io/read.c
|
||||
+++ b/libgfortran/io/read.c
|
||||
@@ -629,6 +629,12 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
||||
|
||||
w = f->u.w;
|
||||
|
||||
+ /* This is a legacy extension, and the frontend will only allow such cases
|
||||
+ * through when -fdec-format-defaults is passed.
|
||||
+ */
|
||||
+ if (w == DEFAULT_WIDTH)
|
||||
+ w = default_width_for_integer (length);
|
||||
+
|
||||
p = read_block_form (dtp, &w);
|
||||
|
||||
if (p == NULL)
|
||||
diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c
|
||||
index a7307a8..c8e52fb 100644
|
||||
--- a/libgfortran/io/write.c
|
||||
+++ b/libgfortran/io/write.c
|
||||
@@ -684,9 +684,8 @@ write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len)
|
||||
p[wlen - 1] = (n) ? 'T' : 'F';
|
||||
}
|
||||
|
||||
-
|
||||
static void
|
||||
-write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n)
|
||||
+write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n, int len)
|
||||
{
|
||||
int w, m, digits, nzero, nblank;
|
||||
char *p;
|
||||
@@ -719,6 +718,9 @@ write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n)
|
||||
/* Select a width if none was specified. The idea here is to always
|
||||
print something. */
|
||||
|
||||
+ if (w == DEFAULT_WIDTH)
|
||||
+ w = default_width_for_integer (len);
|
||||
+
|
||||
if (w == 0)
|
||||
w = ((digits < m) ? m : digits);
|
||||
|
||||
@@ -845,6 +847,8 @@ write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
|
||||
|
||||
/* Select a width if none was specified. The idea here is to always
|
||||
print something. */
|
||||
+ if (w == DEFAULT_WIDTH)
|
||||
+ w = default_width_for_integer (len);
|
||||
|
||||
if (w == 0)
|
||||
w = ((digits < m) ? m : digits) + nsign;
|
||||
@@ -1187,13 +1191,13 @@ write_b (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
|
||||
if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
|
||||
{
|
||||
p = btoa_big (source, itoa_buf, len, &n);
|
||||
- write_boz (dtp, f, p, n);
|
||||
+ write_boz (dtp, f, p, n, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = extract_uint (source, len);
|
||||
p = btoa (n, itoa_buf, sizeof (itoa_buf));
|
||||
- write_boz (dtp, f, p, n);
|
||||
+ write_boz (dtp, f, p, n, len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1208,13 +1212,13 @@ write_o (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
|
||||
if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
|
||||
{
|
||||
p = otoa_big (source, itoa_buf, len, &n);
|
||||
- write_boz (dtp, f, p, n);
|
||||
+ write_boz (dtp, f, p, n, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = extract_uint (source, len);
|
||||
p = otoa (n, itoa_buf, sizeof (itoa_buf));
|
||||
- write_boz (dtp, f, p, n);
|
||||
+ write_boz (dtp, f, p, n, len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1228,13 +1232,13 @@ write_z (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
|
||||
if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
|
||||
{
|
||||
p = ztoa_big (source, itoa_buf, len, &n);
|
||||
- write_boz (dtp, f, p, n);
|
||||
+ write_boz (dtp, f, p, n, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = extract_uint (source, len);
|
||||
p = gfc_xtoa (n, itoa_buf, sizeof (itoa_buf));
|
||||
- write_boz (dtp, f, p, n);
|
||||
+ write_boz (dtp, f, p, n, len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1504,7 +1508,7 @@ size_from_kind (st_parameter_dt *dtp, const fnode *f, int kind)
|
||||
{
|
||||
int size;
|
||||
|
||||
- if (f->format == FMT_F && f->u.real.w == 0)
|
||||
+ if ((f->format == FMT_F && f->u.real.w == 0) || f->u.real.w == DEFAULT_WIDTH)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def
|
||||
index 7f0aa1d..73dc910 100644
|
||||
--- a/libgfortran/io/write_float.def
|
||||
+++ b/libgfortran/io/write_float.def
|
||||
@@ -113,7 +113,8 @@ determine_precision (st_parameter_dt * d
|
||||
static void
|
||||
build_float_string (st_parameter_dt *dtp, const fnode *f, char *buffer,
|
||||
size_t size, int nprinted, int precision, int sign_bit,
|
||||
- bool zero_flag, int npad, char *result, size_t *len)
|
||||
+ bool zero_flag, int npad, int default_width, char *result,
|
||||
+ size_t *len)
|
||||
{
|
||||
char *put;
|
||||
char *digits;
|
||||
@@ -132,8 +133,17 @@ build_float_string (st_parameter_dt *dtp
|
||||
sign_t sign;
|
||||
|
||||
ft = f->format;
|
||||
- w = f->u.real.w;
|
||||
- d = f->u.real.d;
|
||||
+ if (f->u.real.w == DEFAULT_WIDTH)
|
||||
+ /* This codepath can only be reached with -fdec-format-defaults. */
|
||||
+ {
|
||||
+ w = default_width;
|
||||
+ d = precision;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ w = f->u.real.w;
|
||||
+ d = f->u.real.d;
|
||||
+ }
|
||||
p = dtp->u.p.scale_factor;
|
||||
*len = 0;
|
||||
|
||||
@@ -959,6 +969,11 @@ determine_en_precision (st_parameter_dt
|
||||
int save_scale_factor;\
|
||||
volatile GFC_REAL_ ## x temp;\
|
||||
save_scale_factor = dtp->u.p.scale_factor;\
|
||||
+ if (w == DEFAULT_WIDTH)\
|
||||
+ {\
|
||||
+ w = default_width;\
|
||||
+ d = precision;\
|
||||
+ }\
|
||||
switch (dtp->u.p.current_unit->round_status)\
|
||||
{\
|
||||
case ROUND_ZERO:\
|
||||
@@ -1034,7 +1049,8 @@ determine_en_precision (st_parameter_dt
|
||||
nprinted = FDTOA(y,precision,m);\
|
||||
}\
|
||||
build_float_string (dtp, &newf, buffer, size, nprinted, precision,\
|
||||
- sign_bit, zero_flag, npad, result, res_len);\
|
||||
+ sign_bit, zero_flag, npad, default_width,\
|
||||
+ result, res_len);\
|
||||
dtp->u.p.scale_factor = save_scale_factor;\
|
||||
}\
|
||||
else\
|
||||
@@ -1044,7 +1060,8 @@ determine_en_precision (st_parameter_dt
|
||||
else\
|
||||
nprinted = DTOA(y,precision,m);\
|
||||
build_float_string (dtp, f, buffer, size, nprinted, precision,\
|
||||
- sign_bit, zero_flag, npad, result, res_len);\
|
||||
+ sign_bit, zero_flag, npad, default_width,\
|
||||
+ result, res_len);\
|
||||
}\
|
||||
}\
|
||||
|
||||
@@ -1058,6 +1075,16 @@ get_float_string (st_parameter_dt *dtp,
|
||||
{
|
||||
int sign_bit, nprinted;
|
||||
bool zero_flag;
|
||||
+ int default_width = 0;
|
||||
+
|
||||
+ if (f->u.real.w == DEFAULT_WIDTH)
|
||||
+ /* This codepath can only be reached with -fdec-format-defaults. The default
|
||||
+ * values are based on those used in the Oracle Fortran compiler.
|
||||
+ */
|
||||
+ {
|
||||
+ default_width = default_width_for_float (kind);
|
||||
+ precision = default_precision_for_float (kind);
|
||||
+ }
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,41 +0,0 @@
|
||||
--- libgomp/testsuite/libgomp-test-support.exp.in.jj 2018-04-25 09:40:31.323655308 +0200
|
||||
+++ libgomp/testsuite/libgomp-test-support.exp.in 2019-04-25 20:01:50.028243827 +0200
|
||||
@@ -2,4 +2,5 @@ set cuda_driver_include "@CUDA_DRIVER_IN
|
||||
set cuda_driver_lib "@CUDA_DRIVER_LIB@"
|
||||
set hsa_runtime_lib "@HSA_RUNTIME_LIB@"
|
||||
|
||||
+set offload_plugins "@offload_plugins@"
|
||||
set offload_targets "@offload_targets@"
|
||||
--- libgomp/testsuite/lib/libgomp.exp.jj 2018-04-25 09:40:31.584655429 +0200
|
||||
+++ libgomp/testsuite/lib/libgomp.exp 2019-05-24 11:41:51.015822702 +0200
|
||||
@@ -40,7 +40,7 @@ load_file libgomp-test-support.exp
|
||||
# Populate offload_targets_s (offloading targets separated by a space), and
|
||||
# offload_targets_s_openacc (the same, but with OpenACC names; OpenACC spells
|
||||
# some of them a little differently).
|
||||
-set offload_targets_s [split $offload_targets ","]
|
||||
+set offload_targets_s [split $offload_plugins ","]
|
||||
set offload_targets_s_openacc {}
|
||||
foreach offload_target_openacc $offload_targets_s {
|
||||
# Translate to OpenACC names, or skip if not yet supported.
|
||||
@@ -137,8 +137,8 @@ proc libgomp_init { args } {
|
||||
|
||||
# Add liboffloadmic build directory in LD_LIBRARY_PATH to support
|
||||
# non-fallback testing for Intel MIC targets
|
||||
- global offload_targets
|
||||
- if { [string match "*,intelmic,*" ",$offload_targets,"] } {
|
||||
+ global offload_plugins
|
||||
+ if { [string match "*,intelmic,*" ",$offload_plugins,"] } {
|
||||
append always_ld_library_path ":${blddir}/../liboffloadmic/.libs"
|
||||
append always_ld_library_path ":${blddir}/../liboffloadmic/plugin/.libs"
|
||||
# libstdc++ is required by liboffloadmic
|
||||
@@ -362,8 +362,8 @@ proc check_effective_target_offload_devi
|
||||
# Return 1 if configured for nvptx offloading.
|
||||
|
||||
proc check_effective_target_openacc_nvidia_accel_configured { } {
|
||||
- global offload_targets
|
||||
- if { ![string match "*,nvptx,*" ",$offload_targets,"] } {
|
||||
+ global offload_plugins
|
||||
+ if { ![string match "*,nvptx,*" ",$offload_plugins,"] } {
|
||||
return 0
|
||||
}
|
||||
# PR libgomp/65099: Currently, we only support offloading in 64-bit
|
||||
@ -1,61 +0,0 @@
|
||||
commit 79fa567e234585dc6a71f9bd069101c993513f3e
|
||||
Author: Jonathan Wakely <jwakely@redhat.com>
|
||||
Date: Thu Apr 22 15:46:51 2021 +0100
|
||||
|
||||
libstdc++: Reject std::make_shared<T[]> [PR 99006]
|
||||
|
||||
Prior to C++20 it should be ill-formed to use std::make_shared with an
|
||||
array type (and we don't support the C++20 feature to make it valid yet
|
||||
anyway).
|
||||
|
||||
libstdc++-v3/ChangeLog:
|
||||
|
||||
PR libstdc++/99006
|
||||
* include/bits/shared_ptr.h (allocate_shared): Assert that _Tp
|
||||
is not an array type.
|
||||
* include/bits/shared_ptr_base.h (__allocate_shared): Likewise.
|
||||
* testsuite/20_util/shared_ptr/creation/99006.cc: New test.
|
||||
|
||||
(cherry picked from commit 55650236cd97d81f42f9fdb4f6bcb12babafe51f)
|
||||
|
||||
diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
|
||||
index 281600b2901..4ddc52ae723 100644
|
||||
--- a/libstdc++-v3/include/bits/shared_ptr.h
|
||||
+++ b/libstdc++-v3/include/bits/shared_ptr.h
|
||||
@@ -698,6 +698,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
inline shared_ptr<_Tp>
|
||||
allocate_shared(const _Alloc& __a, _Args&&... __args)
|
||||
{
|
||||
+ static_assert(!is_array<_Tp>::value, "make_shared<T[]> not supported");
|
||||
+
|
||||
return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
|
||||
std::forward<_Args>(__args)...);
|
||||
}
|
||||
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
|
||||
index 0367c2d51a5..8af6e9fb11c 100644
|
||||
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
|
||||
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
|
||||
@@ -1822,6 +1822,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
inline __shared_ptr<_Tp, _Lp>
|
||||
__allocate_shared(const _Alloc& __a, _Args&&... __args)
|
||||
{
|
||||
+ static_assert(!is_array<_Tp>::value, "make_shared<T[]> not supported");
|
||||
+
|
||||
return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a},
|
||||
std::forward<_Args>(__args)...);
|
||||
}
|
||||
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc
|
||||
new file mode 100644
|
||||
index 00000000000..d5f7a5da5e9
|
||||
--- /dev/null
|
||||
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc
|
||||
@@ -0,0 +1,9 @@
|
||||
+// FIXME: This should use { target { ! c++20 } }
|
||||
+// { dg-do compile }
|
||||
+
|
||||
+#include <memory>
|
||||
+
|
||||
+auto p = std::make_shared<int[]>(2); // { dg-error "here" }
|
||||
+auto q = std::make_shared<int[2]>(1, 2); // { dg-error "here" }
|
||||
+
|
||||
+// { dg-prune-output "static assertion failed" }
|
||||
@ -1,27 +0,0 @@
|
||||
NullablePointer support not available, so drop these tests.
|
||||
|
||||
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc.new
|
||||
index 2f75d12..6fb19c3 100644
|
||||
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
|
||||
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
|
||||
@@ -145,20 +145,6 @@ main()
|
||||
std::unique_ptr<data>& rarrptr = arrptr;
|
||||
// { dg-final { regexp-test rarrptr {std::unique_ptr.datum \[\]. = {get\(\) = 0x.*}} } }
|
||||
|
||||
- struct Deleter
|
||||
- {
|
||||
- int deleter_member = -1;
|
||||
- using pointer = __gnu_test::NullablePointer<void>;
|
||||
- void operator()(pointer) const noexcept { }
|
||||
- };
|
||||
- static_assert( !std::is_empty<Deleter>(), "Deleter is not empty" );
|
||||
- static_assert( std::is_empty<Deleter::pointer>(), "but pointer is empty" );
|
||||
-
|
||||
- std::unique_ptr<int, Deleter> empty_ptr;
|
||||
-// { dg-final { note-test empty_ptr {std::unique_ptr<int> = {get() = {<No data fields>}}} } }
|
||||
- std::unique_ptr<int, Deleter>& rempty_ptr = empty_ptr;
|
||||
-// { dg-final { note-test rempty_ptr {std::unique_ptr<int> = {get() = {<No data fields>}}} } }
|
||||
-
|
||||
struct Deleter_pr103086
|
||||
{
|
||||
int deleter_member = -1;
|
||||
@ -1,44 +0,0 @@
|
||||
Revert this commit for libstdc++-prettyprinters (only cxx17, 91997
|
||||
doesn't exist in this tree) since gcc8 does not default to c++17. The
|
||||
context has been adapted but the change should be exact:
|
||||
|
||||
commit 0498d2d09a2364aae1e6b5e085c8ebb8fc517684
|
||||
Author: Jonathan Wakely <jwakely@redhat.com>
|
||||
Date: Mon May 10 16:22:54 2021 +0100
|
||||
|
||||
libstdc++: Remove redundant -std=gnu++17 option from remaining tests
|
||||
|
||||
Also remove the filesystem tests since it's not supported by RHEL8 gcc.
|
||||
|
||||
diff --git b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
|
||||
index 72c66d3b785..98e21e963fe 100644
|
||||
--- b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
|
||||
+++ a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
|
||||
@@ -1,4 +1,4 @@
|
||||
-// { dg-options "-g -O0" }
|
||||
+// { dg-options "-g -O0 -std=gnu++17" }
|
||||
// { dg-do run { target c++17 } }
|
||||
|
||||
// Copyright (C) 2014-2025 Free Software Foundation, Inc.
|
||||
@@ -18,7 +18,6 @@
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
-#include <filesystem>
|
||||
#include <any>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
@@ -120,13 +119,6 @@ main()
|
||||
// { dg-final { regexp-test q {std::shared_ptr.int \[2\]. \(use count 2, weak count 1\) = {get\(\) = 0x.*}} } }
|
||||
// { dg-final { regexp-test wq {std::weak_ptr.int \[2\]. \(use count 2, weak count 1\) = {get\(\) = 0x.*}} } }
|
||||
|
||||
- std::filesystem::path path0;
|
||||
-// { dg-final { note-test path0 {filesystem::path ""} } }
|
||||
- std::filesystem::path path1("filename");
|
||||
-// { dg-final { note-test path1 {filesystem::path "filename"} } }
|
||||
- std::filesystem::path path2("/dir/.");
|
||||
-// { dg-final { note-test path2 {filesystem::path "/dir/." = {[root-directory] = "/", [1] = "dir", [2] = "."}} } }
|
||||
-
|
||||
std::cout << "\n";
|
||||
return 0; // Mark SPOT
|
||||
}
|
||||
@ -1,458 +0,0 @@
|
||||
.../testsuite/libstdc++-prettyprinters/compat.cc | 11 +-
|
||||
.../testsuite/libstdc++-prettyprinters/cxx11.cc | 129 +++++++++++++++------
|
||||
.../testsuite/libstdc++-prettyprinters/cxx17.cc | 50 +++++---
|
||||
.../libstdc++-prettyprinters/filesystem-ts.cc | 8 +-
|
||||
.../libstdc++-prettyprinters/libfundts.cc | 26 +++--
|
||||
5 files changed, 146 insertions(+), 78 deletions(-)
|
||||
|
||||
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc
|
||||
index 81e0ce7213f..2ef5979834f 100644
|
||||
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc
|
||||
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc
|
||||
@@ -1,8 +1,7 @@
|
||||
// { dg-options "-g -O0" }
|
||||
// { dg-do run { target c++11 } }
|
||||
-// { dg-skip-if "" { *-*-* } { "-D_GLIBCXX_PROFILE" } }
|
||||
|
||||
-// Copyright (C) 2014-2019 Free Software Foundation, Inc.
|
||||
+// Copyright (C) 2014-2025 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
@@ -103,13 +102,13 @@ main()
|
||||
using std::optional;
|
||||
|
||||
optional<int> o;
|
||||
-// { dg-final { note-test o {std::optional<int> [no contained value]} } }
|
||||
+// { dg-final { note-test o {std::optional [no contained value]} } }
|
||||
optional<bool> ob{false};
|
||||
-// { dg-final { note-test ob {std::optional<bool> = {[contained value] = false}} } }
|
||||
+// { dg-final { note-test ob {std::optional = {[contained value] = false}} } }
|
||||
optional<int> oi{5};
|
||||
-// { dg-final { note-test oi {std::optional<int> = {[contained value] = 5}} } }
|
||||
+// { dg-final { note-test oi {std::optional = {[contained value] = 5}} } }
|
||||
optional<void*> op{nullptr};
|
||||
-// { dg-final { note-test op {std::optional<void *> = {[contained value] = 0x0}} } }
|
||||
+// { dg-final { note-test op {std::optional = {[contained value] = 0x0}} } }
|
||||
|
||||
__builtin_puts("");
|
||||
return 0; // Mark SPOT
|
||||
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
|
||||
index 9a90d8d91db..23f6d97ddd4 100644
|
||||
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
|
||||
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
|
||||
@@ -1,8 +1,7 @@
|
||||
// { dg-do run { target c++11 } }
|
||||
// { dg-options "-g -O0" }
|
||||
-// { dg-skip-if "" { *-*-* } { "-D_GLIBCXX_PROFILE" } }
|
||||
|
||||
-// Copyright (C) 2011-2018 Free Software Foundation, Inc.
|
||||
+// Copyright (C) 2011-2025 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
@@ -25,6 +24,10 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
+#include <future>
|
||||
+#include <initializer_list>
|
||||
+#include <atomic>
|
||||
+#include "../util/testsuite_allocator.h" // NullablePointer
|
||||
|
||||
typedef std::tuple<int, int> ExTuple;
|
||||
|
||||
@@ -60,84 +63,74 @@ struct datum
|
||||
|
||||
std::unique_ptr<datum> global;
|
||||
|
||||
-struct Deleter
|
||||
-{
|
||||
- // Deleter is not an empty class:
|
||||
- int deleter_member = -1;
|
||||
- // But pointer is an empty class:
|
||||
- struct pointer
|
||||
- {
|
||||
- pointer(const void* = nullptr) { }
|
||||
- explicit operator bool() const noexcept { return false; }
|
||||
- friend bool operator==(pointer, pointer) noexcept { return true; }
|
||||
- friend bool operator!=(pointer, pointer) noexcept { return false; }
|
||||
- };
|
||||
- void operator()(pointer) const noexcept { }
|
||||
+struct custom_cat : std::error_category {
|
||||
+ const char* name() const noexcept { return "miaow"; }
|
||||
+ std::string message(int) const { return ""; }
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
std::forward_list<int> efl;
|
||||
-// { dg-final { note-test efl "empty std::forward_list" } }
|
||||
+// { dg-final { regexp-test efl "empty std::(__debug::)?forward_list" } }
|
||||
|
||||
std::forward_list<int> &refl = efl;
|
||||
-// { dg-final { note-test refl "empty std::forward_list" } }
|
||||
+// { dg-final { regexp-test refl "empty std::(__debug::)?forward_list" } }
|
||||
|
||||
std::forward_list<int> fl;
|
||||
fl.push_front(2);
|
||||
fl.push_front(1);
|
||||
-// { dg-final { note-test fl {std::forward_list = {[0] = 1, [1] = 2}} } }
|
||||
+// { dg-final { regexp-test fl {std::(__debug::)?forward_list = {\[0\] = 1, \[1\] = 2}} } }
|
||||
|
||||
std::forward_list<int> &rfl = fl;
|
||||
-// { dg-final { note-test rfl {std::forward_list = {[0] = 1, [1] = 2}} } }
|
||||
+// { dg-final { regexp-test rfl {std::(__debug::)?forward_list = {\[0\] = 1, \[1\] = 2}} } }
|
||||
|
||||
std::unordered_map<int, std::string> eum;
|
||||
-// { dg-final { note-test eum "std::unordered_map with 0 elements" } }
|
||||
+// { dg-final { regexp-test eum "std::(__debug::)?unordered_map with 0 elements" } }
|
||||
std::unordered_map<int, std::string> &reum = eum;
|
||||
-// { dg-final { note-test reum "std::unordered_map with 0 elements" } }
|
||||
+// { dg-final { regexp-test reum "std::(__debug::)?unordered_map with 0 elements" } }
|
||||
|
||||
std::unordered_multimap<int, std::string> eumm;
|
||||
-// { dg-final { note-test eumm "std::unordered_multimap with 0 elements" } }
|
||||
+// { dg-final { regexp-test eumm "std::(__debug::)?unordered_multimap with 0 elements" } }
|
||||
std::unordered_multimap<int, std::string> &reumm = eumm;
|
||||
-// { dg-final { note-test reumm "std::unordered_multimap with 0 elements" } }
|
||||
+// { dg-final { regexp-test reumm "std::(__debug::)?unordered_multimap with 0 elements" } }
|
||||
|
||||
std::unordered_set<int> eus;
|
||||
-// { dg-final { note-test eus "std::unordered_set with 0 elements" } }
|
||||
+// { dg-final { regexp-test eus "std::(__debug::)?unordered_set with 0 elements" } }
|
||||
std::unordered_set<int> &reus = eus;
|
||||
-// { dg-final { note-test reus "std::unordered_set with 0 elements" } }
|
||||
+// { dg-final { regexp-test reus "std::(__debug::)?unordered_set with 0 elements" } }
|
||||
|
||||
std::unordered_multiset<int> eums;
|
||||
-// { dg-final { note-test eums "std::unordered_multiset with 0 elements" } }
|
||||
+// { dg-final { regexp-test eums "std::(__debug::)?unordered_multiset with 0 elements" } }
|
||||
std::unordered_multiset<int> &reums = eums;
|
||||
-// { dg-final { note-test reums "std::unordered_multiset with 0 elements" } }
|
||||
+// { dg-final { regexp-test reums "std::(__debug::)?unordered_multiset with 0 elements" } }
|
||||
|
||||
std::unordered_map<int, std::string> uom;
|
||||
uom[5] = "three";
|
||||
uom[3] = "seven";
|
||||
-// { dg-final { note-test uom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
|
||||
+// { dg-final { regexp-test uom {std::(__debug::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
|
||||
|
||||
std::unordered_map<int, std::string> &ruom = uom;
|
||||
-// { dg-final { note-test ruom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
|
||||
+// { dg-final { regexp-test ruom {std::(__debug::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
|
||||
|
||||
std::unordered_multimap<int, std::string> uomm;
|
||||
uomm.insert(std::pair<int, std::string> (5, "three"));
|
||||
uomm.insert(std::pair<int, std::string> (5, "seven"));
|
||||
-// { dg-final { note-test uomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } }
|
||||
+// { dg-final { regexp-test uomm {std::(__debug::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } }
|
||||
std::unordered_multimap<int, std::string> &ruomm = uomm;
|
||||
-// { dg-final { note-test ruomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } }
|
||||
+// { dg-final { regexp-test ruomm {std::(__debug::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } }
|
||||
|
||||
std::unordered_set<int> uos;
|
||||
uos.insert(5);
|
||||
-// { dg-final { note-test uos {std::unordered_set with 1 element = {[0] = 5}} } }
|
||||
+// { dg-final { regexp-test uos {std::(__debug::)?unordered_set with 1 element = {\[0\] = 5}} } }
|
||||
std::unordered_set<int> &ruos = uos;
|
||||
-// { dg-final { note-test ruos {std::unordered_set with 1 element = {[0] = 5}} } }
|
||||
+// { dg-final { regexp-test ruos {std::(__debug::)?unordered_set with 1 element = {\[0\] = 5}} } }
|
||||
|
||||
std::unordered_multiset<int> uoms;
|
||||
uoms.insert(5);
|
||||
-// { dg-final { note-test uoms {std::unordered_multiset with 1 element = {[0] = 5}} } }
|
||||
+// { dg-final { regexp-test uoms {std::(__debug::)?unordered_multiset with 1 element = {\[0\] = 5}} } }
|
||||
std::unordered_multiset<int> &ruoms = uoms;
|
||||
-// { dg-final { note-test ruoms {std::unordered_multiset with 1 element = {[0] = 5}} } }
|
||||
+// { dg-final { regexp-test ruoms {std::(__debug::)?unordered_multiset with 1 element = {\[0\] = 5}} } }
|
||||
|
||||
std::unique_ptr<datum> uptr (new datum);
|
||||
uptr->s = "hi bob";
|
||||
@@ -152,15 +145,77 @@ main()
|
||||
std::unique_ptr<data>& rarrptr = arrptr;
|
||||
// { dg-final { regexp-test rarrptr {std::unique_ptr.datum \[\]. = {get\(\) = 0x.*}} } }
|
||||
|
||||
+ struct Deleter
|
||||
+ {
|
||||
+ int deleter_member = -1;
|
||||
+ using pointer = __gnu_test::NullablePointer<void>;
|
||||
+ void operator()(pointer) const noexcept { }
|
||||
+ };
|
||||
+ static_assert( !std::is_empty<Deleter>(), "Deleter is not empty" );
|
||||
+ static_assert( std::is_empty<Deleter::pointer>(), "but pointer is empty" );
|
||||
+
|
||||
std::unique_ptr<int, Deleter> empty_ptr;
|
||||
// { dg-final { note-test empty_ptr {std::unique_ptr<int> = {get() = {<No data fields>}}} } }
|
||||
std::unique_ptr<int, Deleter>& rempty_ptr = empty_ptr;
|
||||
// { dg-final { note-test rempty_ptr {std::unique_ptr<int> = {get() = {<No data fields>}}} } }
|
||||
|
||||
+ struct Deleter_pr103086
|
||||
+ {
|
||||
+ int deleter_member = -1;
|
||||
+ void operator()(int*) const noexcept { }
|
||||
+ };
|
||||
+
|
||||
+ std::unique_ptr<int, Deleter_pr103086> uniq_ptr;
|
||||
+// { dg-final { note-test uniq_ptr {std::unique_ptr<int> = {get() = 0x0}} } }
|
||||
+ std::unique_ptr<int, Deleter_pr103086>& runiq_ptr = uniq_ptr;
|
||||
+// { dg-final { note-test runiq_ptr {std::unique_ptr<int> = {get() = 0x0}} } }
|
||||
+
|
||||
ExTuple tpl(6,7);
|
||||
-// { dg-final { note-test tpl {std::tuple containing = {[1] = 6, [2] = 7}} } }
|
||||
+// { dg-final { note-test tpl {std::tuple containing = {[0] = 6, [1] = 7}} } }
|
||||
ExTuple &rtpl = tpl;
|
||||
-// { dg-final { note-test rtpl {std::tuple containing = {[1] = 6, [2] = 7}} } }
|
||||
+// { dg-final { note-test rtpl {std::tuple containing = {[0] = 6, [1] = 7}} } }
|
||||
+
|
||||
+ std::error_code e0;
|
||||
+ // { dg-final { note-test e0 {std::error_code = { }} } }
|
||||
+ std::error_condition ec0;
|
||||
+ // { dg-final { note-test ec0 {std::error_condition = { }} } }
|
||||
+ std::error_code einval = std::make_error_code(std::errc::invalid_argument);
|
||||
+ // { dg-final { note-test einval {std::error_code = {"generic": EINVAL}} } }
|
||||
+ std::error_condition ecinval = std::make_error_condition(std::errc::invalid_argument);
|
||||
+ // { dg-final { note-test ecinval {std::error_condition = {"generic": EINVAL}} } }
|
||||
+
|
||||
+ custom_cat cat;
|
||||
+ std::error_code emiaow(42, cat);
|
||||
+ // { dg-final { note-test emiaow {std::error_code = {custom_cat: 42}} } }
|
||||
+ std::error_condition ecmiaow(42, cat);
|
||||
+ // { dg-final { note-test ecmiaow {std::error_condition = {custom_cat: 42}} } }
|
||||
+
|
||||
+ std::error_code ecio = std::make_error_code(std::io_errc::stream);
|
||||
+ // { dg-final { note-test ecio {std::error_code = {"io": stream}} } }
|
||||
+ std::error_code ecfut0 = std::make_error_code(std::future_errc{});
|
||||
+ // { dg-final { note-test ecfut0 {std::error_code = {"future": 0}} } }
|
||||
+
|
||||
+ std::initializer_list<int> emptyIl = {};
|
||||
+ // { dg-final { note-test emptyIl {std::initializer_list of length 0} } }
|
||||
+ std::initializer_list<int> il = {3, 4};
|
||||
+ // { dg-final { note-test il {std::initializer_list of length 2 = {3, 4}} } }
|
||||
+
|
||||
+ std::atomic<int> ai{100};
|
||||
+ // { dg-final { note-test ai {std::atomic<int> = { 100 }} } }
|
||||
+ long l{};
|
||||
+ std::atomic<long*> ap{&l};
|
||||
+ // { dg-final { regexp-test ap {std::atomic.long \*. = { 0x.* }} } }
|
||||
+ struct Value { int i, j; };
|
||||
+ std::atomic<Value> av{{8, 9}};
|
||||
+ // { dg-final { note-test av {std::atomic<Value> = { {i = 8, j = 9} }} } }
|
||||
+
|
||||
+ std::integral_constant<int, 1> one;
|
||||
+ // { dg-final { note-test one {std::integral_constant<int, 1>} } }
|
||||
+ std::integral_constant<bool, true> truth;
|
||||
+ // { dg-final { note-test truth {std::true_type} } }
|
||||
+ std::integral_constant<bool, 0> lies;
|
||||
+ // { dg-final { note-test lies {std::false_type} } }
|
||||
+
|
||||
placeholder(""); // Mark SPOT
|
||||
use(efl);
|
||||
use(fl);
|
||||
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
|
||||
index 0c7cb4c9bb6..6dd2b60c0a5 100644
|
||||
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
|
||||
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
|
||||
@@ -1,8 +1,7 @@
|
||||
-// { dg-options "-g -O0 -std=gnu++17" }
|
||||
+// { dg-options "-g -O0" }
|
||||
// { dg-do run { target c++17 } }
|
||||
-// { dg-skip-if "" { *-*-* } { "-D_GLIBCXX_PROFILE" } }
|
||||
|
||||
-// Copyright (C) 2014-2018 Free Software Foundation, Inc.
|
||||
+// Copyright (C) 2014-2025 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
@@ -19,9 +18,7 @@
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
-// Type printers only recognize the old std::string for now.
|
||||
-#define _GLIBCXX_USE_CXX11_ABI 0
|
||||
-
|
||||
+#include <filesystem>
|
||||
#include <any>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
@@ -41,6 +38,11 @@ using std::unordered_set;
|
||||
using std::shared_ptr;
|
||||
using std::weak_ptr;
|
||||
|
||||
+struct X {
|
||||
+ X(int) { }
|
||||
+ X(const X&) { } // not trivially-copyable
|
||||
+};
|
||||
+
|
||||
int
|
||||
main()
|
||||
{
|
||||
@@ -48,18 +50,18 @@ main()
|
||||
// { dg-final { note-test str "\"string\"" } }
|
||||
|
||||
optional<int> o;
|
||||
-// { dg-final { note-test o {std::optional<int> [no contained value]} } }
|
||||
+// { dg-final { note-test o {std::optional [no contained value]} } }
|
||||
optional<bool> ob{false};
|
||||
-// { dg-final { note-test ob {std::optional<bool> = {[contained value] = false}} } }
|
||||
+// { dg-final { note-test ob {std::optional = {[contained value] = false}} } }
|
||||
optional<int> oi{5};
|
||||
-// { dg-final { note-test oi {std::optional<int> = {[contained value] = 5}} } }
|
||||
+// { dg-final { note-test oi {std::optional = {[contained value] = 5}} } }
|
||||
optional<void*> op{nullptr};
|
||||
-// { dg-final { note-test op {std::optional<void *> = {[contained value] = 0x0}} } }
|
||||
+// { dg-final { note-test op {std::optional = {[contained value] = 0x0}} } }
|
||||
optional<std::map<int, double>> om;
|
||||
om = std::map<int, double>{ {1, 2.}, {3, 4.}, {5, 6.} };
|
||||
-// { dg-final { note-test om {std::optional<std::map<int, double>> containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
|
||||
+// { dg-final { regexp-test om {std::optional containing std::(__debug::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
|
||||
optional<std::string> os{ "stringy" };
|
||||
-// { dg-final { note-test os {std::optional<std::string> = {[contained value] = "stringy"}} } }
|
||||
+// { dg-final { note-test os {std::optional = {[contained value] = "stringy"}} } }
|
||||
|
||||
any a;
|
||||
// { dg-final { note-test a {std::any [no contained value]} } }
|
||||
@@ -74,22 +76,25 @@ main()
|
||||
any as2("stringiest");
|
||||
// { dg-final { regexp-test as2 {std::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
|
||||
any am = *om;
|
||||
-// { dg-final { note-test am {std::any containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
|
||||
+// { dg-final { regexp-test am {std::any containing std::(__debug::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
|
||||
+ struct local_type { int i = 99; };
|
||||
+ any al = local_type{};
|
||||
+// { dg-final { note-test al {std::any containing local_type = {[contained value] = {i = 99}}} } }
|
||||
|
||||
struct S { operator int() { throw 42; }};
|
||||
variant<float, int, string_view> v0;
|
||||
-// { dg-final { note-test v0 {std::variant<float, int, std::string_view> [index 0] = {0}} } }
|
||||
+// { dg-final { note-test v0 {std::variant [index 0] = {0}} } }
|
||||
variant<float, int, string_view> v1{ 0.5f };
|
||||
-// { dg-final { note-test v1 {std::variant<float, int, std::string_view> [index 0] = {0.5}} } }
|
||||
- variant<float, int, string_view> v2;
|
||||
+// { dg-final { note-test v1 {std::variant [index 0] = {0.5}} } }
|
||||
+ variant<float, X, string_view> v2;
|
||||
try {
|
||||
v2.emplace<1>(S());
|
||||
} catch (int) { }
|
||||
-// { dg-final { note-test v2 {std::variant<float, int, std::string_view> [no contained value]} } }
|
||||
+// { dg-final { note-test v2 {std::variant [no contained value]} } }
|
||||
variant<float, int, string_view> v3{ 3 };
|
||||
-// { dg-final { note-test v3 {std::variant<float, int, std::string_view> [index 1] = {3}} } }
|
||||
+// { dg-final { note-test v3 {std::variant [index 1] = {3}} } }
|
||||
variant<float, int, string_view> v4{ str };
|
||||
-// { dg-final { note-test v4 {std::variant<float, int, std::string_view> [index 2] = {"string"}} } }
|
||||
+// { dg-final { note-test v4 {std::variant [index 2] = {"string"}} } }
|
||||
|
||||
map<int, string_view> m{ {1, "one"} };
|
||||
map<int, string_view>::node_type n0;
|
||||
@@ -115,6 +120,13 @@ main()
|
||||
// { dg-final { regexp-test q {std::shared_ptr.int \[2\]. \(use count 2, weak count 1\) = {get\(\) = 0x.*}} } }
|
||||
// { dg-final { regexp-test wq {std::weak_ptr.int \[2\]. \(use count 2, weak count 1\) = {get\(\) = 0x.*}} } }
|
||||
|
||||
+ std::filesystem::path path0;
|
||||
+// { dg-final { note-test path0 {filesystem::path ""} } }
|
||||
+ std::filesystem::path path1("filename");
|
||||
+// { dg-final { note-test path1 {filesystem::path "filename"} } }
|
||||
+ std::filesystem::path path2("/dir/.");
|
||||
+// { dg-final { note-test path2 {filesystem::path "/dir/." = {[root-directory] = "/", [1] = "dir", [2] = "."}} } }
|
||||
+
|
||||
std::cout << "\n";
|
||||
return 0; // Mark SPOT
|
||||
}
|
||||
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc
|
||||
index 8a1398f6c85..3221f2df90d 100644
|
||||
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc
|
||||
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/filesystem-ts.cc
|
||||
@@ -2,7 +2,7 @@
|
||||
// { dg-do run { target c++11 } }
|
||||
// { dg-require-filesystem-ts "" }
|
||||
|
||||
-// Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
+// Copyright (C) 2020-2025 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
@@ -26,11 +26,11 @@ int
|
||||
main()
|
||||
{
|
||||
std::experimental::filesystem::path path0;
|
||||
-// { dg-final { note-test path0 {filesystem::path ""} } }
|
||||
+// { dg-final { note-test path0 {experimental::filesystem::path ""} } }
|
||||
std::experimental::filesystem::path path1("filename");
|
||||
-// { dg-final { note-test path1 {filesystem::path "filename"} } }
|
||||
+// { dg-final { note-test path1 {experimental::filesystem::path "filename"} } }
|
||||
std::experimental::filesystem::path path2("/dir/.");
|
||||
-// { dg-final { note-test path2 {filesystem::path "/dir/." = {[root-directory] = "/", [1] = "dir", [2] = "."}} } }
|
||||
+// { dg-final { note-test path2 {experimental::filesystem::path "/dir/." = {[root-directory] = "/", [1] = "dir", [2] = "."}} } }
|
||||
|
||||
std::cout << "\n";
|
||||
return 0; // Mark SPOT
|
||||
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
|
||||
index ea13ebe71ee..bfb86885457 100644
|
||||
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
|
||||
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
|
||||
@@ -1,8 +1,7 @@
|
||||
// { dg-do run { target c++14 } }
|
||||
// { dg-options "-g -O0" }
|
||||
-// { dg-skip-if "" { *-*-* } { "-D_GLIBCXX_PROFILE" } }
|
||||
|
||||
-// Copyright (C) 2014-2018 Free Software Foundation, Inc.
|
||||
+// Copyright (C) 2014-2025 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
@@ -19,9 +18,6 @@
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
-// Type printers only recognize the old std::string for now.
|
||||
-#define _GLIBCXX_USE_CXX11_ABI 0
|
||||
-
|
||||
#include <experimental/any>
|
||||
#include <experimental/optional>
|
||||
#include <experimental/string_view>
|
||||
@@ -36,22 +32,28 @@ using std::experimental::string_view;
|
||||
int
|
||||
main()
|
||||
{
|
||||
+ // Ensure debug info for std::string is issued in the local
|
||||
+ // translation unit, so that GDB won't pick up any alternate
|
||||
+ // std::string notion that might be present in libstdc++.so.
|
||||
+ std::string bah = "hi";
|
||||
+ (void)bah;
|
||||
+
|
||||
string_view str = "string";
|
||||
// { dg-final { note-test str "\"string\"" } }
|
||||
|
||||
optional<int> o;
|
||||
-// { dg-final { note-test o {std::experimental::optional<int> [no contained value]} } }
|
||||
+// { dg-final { note-test o {std::experimental::optional [no contained value]} } }
|
||||
optional<bool> ob{false};
|
||||
-// { dg-final { note-test ob {std::experimental::optional<bool> = {[contained value] = false}} } }
|
||||
+// { dg-final { note-test ob {std::experimental::optional = {[contained value] = false}} } }
|
||||
optional<int> oi{5};
|
||||
-// { dg-final { note-test oi {std::experimental::optional<int> = {[contained value] = 5}} } }
|
||||
+// { dg-final { note-test oi {std::experimental::optional = {[contained value] = 5}} } }
|
||||
optional<void*> op{nullptr};
|
||||
-// { dg-final { note-test op {std::experimental::optional<void *> = {[contained value] = 0x0}} } }
|
||||
+// { dg-final { note-test op {std::experimental::optional = {[contained value] = 0x0}} } }
|
||||
optional<std::map<int, double>> om;
|
||||
om = std::map<int, double>{ {1, 2.}, {3, 4.}, {5, 6.} };
|
||||
-// { dg-final { note-test om {std::experimental::optional<std::map<int, double>> containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
|
||||
+// { dg-final { regexp-test om {std::experimental::optional containing std::(__debug::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
|
||||
optional<std::string> os{ "stringy" };
|
||||
-// { dg-final { note-test os {std::experimental::optional<std::string> = {[contained value] = "stringy"}} } }
|
||||
+// { dg-final { note-test os {std::experimental::optional = {[contained value] = "stringy"}} } }
|
||||
|
||||
any a;
|
||||
// { dg-final { note-test a {std::experimental::any [no contained value]} } }
|
||||
@@ -66,7 +68,7 @@ main()
|
||||
any as2("stringiest");
|
||||
// { dg-final { regexp-test as2 {std::experimental::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
|
||||
any am = *om;
|
||||
-// { dg-final { note-test am {std::experimental::any containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
|
||||
+// { dg-final { regexp-test am {std::experimental::any containing std::(__debug::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
|
||||
|
||||
std::cout << "\n";
|
||||
return 0; // Mark SPOT
|
||||
@ -1,17 +0,0 @@
|
||||
2018-04-24 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* config/i386/i386.opt (mcet): Remporarily re-add as alias to -mshstk.
|
||||
|
||||
--- gcc/config/i386/i386.opt (revision 259613)
|
||||
+++ gcc/config/i386/i386.opt (revision 259612)
|
||||
@@ -1006,6 +1006,10 @@ mgeneral-regs-only
|
||||
Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save
|
||||
Generate code which uses only the general registers.
|
||||
|
||||
+mcet
|
||||
+Target Undocumented Alias(mshstk)
|
||||
+;; Deprecated
|
||||
+
|
||||
mshstk
|
||||
Target Report Mask(ISA_SHSTK) Var(ix86_isa_flags) Save
|
||||
Enable shadow stack built-in functions from Control-flow Enforcement
|
||||
@ -1,74 +0,0 @@
|
||||
commit ba374dfb937a8ac1c7c4740913331951a924f88b
|
||||
Author: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Wed May 12 10:38:35 2021 +0200
|
||||
|
||||
expand: Don't reuse DEBUG_EXPRs with vector type if they have different modes [PR100508]
|
||||
|
||||
The inliner doesn't remap DEBUG_EXPR_DECLs, so the same decls can appear
|
||||
in multiple functions.
|
||||
Furthermore, expansion reuses corresponding DEBUG_EXPRs too, so they again
|
||||
can be reused in multiple functions.
|
||||
Neither of that is a major problem, DEBUG_EXPRs are just magic value holders
|
||||
and what value they stand for is independent in each function and driven by
|
||||
what debug stmts or DEBUG_INSNs they are bound to.
|
||||
Except for DEBUG_EXPR*s with vector types, TYPE_MODE can be either BLKmode
|
||||
or some vector mode depending on whether current function's enabled ISAs
|
||||
support that vector mode or not. On the following testcase, we expand it
|
||||
first in foo function without AVX2 enabled and so the DEBUG_EXPR is
|
||||
BLKmode, but later the same DEBUG_EXPR_DECL is used in a simd clone with
|
||||
AVX2 enabled and expansion ICEs because of a mode mismatch.
|
||||
|
||||
The following patch fixes that by forcing recreation of a DEBUG_EXPR if
|
||||
there is a mode mismatch for vector typed DEBUG_EXPR_DECL, DEBUG_EXPRs
|
||||
will be still reused in between functions otherwise and within the same
|
||||
function the mode should be always the same.
|
||||
|
||||
2021-05-12 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR middle-end/100508
|
||||
* cfgexpand.c (expand_debug_expr): For DEBUG_EXPR_DECL with vector
|
||||
type, don't reuse DECL_RTL if it has different mode, instead force
|
||||
creation of a new DEBUG_EXPR.
|
||||
|
||||
* gcc.dg/gomp/pr100508.c: New test.
|
||||
|
||||
(cherry picked from commit 19040050aa2c8ee890fc58dda48639fc91bf0af0)
|
||||
|
||||
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
|
||||
index b1535e15d28..a7d05202184 100644
|
||||
--- a/gcc/cfgexpand.c
|
||||
+++ b/gcc/cfgexpand.c
|
||||
@@ -4358,7 +4358,12 @@ expand_debug_expr (tree exp)
|
||||
op0 = DECL_RTL_IF_SET (exp);
|
||||
|
||||
if (op0)
|
||||
- return op0;
|
||||
+ {
|
||||
+ if (GET_MODE (op0) != mode)
|
||||
+ gcc_assert (VECTOR_TYPE_P (TREE_TYPE (exp)));
|
||||
+ else
|
||||
+ return op0;
|
||||
+ }
|
||||
|
||||
op0 = gen_rtx_DEBUG_EXPR (mode);
|
||||
DEBUG_EXPR_TREE_DECL (op0) = exp;
|
||||
diff --git a/gcc/testsuite/gcc.dg/gomp/pr100508.c b/gcc/testsuite/gcc.dg/gomp/pr100508.c
|
||||
new file mode 100644
|
||||
index 00000000000..c3fa2fc258e
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.dg/gomp/pr100508.c
|
||||
@@ -0,0 +1,14 @@
|
||||
+/* PR middle-end/100508 */
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -g -fopenmp-simd" } */
|
||||
+
|
||||
+typedef int __attribute__((__vector_size__(32))) V;
|
||||
+V j;
|
||||
+
|
||||
+#pragma omp declare simd
|
||||
+int
|
||||
+foo (void)
|
||||
+{
|
||||
+ V m = j;
|
||||
+ return 0;
|
||||
+}
|
||||
@ -1,137 +0,0 @@
|
||||
commit ebfe8b28d40746ff33724bd5b9ade2552e619213
|
||||
Author: Jason Merrill <jason@redhat.com>
|
||||
Date: Thu May 27 23:54:52 2021 -0400
|
||||
|
||||
c++: 'this' adjustment for devirtualized call
|
||||
|
||||
My patch for 95719 made us do a better job of finding the actual virtual
|
||||
function we want to call, but didn't update the 'this' pointer adjustment to
|
||||
match.
|
||||
|
||||
This backport also incorporates a bit of the r11-1638 reorganization.
|
||||
|
||||
PR c++/100797
|
||||
PR c++/95719
|
||||
|
||||
gcc/cp/ChangeLog:
|
||||
|
||||
* call.c (build_over_call): Adjust base_binfo in
|
||||
resolves_to_fixed_type_p case.
|
||||
|
||||
gcc/testsuite/ChangeLog:
|
||||
|
||||
* g++.dg/inherit/virtual15.C: New test.
|
||||
* g++.dg/inherit/virtual15a.C: New test.
|
||||
|
||||
--- gcc/cp/call.c
|
||||
+++ gcc/cp/call.c
|
||||
@@ -8309,19 +8309,6 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
||||
|| CLASSTYPE_FINAL (TYPE_METHOD_BASETYPE (TREE_TYPE (fn))))
|
||||
flags |= LOOKUP_NONVIRTUAL;
|
||||
|
||||
- /* If we know the dynamic type of the object, look up the final overrider
|
||||
- in the BINFO. */
|
||||
- if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0
|
||||
- && resolves_to_fixed_type_p (arg))
|
||||
- {
|
||||
- tree binfo = cand->conversion_path;
|
||||
- if (BINFO_TYPE (binfo) != DECL_CONTEXT (fn))
|
||||
- binfo = lookup_base (binfo, DECL_CONTEXT (fn), ba_unique,
|
||||
- NULL, complain);
|
||||
- fn = lookup_vfn_in_binfo (DECL_VINDEX (fn), binfo);
|
||||
- flags |= LOOKUP_NONVIRTUAL;
|
||||
- }
|
||||
-
|
||||
/* [class.mfct.nonstatic]: If a nonstatic member function of a class
|
||||
X is called for an object that is not of type X, or of a type
|
||||
derived from X, the behavior is undefined.
|
||||
@@ -8331,10 +8318,6 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
||||
gcc_assert (TYPE_PTR_P (parmtype));
|
||||
/* Convert to the base in which the function was declared. */
|
||||
gcc_assert (cand->conversion_path != NULL_TREE);
|
||||
- converted_arg = build_base_path (PLUS_EXPR,
|
||||
- arg,
|
||||
- cand->conversion_path,
|
||||
- 1, complain);
|
||||
/* Check that the base class is accessible. */
|
||||
if (!accessible_base_p (TREE_TYPE (argtype),
|
||||
BINFO_TYPE (cand->conversion_path), true))
|
||||
@@ -8349,10 +8332,33 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
||||
/* If fn was found by a using declaration, the conversion path
|
||||
will be to the derived class, not the base declaring fn. We
|
||||
must convert from derived to base. */
|
||||
- base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),
|
||||
+ base_binfo = lookup_base (cand->conversion_path,
|
||||
TREE_TYPE (parmtype), ba_unique,
|
||||
NULL, complain);
|
||||
- converted_arg = build_base_path (PLUS_EXPR, converted_arg,
|
||||
+
|
||||
+ /* If we know the dynamic type of the object, look up the final overrider
|
||||
+ in the BINFO. */
|
||||
+ if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0
|
||||
+ && resolves_to_fixed_type_p (arg))
|
||||
+ {
|
||||
+ tree ov = lookup_vfn_in_binfo (DECL_VINDEX (fn), base_binfo);
|
||||
+
|
||||
+ /* And unwind base_binfo to match. If we don't find the type we're
|
||||
+ looking for in BINFO_INHERITANCE_CHAIN, we're looking at diamond
|
||||
+ inheritance; for now do a normal virtual call in that case. */
|
||||
+ tree octx = DECL_CONTEXT (ov);
|
||||
+ tree obinfo = base_binfo;
|
||||
+ while (obinfo && !SAME_BINFO_TYPE_P (BINFO_TYPE (obinfo), octx))
|
||||
+ obinfo = BINFO_INHERITANCE_CHAIN (obinfo);
|
||||
+ if (obinfo)
|
||||
+ {
|
||||
+ fn = ov;
|
||||
+ base_binfo = obinfo;
|
||||
+ flags |= LOOKUP_NONVIRTUAL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ converted_arg = build_base_path (PLUS_EXPR, arg,
|
||||
base_binfo, 1, complain);
|
||||
|
||||
argarray[j++] = converted_arg;
|
||||
--- /dev/null
|
||||
+++ gcc/testsuite/g++.dg/inherit/virtual15.C
|
||||
@@ -0,0 +1,18 @@
|
||||
+// PR c++/100797
|
||||
+// { dg-do run }
|
||||
+
|
||||
+bool ok = false;
|
||||
+struct S1 { virtual ~S1() {} };
|
||||
+struct S2 { virtual void f1() = 0; };
|
||||
+struct S3: S1, S2 {
|
||||
+ void f1() { f2(); }
|
||||
+ virtual void f2() = 0;
|
||||
+};
|
||||
+struct S4: S3 {
|
||||
+ void f2() { ok = true; }
|
||||
+ using S2::f1;
|
||||
+};
|
||||
+int main() {
|
||||
+ S4().f1();
|
||||
+ if (!ok) __builtin_abort ();
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ gcc/testsuite/g++.dg/inherit/virtual15a.C
|
||||
@@ -0,0 +1,19 @@
|
||||
+// PR c++/100797 plus diamond inheritance
|
||||
+// { dg-do run }
|
||||
+
|
||||
+bool ok = false;
|
||||
+struct S1 { virtual ~S1() {} };
|
||||
+struct S2 { virtual void f1() = 0; };
|
||||
+struct S3: S1, virtual S2 {
|
||||
+ void f1() { f2(); }
|
||||
+ virtual void f2() = 0;
|
||||
+};
|
||||
+struct SX: virtual S2 { };
|
||||
+struct S4: SX, S3 {
|
||||
+ void f2() { ok = true; }
|
||||
+ using S2::f1;
|
||||
+};
|
||||
+int main() {
|
||||
+ S4().f1();
|
||||
+ if (!ok) __builtin_abort ();
|
||||
+}
|
||||
@ -1,98 +0,0 @@
|
||||
From b005000525ab0a5116d21217c41fb1da5bd03796 Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Wakely <jwakely@redhat.com>
|
||||
Date: Fri, 6 May 2022 21:19:17 +0100
|
||||
Subject: [PATCH] libstdc++: Fix deserialization for std::normal_distribution
|
||||
[PR105502]
|
||||
|
||||
This fixes a regression in std::normal_distribution deserialization that
|
||||
caused the object to be left unchanged if the __state_avail value read
|
||||
from the stream was false.
|
||||
|
||||
libstdc++-v3/ChangeLog:
|
||||
|
||||
PR libstdc++/105502
|
||||
* include/bits/random.tcc
|
||||
(operator>>(basic_istream<C,T>&, normal_distribution<R>&)):
|
||||
Update state when __state_avail is false.
|
||||
* testsuite/26_numerics/random/normal_distribution/operators/serialize.cc:
|
||||
Check that deserialized object equals serialized one.
|
||||
|
||||
(cherry picked from commit 909ef4e2727ddc50a32d6ad379a1f1ccc1043c6a)
|
||||
---
|
||||
libstdc++-v3/include/bits/random.tcc | 2 +-
|
||||
.../operators/serialize.cc | 36 ++++++++++++++++++-
|
||||
2 files changed, 36 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc
|
||||
index 0a299baedc5..0f758671f69 100644
|
||||
--- a/libstdc++-v3/include/bits/random.tcc
|
||||
+++ b/libstdc++-v3/include/bits/random.tcc
|
||||
@@ -1941,7 +1941,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
bool __saved_avail;
|
||||
if (__is >> __mean >> __stddev >> __saved_avail)
|
||||
{
|
||||
- if (__saved_avail && (__is >> __x._M_saved))
|
||||
+ if (!__saved_avail || (__is >> __x._M_saved))
|
||||
{
|
||||
__x._M_saved_available = __saved_avail;
|
||||
__x.param(typename normal_distribution<_RealType>::
|
||||
diff --git a/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc b/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc
|
||||
index a65d4004161..8cc70886bc7 100644
|
||||
--- a/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc
|
||||
+++ b/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
+#include <testsuite_hooks.h>
|
||||
|
||||
void
|
||||
test01()
|
||||
@@ -37,10 +38,43 @@ test01()
|
||||
str << u;
|
||||
|
||||
str >> v;
|
||||
+ VERIFY( u == v );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+test_pr105502()
|
||||
+{
|
||||
+ // PR libstdc++/105502 std::normal_distribution deserialization issue
|
||||
+ std::stringstream str;
|
||||
+ std::normal_distribution<> d{1, 2}, d2;
|
||||
+ std::minstd_rand0 g;
|
||||
+ str << d;
|
||||
+ VERIFY( str );
|
||||
+ str >> d2;
|
||||
+ VERIFY( str );
|
||||
+ VERIFY( d == d2 );
|
||||
+
|
||||
+ (void) d(g); // sets d._M_saved_available = true
|
||||
+ str.str("");
|
||||
+ str.clear();
|
||||
+ str << d;
|
||||
+ VERIFY( str );
|
||||
+ str >> d2;
|
||||
+ VERIFY( str );
|
||||
+ VERIFY( d == d2 );
|
||||
+
|
||||
+ (void) d(g); // sets d._M_saved_available = false
|
||||
+ str.str("");
|
||||
+ str.clear();
|
||||
+ str << d;
|
||||
+ VERIFY( str );
|
||||
+ str >> d2;
|
||||
+ VERIFY( str );
|
||||
+ VERIFY( d == d2 );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
- return 0;
|
||||
+ test_pr105502();
|
||||
}
|
||||
--
|
||||
2.31.1
|
||||
|
||||
@ -1,61 +0,0 @@
|
||||
commit e150cbf591759af10f3d57acbe0eb381aafa00de
|
||||
Author: Richard Biener <rguenther@suse.de>
|
||||
Date: Thu Aug 17 13:10:14 2023 +0200
|
||||
|
||||
tree-optimization/111039 - abnormals and bit test merging
|
||||
|
||||
The following guards the bit test merging code in if-combine against
|
||||
the appearance of SSA names used in abnormal PHIs.
|
||||
|
||||
PR tree-optimization/111039
|
||||
* tree-ssa-ifcombine.cc (ifcombine_ifandif): Check for
|
||||
SSA_NAME_OCCURS_IN_ABNORMAL_PHI.
|
||||
|
||||
* gcc.dg/pr111039.c: New testcase.
|
||||
|
||||
(cherry picked from commit 482551a79a3d3f107f6239679ee74655cfe8707e)
|
||||
|
||||
diff --git a/gcc/testsuite/gcc.dg/pr111039.c b/gcc/testsuite/gcc.dg/pr111039.c
|
||||
new file mode 100644
|
||||
index 00000000000..bec9983b35f
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.dg/pr111039.c
|
||||
@@ -0,0 +1,15 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O" } */
|
||||
+
|
||||
+int _setjmp ();
|
||||
+void abcd ();
|
||||
+void abcde ();
|
||||
+void compiler_corruption_function(int flags)
|
||||
+{
|
||||
+ int nowait = flags & 1048576, isexpand = flags & 8388608;
|
||||
+ abcd();
|
||||
+ _setjmp(flags);
|
||||
+ if (nowait && isexpand)
|
||||
+ flags &= 0;
|
||||
+ abcde();
|
||||
+}
|
||||
--- a/gcc/tree-ssa-ifcombine.c
|
||||
+++ b/gcc/tree-ssa-ifcombine.c
|
||||
@@ -407,6 +407,9 @@ ifcombine_ifandif (basic_block inner_con
|
||||
{
|
||||
tree t, t2;
|
||||
|
||||
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1))
|
||||
+ return false;
|
||||
+
|
||||
/* Do it. */
|
||||
gsi = gsi_for_stmt (inner_cond);
|
||||
t = fold_build2 (LSHIFT_EXPR, TREE_TYPE (name1),
|
||||
@@ -457,6 +460,10 @@ ifcombine_ifandif (basic_block inner_con
|
||||
gimple_stmt_iterator gsi;
|
||||
tree t;
|
||||
|
||||
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1)
|
||||
+ || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2))
|
||||
+ return false;
|
||||
+
|
||||
/* Find the common name which is bit-tested. */
|
||||
if (name1 == name2)
|
||||
;
|
||||
@ -1,68 +0,0 @@
|
||||
commit ad42dcf501e41713047cf6c47cbb1dd9f01088a4
|
||||
Author: Richard Biener <rguenther@suse.de>
|
||||
Date: Mon Aug 21 09:01:00 2023 +0200
|
||||
|
||||
tree-optimization/111070 - fix ICE with recent ifcombine fix
|
||||
|
||||
We now got test coverage for non-SSA name bits so the following amends
|
||||
the SSA_NAME_OCCURS_IN_ABNORMAL_PHI checks.
|
||||
|
||||
PR tree-optimization/111070
|
||||
* tree-ssa-ifcombine.cc (ifcombine_ifandif): Check we have
|
||||
an SSA name before checking SSA_NAME_OCCURS_IN_ABNORMAL_PHI.
|
||||
|
||||
* gcc.dg/pr111070.c: New testcase.
|
||||
|
||||
(cherry picked from commit 966b0a96523fb7adbf498ac71df5e033c70dc546)
|
||||
|
||||
diff --git a/gcc/testsuite/gcc.dg/pr111070.c b/gcc/testsuite/gcc.dg/pr111070.c
|
||||
new file mode 100644
|
||||
index 00000000000..1ebc7adf782
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.dg/pr111070.c
|
||||
@@ -0,0 +1,20 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O" } */
|
||||
+
|
||||
+/* common */
|
||||
+char c;
|
||||
+/* arrays must be 8 byte aligned, regardless of size */
|
||||
+char c_ary[1];
|
||||
+
|
||||
+/* data */
|
||||
+char d = 1;
|
||||
+char d_ary[1] = {1};
|
||||
+
|
||||
+int main ()
|
||||
+{
|
||||
+ if (((unsigned long)&c_ary[0] & 7) != 0)
|
||||
+ return 1;
|
||||
+ if (((unsigned long)&d_ary[0] & 7) != 0)
|
||||
+ return 1;
|
||||
+ return 0;
|
||||
+}
|
||||
--- a/gcc/tree-ssa-ifcombine.c
|
||||
+++ b/gcc/tree-ssa-ifcombine.c
|
||||
@@ -436,7 +436,8 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
|
||||
{
|
||||
tree t, t2;
|
||||
|
||||
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1))
|
||||
+ if (TREE_CODE (name1) == SSA_NAME
|
||||
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1))
|
||||
return false;
|
||||
|
||||
/* Do it. */
|
||||
@@ -495,8 +496,10 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
|
||||
gimple_stmt_iterator gsi;
|
||||
tree t;
|
||||
|
||||
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1)
|
||||
- || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2))
|
||||
+ if ((TREE_CODE (name1) == SSA_NAME
|
||||
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1))
|
||||
+ || (TREE_CODE (name2) == SSA_NAME
|
||||
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2)))
|
||||
return false;
|
||||
|
||||
/* Find the common name which is bit-tested. */
|
||||
@ -1,71 +0,0 @@
|
||||
commit 8c21b0d164f33d9d47acc26f4f9b99b53e3b1945
|
||||
Author: Andreas Krebbel <krebbel@linux.ibm.com>
|
||||
Date: Tue Nov 6 10:22:05 2018 +0000
|
||||
|
||||
S/390: Fix PR87723
|
||||
|
||||
gcc/ChangeLog:
|
||||
|
||||
2018-11-06 Andreas Krebbel <krebbel@linux.ibm.com>
|
||||
|
||||
PR target/87723
|
||||
* config/s390/s390.md ("*r<noxa>sbg_di_rotl"): Remove mode
|
||||
attributes for operands 3 and 4.
|
||||
|
||||
gcc/testsuite/ChangeLog:
|
||||
|
||||
2018-11-06 Andreas Krebbel <krebbel@linux.ibm.com>
|
||||
|
||||
PR target/87723
|
||||
* gcc.target/s390/pr87723.c: New test.
|
||||
|
||||
From-SVN: r265832
|
||||
|
||||
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
|
||||
index 8e7b285e1c3..4ffd438c07c 100644
|
||||
--- a/gcc/config/s390/s390.md
|
||||
+++ b/gcc/config/s390/s390.md
|
||||
@@ -4230,7 +4230,7 @@ (define_insn "*r<noxa>sbg_di_rotl"
|
||||
(match_operand:DI 4 "nonimmediate_operand" "0")))
|
||||
(clobber (reg:CC CC_REGNUM))]
|
||||
"TARGET_Z10"
|
||||
- "r<noxa>sbg\t%0,%1,%<bfstart>2,%<bfend>2,%b3"
|
||||
+ "r<noxa>sbg\t%0,%1,%s2,%e2,%b3"
|
||||
[(set_attr "op_type" "RIE")])
|
||||
|
||||
; rosbg, rxsbg
|
||||
diff --git a/gcc/testsuite/gcc.target/s390/pr87723.c b/gcc/testsuite/gcc.target/s390/pr87723.c
|
||||
new file mode 100644
|
||||
index 00000000000..b0e8a5a3118
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.target/s390/pr87723.c
|
||||
@@ -0,0 +1,29 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O3 -march=z196 -m64 -mzarch" } */
|
||||
+
|
||||
+unsigned long a;
|
||||
+int b;
|
||||
+void c(char* i) {
|
||||
+ for (;;) {
|
||||
+ char g = 0;
|
||||
+ for (; g < 24; ++g)
|
||||
+ b = a << g | a >> 64 - g;
|
||||
+ {
|
||||
+ char *d = i;
|
||||
+ long h = b;
|
||||
+ char e = 0;
|
||||
+ for (; e < 8; ++e)
|
||||
+ d[e] = h;
|
||||
+ }
|
||||
+ char *d = i;
|
||||
+ signed e;
|
||||
+ unsigned long f = 0;
|
||||
+ e = 7;
|
||||
+ for (; e; --e) {
|
||||
+ f <<= 8;
|
||||
+ f |= d[e];
|
||||
+ }
|
||||
+ for (; e < 8; ++e)
|
||||
+ d[e] = f;
|
||||
+ }
|
||||
+}
|
||||
@ -1,254 +0,0 @@
|
||||
commit 6001db79c477b03eacc7e7049560921fb54b7845
|
||||
Author: Richard Sandiford <richard.sandiford@arm.com>
|
||||
Date: Mon Sep 7 20:15:36 2020 +0100
|
||||
|
||||
lra: Avoid cycling on certain subreg reloads [PR96796]
|
||||
|
||||
This PR is about LRA cycling for a reload of the form:
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Changing pseudo 196 in operand 1 of insn 103 on equiv [r105:DI*0x8+r140:DI]
|
||||
Creating newreg=287, assigning class ALL_REGS to slow/invalid mem r287
|
||||
Creating newreg=288, assigning class ALL_REGS to slow/invalid mem r288
|
||||
103: r203:SI=r288:SI<<0x1+r196:DI#0
|
||||
REG_DEAD r196:DI
|
||||
Inserting slow/invalid mem reload before:
|
||||
316: r287:DI=[r105:DI*0x8+r140:DI]
|
||||
317: r288:SI=r287:DI#0
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
The problem is with r287. We rightly give it a broad starting class of
|
||||
POINTER_AND_FP_REGS (reduced from ALL_REGS by preferred_reload_class).
|
||||
However, we never make forward progress towards narrowing it down to
|
||||
a specific choice of class (POINTER_REGS or FP_REGS).
|
||||
|
||||
I think in practice we rely on two things to narrow a reload pseudo's
|
||||
class down to a specific choice:
|
||||
|
||||
(1) a restricted class is specified when the pseudo is created
|
||||
|
||||
This happens for input address reloads, where the class is taken
|
||||
from the target's chosen base register class. It also happens
|
||||
for simple REG reloads, where the class is taken from the chosen
|
||||
alternative's constraints.
|
||||
|
||||
(2) uses of the reload pseudo as a direct input operand
|
||||
|
||||
In this case get_reload_reg tries to reuse the existing register
|
||||
and narrow its class, instead of creating a new reload pseudo.
|
||||
|
||||
However, neither occurs here. As described above, r287 rightly
|
||||
starts out with a wide choice of class, ultimately derived from
|
||||
ALL_REGS, so we don't get (1). And as the comments in the PR
|
||||
explain, r287 is never used as an input reload, only the subreg is,
|
||||
so we don't get (2):
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Choosing alt 13 in insn 317: (0) r (1) w {*movsi_aarch64}
|
||||
Creating newreg=291, assigning class FP_REGS to r291
|
||||
317: r288:SI=r291:SI
|
||||
Inserting insn reload before:
|
||||
320: r291:SI=r287:DI#0
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
IMO, in this case we should rely on the reload of r316 to narrow
|
||||
down the class of r278. Currently we do:
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Choosing alt 7 in insn 316: (0) r (1) m {*movdi_aarch64}
|
||||
Creating newreg=289 from oldreg=287, assigning class GENERAL_REGS to r289
|
||||
316: r289:DI=[r105:DI*0x8+r140:DI]
|
||||
Inserting insn reload after:
|
||||
318: r287:DI=r289:DI
|
||||
---------------------------------------------------
|
||||
|
||||
i.e. we create a new pseudo register r289 and give *that* pseudo
|
||||
GENERAL_REGS instead. This is because get_reload_reg only narrows
|
||||
down the existing class for OP_IN and OP_INOUT, not OP_OUT.
|
||||
|
||||
But if we have a reload pseudo in a reload instruction and have chosen
|
||||
a specific class for the reload pseudo, I think we should simply install
|
||||
it for OP_OUT reloads too, if the class is a subset of the existing class.
|
||||
We will need to pick such a register whatever happens (for r289 in the
|
||||
example above). And as explained in the PR, doing this actually avoids
|
||||
an unnecessary move via the FP registers too.
|
||||
|
||||
The patch is quite aggressive in that it does this for all reload
|
||||
pseudos in all reload instructions. I wondered about reusing the
|
||||
condition for a reload move in in_class_p:
|
||||
|
||||
INSN_UID (curr_insn) >= new_insn_uid_start
|
||||
&& curr_insn_set != NULL
|
||||
&& ((OBJECT_P (SET_SRC (curr_insn_set))
|
||||
&& ! CONSTANT_P (SET_SRC (curr_insn_set)))
|
||||
|| (GET_CODE (SET_SRC (curr_insn_set)) == SUBREG
|
||||
&& OBJECT_P (SUBREG_REG (SET_SRC (curr_insn_set)))
|
||||
&& ! CONSTANT_P (SUBREG_REG (SET_SRC (curr_insn_set)))))))
|
||||
|
||||
but I can't really justify that on first principles. I think we
|
||||
should apply the rule consistently until we have a specific reason
|
||||
for doing otherwise.
|
||||
|
||||
gcc/
|
||||
PR rtl-optimization/96796
|
||||
* lra-constraints.c (in_class_p): Add a default-false
|
||||
allow_all_reload_class_changes_p parameter. Do not treat
|
||||
reload moves specially when the parameter is true.
|
||||
(get_reload_reg): Try to narrow the class of an existing OP_OUT
|
||||
reload if we're reloading a reload pseudo in a reload instruction.
|
||||
|
||||
gcc/testsuite/
|
||||
PR rtl-optimization/96796
|
||||
* gcc.c-torture/compile/pr96796.c: New test.
|
||||
|
||||
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
|
||||
index 580da9c3ed6..161b721efb1 100644
|
||||
--- a/gcc/lra-constraints.c
|
||||
+++ b/gcc/lra-constraints.c
|
||||
@@ -236,12 +236,17 @@ get_reg_class (int regno)
|
||||
CL. Use elimination first if REG is a hard register. If REG is a
|
||||
reload pseudo created by this constraints pass, assume that it will
|
||||
be allocated a hard register from its allocno class, but allow that
|
||||
- class to be narrowed to CL if it is currently a superset of CL.
|
||||
+ class to be narrowed to CL if it is currently a superset of CL and
|
||||
+ if either:
|
||||
+
|
||||
+ - ALLOW_ALL_RELOAD_CLASS_CHANGES_P is true or
|
||||
+ - the instruction we're processing is not a reload move.
|
||||
|
||||
If NEW_CLASS is nonnull, set *NEW_CLASS to the new allocno class of
|
||||
REGNO (reg), or NO_REGS if no change in its class was needed. */
|
||||
static bool
|
||||
-in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class)
|
||||
+in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class,
|
||||
+ bool allow_all_reload_class_changes_p = false)
|
||||
{
|
||||
enum reg_class rclass, common_class;
|
||||
machine_mode reg_mode;
|
||||
@@ -266,7 +271,8 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class)
|
||||
typically moves that have many alternatives, and restricting
|
||||
reload pseudos for one alternative may lead to situations
|
||||
where other reload pseudos are no longer allocatable. */
|
||||
- || (INSN_UID (curr_insn) >= new_insn_uid_start
|
||||
+ || (!allow_all_reload_class_changes_p
|
||||
+ && INSN_UID (curr_insn) >= new_insn_uid_start
|
||||
&& curr_insn_set != NULL
|
||||
&& ((OBJECT_P (SET_SRC (curr_insn_set))
|
||||
&& ! CONSTANT_P (SET_SRC (curr_insn_set)))
|
||||
@@ -551,13 +557,12 @@ init_curr_insn_input_reloads (void)
|
||||
curr_insn_input_reloads_num = 0;
|
||||
}
|
||||
|
||||
-/* Create a new pseudo using MODE, RCLASS, ORIGINAL or reuse already
|
||||
- created input reload pseudo (only if TYPE is not OP_OUT). Don't
|
||||
- reuse pseudo if IN_SUBREG_P is true and the reused pseudo should be
|
||||
- wrapped up in SUBREG. The result pseudo is returned through
|
||||
- RESULT_REG. Return TRUE if we created a new pseudo, FALSE if we
|
||||
- reused the already created input reload pseudo. Use TITLE to
|
||||
- describe new registers for debug purposes. */
|
||||
+/* Create a new pseudo using MODE, RCLASS, ORIGINAL or reuse an existing
|
||||
+ reload pseudo. Don't reuse an existing reload pseudo if IN_SUBREG_P
|
||||
+ is true and the reused pseudo should be wrapped up in a SUBREG.
|
||||
+ The result pseudo is returned through RESULT_REG. Return TRUE if we
|
||||
+ created a new pseudo, FALSE if we reused an existing reload pseudo.
|
||||
+ Use TITLE to describe new registers for debug purposes. */
|
||||
static bool
|
||||
get_reload_reg (enum op_type type, machine_mode mode, rtx original,
|
||||
enum reg_class rclass, bool in_subreg_p,
|
||||
@@ -616,6 +621,35 @@ get_reload_reg (enum op_type type, machine_mode mode, rtx original,
|
||||
|
||||
if (type == OP_OUT)
|
||||
{
|
||||
+ /* Output reload registers tend to start out with a conservative
|
||||
+ choice of register class. Usually this is ALL_REGS, although
|
||||
+ a target might narrow it (for performance reasons) through
|
||||
+ targetm.preferred_reload_class. It's therefore quite common
|
||||
+ for a reload instruction to require a more restrictive class
|
||||
+ than the class that was originally assigned to the reload register.
|
||||
+
|
||||
+ In these situations, it's more efficient to refine the choice
|
||||
+ of register class rather than create a second reload register.
|
||||
+ This also helps to avoid cycling for registers that are only
|
||||
+ used by reload instructions. */
|
||||
+ if (REG_P (original)
|
||||
+ && (int) REGNO (original) >= new_regno_start
|
||||
+ && INSN_UID (curr_insn) >= new_insn_uid_start
|
||||
+ && in_class_p (original, rclass, &new_class, true))
|
||||
+ {
|
||||
+ unsigned int regno = REGNO (original);
|
||||
+ if (lra_dump_file != NULL)
|
||||
+ {
|
||||
+ fprintf (lra_dump_file, " Reuse r%d for output ", regno);
|
||||
+ dump_value_slim (lra_dump_file, original, 1);
|
||||
+ }
|
||||
+ if (new_class != lra_get_allocno_class (regno))
|
||||
+ lra_change_class (regno, new_class, ", change to", false);
|
||||
+ if (lra_dump_file != NULL)
|
||||
+ fprintf (lra_dump_file, "\n");
|
||||
+ *result_reg = original;
|
||||
+ return false;
|
||||
+ }
|
||||
*result_reg
|
||||
= lra_create_new_reg_with_unique_value (mode, original, rclass, title);
|
||||
return true;
|
||||
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr96796.c b/gcc/testsuite/gcc.c-torture/compile/pr96796.c
|
||||
new file mode 100644
|
||||
index 00000000000..8808e62fe77
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.c-torture/compile/pr96796.c
|
||||
@@ -0,0 +1,55 @@
|
||||
+/* { dg-additional-options "-fcommon" } */
|
||||
+
|
||||
+struct S0 {
|
||||
+ signed f0 : 8;
|
||||
+ unsigned f1;
|
||||
+ unsigned f4;
|
||||
+};
|
||||
+struct S1 {
|
||||
+ long f3;
|
||||
+ char f4;
|
||||
+} g_3_4;
|
||||
+
|
||||
+int g_5, func_1_l_32, func_50___trans_tmp_31;
|
||||
+static struct S0 g_144, g_834, g_1255, g_1261;
|
||||
+
|
||||
+int g_273[120] = {};
|
||||
+int *g_555;
|
||||
+char **g_979;
|
||||
+static int g_1092_0;
|
||||
+static int g_1193;
|
||||
+int safe_mul_func_int16_t_s_s(int si1, int si2) { return si1 * si2; }
|
||||
+static struct S0 *func_50();
|
||||
+int func_1() { func_50(g_3_4, g_5, func_1_l_32, 8, 3); }
|
||||
+void safe_div_func_int64_t_s_s(int *);
|
||||
+void safe_mod_func_uint32_t_u_u(struct S0);
|
||||
+struct S0 *func_50(int p_51, struct S0 p_52, struct S1 p_53, int p_54,
|
||||
+ int p_55) {
|
||||
+ int __trans_tmp_30;
|
||||
+ char __trans_tmp_22;
|
||||
+ short __trans_tmp_19;
|
||||
+ long l_985_1;
|
||||
+ long l_1191[8];
|
||||
+ safe_div_func_int64_t_s_s(g_273);
|
||||
+ __builtin_printf((char*)g_1261.f4);
|
||||
+ safe_mod_func_uint32_t_u_u(g_834);
|
||||
+ g_144.f0 += 1;
|
||||
+ for (;;) {
|
||||
+ struct S1 l_1350 = {&l_1350};
|
||||
+ for (; p_53.f3; p_53.f3 -= 1)
|
||||
+ for (; g_1193 <= 2; g_1193 += 1) {
|
||||
+ __trans_tmp_19 = safe_mul_func_int16_t_s_s(l_1191[l_985_1 + p_53.f3],
|
||||
+ p_55 % (**g_979 = 10));
|
||||
+ __trans_tmp_22 = g_1255.f1 * p_53.f4;
|
||||
+ __trans_tmp_30 = __trans_tmp_19 + __trans_tmp_22;
|
||||
+ if (__trans_tmp_30)
|
||||
+ g_1261.f0 = p_51;
|
||||
+ else {
|
||||
+ g_1255.f0 = p_53.f3;
|
||||
+ int *l_1422 = g_834.f0 = g_144.f4 != (*l_1422)++ > 0 < 0 ^ 51;
|
||||
+ g_555 = ~0;
|
||||
+ g_1092_0 |= func_50___trans_tmp_31;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
@ -1,77 +0,0 @@
|
||||
commit 6d134ca4b963706f31251f061fc180e517b32546
|
||||
Author: Martin Sebor <msebor@redhat.com>
|
||||
Date: Tue Feb 23 14:09:00 2021 -0700
|
||||
|
||||
PR c++/99074 - crash in dynamic_cast<>() on null pointer
|
||||
|
||||
libstdc++-v3/ChangeLog:
|
||||
|
||||
PR c++/99074
|
||||
* libsupc++/dyncast.cc (__dynamic_cast): Return null when
|
||||
first argument is null.
|
||||
|
||||
gcc/testsuite/ChangeLog:
|
||||
|
||||
PR c++/99074
|
||||
* g++.dg/warn/Wnonnull11.C: New test.
|
||||
|
||||
diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull11.C b/gcc/testsuite/g++.dg/warn/Wnonnull11.C
|
||||
new file mode 100644
|
||||
index 00000000000..5f1b69d9a41
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/g++.dg/warn/Wnonnull11.C
|
||||
@@ -0,0 +1,40 @@
|
||||
+/* PR c++/99074 - gcc 8 and above is crashing with dynamic_cast<>() on null
|
||||
+ pointer with optimization level -O1 and above
|
||||
+ { dg-do run }
|
||||
+ { dg-options "-O1 -Wall" } */
|
||||
+
|
||||
+class Base
|
||||
+{
|
||||
+public:
|
||||
+ virtual ~Base() {}
|
||||
+ virtual void op() = 0;
|
||||
+};
|
||||
+
|
||||
+class Object: public virtual Base { };
|
||||
+
|
||||
+class AbstractBase: public virtual Base
|
||||
+{
|
||||
+public:
|
||||
+ Object* _to_object ()
|
||||
+ {
|
||||
+ return dynamic_cast<Object*>(this); // { dg-warning "\\\[-Wnonnull" "" { xfail *-*-* } }
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+class MyAbstractClass: public virtual AbstractBase
|
||||
+{
|
||||
+public:
|
||||
+ static MyAbstractClass* _nil () { return 0; }
|
||||
+};
|
||||
+
|
||||
+
|
||||
+int main ()
|
||||
+{
|
||||
+ MyAbstractClass *my_abs_type = MyAbstractClass::_nil ();
|
||||
+ AbstractBase *abs_base = my_abs_type;
|
||||
+ Object *obj = abs_base->_to_object ();
|
||||
+
|
||||
+ __builtin_printf ("object is: %p\n", obj);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/libstdc++-v3/libsupc++/dyncast.cc b/libstdc++-v3/libsupc++/dyncast.cc
|
||||
index b7d98495ad3..f8f707ee4d4 100644
|
||||
--- a/libstdc++-v3/libsupc++/dyncast.cc
|
||||
+++ b/libstdc++-v3/libsupc++/dyncast.cc
|
||||
@@ -47,6 +47,9 @@ __dynamic_cast (const void *src_ptr, // object started from
|
||||
const __class_type_info *dst_type, // desired target type
|
||||
ptrdiff_t src2dst) // how src and dst are related
|
||||
{
|
||||
+ if (!src_ptr)
|
||||
+ /* Handle precondition violations gracefully. */
|
||||
+ return NULL;
|
||||
const void *vtable = *static_cast <const void *const *> (src_ptr);
|
||||
const vtable_prefix *prefix =
|
||||
adjust_pointer <vtable_prefix> (vtable,
|
||||
@ -1,47 +0,0 @@
|
||||
commit 29dad307b5d7cfdb6626c11c8e43ebff941c950b
|
||||
Author: Jonathan Wakely <jwakely@redhat.com>
|
||||
Date: Thu Mar 11 16:43:51 2021 +0000
|
||||
|
||||
libstdc++: Initialize std::normal_distribution::_M_saved [PR 99536]
|
||||
|
||||
This avoids a false positive -Wmaybe-uninitialized warning, by
|
||||
initializing _M_saved on construction.
|
||||
|
||||
libstdc++-v3/ChangeLog:
|
||||
|
||||
PR libstdc++/99536
|
||||
* include/bits/random.h (normal_distribution): Use
|
||||
default-initializer for _M_saved and _M_saved_available.
|
||||
|
||||
(cherry picked from commit 67e397660611990efd98f9e4106c1ee81f6803a4)
|
||||
|
||||
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h
|
||||
index b36781ed290..3385345d273 100644
|
||||
--- a/libstdc++-v3/include/bits/random.h
|
||||
+++ b/libstdc++-v3/include/bits/random.h
|
||||
@@ -1974,12 +1974,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
explicit
|
||||
normal_distribution(result_type __mean = result_type(0),
|
||||
result_type __stddev = result_type(1))
|
||||
- : _M_param(__mean, __stddev), _M_saved_available(false)
|
||||
+ : _M_param(__mean, __stddev)
|
||||
{ }
|
||||
|
||||
explicit
|
||||
normal_distribution(const param_type& __p)
|
||||
- : _M_param(__p), _M_saved_available(false)
|
||||
+ : _M_param(__p)
|
||||
{ }
|
||||
|
||||
/**
|
||||
@@ -2158,8 +2158,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
const param_type& __p);
|
||||
|
||||
param_type _M_param;
|
||||
- result_type _M_saved;
|
||||
- bool _M_saved_available;
|
||||
+ result_type _M_saved = 0;
|
||||
+ bool _M_saved_available = false;
|
||||
};
|
||||
|
||||
/**
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,445 +0,0 @@
|
||||
--- gcc/config/aarch64/aarch64.c
|
||||
+++ gcc/config/aarch64/aarch64.c
|
||||
@@ -3799,7 +3799,14 @@ aarch64_output_probe_stack_range (rtx reg1, rtx reg2)
|
||||
output_asm_insn ("sub\t%0, %0, %1", xops);
|
||||
|
||||
/* Probe at TEST_ADDR. */
|
||||
- output_asm_insn ("str\txzr, [%0]", xops);
|
||||
+ if (flag_stack_clash_protection)
|
||||
+ {
|
||||
+ gcc_assert (xops[0] == stack_pointer_rtx);
|
||||
+ xops[1] = GEN_INT (PROBE_INTERVAL - 8);
|
||||
+ output_asm_insn ("str\txzr, [%0, %1]", xops);
|
||||
+ }
|
||||
+ else
|
||||
+ output_asm_insn ("str\txzr, [%0]", xops);
|
||||
|
||||
/* Test if TEST_ADDR == LAST_ADDR. */
|
||||
xops[1] = reg2;
|
||||
@@ -4589,6 +4596,133 @@ aarch64_set_handled_components (sbitmap components)
|
||||
cfun->machine->reg_is_wrapped_separately[regno] = true;
|
||||
}
|
||||
|
||||
+/* Allocate POLY_SIZE bytes of stack space using TEMP1 and TEMP2 as scratch
|
||||
+ registers. */
|
||||
+
|
||||
+static void
|
||||
+aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
|
||||
+ poly_int64 poly_size)
|
||||
+{
|
||||
+ HOST_WIDE_INT size;
|
||||
+ if (!poly_size.is_constant (&size))
|
||||
+ {
|
||||
+ sorry ("stack probes for SVE frames");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ HOST_WIDE_INT probe_interval
|
||||
+ = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL);
|
||||
+ HOST_WIDE_INT guard_size
|
||||
+ = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE);
|
||||
+ HOST_WIDE_INT guard_used_by_caller = 1024;
|
||||
+
|
||||
+ /* SIZE should be large enough to require probing here. ie, it
|
||||
+ must be larger than GUARD_SIZE - GUARD_USED_BY_CALLER.
|
||||
+
|
||||
+ We can allocate GUARD_SIZE - GUARD_USED_BY_CALLER as a single chunk
|
||||
+ without any probing. */
|
||||
+ gcc_assert (size >= guard_size - guard_used_by_caller);
|
||||
+ aarch64_sub_sp (temp1, temp2, guard_size - guard_used_by_caller, true);
|
||||
+ HOST_WIDE_INT orig_size = size;
|
||||
+ size -= (guard_size - guard_used_by_caller);
|
||||
+
|
||||
+ HOST_WIDE_INT rounded_size = size & -probe_interval;
|
||||
+ HOST_WIDE_INT residual = size - rounded_size;
|
||||
+
|
||||
+ /* We can handle a small number of allocations/probes inline. Otherwise
|
||||
+ punt to a loop. */
|
||||
+ if (rounded_size && rounded_size <= 4 * probe_interval)
|
||||
+ {
|
||||
+ /* We don't use aarch64_sub_sp here because we don't want to
|
||||
+ repeatedly load TEMP1. */
|
||||
+ rtx step = GEN_INT (-probe_interval);
|
||||
+ if (probe_interval > ARITH_FACTOR)
|
||||
+ {
|
||||
+ emit_move_insn (temp1, step);
|
||||
+ step = temp1;
|
||||
+ }
|
||||
+
|
||||
+ for (HOST_WIDE_INT i = 0; i < rounded_size; i += probe_interval)
|
||||
+ {
|
||||
+ rtx_insn *insn = emit_insn (gen_add2_insn (stack_pointer_rtx, step));
|
||||
+ add_reg_note (insn, REG_STACK_CHECK, const0_rtx);
|
||||
+
|
||||
+ if (probe_interval > ARITH_FACTOR)
|
||||
+ {
|
||||
+ RTX_FRAME_RELATED_P (insn) = 1;
|
||||
+ rtx adj = plus_constant (Pmode, stack_pointer_rtx, -probe_interval);
|
||||
+ add_reg_note (insn, REG_CFA_ADJUST_CFA,
|
||||
+ gen_rtx_SET (stack_pointer_rtx, adj));
|
||||
+ }
|
||||
+
|
||||
+ emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
|
||||
+ (probe_interval
|
||||
+ - GET_MODE_SIZE (word_mode))));
|
||||
+ emit_insn (gen_blockage ());
|
||||
+ }
|
||||
+ dump_stack_clash_frame_info (PROBE_INLINE, size != rounded_size);
|
||||
+ }
|
||||
+ else if (rounded_size)
|
||||
+ {
|
||||
+ /* Compute the ending address. */
|
||||
+ unsigned int scratchreg = REGNO (temp1);
|
||||
+ emit_move_insn (temp1, GEN_INT (-rounded_size));
|
||||
+ rtx_insn *insn
|
||||
+ = emit_insn (gen_add3_insn (temp1, stack_pointer_rtx, temp1));
|
||||
+
|
||||
+ /* For the initial allocation, we don't have a frame pointer
|
||||
+ set up, so we always need CFI notes. If we're doing the
|
||||
+ final allocation, then we may have a frame pointer, in which
|
||||
+ case it is the CFA, otherwise we need CFI notes.
|
||||
+
|
||||
+ We can determine which allocation we are doing by looking at
|
||||
+ the temporary register. IP0 is the initial allocation, IP1
|
||||
+ is the final allocation. */
|
||||
+ if (scratchreg == IP0_REGNUM || !frame_pointer_needed)
|
||||
+ {
|
||||
+ /* We want the CFA independent of the stack pointer for the
|
||||
+ duration of the loop. */
|
||||
+ add_reg_note (insn, REG_CFA_DEF_CFA,
|
||||
+ plus_constant (Pmode, temp1,
|
||||
+ (rounded_size + (orig_size - size))));
|
||||
+ RTX_FRAME_RELATED_P (insn) = 1;
|
||||
+ }
|
||||
+
|
||||
+ /* This allocates and probes the stack.
|
||||
+
|
||||
+ It also probes at a 4k interval regardless of the value of
|
||||
+ PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL. */
|
||||
+ insn = emit_insn (gen_probe_stack_range (stack_pointer_rtx,
|
||||
+ stack_pointer_rtx, temp1));
|
||||
+
|
||||
+ /* Now reset the CFA register if needed. */
|
||||
+ if (scratchreg == IP0_REGNUM || !frame_pointer_needed)
|
||||
+ {
|
||||
+ add_reg_note (insn, REG_CFA_DEF_CFA,
|
||||
+ plus_constant (Pmode, stack_pointer_rtx,
|
||||
+ (rounded_size + (orig_size - size))));
|
||||
+ RTX_FRAME_RELATED_P (insn) = 1;
|
||||
+ }
|
||||
+
|
||||
+ emit_insn (gen_blockage ());
|
||||
+ dump_stack_clash_frame_info (PROBE_LOOP, size != rounded_size);
|
||||
+ }
|
||||
+ else
|
||||
+ dump_stack_clash_frame_info (PROBE_INLINE, size != rounded_size);
|
||||
+
|
||||
+ /* Handle any residuals.
|
||||
+ Note that any residual must be probed. */
|
||||
+ if (residual)
|
||||
+ {
|
||||
+ aarch64_sub_sp (temp1, temp2, residual, true);
|
||||
+ add_reg_note (get_last_insn (), REG_STACK_CHECK, const0_rtx);
|
||||
+ emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
|
||||
+ (residual - GET_MODE_SIZE (word_mode))));
|
||||
+ emit_insn (gen_blockage ());
|
||||
+ }
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
/* Add a REG_CFA_EXPRESSION note to INSN to say that register REG
|
||||
is saved at BASE + OFFSET. */
|
||||
|
||||
@@ -4686,7 +4820,54 @@ aarch64_expand_prologue (void)
|
||||
rtx ip0_rtx = gen_rtx_REG (Pmode, IP0_REGNUM);
|
||||
rtx ip1_rtx = gen_rtx_REG (Pmode, IP1_REGNUM);
|
||||
|
||||
- aarch64_sub_sp (ip0_rtx, ip1_rtx, initial_adjust, true);
|
||||
+ /* We do not fully protect aarch64 against stack clash style attacks
|
||||
+ as doing so would be prohibitively expensive with less utility over
|
||||
+ time as newer compilers are deployed.
|
||||
+
|
||||
+ We assume the guard is at least 64k. Furthermore, we assume that
|
||||
+ the caller has not pushed the stack pointer more than 1k into
|
||||
+ the guard. A caller that pushes the stack pointer than 1k into
|
||||
+ the guard is considered invalid.
|
||||
+
|
||||
+ Note that the caller's ability to push the stack pointer into the
|
||||
+ guard is a function of the number and size of outgoing arguments and/or
|
||||
+ dynamic stack allocations due to the mandatory save of the link register
|
||||
+ in the caller's frame.
|
||||
+
|
||||
+ With those assumptions the callee can allocate up to 63k of stack
|
||||
+ space without probing.
|
||||
+
|
||||
+ When probing is needed, we emit a probe at the start of the prologue
|
||||
+ and every PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL bytes thereafter.
|
||||
+
|
||||
+ We have to track how much space has been allocated, but we do not
|
||||
+ track stores into the stack as implicit probes except for the
|
||||
+ fp/lr store. */
|
||||
+ HOST_WIDE_INT guard_size
|
||||
+ = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE);
|
||||
+ HOST_WIDE_INT guard_used_by_caller = 1024;
|
||||
+ if (flag_stack_clash_protection)
|
||||
+ {
|
||||
+ if (known_eq (frame_size, 0))
|
||||
+ dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
|
||||
+ else if (known_lt (initial_adjust, guard_size - guard_used_by_caller)
|
||||
+ && known_lt (final_adjust, guard_size - guard_used_by_caller))
|
||||
+ dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true);
|
||||
+ }
|
||||
+
|
||||
+ /* In theory we should never have both an initial adjustment
|
||||
+ and a callee save adjustment. Verify that is the case since the
|
||||
+ code below does not handle it for -fstack-clash-protection. */
|
||||
+ gcc_assert (known_eq (initial_adjust, 0) || callee_adjust == 0);
|
||||
+
|
||||
+ /* Only probe if the initial adjustment is larger than the guard
|
||||
+ less the amount of the guard reserved for use by the caller's
|
||||
+ outgoing args. */
|
||||
+ if (flag_stack_clash_protection
|
||||
+ && maybe_ge (initial_adjust, guard_size - guard_used_by_caller))
|
||||
+ aarch64_allocate_and_probe_stack_space (ip0_rtx, ip1_rtx, initial_adjust);
|
||||
+ else
|
||||
+ aarch64_sub_sp (ip0_rtx, ip1_rtx, initial_adjust, true);
|
||||
|
||||
if (callee_adjust != 0)
|
||||
aarch64_push_regs (reg1, reg2, callee_adjust);
|
||||
@@ -4742,7 +4923,31 @@ aarch64_expand_prologue (void)
|
||||
callee_adjust != 0 || emit_frame_chain);
|
||||
aarch64_save_callee_saves (DFmode, callee_offset, V0_REGNUM, V31_REGNUM,
|
||||
callee_adjust != 0 || emit_frame_chain);
|
||||
- aarch64_sub_sp (ip1_rtx, ip0_rtx, final_adjust, !frame_pointer_needed);
|
||||
+
|
||||
+ /* We may need to probe the final adjustment as well. */
|
||||
+ if (flag_stack_clash_protection && maybe_ne (final_adjust, 0))
|
||||
+ {
|
||||
+ /* First probe if the final adjustment is larger than the guard size
|
||||
+ less the amount of the guard reserved for use by the caller's
|
||||
+ outgoing args. */
|
||||
+ if (maybe_ge (final_adjust, guard_size - guard_used_by_caller))
|
||||
+ aarch64_allocate_and_probe_stack_space (ip1_rtx, ip0_rtx,
|
||||
+ final_adjust);
|
||||
+ else
|
||||
+ aarch64_sub_sp (ip1_rtx, ip0_rtx, final_adjust, !frame_pointer_needed);
|
||||
+
|
||||
+ /* We must also probe if the final adjustment is larger than the guard
|
||||
+ that is assumed used by the caller. This may be sub-optimal. */
|
||||
+ if (maybe_ge (final_adjust, guard_used_by_caller))
|
||||
+ {
|
||||
+ if (dump_file)
|
||||
+ fprintf (dump_file,
|
||||
+ "Stack clash aarch64 large outgoing arg, probing\n");
|
||||
+ emit_stack_probe (stack_pointer_rtx);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ aarch64_sub_sp (ip1_rtx, ip0_rtx, final_adjust, !frame_pointer_needed);
|
||||
}
|
||||
|
||||
/* Return TRUE if we can use a simple_return insn.
|
||||
@@ -10476,6 +10681,12 @@ aarch64_override_options_internal (struct gcc_options *opts)
|
||||
&& opts->x_optimize >= aarch64_tune_params.prefetch->default_opt_level)
|
||||
opts->x_flag_prefetch_loop_arrays = 1;
|
||||
|
||||
+ /* We assume the guard page is 64k. */
|
||||
+ maybe_set_param_value (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE,
|
||||
+ 16,
|
||||
+ opts->x_param_values,
|
||||
+ global_options_set.x_param_values);
|
||||
+
|
||||
aarch64_override_options_after_change_1 (opts);
|
||||
}
|
||||
|
||||
@@ -17161,6 +17372,28 @@ aarch64_sched_can_speculate_insn (rtx_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
+/* It has been decided that to allow up to 1kb of outgoing argument
|
||||
+ space to be allocated w/o probing. If more than 1kb of outgoing
|
||||
+ argment space is allocated, then it must be probed and the last
|
||||
+ probe must occur no more than 1kbyte away from the end of the
|
||||
+ allocated space.
|
||||
+
|
||||
+ This implies that the residual part of an alloca allocation may
|
||||
+ need probing in cases where the generic code might not otherwise
|
||||
+ think a probe is needed.
|
||||
+
|
||||
+ This target hook returns TRUE when allocating RESIDUAL bytes of
|
||||
+ alloca space requires an additional probe, otherwise FALSE is
|
||||
+ returned. */
|
||||
+
|
||||
+static bool
|
||||
+aarch64_stack_clash_protection_final_dynamic_probe (rtx residual)
|
||||
+{
|
||||
+ return (residual == CONST0_RTX (Pmode)
|
||||
+ || GET_CODE (residual) != CONST_INT
|
||||
+ || INTVAL (residual) >= 1024);
|
||||
+}
|
||||
+
|
||||
/* Implement TARGET_COMPUTE_PRESSURE_CLASSES. */
|
||||
|
||||
static int
|
||||
@@ -17669,6 +17902,10 @@ aarch64_libgcc_floating_mode_supported_p
|
||||
#undef TARGET_CONSTANT_ALIGNMENT
|
||||
#define TARGET_CONSTANT_ALIGNMENT aarch64_constant_alignment
|
||||
|
||||
+#undef TARGET_STACK_CLASH_PROTECTION_FINAL_DYNAMIC_PROBE
|
||||
+#define TARGET_STACK_CLASH_PROTECTION_FINAL_DYNAMIC_PROBE \
|
||||
+ aarch64_stack_clash_protection_final_dynamic_probe
|
||||
+
|
||||
#undef TARGET_COMPUTE_PRESSURE_CLASSES
|
||||
#define TARGET_COMPUTE_PRESSURE_CLASSES aarch64_compute_pressure_classes
|
||||
|
||||
--- gcc/config/aarch64/aarch64.md
|
||||
+++ gcc/config/aarch64/aarch64.md
|
||||
@@ -5812,7 +5812,7 @@
|
||||
)
|
||||
|
||||
(define_insn "probe_stack_range"
|
||||
- [(set (match_operand:DI 0 "register_operand" "=r")
|
||||
+ [(set (match_operand:DI 0 "register_operand" "=rk")
|
||||
(unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
|
||||
(match_operand:DI 2 "register_operand" "r")]
|
||||
UNSPECV_PROBE_STACK_RANGE))]
|
||||
--- gcc/testsuite/gcc.target/aarch64/stack-check-12.c
|
||||
+++ gcc/testsuite/gcc.target/aarch64/stack-check-12.c
|
||||
@@ -0,0 +1,20 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
|
||||
+/* { dg-require-effective-target supports_stack_clash_protection } */
|
||||
+
|
||||
+extern void arf (unsigned long int *, unsigned long int *);
|
||||
+void
|
||||
+frob ()
|
||||
+{
|
||||
+ unsigned long int num[1000];
|
||||
+ unsigned long int den[1000];
|
||||
+ arf (den, num);
|
||||
+}
|
||||
+
|
||||
+/* This verifies that the scheduler did not break the dependencies
|
||||
+ by adjusting the offsets within the probe and that the scheduler
|
||||
+ did not reorder around the stack probes. */
|
||||
+/* { dg-final { scan-assembler-times "sub\\tsp, sp, #4096\\n\\tstr\\txzr, .sp, 4088." 3 } } */
|
||||
+
|
||||
+
|
||||
+
|
||||
--- gcc/testsuite/gcc.target/aarch64/stack-check-13.c
|
||||
+++ gcc/testsuite/gcc.target/aarch64/stack-check-13.c
|
||||
@@ -0,0 +1,28 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
|
||||
+/* { dg-require-effective-target supports_stack_clash_protection } */
|
||||
+
|
||||
+#define ARG32(X) X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
|
||||
+#define ARG192(X) ARG32(X),ARG32(X),ARG32(X),ARG32(X),ARG32(X),ARG32(X)
|
||||
+void out1(ARG192(__int128));
|
||||
+int t1(int);
|
||||
+
|
||||
+int t3(int x)
|
||||
+{
|
||||
+ if (x < 1000)
|
||||
+ return t1 (x) + 1;
|
||||
+
|
||||
+ out1 (ARG192(1));
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+/* This test creates a large (> 1k) outgoing argument area that needs
|
||||
+ to be probed. We don't test the exact size of the space or the
|
||||
+ exact offset to make the test a little less sensitive to trivial
|
||||
+ output changes. */
|
||||
+/* { dg-final { scan-assembler-times "sub\\tsp, sp, #....\\n\\tstr\\txzr, \\\[sp" 1 } } */
|
||||
+
|
||||
+
|
||||
+
|
||||
--- gcc/testsuite/gcc.target/aarch64/stack-check-14.c
|
||||
+++ gcc/testsuite/gcc.target/aarch64/stack-check-14.c
|
||||
@@ -0,0 +1,25 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
|
||||
+/* { dg-require-effective-target supports_stack_clash_protection } */
|
||||
+
|
||||
+int t1(int);
|
||||
+
|
||||
+int t2(int x)
|
||||
+{
|
||||
+ char *p = __builtin_alloca (4050);
|
||||
+ x = t1 (x);
|
||||
+ return p[x];
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* This test has a constant sized alloca that is smaller than the
|
||||
+ probe interval. But it actually requires two probes instead
|
||||
+ of one because of the optimistic assumptions we made in the
|
||||
+ aarch64 prologue code WRT probing state.
|
||||
+
|
||||
+ The form can change quite a bit so we just check for two
|
||||
+ probes without looking at the actual address. */
|
||||
+/* { dg-final { scan-assembler-times "str\\txzr," 2 } } */
|
||||
+
|
||||
+
|
||||
+
|
||||
--- gcc/testsuite/gcc.target/aarch64/stack-check-15.c
|
||||
+++ gcc/testsuite/gcc.target/aarch64/stack-check-15.c
|
||||
@@ -0,0 +1,24 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
|
||||
+/* { dg-require-effective-target supports_stack_clash_protection } */
|
||||
+
|
||||
+int t1(int);
|
||||
+
|
||||
+int t2(int x)
|
||||
+{
|
||||
+ char *p = __builtin_alloca (x);
|
||||
+ x = t1 (x);
|
||||
+ return p[x];
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* This test has a variable sized alloca. It requires 3 probes.
|
||||
+ One in the loop, one for the residual and at the end of the
|
||||
+ alloca area.
|
||||
+
|
||||
+ The form can change quite a bit so we just check for two
|
||||
+ probes without looking at the actual address. */
|
||||
+/* { dg-final { scan-assembler-times "str\\txzr," 3 } } */
|
||||
+
|
||||
+
|
||||
+
|
||||
--- gcc/testsuite/lib/target-supports.exp
|
||||
+++ gcc/testsuite/lib/target-supports.exp
|
||||
@@ -9201,14 +9201,9 @@ proc check_effective_target_autoincdec { } {
|
||||
#
|
||||
proc check_effective_target_supports_stack_clash_protection { } {
|
||||
|
||||
- # Temporary until the target bits are fully ACK'd.
|
||||
-# if { [istarget aarch*-*-*] } {
|
||||
-# return 1
|
||||
-# }
|
||||
-
|
||||
if { [istarget x86_64-*-*] || [istarget i?86-*-*]
|
||||
|| [istarget powerpc*-*-*] || [istarget rs6000*-*-*]
|
||||
- || [istarget s390*-*-*] } {
|
||||
+ || [istarget aarch64*-**] || [istarget s390*-*-*] } {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
@@ -9217,9 +9212,9 @@ proc check_effective_target_supports_stack_clash_protection { } {
|
||||
# Return 1 if the target creates a frame pointer for non-leaf functions
|
||||
# Note we ignore cases where we apply tail call optimization here.
|
||||
proc check_effective_target_frame_pointer_for_non_leaf { } {
|
||||
- if { [istarget aarch*-*-*] } {
|
||||
- return 1
|
||||
- }
|
||||
+# if { [istarget aarch*-*-*] } {
|
||||
+# return 1
|
||||
+# }
|
||||
|
||||
# Solaris/x86 defaults to -fno-omit-frame-pointer.
|
||||
if { [istarget i?86-*-solaris*] || [istarget x86_64-*-solaris*] } {
|
||||
@ -1,406 +0,0 @@
|
||||
commit 126dab7c9d84294f256b1f7bf91c24a9e7103249
|
||||
Author: qinzhao <qinzhao@138bc75d-0d04-0410-961f-82ee72b054a4>
|
||||
Date: Thu Nov 29 16:06:03 2018 +0000
|
||||
|
||||
Add a new option -flive-patching={inline-only-static|inline-clone}
|
||||
to support live patching in GCC.
|
||||
|
||||
2018-11-29 qing zhao <qing.zhao@oracle.com>
|
||||
|
||||
gcc/ChangeLog:
|
||||
|
||||
* cif-code.def (EXTERN_LIVE_ONLY_STATIC): New CIF code.
|
||||
* common.opt: Add -flive-patching flag.
|
||||
* doc/invoke.texi: Document -flive-patching.
|
||||
* flag-types.h (enum live_patching_level): New enum.
|
||||
* ipa-inline.c (can_inline_edge_p): Disable external functions from
|
||||
inlining when flag_live_patching is LIVE_PATCHING_INLINE_ONLY_STATIC.
|
||||
* opts.c (control_options_for_live_patching): New function.
|
||||
(finish_options): Make flag_live_patching incompatible with flag_lto.
|
||||
Control IPA optimizations based on different levels of
|
||||
flag_live_patching.
|
||||
|
||||
gcc/testsuite/ChangeLog:
|
||||
|
||||
* gcc.dg/live-patching-1.c: New test.
|
||||
* gcc.dg/live-patching-2.c: New test.
|
||||
* gcc.dg/live-patching-3.c: New test.
|
||||
* gcc.dg/tree-ssa/writeonly-3.c: New test.
|
||||
* gcc.target/i386/ipa-stack-alignment-2.c: New test.
|
||||
|
||||
|
||||
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@266627 138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
--- gcc/cif-code.def
|
||||
+++ gcc/cif-code.def
|
||||
@@ -132,6 +132,12 @@ DEFCIFCODE(USES_COMDAT_LOCAL, CIF_FINAL_ERROR,
|
||||
DEFCIFCODE(ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR,
|
||||
N_("function attribute mismatch"))
|
||||
|
||||
+/* We can't inline because the user requests only static functions
|
||||
+ but the function has external linkage for live patching purpose. */
|
||||
+DEFCIFCODE(EXTERN_LIVE_ONLY_STATIC, CIF_FINAL_ERROR,
|
||||
+ N_("function has external linkage when the user requests only"
|
||||
+ " inlining static for live patching"))
|
||||
+
|
||||
/* We proved that the call is unreachable. */
|
||||
DEFCIFCODE(UNREACHABLE, CIF_FINAL_ERROR,
|
||||
N_("unreachable"))
|
||||
--- gcc/common.opt
|
||||
+++ gcc/common.opt
|
||||
@@ -2181,6 +2181,24 @@ starts and when the destructor finishes.
|
||||
flifetime-dse=
|
||||
Common Joined RejectNegative UInteger Var(flag_lifetime_dse) Optimization IntegerRange(0, 2)
|
||||
|
||||
+flive-patching
|
||||
+Common RejectNegative Alias(flive-patching=,inline-clone) Optimization
|
||||
+
|
||||
+flive-patching=
|
||||
+Common Report Joined RejectNegative Enum(live_patching_level) Var(flag_live_patching) Init(LIVE_PATCHING_NONE) Optimization
|
||||
+-flive-patching=[inline-only-static|inline-clone] Control IPA
|
||||
+optimizations to provide a safe compilation for live-patching. At the same
|
||||
+time, provides multiple-level control on the enabled IPA optimizations.
|
||||
+
|
||||
+Enum
|
||||
+Name(live_patching_level) Type(enum live_patching_level) UnknownError(unknown Live-Patching Level %qs)
|
||||
+
|
||||
+EnumValue
|
||||
+Enum(live_patching_level) String(inline-only-static) Value(LIVE_PATCHING_INLINE_ONLY_STATIC)
|
||||
+
|
||||
+EnumValue
|
||||
+Enum(live_patching_level) String(inline-clone) Value(LIVE_PATCHING_INLINE_CLONE)
|
||||
+
|
||||
flive-range-shrinkage
|
||||
Common Report Var(flag_live_range_shrinkage) Init(0) Optimization
|
||||
Relief of register pressure through live range shrinkage.
|
||||
--- gcc/doc/invoke.texi
|
||||
+++ gcc/doc/invoke.texi
|
||||
@@ -389,6 +389,7 @@ Objective-C and Objective-C++ Dialects}.
|
||||
-fipa-bit-cp -fipa-vrp @gol
|
||||
-fipa-pta -fipa-profile -fipa-pure-const -fipa-reference -fipa-icf @gol
|
||||
-fira-algorithm=@var{algorithm} @gol
|
||||
+-flive-patching=@var{level} @gol
|
||||
-fira-region=@var{region} -fira-hoist-pressure @gol
|
||||
-fira-loop-pressure -fno-ira-share-save-slots @gol
|
||||
-fno-ira-share-spill-slots @gol
|
||||
@@ -9291,6 +9292,65 @@ equivalences that are found only by GCC and equivalences found only by Gold.
|
||||
|
||||
This flag is enabled by default at @option{-O2} and @option{-Os}.
|
||||
|
||||
+@item -flive-patching=@var{level}
|
||||
+@opindex flive-patching
|
||||
+Control GCC's optimizations to provide a safe compilation for live-patching.
|
||||
+
|
||||
+If the compiler's optimization uses a function's body or information extracted
|
||||
+from its body to optimize/change another function, the latter is called an
|
||||
+impacted function of the former. If a function is patched, its impacted
|
||||
+functions should be patched too.
|
||||
+
|
||||
+The impacted functions are decided by the compiler's interprocedural
|
||||
+optimizations. For example, inlining a function into its caller, cloning
|
||||
+a function and changing its caller to call this new clone, or extracting
|
||||
+a function's pureness/constness information to optimize its direct or
|
||||
+indirect callers, etc.
|
||||
+
|
||||
+Usually, the more IPA optimizations enabled, the larger the number of
|
||||
+impacted functions for each function. In order to control the number of
|
||||
+impacted functions and computed the list of impacted function easily,
|
||||
+we provide control to partially enable IPA optimizations on two different
|
||||
+levels.
|
||||
+
|
||||
+The @var{level} argument should be one of the following:
|
||||
+
|
||||
+@table @samp
|
||||
+
|
||||
+@item inline-clone
|
||||
+
|
||||
+Only enable inlining and cloning optimizations, which includes inlining,
|
||||
+cloning, interprocedural scalar replacement of aggregates and partial inlining.
|
||||
+As a result, when patching a function, all its callers and its clones'
|
||||
+callers need to be patched as well.
|
||||
+
|
||||
+@option{-flive-patching=inline-clone} disables the following optimization flags:
|
||||
+@gccoptlist{-fwhole-program -fipa-pta -fipa-reference -fipa-ra @gol
|
||||
+-fipa-icf -fipa-icf-functions -fipa-icf-variables @gol
|
||||
+-fipa-bit-cp -fipa-vrp -fipa-pure-const -fipa-reference-addressable @gol
|
||||
+-fipa-stack-alignment}
|
||||
+
|
||||
+@item inline-only-static
|
||||
+
|
||||
+Only enable inlining of static functions.
|
||||
+As a result, when patching a static function, all its callers need to be
|
||||
+patches as well.
|
||||
+
|
||||
+In addition to all the flags that -flive-patching=inline-clone disables,
|
||||
+@option{-flive-patching=inline-only-static} disables the following additional
|
||||
+optimization flags:
|
||||
+@gccoptlist{-fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp}
|
||||
+
|
||||
+@end table
|
||||
+
|
||||
+When -flive-patching specified without any value, the default value
|
||||
+is "inline-clone".
|
||||
+
|
||||
+This flag is disabled by default.
|
||||
+
|
||||
+Note that -flive-patching is not supported with link-time optimizer.
|
||||
+(@option{-flto}).
|
||||
+
|
||||
@item -fisolate-erroneous-paths-dereference
|
||||
@opindex fisolate-erroneous-paths-dereference
|
||||
Detect paths that trigger erroneous or undefined behavior due to
|
||||
--- gcc/flag-types.h
|
||||
+++ gcc/flag-types.h
|
||||
@@ -123,6 +123,14 @@ enum stack_reuse_level
|
||||
SR_ALL
|
||||
};
|
||||
|
||||
+/* The live patching level. */
|
||||
+enum live_patching_level
|
||||
+{
|
||||
+ LIVE_PATCHING_NONE = 0,
|
||||
+ LIVE_PATCHING_INLINE_ONLY_STATIC,
|
||||
+ LIVE_PATCHING_INLINE_CLONE
|
||||
+};
|
||||
+
|
||||
/* The algorithm used for basic block reordering. */
|
||||
enum reorder_blocks_algorithm
|
||||
{
|
||||
--- gcc/ipa-inline.c
|
||||
+++ gcc/ipa-inline.c
|
||||
@@ -379,6 +379,12 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
|
||||
e->inline_failed = CIF_ATTRIBUTE_MISMATCH;
|
||||
inlinable = false;
|
||||
}
|
||||
+ else if (callee->externally_visible
|
||||
+ && flag_live_patching == LIVE_PATCHING_INLINE_ONLY_STATIC)
|
||||
+ {
|
||||
+ e->inline_failed = CIF_EXTERN_LIVE_ONLY_STATIC;
|
||||
+ inlinable = false;
|
||||
+ }
|
||||
if (!inlinable && report)
|
||||
report_inline_failed_reason (e);
|
||||
return inlinable;
|
||||
--- gcc/opts.c
|
||||
+++ gcc/opts.c
|
||||
@@ -699,6 +699,152 @@ default_options_optimization (struct gcc
|
||||
lang_mask, handlers, loc, dc);
|
||||
}
|
||||
|
||||
+/* Control IPA optimizations based on different live patching LEVEL. */
|
||||
+static void
|
||||
+control_options_for_live_patching (struct gcc_options *opts,
|
||||
+ struct gcc_options *opts_set,
|
||||
+ enum live_patching_level level,
|
||||
+ location_t loc)
|
||||
+{
|
||||
+ gcc_assert (level > LIVE_PATCHING_NONE);
|
||||
+
|
||||
+ switch (level)
|
||||
+ {
|
||||
+ case LIVE_PATCHING_INLINE_ONLY_STATIC:
|
||||
+ if (opts_set->x_flag_ipa_cp_clone && opts->x_flag_ipa_cp_clone)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-cp-clone%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_cp_clone = 0;
|
||||
+
|
||||
+ if (opts_set->x_flag_ipa_sra && opts->x_flag_ipa_sra)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-sra%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_sra = 0;
|
||||
+
|
||||
+ if (opts_set->x_flag_partial_inlining && opts->x_flag_partial_inlining)
|
||||
+ error_at (loc,
|
||||
+ "%<-fpartial-inlining%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static%>");
|
||||
+ else
|
||||
+ opts->x_flag_partial_inlining = 0;
|
||||
+
|
||||
+ if (opts_set->x_flag_ipa_cp && opts->x_flag_ipa_cp)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-cp%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_cp = 0;
|
||||
+
|
||||
+ /* FALLTHROUGH. */
|
||||
+ case LIVE_PATCHING_INLINE_CLONE:
|
||||
+ /* live patching should disable whole-program optimization. */
|
||||
+ if (opts_set->x_flag_whole_program && opts->x_flag_whole_program)
|
||||
+ error_at (loc,
|
||||
+ "%<-fwhole-program%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_whole_program = 0;
|
||||
+
|
||||
+ /* visibility change should be excluded by !flag_whole_program
|
||||
+ && !in_lto_p && !flag_ipa_cp_clone && !flag_ipa_sra
|
||||
+ && !flag_partial_inlining. */
|
||||
+
|
||||
+ if (opts_set->x_flag_ipa_pta && opts->x_flag_ipa_pta)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-pta%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_pta = 0;
|
||||
+
|
||||
+ if (opts_set->x_flag_ipa_reference && opts->x_flag_ipa_reference)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-reference%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_reference = 0;
|
||||
+
|
||||
+ if (opts_set->x_flag_ipa_ra && opts->x_flag_ipa_ra)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-ra%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_ra = 0;
|
||||
+
|
||||
+ if (opts_set->x_flag_ipa_icf && opts->x_flag_ipa_icf)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-icf%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_icf = 0;
|
||||
+
|
||||
+ if (opts_set->x_flag_ipa_icf_functions && opts->x_flag_ipa_icf_functions)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-icf-functions%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_icf_functions = 0;
|
||||
+
|
||||
+ if (opts_set->x_flag_ipa_icf_variables && opts->x_flag_ipa_icf_variables)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-icf-variables%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_icf_variables = 0;
|
||||
+
|
||||
+ if (opts_set->x_flag_ipa_bit_cp && opts->x_flag_ipa_bit_cp)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-bit-cp%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_bit_cp = 0;
|
||||
+
|
||||
+ if (opts_set->x_flag_ipa_vrp && opts->x_flag_ipa_vrp)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-vrp%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_vrp = 0;
|
||||
+
|
||||
+ if (opts_set->x_flag_ipa_pure_const && opts->x_flag_ipa_pure_const)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-pure-const%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_pure_const = 0;
|
||||
+
|
||||
+ /* FIXME: disable unreachable code removal. */
|
||||
+
|
||||
+ /* discovery of functions/variables with no address taken. */
|
||||
+// GCC 8 doesn't have these options.
|
||||
+#if 0
|
||||
+ if (opts_set->x_flag_ipa_reference_addressable
|
||||
+ && opts->x_flag_ipa_reference_addressable)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-reference-addressable%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_reference_addressable = 0;
|
||||
+
|
||||
+ /* ipa stack alignment propagation. */
|
||||
+ if (opts_set->x_flag_ipa_stack_alignment
|
||||
+ && opts->x_flag_ipa_stack_alignment)
|
||||
+ error_at (loc,
|
||||
+ "%<-fipa-stack-alignment%> is incompatible with "
|
||||
+ "%<-flive-patching=inline-only-static|inline-clone%>");
|
||||
+ else
|
||||
+ opts->x_flag_ipa_stack_alignment = 0;
|
||||
+#endif
|
||||
+
|
||||
+ break;
|
||||
+ default:
|
||||
+ gcc_unreachable ();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* After all options at LOC have been read into OPTS and OPTS_SET,
|
||||
finalize settings of those options and diagnose incompatible
|
||||
combinations. */
|
||||
@@ -1057,6 +1203,18 @@ finish_options (struct gcc_options *opts
|
||||
sorry ("transactional memory is not supported with "
|
||||
"%<-fsanitize=kernel-address%>");
|
||||
|
||||
+ /* Currently live patching is not support for LTO. */
|
||||
+ if (opts->x_flag_live_patching && opts->x_flag_lto)
|
||||
+ sorry ("live patching is not supported with LTO");
|
||||
+
|
||||
+ /* Control IPA optimizations based on different -flive-patching level. */
|
||||
+ if (opts->x_flag_live_patching)
|
||||
+ {
|
||||
+ control_options_for_live_patching (opts, opts_set,
|
||||
+ opts->x_flag_live_patching,
|
||||
+ loc);
|
||||
+ }
|
||||
+
|
||||
/* Comes from final.c -- no real reason to change it. */
|
||||
#define MAX_CODE_ALIGN 16
|
||||
#define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN)
|
||||
--- /dev/null
|
||||
+++ gcc/testsuite/gcc.dg/live-patching-1.c
|
||||
@@ -0,0 +1,22 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -flive-patching=inline-only-static -fdump-ipa-inline" } */
|
||||
+
|
||||
+extern int sum, n, m;
|
||||
+
|
||||
+int foo (int a)
|
||||
+{
|
||||
+ return a + n;
|
||||
+}
|
||||
+
|
||||
+static int bar (int b)
|
||||
+{
|
||||
+ return b * m;
|
||||
+}
|
||||
+
|
||||
+int main()
|
||||
+{
|
||||
+ sum = foo (m) + bar (n);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* { dg-final { scan-ipa-dump "foo/0 function has external linkage when the user requests only inlining static for live patching" "inline" } } */
|
||||
--- /dev/null
|
||||
+++ gcc/testsuite/gcc.dg/live-patching-2.c
|
||||
@@ -0,0 +1,9 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -flive-patching -flto" } */
|
||||
+
|
||||
+int main()
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* { dg-message "sorry, unimplemented: live patching is not supported with LTO" "-flive-patching and -flto together" { target *-*-* } 0 } */
|
||||
--- /dev/null
|
||||
+++ gcc/testsuite/gcc.dg/live-patching-3.c
|
||||
@@ -0,0 +1,9 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O1 -flive-patching -fwhole-program" } */
|
||||
+
|
||||
+int main()
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* { dg-message "'-fwhole-program' is incompatible with '-flive-patching=inline-only-static|inline-clone’" "" {target "*-*-*"} 0 } */
|
||||
@ -1,73 +0,0 @@
|
||||
commit 9939b2f79bd9b75b99080a17f3d6f1214d543477
|
||||
Author: qinzhao <qinzhao@138bc75d-0d04-0410-961f-82ee72b054a4>
|
||||
Date: Wed Apr 3 19:00:25 2019 +0000
|
||||
|
||||
2019-04-03 qing zhao <qing.zhao@oracle.com>
|
||||
|
||||
PR tree-optimization/89730
|
||||
* ipa-inline.c (can_inline_edge_p): Delete the checking for
|
||||
-flive-patching=inline-only-static.
|
||||
(can_inline_edge_by_limits_p): Add the checking for
|
||||
-flive-patching=inline-only-static and grant always_inline
|
||||
even when -flive-patching=inline-only-static is specified.
|
||||
|
||||
* gcc.dg/live-patching-4.c: New test.
|
||||
|
||||
|
||||
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@270134 138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
--- gcc/ipa-inline.c
|
||||
+++ gcc/ipa-inline.c
|
||||
@@ -385,12 +385,6 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
|
||||
e->inline_failed = CIF_ATTRIBUTE_MISMATCH;
|
||||
inlinable = false;
|
||||
}
|
||||
- else if (callee->externally_visible
|
||||
- && flag_live_patching == LIVE_PATCHING_INLINE_ONLY_STATIC)
|
||||
- {
|
||||
- e->inline_failed = CIF_EXTERN_LIVE_ONLY_STATIC;
|
||||
- inlinable = false;
|
||||
- }
|
||||
if (!inlinable && report)
|
||||
report_inline_failed_reason (e);
|
||||
return inlinable;
|
||||
@@ -433,6 +427,13 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, bool report,
|
||||
DECL_ATTRIBUTES (caller->decl))
|
||||
&& !caller_growth_limits (e))
|
||||
inlinable = false;
|
||||
+ else if (callee->externally_visible
|
||||
+ && !DECL_DISREGARD_INLINE_LIMITS (callee->decl)
|
||||
+ && flag_live_patching == LIVE_PATCHING_INLINE_ONLY_STATIC)
|
||||
+ {
|
||||
+ e->inline_failed = CIF_EXTERN_LIVE_ONLY_STATIC;
|
||||
+ inlinable = false;
|
||||
+ }
|
||||
/* Don't inline a function with a higher optimization level than the
|
||||
caller. FIXME: this is really just tip of iceberg of handling
|
||||
optimization attribute. */
|
||||
--- /dev/null
|
||||
+++ gcc/testsuite/gcc.dg/live-patching-4.c
|
||||
@@ -0,0 +1,23 @@
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-O2 -flive-patching=inline-only-static -fdump-tree-einline-optimized" } */
|
||||
+
|
||||
+extern int sum, n, m;
|
||||
+
|
||||
+extern inline __attribute__((always_inline)) int foo (int a);
|
||||
+inline __attribute__((always_inline)) int foo (int a)
|
||||
+{
|
||||
+ return a + n;
|
||||
+}
|
||||
+
|
||||
+static int bar (int b)
|
||||
+{
|
||||
+ return b * m;
|
||||
+}
|
||||
+
|
||||
+int main()
|
||||
+{
|
||||
+ sum = foo (m) + bar (n);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* { dg-final { scan-tree-dump "Inlining foo into main" "einline" } } */
|
||||
@ -1,85 +0,0 @@
|
||||
commit 77e6311332590004c5aec82ceeb45e4d4d93f690
|
||||
Author: redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
|
||||
Date: Thu Apr 11 08:52:22 2019 +0000
|
||||
|
||||
Clarify documentation for -flive-patching
|
||||
|
||||
* doc/invoke.texi (Optimize Options): Clarify -flive-patching docs.
|
||||
|
||||
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@270276 138bc75d-0d04-0410-961f-82ee72b054a4
|
||||
|
||||
--- gcc/doc/invoke.texi
|
||||
+++ gcc/doc/invoke.texi
|
||||
@@ -9367,24 +9367,24 @@ This flag is enabled by default at @option{-O2} and @option{-Os}.
|
||||
|
||||
@item -flive-patching=@var{level}
|
||||
@opindex flive-patching
|
||||
-Control GCC's optimizations to provide a safe compilation for live-patching.
|
||||
+Control GCC's optimizations to produce output suitable for live-patching.
|
||||
|
||||
If the compiler's optimization uses a function's body or information extracted
|
||||
from its body to optimize/change another function, the latter is called an
|
||||
impacted function of the former. If a function is patched, its impacted
|
||||
functions should be patched too.
|
||||
|
||||
-The impacted functions are decided by the compiler's interprocedural
|
||||
-optimizations. For example, inlining a function into its caller, cloning
|
||||
-a function and changing its caller to call this new clone, or extracting
|
||||
-a function's pureness/constness information to optimize its direct or
|
||||
-indirect callers, etc.
|
||||
+The impacted functions are determined by the compiler's interprocedural
|
||||
+optimizations. For example, a caller is impacted when inlining a function
|
||||
+into its caller,
|
||||
+cloning a function and changing its caller to call this new clone,
|
||||
+or extracting a function's pureness/constness information to optimize
|
||||
+its direct or indirect callers, etc.
|
||||
|
||||
Usually, the more IPA optimizations enabled, the larger the number of
|
||||
impacted functions for each function. In order to control the number of
|
||||
-impacted functions and computed the list of impacted function easily,
|
||||
-we provide control to partially enable IPA optimizations on two different
|
||||
-levels.
|
||||
+impacted functions and more easily compute the list of impacted function,
|
||||
+IPA optimizations can be partially enabled at two different levels.
|
||||
|
||||
The @var{level} argument should be one of the following:
|
||||
|
||||
@@ -9395,7 +9395,7 @@ The @var{level} argument should be one of the following:
|
||||
Only enable inlining and cloning optimizations, which includes inlining,
|
||||
cloning, interprocedural scalar replacement of aggregates and partial inlining.
|
||||
As a result, when patching a function, all its callers and its clones'
|
||||
-callers need to be patched as well.
|
||||
+callers are impacted, therefore need to be patched as well.
|
||||
|
||||
@option{-flive-patching=inline-clone} disables the following optimization flags:
|
||||
@gccoptlist{-fwhole-program -fipa-pta -fipa-reference -fipa-ra @gol
|
||||
@@ -9406,22 +9406,23 @@ callers need to be patched as well.
|
||||
@item inline-only-static
|
||||
|
||||
Only enable inlining of static functions.
|
||||
-As a result, when patching a static function, all its callers need to be
|
||||
-patches as well.
|
||||
+As a result, when patching a static function, all its callers are impacted
|
||||
+and so need to be patched as well.
|
||||
|
||||
-In addition to all the flags that -flive-patching=inline-clone disables,
|
||||
+In addition to all the flags that @option{-flive-patching=inline-clone}
|
||||
+disables,
|
||||
@option{-flive-patching=inline-only-static} disables the following additional
|
||||
optimization flags:
|
||||
@gccoptlist{-fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp}
|
||||
|
||||
@end table
|
||||
|
||||
-When -flive-patching specified without any value, the default value
|
||||
-is "inline-clone".
|
||||
+When @option{-flive-patching} is specified without any value, the default value
|
||||
+is @var{inline-clone}.
|
||||
|
||||
This flag is disabled by default.
|
||||
|
||||
-Note that -flive-patching is not supported with link-time optimizer.
|
||||
+Note that @option{-flive-patching} is not supported with link-time optimization
|
||||
(@option{-flto}).
|
||||
|
||||
@item -fisolate-erroneous-paths-dereference
|
||||
@ -1,93 +0,0 @@
|
||||
2018-11-08 Roman Geissler <roman.geissler@amadeus.com>
|
||||
|
||||
* collect2.c (linker_select): Add USE_LLD_LD.
|
||||
(ld_suffixes): Add ld.lld.
|
||||
(main): Handle -fuse-ld=lld.
|
||||
* common.opt (-fuse-ld=lld): New option.
|
||||
* doc/invoke.texi (-fuse-ld=lld): Document.
|
||||
* opts.c (common_handle_option): Handle OPT_fuse_ld_lld.
|
||||
|
||||
--- gcc/collect2.c
|
||||
+++ gcc/collect2.c
|
||||
@@ -831,6 +831,7 @@ main (int argc, char **argv)
|
||||
USE_PLUGIN_LD,
|
||||
USE_GOLD_LD,
|
||||
USE_BFD_LD,
|
||||
+ USE_LLD_LD,
|
||||
USE_LD_MAX
|
||||
} selected_linker = USE_DEFAULT_LD;
|
||||
static const char *const ld_suffixes[USE_LD_MAX] =
|
||||
@@ -838,7 +839,8 @@ main (int argc, char **argv)
|
||||
"ld",
|
||||
PLUGIN_LD_SUFFIX,
|
||||
"ld.gold",
|
||||
- "ld.bfd"
|
||||
+ "ld.bfd",
|
||||
+ "ld.lld"
|
||||
};
|
||||
static const char *const real_ld_suffix = "real-ld";
|
||||
static const char *const collect_ld_suffix = "collect-ld";
|
||||
@@ -1007,6 +1009,8 @@ main (int argc, char **argv)
|
||||
selected_linker = USE_BFD_LD;
|
||||
else if (strcmp (argv[i], "-fuse-ld=gold") == 0)
|
||||
selected_linker = USE_GOLD_LD;
|
||||
+ else if (strcmp (argv[i], "-fuse-ld=lld") == 0)
|
||||
+ selected_linker = USE_LLD_LD;
|
||||
|
||||
#ifdef COLLECT_EXPORT_LIST
|
||||
/* These flags are position independent, although their order
|
||||
@@ -1096,7 +1100,8 @@ main (int argc, char **argv)
|
||||
/* Maybe we know the right file to use (if not cross). */
|
||||
ld_file_name = 0;
|
||||
#ifdef DEFAULT_LINKER
|
||||
- if (selected_linker == USE_BFD_LD || selected_linker == USE_GOLD_LD)
|
||||
+ if (selected_linker == USE_BFD_LD || selected_linker == USE_GOLD_LD ||
|
||||
+ selected_linker == USE_LLD_LD)
|
||||
{
|
||||
char *linker_name;
|
||||
# ifdef HOST_EXECUTABLE_SUFFIX
|
||||
@@ -1315,7 +1320,7 @@ main (int argc, char **argv)
|
||||
else if (!use_collect_ld
|
||||
&& strncmp (arg, "-fuse-ld=", 9) == 0)
|
||||
{
|
||||
- /* Do not pass -fuse-ld={bfd|gold} to the linker. */
|
||||
+ /* Do not pass -fuse-ld={bfd|gold|lld} to the linker. */
|
||||
ld1--;
|
||||
ld2--;
|
||||
}
|
||||
--- gcc/common.opt
|
||||
+++ gcc/common.opt
|
||||
@@ -2732,6 +2732,10 @@ fuse-ld=gold
|
||||
Common Driver Negative(fuse-ld=bfd)
|
||||
Use the gold linker instead of the default linker.
|
||||
|
||||
+fuse-ld=lld
|
||||
+Common Driver Negative(fuse-ld=lld)
|
||||
+Use the lld LLVM linker instead of the default linker.
|
||||
+
|
||||
fuse-linker-plugin
|
||||
Common Undocumented Var(flag_use_linker_plugin)
|
||||
|
||||
--- gcc/doc/invoke.texi
|
||||
+++ gcc/doc/invoke.texi
|
||||
@@ -12610,6 +12610,10 @@ Use the @command{bfd} linker instead of the default linker.
|
||||
@opindex fuse-ld=gold
|
||||
Use the @command{gold} linker instead of the default linker.
|
||||
|
||||
+@item -fuse-ld=lld
|
||||
+@opindex fuse-ld=lld
|
||||
+Use the LLVM @command{lld} linker instead of the default linker.
|
||||
+
|
||||
@cindex Libraries
|
||||
@item -l@var{library}
|
||||
@itemx -l @var{library}
|
||||
--- gcc/opts.c
|
||||
+++ gcc/opts.c
|
||||
@@ -2557,6 +2557,7 @@ common_handle_option (struct gcc_options *opts,
|
||||
|
||||
case OPT_fuse_ld_bfd:
|
||||
case OPT_fuse_ld_gold:
|
||||
+ case OPT_fuse_ld_lld:
|
||||
case OPT_fuse_linker_plugin:
|
||||
/* No-op. Used by the driver and passed to us because it starts with f.*/
|
||||
break;
|
||||
@ -1,64 +0,0 @@
|
||||
--- gcc/cp/call.c
|
||||
+++ gcc/cp/call.c
|
||||
@@ -6904,7 +6904,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
|
||||
elttype = cp_build_qualified_type
|
||||
(elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST);
|
||||
array = build_array_of_n_type (elttype, len);
|
||||
- array = finish_compound_literal (array, new_ctor, complain, fcl_c99);
|
||||
+ array = finish_compound_literal (array, new_ctor, complain);
|
||||
/* Take the address explicitly rather than via decay_conversion
|
||||
to avoid the error about taking the address of a temporary. */
|
||||
array = cp_build_addr_expr (array, complain);
|
||||
@@ -10984,13 +10984,11 @@ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups,
|
||||
lvalue-rvalue conversion applied to "a glvalue of literal type
|
||||
that refers to a non-volatile temporary object initialized
|
||||
with a constant expression". Rather than try to communicate
|
||||
- that this VAR_DECL is a temporary, just mark it constexpr.
|
||||
-
|
||||
- Currently this is only useful for initializer_list temporaries,
|
||||
- since reference vars can't appear in constant expressions. */
|
||||
+ that this VAR_DECL is a temporary, just mark it constexpr. */
|
||||
DECL_DECLARED_CONSTEXPR_P (var) = true;
|
||||
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (var) = true;
|
||||
TREE_CONSTANT (var) = true;
|
||||
+ TREE_READONLY (var) = true;
|
||||
}
|
||||
DECL_INITIAL (var) = init;
|
||||
init = NULL_TREE;
|
||||
--- gcc/cp/tree.c
|
||||
+++ gcc/cp/tree.c
|
||||
@@ -442,6 +442,14 @@ build_target_expr (tree decl, tree value, tsubst_flags_t complain)
|
||||
|| useless_type_conversion_p (TREE_TYPE (decl),
|
||||
TREE_TYPE (value)));
|
||||
|
||||
+ /* Set TREE_READONLY for optimization, such as gimplify_init_constructor
|
||||
+ moving a constant aggregate into .rodata. */
|
||||
+ if (CP_TYPE_CONST_NON_VOLATILE_P (type)
|
||||
+ && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
|
||||
+ && !VOID_TYPE_P (TREE_TYPE (value))
|
||||
+ && reduced_constant_expression_p (value))
|
||||
+ TREE_READONLY (decl) = true;
|
||||
+
|
||||
if (complain & tf_no_cleanup)
|
||||
/* The caller is building a new-expr and does not need a cleanup. */
|
||||
t = NULL_TREE;
|
||||
--- /dev/null
|
||||
+++ gcc/testsuite/g++.dg/cpp1y/pr95226.C
|
||||
@@ -0,0 +1,17 @@
|
||||
+// PR c++/95226
|
||||
+// { dg-do run { target c++14 } }
|
||||
+
|
||||
+#include <vector>
|
||||
+
|
||||
+struct T {
|
||||
+ unsigned a;
|
||||
+ float b {8.};
|
||||
+};
|
||||
+
|
||||
+int main()
|
||||
+{
|
||||
+ T t = {1};
|
||||
+ std::vector<T> tt = {{1}, {2}};
|
||||
+ if (t.a != 1 || t.b != 8.0f || tt[0].a != 1 || tt[0].b != 8.0f || tt[1].a != 2 || tt[1].b != 8.0f)
|
||||
+ __builtin_abort ();
|
||||
+}
|
||||
@ -1,70 +0,0 @@
|
||||
From 55f40d968b0bd3be4478a9481e829a99ee0fa04f Mon Sep 17 00:00:00 2001
|
||||
From: Jason Merrill <jason@redhat.com>
|
||||
Date: Mon, 5 Apr 2021 22:50:44 -0400
|
||||
Subject: [PATCH] c++: mangling of lambdas in default args [PR91241]
|
||||
|
||||
In this testcase, the parms remembered in LAMBDA_EXPR_EXTRA_SCOPE are no
|
||||
longer the parms of the FUNCTION_DECL they have as their DECL_CONTEXT, so we
|
||||
were mangling both lambdas as parm #0. But since the parms are numbered
|
||||
from right to left we don't need to need to find them in the FUNCTION_DECL,
|
||||
we can measure their own DECL_CHAIN.
|
||||
|
||||
gcc/cp/ChangeLog:
|
||||
|
||||
PR c++/91241
|
||||
* mangle.c (write_compact_number): Add sanity check.
|
||||
(write_local_name): Use list_length for parm number.
|
||||
|
||||
gcc/testsuite/ChangeLog:
|
||||
|
||||
PR c++/91241
|
||||
* g++.dg/abi/lambda-defarg1.C: New test.
|
||||
---
|
||||
gcc/cp/mangle.c | 11 ++---------
|
||||
gcc/testsuite/g++.dg/abi/lambda-defarg1.C | 11 +++++++++++
|
||||
2 files changed, 13 insertions(+), 9 deletions(-)
|
||||
create mode 100644 gcc/testsuite/g++.dg/abi/lambda-defarg1.C
|
||||
|
||||
--- gcc/cp/mangle.c
|
||||
+++ gcc/cp/mangle.c
|
||||
@@ -1628,6 +1628,7 @@ write_literal_operator_name (tree identifier)
|
||||
static void
|
||||
write_compact_number (int num)
|
||||
{
|
||||
+ gcc_checking_assert (num >= 0);
|
||||
if (num > 0)
|
||||
write_unsigned_number (num - 1);
|
||||
write_char ('_');
|
||||
@@ -2027,15 +2028,7 @@ write_local_name (tree function, const tree local_entity,
|
||||
/* For this purpose, parameters are numbered from right-to-left. */
|
||||
if (parm)
|
||||
{
|
||||
- tree t;
|
||||
- int i = 0;
|
||||
- for (t = DECL_ARGUMENTS (function); t; t = DECL_CHAIN (t))
|
||||
- {
|
||||
- if (t == parm)
|
||||
- i = 1;
|
||||
- else if (i)
|
||||
- ++i;
|
||||
- }
|
||||
+ int i = list_length (parm);
|
||||
write_char ('d');
|
||||
write_compact_number (i - 1);
|
||||
}
|
||||
--- /dev/null
|
||||
+++ gcc/testsuite/g++.dg/abi/lambda-defarg1.C
|
||||
@@ -0,0 +1,11 @@
|
||||
+// PR c++/91241
|
||||
+// { dg-do compile { target c++11 } }
|
||||
+
|
||||
+struct A {
|
||||
+ int *b(const int & = []() -> int { return 0; }(),
|
||||
+ const int & = []() -> int { return 0; }());
|
||||
+};
|
||||
+int *A::b(const int &, const int &) { b(); return 0; }
|
||||
+// { dg-final { scan-assembler "_ZN1A1bERKiS1_" } }
|
||||
+// { dg-final { scan-assembler "_ZZN1A1bERKiS1_Ed_NKUlvE_clEv" } }
|
||||
+// { dg-final { scan-assembler "_ZZN1A1bERKiS1_Ed0_NKUlvE_clEv" } }
|
||||
--
|
||||
2.27.0
|
||||
@ -1,456 +0,0 @@
|
||||
commit ee3db7c8f844556d35a66b3732bad9f44a086491
|
||||
Author: Jonathan Wakely <jwakely@redhat.com>
|
||||
Date: Mon Sep 27 20:44:24 2021 +0100
|
||||
|
||||
libstdc++: Fix handling of invalid ranges in std::regex [PR102447]
|
||||
|
||||
std::regex currently allows invalid bracket ranges such as [\w-a] which
|
||||
are only allowed by ECMAScript when in web browser compatibility mode.
|
||||
It should be an error, because the start of the range is a character
|
||||
class, not a single character. The current implementation of
|
||||
_Compiler::_M_expression_term does not provide a way to reject this,
|
||||
because we only remember a previous character, not whether we just
|
||||
processed a character class (or collating symbol etc.)
|
||||
|
||||
This patch replaces the pair<bool, CharT> used to emulate
|
||||
optional<CharT> with a custom class closer to pair<tribool,CharT>. That
|
||||
allows us to track three states, so that we can tell when we've just
|
||||
seen a character class.
|
||||
|
||||
With this additional state the code in _M_expression_term for processing
|
||||
the _S_token_bracket_dash can be improved to correctly reject the [\w-a]
|
||||
case, without regressing for valid cases such as [\w-] and [----].
|
||||
|
||||
libstdc++-v3/ChangeLog:
|
||||
|
||||
PR libstdc++/102447
|
||||
* include/bits/regex_compiler.h (_Compiler::_BracketState): New
|
||||
class.
|
||||
(_Compiler::_BrackeyMatcher): New alias template.
|
||||
(_Compiler::_M_expression_term): Change pair<bool, CharT>
|
||||
parameter to _BracketState. Process first character for
|
||||
ECMAScript syntax as well as POSIX.
|
||||
* include/bits/regex_compiler.tcc
|
||||
(_Compiler::_M_insert_bracket_matcher): Pass _BracketState.
|
||||
(_Compiler::_M_expression_term): Use _BracketState to store
|
||||
state between calls. Improve handling of dashes in ranges.
|
||||
* testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc:
|
||||
Add more tests for ranges containing dashes. Check invalid
|
||||
ranges with character class at the beginning.
|
||||
|
||||
(cherry picked from commit 7ce3c230edf6e498e125c805a6dd313bf87dc439)
|
||||
|
||||
diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h
|
||||
index 7e5c2073554..2eb1c3f7863 100644
|
||||
--- a/libstdc++-v3/include/bits/regex_compiler.h
|
||||
+++ b/libstdc++-v3/include/bits/regex_compiler.h
|
||||
@@ -122,13 +122,45 @@ namespace __detail
|
||||
void
|
||||
_M_insert_bracket_matcher(bool __neg);
|
||||
|
||||
- // Returns true if successfully matched one term and should continue.
|
||||
+ // Cache of the last atom seen in a bracketed range expression.
|
||||
+ struct _BracketState
|
||||
+ {
|
||||
+ enum class _Type : char { _None, _Char, _Class } _M_type = _Type::_None;
|
||||
+ _CharT _M_char;
|
||||
+
|
||||
+ void
|
||||
+ set(_CharT __c) noexcept { _M_type = _Type::_Char; _M_char = __c; }
|
||||
+
|
||||
+ _GLIBCXX_NODISCARD _CharT
|
||||
+ get() const noexcept { return _M_char; }
|
||||
+
|
||||
+ void
|
||||
+ reset(_Type __t = _Type::_None) noexcept { _M_type = __t; }
|
||||
+
|
||||
+ explicit operator bool() const noexcept
|
||||
+ { return _M_type != _Type::_None; }
|
||||
+
|
||||
+ // Previous token was a single character.
|
||||
+ _GLIBCXX_NODISCARD bool
|
||||
+ _M_is_char() const noexcept { return _M_type == _Type::_Char; }
|
||||
+
|
||||
+ // Previous token was a character class, equivalent class,
|
||||
+ // collating symbol etc.
|
||||
+ _GLIBCXX_NODISCARD bool
|
||||
+ _M_is_class() const noexcept { return _M_type == _Type::_Class; }
|
||||
+ };
|
||||
+
|
||||
+ template<bool __icase, bool __collate>
|
||||
+ using _BracketMatcher
|
||||
+ = std::__detail::_BracketMatcher<_TraitsT, __icase, __collate>;
|
||||
+
|
||||
+ // Returns true if successfully parsed one term and should continue
|
||||
+ // compiling a bracket expression.
|
||||
// Returns false if the compiler should move on.
|
||||
template<bool __icase, bool __collate>
|
||||
bool
|
||||
- _M_expression_term(pair<bool, _CharT>& __last_char,
|
||||
- _BracketMatcher<_TraitsT, __icase, __collate>&
|
||||
- __matcher);
|
||||
+ _M_expression_term(_BracketState& __last_char,
|
||||
+ _BracketMatcher<__icase, __collate>& __matcher);
|
||||
|
||||
int
|
||||
_M_cur_int_value(int __radix);
|
||||
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
|
||||
index b1169428afb..5877d30ba52 100644
|
||||
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
|
||||
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
|
||||
@@ -140,7 +140,8 @@ namespace __detail
|
||||
return true;
|
||||
if (this->_M_atom())
|
||||
{
|
||||
- while (this->_M_quantifier());
|
||||
+ while (this->_M_quantifier())
|
||||
+ ;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -410,7 +411,7 @@ namespace __detail
|
||||
_M_insert_character_class_matcher()
|
||||
{
|
||||
__glibcxx_assert(_M_value.size() == 1);
|
||||
- _BracketMatcher<_TraitsT, __icase, __collate> __matcher
|
||||
+ _BracketMatcher<__icase, __collate> __matcher
|
||||
(_M_ctype.is(_CtypeT::upper, _M_value[0]), _M_traits);
|
||||
__matcher._M_add_character_class(_M_value, false);
|
||||
__matcher._M_ready();
|
||||
@@ -424,25 +425,17 @@ namespace __detail
|
||||
_Compiler<_TraitsT>::
|
||||
_M_insert_bracket_matcher(bool __neg)
|
||||
{
|
||||
- _BracketMatcher<_TraitsT, __icase, __collate> __matcher(__neg, _M_traits);
|
||||
- pair<bool, _CharT> __last_char; // Optional<_CharT>
|
||||
- __last_char.first = false;
|
||||
- if (!(_M_flags & regex_constants::ECMAScript))
|
||||
- {
|
||||
- if (_M_try_char())
|
||||
- {
|
||||
- __last_char.first = true;
|
||||
- __last_char.second = _M_value[0];
|
||||
- }
|
||||
- else if (_M_match_token(_ScannerT::_S_token_bracket_dash))
|
||||
- {
|
||||
- __last_char.first = true;
|
||||
- __last_char.second = '-';
|
||||
- }
|
||||
- }
|
||||
- while (_M_expression_term(__last_char, __matcher));
|
||||
- if (__last_char.first)
|
||||
- __matcher._M_add_char(__last_char.second);
|
||||
+ _BracketMatcher<__icase, __collate> __matcher(__neg, _M_traits);
|
||||
+ _BracketState __last_char;
|
||||
+ if (_M_try_char())
|
||||
+ __last_char.set(_M_value[0]);
|
||||
+ else if (_M_match_token(_ScannerT::_S_token_bracket_dash))
|
||||
+ // Dash as first character is a normal character.
|
||||
+ __last_char.set('-');
|
||||
+ while (_M_expression_term(__last_char, __matcher))
|
||||
+ ;
|
||||
+ if (__last_char._M_is_char())
|
||||
+ __matcher._M_add_char(__last_char.get());
|
||||
__matcher._M_ready();
|
||||
_M_stack.push(_StateSeqT(
|
||||
*_M_nfa,
|
||||
@@ -453,27 +446,27 @@ namespace __detail
|
||||
template<bool __icase, bool __collate>
|
||||
bool
|
||||
_Compiler<_TraitsT>::
|
||||
- _M_expression_term(pair<bool, _CharT>& __last_char,
|
||||
- _BracketMatcher<_TraitsT, __icase, __collate>& __matcher)
|
||||
+ _M_expression_term(_BracketState& __last_char,
|
||||
+ _BracketMatcher<__icase, __collate>& __matcher)
|
||||
{
|
||||
if (_M_match_token(_ScannerT::_S_token_bracket_end))
|
||||
return false;
|
||||
|
||||
+ // Add any previously cached char into the matcher and update cache.
|
||||
const auto __push_char = [&](_CharT __ch)
|
||||
{
|
||||
- if (__last_char.first)
|
||||
- __matcher._M_add_char(__last_char.second);
|
||||
- else
|
||||
- __last_char.first = true;
|
||||
- __last_char.second = __ch;
|
||||
+ if (__last_char._M_is_char())
|
||||
+ __matcher._M_add_char(__last_char.get());
|
||||
+ __last_char.set(__ch);
|
||||
};
|
||||
- const auto __flush = [&]
|
||||
+ // Add any previously cached char into the matcher and update cache.
|
||||
+ const auto __push_class = [&]
|
||||
{
|
||||
- if (__last_char.first)
|
||||
- {
|
||||
- __matcher._M_add_char(__last_char.second);
|
||||
- __last_char.first = false;
|
||||
- }
|
||||
+ if (__last_char._M_is_char())
|
||||
+ __matcher._M_add_char(__last_char.get());
|
||||
+ // We don't cache anything here, just record that the last thing
|
||||
+ // processed was a character class (or similar).
|
||||
+ __last_char.reset(_BracketState::_Type::_Class);
|
||||
};
|
||||
|
||||
if (_M_match_token(_ScannerT::_S_token_collsymbol))
|
||||
@@ -482,16 +475,16 @@ namespace __detail
|
||||
if (__symbol.size() == 1)
|
||||
__push_char(__symbol[0]);
|
||||
else
|
||||
- __flush();
|
||||
+ __push_class();
|
||||
}
|
||||
else if (_M_match_token(_ScannerT::_S_token_equiv_class_name))
|
||||
{
|
||||
- __flush();
|
||||
+ __push_class();
|
||||
__matcher._M_add_equivalence_class(_M_value);
|
||||
}
|
||||
else if (_M_match_token(_ScannerT::_S_token_char_class_name))
|
||||
{
|
||||
- __flush();
|
||||
+ __push_class();
|
||||
__matcher._M_add_character_class(_M_value, false);
|
||||
}
|
||||
else if (_M_try_char())
|
||||
@@ -508,49 +501,50 @@ namespace __detail
|
||||
// It turns out that no one reads BNFs ;)
|
||||
else if (_M_match_token(_ScannerT::_S_token_bracket_dash))
|
||||
{
|
||||
- if (!__last_char.first)
|
||||
+ if (_M_match_token(_ScannerT::_S_token_bracket_end))
|
||||
{
|
||||
- if (!(_M_flags & regex_constants::ECMAScript))
|
||||
- {
|
||||
- if (_M_match_token(_ScannerT::_S_token_bracket_end))
|
||||
- {
|
||||
- __push_char('-');
|
||||
- return false;
|
||||
- }
|
||||
- __throw_regex_error(
|
||||
- regex_constants::error_range,
|
||||
- "Unexpected dash in bracket expression. For POSIX syntax, "
|
||||
- "a dash is not treated literally only when it is at "
|
||||
- "beginning or end.");
|
||||
- }
|
||||
+ // For "-]" the dash is a literal character.
|
||||
__push_char('-');
|
||||
+ return false;
|
||||
}
|
||||
- else
|
||||
+ else if (__last_char._M_is_class())
|
||||
+ {
|
||||
+ // "\\w-" is invalid, start of range must be a single char.
|
||||
+ __throw_regex_error(regex_constants::error_range,
|
||||
+ "Invalid start of range in bracket expression.");
|
||||
+ }
|
||||
+ else if (__last_char._M_is_char())
|
||||
{
|
||||
if (_M_try_char())
|
||||
{
|
||||
- __matcher._M_make_range(__last_char.second, _M_value[0]);
|
||||
- __last_char.first = false;
|
||||
+ // "x-y"
|
||||
+ __matcher._M_make_range(__last_char.get(), _M_value[0]);
|
||||
+ __last_char.reset();
|
||||
}
|
||||
else if (_M_match_token(_ScannerT::_S_token_bracket_dash))
|
||||
{
|
||||
- __matcher._M_make_range(__last_char.second, '-');
|
||||
- __last_char.first = false;
|
||||
+ // "x--"
|
||||
+ __matcher._M_make_range(__last_char.get(), '-');
|
||||
+ __last_char.reset();
|
||||
}
|
||||
else
|
||||
- {
|
||||
- if (_M_scanner._M_get_token()
|
||||
- != _ScannerT::_S_token_bracket_end)
|
||||
- __throw_regex_error(
|
||||
- regex_constants::error_range,
|
||||
- "Character is expected after a dash.");
|
||||
- __push_char('-');
|
||||
- }
|
||||
+ __throw_regex_error(regex_constants::error_range,
|
||||
+ "Invalid end of range in bracket expression.");
|
||||
}
|
||||
+ else if (_M_flags & regex_constants::ECMAScript)
|
||||
+ {
|
||||
+ // A dash that is not part of an existing range. Might be the
|
||||
+ // start of a new range, or might just be a literal '-' char.
|
||||
+ // Only ECMAScript allows that in the middle of a bracket expr.
|
||||
+ __push_char('-');
|
||||
+ }
|
||||
+ else
|
||||
+ __throw_regex_error(regex_constants::error_range,
|
||||
+ "Invalid dash in bracket expression.");
|
||||
}
|
||||
else if (_M_match_token(_ScannerT::_S_token_quoted_class))
|
||||
{
|
||||
- __flush();
|
||||
+ __push_class();
|
||||
__matcher._M_add_character_class(_M_value,
|
||||
_M_ctype.is(_CtypeT::upper,
|
||||
_M_value[0]));
|
||||
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc
|
||||
index 236ab663fc0..57088f5af83 100644
|
||||
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc
|
||||
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc
|
||||
@@ -68,6 +68,16 @@ test01()
|
||||
void
|
||||
test02()
|
||||
{
|
||||
+ VERIFY(regex_match("-", regex("[-]", regex_constants::ECMAScript)));
|
||||
+ VERIFY(regex_match("-", regex("[--]", regex_constants::ECMAScript)));
|
||||
+ VERIFY(regex_match("-", regex("[---]", regex_constants::ECMAScript)));
|
||||
+ VERIFY(regex_match("-", regex("[----]", regex_constants::ECMAScript)));
|
||||
+ VERIFY(regex_match("-", regex("[-----]", regex_constants::ECMAScript)));
|
||||
+
|
||||
+ VERIFY(regex_match("-", regex("[-]", regex_constants::extended)));
|
||||
+ VERIFY(regex_match("-", regex("[--]", regex_constants::extended)));
|
||||
+ VERIFY(regex_match("-", regex("[---]", regex_constants::extended)));
|
||||
+ VERIFY(regex_match("-", regex("[----]", regex_constants::extended)));
|
||||
try
|
||||
{
|
||||
std::regex re("[-----]", std::regex::extended);
|
||||
@@ -77,7 +87,6 @@ test02()
|
||||
{
|
||||
VERIFY(e.code() == std::regex_constants::error_range);
|
||||
}
|
||||
- std::regex re("[-----]", std::regex::ECMAScript);
|
||||
|
||||
VERIFY(!regex_match("b", regex("[-ac]", regex_constants::extended)));
|
||||
VERIFY(!regex_match("b", regex("[ac-]", regex_constants::extended)));
|
||||
@@ -92,7 +101,27 @@ test02()
|
||||
}
|
||||
catch (const std::regex_error& e)
|
||||
{
|
||||
+ VERIFY(e.code() == std::regex_constants::error_range);
|
||||
+ }
|
||||
+ try
|
||||
+ {
|
||||
+ regex("[@--]", regex_constants::extended);
|
||||
+ VERIFY(false);
|
||||
}
|
||||
+ catch (const std::regex_error& e)
|
||||
+ {
|
||||
+ VERIFY(e.code() == std::regex_constants::error_range);
|
||||
+ }
|
||||
+ try
|
||||
+ {
|
||||
+ regex("[--%]", regex_constants::extended);
|
||||
+ VERIFY(false);
|
||||
+ }
|
||||
+ catch (const std::regex_error& e)
|
||||
+ {
|
||||
+ VERIFY(e.code() == std::regex_constants::error_range);
|
||||
+ }
|
||||
+
|
||||
VERIFY(regex_match("].", regex("[][.hyphen.]-0]*", regex_constants::extended)));
|
||||
}
|
||||
|
||||
@@ -157,6 +186,36 @@ test06()
|
||||
VERIFY(regex_match("a-", debian_cron_namespace_ok));
|
||||
}
|
||||
|
||||
+// libstdc++/102447
|
||||
+void
|
||||
+test07()
|
||||
+{
|
||||
+ VERIFY(regex_match("-", std::regex("[\\w-]", std::regex::ECMAScript)));
|
||||
+ VERIFY(regex_match("a", std::regex("[\\w-]", std::regex::ECMAScript)));
|
||||
+ VERIFY(regex_match("-", std::regex("[a-]", std::regex::ECMAScript)));
|
||||
+ VERIFY(regex_match("a", std::regex("[a-]", std::regex::ECMAScript)));
|
||||
+
|
||||
+ try
|
||||
+ {
|
||||
+ std::regex re("[\\w-a]", std::regex::ECMAScript);
|
||||
+ VERIFY(false);
|
||||
+ }
|
||||
+ catch (const std::regex_error& e)
|
||||
+ {
|
||||
+ VERIFY(e.code() == std::regex_constants::error_range);
|
||||
+ }
|
||||
+
|
||||
+ try
|
||||
+ {
|
||||
+ std::regex re("[\\w--]", std::regex::ECMAScript);
|
||||
+ VERIFY(false);
|
||||
+ }
|
||||
+ catch (const std::regex_error& e)
|
||||
+ {
|
||||
+ VERIFY(e.code() == std::regex_constants::error_range);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
int
|
||||
main()
|
||||
{
|
||||
@@ -166,6 +225,7 @@ main()
|
||||
test04();
|
||||
test05();
|
||||
test06();
|
||||
+ test07();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
commit 1851cc4c5f2666dfdec53a2ada57095ffc59e08b
|
||||
Author: Jonathan Wakely <jwakely@redhat.com>
|
||||
Date: Mon Dec 13 13:36:33 2021 +0000
|
||||
|
||||
libstdc++: Fix non-reserved name in <regex> header
|
||||
|
||||
libstdc++-v3/ChangeLog:
|
||||
|
||||
* include/bits/regex_compiler.tcc (_Compiler::_M_match_token):
|
||||
Use reserved name for parameter.
|
||||
* testsuite/17_intro/names.cc: Check "token".
|
||||
|
||||
(cherry picked from commit b0e6a257f1862e217cdf19332ea0f7bad56dcddc)
|
||||
|
||||
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
|
||||
index 8af920e5fe9..b1169428afb 100644
|
||||
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
|
||||
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
|
||||
@@ -586,9 +586,9 @@ namespace __detail
|
||||
template<typename _TraitsT>
|
||||
bool
|
||||
_Compiler<_TraitsT>::
|
||||
- _M_match_token(_TokenT token)
|
||||
+ _M_match_token(_TokenT __token)
|
||||
{
|
||||
- if (token == _M_scanner._M_get_token())
|
||||
+ if (__token == _M_scanner._M_get_token())
|
||||
{
|
||||
_M_value = _M_scanner._M_get_value();
|
||||
_M_scanner._M_advance();
|
||||
diff --git a/libstdc++-v3/testsuite/17_intro/names.cc b/libstdc++-v3/testsuite/17_intro/names.cc
|
||||
index d758138dfb1..6c06aba7228 100644
|
||||
--- a/libstdc++-v3/testsuite/17_intro/names.cc
|
||||
+++ b/libstdc++-v3/testsuite/17_intro/names.cc
|
||||
@@ -99,6 +99,7 @@
|
||||
#define z (
|
||||
|
||||
#define tmp (
|
||||
+#define token (
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
#define uses_allocator (
|
||||
--- a/libstdc++-v3/include/bits/c++config.orig 2022-07-08 15:06:14.083231445 -0400
|
||||
+++ b/libstdc++-v3/include/bits/c++config 2022-07-08 15:06:41.733247859 -0400
|
||||
@@ -99,6 +99,12 @@
|
||||
# define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11")))
|
||||
#endif
|
||||
|
||||
+// Macro to warn about unused results.
|
||||
+#if __cplusplus >= 201703L
|
||||
+# define _GLIBCXX_NODISCARD [[__nodiscard__]]
|
||||
+#else
|
||||
+# define _GLIBCXX_NODISCARD
|
||||
+#endif
|
||||
|
||||
#if __cplusplus
|
||||
|
||||
@ -1,101 +0,0 @@
|
||||
The cprop_hardreg pass is built around the assumption that accessing a
|
||||
register in a narrower mode is the same as accessing the lowpart of
|
||||
the register. This unfortunately is not true for vector registers on
|
||||
IBM Z. This caused a miscompile of LLVM with GCC 8.5. The problem
|
||||
could not be reproduced with upstream GCC unfortunately but we have to
|
||||
assume that it is latent there. The right fix would require
|
||||
substantial changes to the cprop pass and is certainly something we
|
||||
would want for our platform. But since this would not be acceptable
|
||||
for older GCCs I'll go with what Vladimir proposed in the RedHat BZ
|
||||
and introduce a hopefully temporary and undocumented target hook to
|
||||
disable that specific transformation in regcprop.c.
|
||||
|
||||
--- a/gcc/config/s390/s390.c
|
||||
+++ b/gcc/config/s390/s390.c
|
||||
@@ -10488,6 +10488,18 @@ s390_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
|
||||
return false;
|
||||
}
|
||||
|
||||
+/* Implement TARGET_NARROW_MODE_REFERS_LOW_PART_P. */
|
||||
+
|
||||
+static bool
|
||||
+s390_narrow_mode_refers_low_part_p (unsigned int regno)
|
||||
+{
|
||||
+ if (reg_classes_intersect_p (VEC_REGS, REGNO_REG_CLASS (regno)))
|
||||
+ return false;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* Implement TARGET_MODES_TIEABLE_P. */
|
||||
|
||||
static bool
|
||||
@@ -16956,6 +16968,9 @@ s390_case_values_threshold (void)
|
||||
#undef TARGET_CASE_VALUES_THRESHOLD
|
||||
#define TARGET_CASE_VALUES_THRESHOLD s390_case_values_threshold
|
||||
|
||||
+#undef TARGET_NARROW_MODE_REFERS_LOW_PART_P
|
||||
+#define TARGET_NARROW_MODE_REFERS_LOW_PART_P s390_narrow_mode_refers_low_part_p
|
||||
+
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
#include "gt-s390.h"
|
||||
--- a/gcc/regcprop.c
|
||||
+++ b/gcc/regcprop.c
|
||||
@@ -426,7 +426,8 @@ maybe_mode_change (machine_mode orig_mode, machine_mode copy_mode,
|
||||
|
||||
if (orig_mode == new_mode)
|
||||
return gen_raw_REG (new_mode, regno);
|
||||
- else if (mode_change_ok (orig_mode, new_mode, regno))
|
||||
+ else if (mode_change_ok (orig_mode, new_mode, regno)
|
||||
+ && targetm.narrow_mode_refers_low_part_p (copy_regno))
|
||||
{
|
||||
int copy_nregs = hard_regno_nregs (copy_regno, copy_mode);
|
||||
int use_nregs = hard_regno_nregs (copy_regno, new_mode);
|
||||
--- a/gcc/target.def
|
||||
+++ b/gcc/target.def
|
||||
@@ -5446,6 +5446,16 @@ value that the middle-end intended.",
|
||||
bool, (machine_mode from, machine_mode to, reg_class_t rclass),
|
||||
hook_bool_mode_mode_reg_class_t_true)
|
||||
|
||||
+/* This hook is used to work around a problem in regcprop. Hardcoded
|
||||
+assumptions currently prevent it from working correctly for targets
|
||||
+where the low part of a multi-word register doesn't align to accessing
|
||||
+the register with a narrower mode. */
|
||||
+DEFHOOK_UNDOC
|
||||
+(narrow_mode_refers_low_part_p,
|
||||
+"",
|
||||
+bool, (unsigned int regno),
|
||||
+hook_bool_uint_true)
|
||||
+
|
||||
/* Change pseudo allocno class calculated by IRA. */
|
||||
DEFHOOK
|
||||
(ira_change_pseudo_allocno_class,
|
||||
--- a/gcc/hooks.h
|
||||
+++ b/gcc/hooks.h
|
||||
@@ -86,6 +86,7 @@ extern void hook_void_tree (tree);
|
||||
extern void hook_void_tree_treeptr (tree, tree *);
|
||||
extern void hook_void_int_int (int, int);
|
||||
extern void hook_void_gcc_optionsp (struct gcc_options *);
|
||||
+extern bool hook_bool_uint_true (unsigned int);
|
||||
extern bool hook_bool_uint_uintp_false (unsigned int, unsigned int *);
|
||||
|
||||
extern int hook_int_uint_mode_1 (unsigned int, machine_mode);
|
||||
--- a/gcc/hooks.c
|
||||
+++ b/gcc/hooks.c
|
||||
@@ -498,6 +498,14 @@ hook_void_gcc_optionsp (struct gcc_optio
|
||||
{
|
||||
}
|
||||
|
||||
+/* Generic hook that takes an unsigned int and returns true. */
|
||||
+
|
||||
+bool
|
||||
+hook_bool_uint_true (unsigned int)
|
||||
+{
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
/* Generic hook that takes an unsigned int, an unsigned int pointer and
|
||||
returns false. */
|
||||
|
||||
@ -1,103 +0,0 @@
|
||||
diff --git a/gcc/testsuite/g++.dg/torture/phi-1.C b/gcc/testsuite/g++.dg/torture/phi-1.C
|
||||
new file mode 100644
|
||||
index 00000000000..69fb3d7ba38
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/g++.dg/torture/phi-1.C
|
||||
@@ -0,0 +1,28 @@
|
||||
+// { dg-do compile { target c++11 } }
|
||||
+// { dg-options "--param early-inlining-insns=14" }
|
||||
+
|
||||
+struct Element;
|
||||
+template <int _Nm> struct __array_traits { typedef Element _Type[_Nm]; };
|
||||
+template <int _Nm> struct array {
|
||||
+ typename __array_traits<_Nm>::_Type _M_elems;
|
||||
+};
|
||||
+bool logLevel();
|
||||
+struct LogCapture {
|
||||
+ void stream();
|
||||
+};
|
||||
+struct Element {
|
||||
+ Element();
|
||||
+ long data_;
|
||||
+};
|
||||
+using ElementArray = array<6>;
|
||||
+struct ElementManager {
|
||||
+ ElementManager();
|
||||
+ ElementArray array_;
|
||||
+};
|
||||
+static ElementArray makeArray() {
|
||||
+ if (logLevel())
|
||||
+ LogCapture().stream();
|
||||
+ ElementArray foo;
|
||||
+ return foo;
|
||||
+}
|
||||
+ElementManager::ElementManager() : array_(makeArray()) {}
|
||||
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
|
||||
index 84e58e66628..78c0c6a4189 100644
|
||||
--- a/gcc/tree-cfg.c
|
||||
+++ b/gcc/tree-cfg.c
|
||||
@@ -2944,35 +2944,6 @@ last_and_only_stmt (basic_block bb)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-/* Reinstall those PHI arguments queued in OLD_EDGE to NEW_EDGE. */
|
||||
-
|
||||
-static void
|
||||
-reinstall_phi_args (edge new_edge, edge old_edge)
|
||||
-{
|
||||
- edge_var_map *vm;
|
||||
- int i;
|
||||
- gphi_iterator phis;
|
||||
-
|
||||
- vec<edge_var_map> *v = redirect_edge_var_map_vector (old_edge);
|
||||
- if (!v)
|
||||
- return;
|
||||
-
|
||||
- for (i = 0, phis = gsi_start_phis (new_edge->dest);
|
||||
- v->iterate (i, &vm) && !gsi_end_p (phis);
|
||||
- i++, gsi_next (&phis))
|
||||
- {
|
||||
- gphi *phi = phis.phi ();
|
||||
- tree result = redirect_edge_var_map_result (vm);
|
||||
- tree arg = redirect_edge_var_map_def (vm);
|
||||
-
|
||||
- gcc_assert (result == gimple_phi_result (phi));
|
||||
-
|
||||
- add_phi_arg (phi, arg, new_edge, redirect_edge_var_map_location (vm));
|
||||
- }
|
||||
-
|
||||
- redirect_edge_var_map_clear (old_edge);
|
||||
-}
|
||||
-
|
||||
/* Returns the basic block after which the new basic block created
|
||||
by splitting edge EDGE_IN should be placed. Tries to keep the new block
|
||||
near its "logical" location. This is of most help to humans looking
|
||||
@@ -3012,11 +2983,24 @@ gimple_split_edge (edge edge_in)
|
||||
new_bb = create_empty_bb (after_bb);
|
||||
new_bb->count = edge_in->count ();
|
||||
|
||||
- e = redirect_edge_and_branch (edge_in, new_bb);
|
||||
- gcc_assert (e == edge_in);
|
||||
-
|
||||
+ /* We want to avoid re-allocating PHIs when we first
|
||||
+ add the fallthru edge from new_bb to dest but we also
|
||||
+ want to avoid changing PHI argument order when
|
||||
+ first redirecting edge_in away from dest. The former
|
||||
+ avoids changing PHI argument order by adding them
|
||||
+ last and then the redirection swapping it back into
|
||||
+ place by means of unordered remove.
|
||||
+ So hack around things by temporarily removing all PHIs
|
||||
+ from the destination during the edge redirection and then
|
||||
+ making sure the edges stay in order. */
|
||||
+ gimple_seq saved_phis = phi_nodes (dest);
|
||||
+ unsigned old_dest_idx = edge_in->dest_idx;
|
||||
+ set_phi_nodes (dest, NULL);
|
||||
new_edge = make_single_succ_edge (new_bb, dest, EDGE_FALLTHRU);
|
||||
- reinstall_phi_args (new_edge, e);
|
||||
+ e = redirect_edge_and_branch (edge_in, new_bb);
|
||||
+ gcc_assert (e == edge_in && new_edge->dest_idx == old_dest_idx);
|
||||
+ /* set_phi_nodes sets the BB of the PHI nodes, so do it manually here. */
|
||||
+ dest->il.gimple.phi_nodes = saved_phis;
|
||||
|
||||
return new_bb;
|
||||
}
|
||||
@ -1,110 +0,0 @@
|
||||
commit 8b89515caca5149329c0cd20485e69e2d0f879d4
|
||||
Author: Marek Polacek <polacek@redhat.com>
|
||||
Date: Wed Dec 7 13:44:38 2022 -0500
|
||||
|
||||
strlen: Use D_S_U in maybe_set_strlen_range
|
||||
|
||||
This patch fixes #2137448 where the customer uses strlen on a buffer
|
||||
that was filled by converting the buffer to a struct and copying a string
|
||||
into a flexible array member of the struct.
|
||||
|
||||
This regressed with r262438 in the sense that the strlen was folded to 0.
|
||||
The strlen=0 result started with
|
||||
https://gcc.gnu.org/pipermail/gcc-patches/2018-July/501912.html
|
||||
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=715fcd73b66c639d9e0e3f3ef9c6ff9d621d7131
|
||||
which seems like an undesirable change. It was fixed (back to strlen=3) by
|
||||
https://gcc.gnu.org/legacy-ml/gcc-patches/2019-01/msg00069.html
|
||||
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=d4bf69750d31d08068f8242225b8fa06cdf11411
|
||||
but the changes are not backportable.
|
||||
|
||||
Instead, this patch makes maybe_set_strlen_range use DECL_SIZE_UNIT
|
||||
rather than TYPE_SIZE_UNIT, fixing the regression.
|
||||
|
||||
I could never reproduce the problem in C, only C++. C/C++ represent array
|
||||
type domains differently: C has
|
||||
|
||||
char[0:]
|
||||
|
||||
but C++
|
||||
|
||||
char[0:18446744073709551615]
|
||||
|
||||
I'm not sure if that explains it. In any case, I put the new test into
|
||||
c-c++-common/.
|
||||
|
||||
Also, the original test had
|
||||
|
||||
printf("strlen = %zu\n", strlen(q->name));
|
||||
|
||||
so naturally, for the testsuite, I wanted to convert that into
|
||||
|
||||
if (strlen(q->name) != ...)
|
||||
__builtin_abort ();
|
||||
|
||||
but then I could no longer reproduce the problem. After some poking
|
||||
I realized I want -fno-early-inlining.
|
||||
|
||||
Co-authored-by: Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
diff --git a/gcc/testsuite/c-c++-common/torture/strlenopt-1.c b/gcc/testsuite/c-c++-common/torture/strlenopt-1.c
|
||||
new file mode 100644
|
||||
index 00000000000..e8c11044119
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/c-c++-common/torture/strlenopt-1.c
|
||||
@@ -0,0 +1,38 @@
|
||||
+/* { dg-do run } */
|
||||
+/* { dg-options "-fno-early-inlining" } */
|
||||
+
|
||||
+#define FORTIFY_SOURCE 2
|
||||
+
|
||||
+struct S {
|
||||
+ char skip;
|
||||
+ char name[0];
|
||||
+};
|
||||
+
|
||||
+static char static_buf[4];
|
||||
+
|
||||
+static void
|
||||
+print_name_len(void *p)
|
||||
+{
|
||||
+ struct S *q = (struct S *) p;
|
||||
+ if (__builtin_strlen(q->name) != 2)
|
||||
+ __builtin_abort ();
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main(void)
|
||||
+{
|
||||
+ // treat static storage as struct
|
||||
+ struct S *c = (struct S *)static_buf;
|
||||
+ __builtin_strcpy(c->name, "aa");
|
||||
+
|
||||
+ // copy static storage to stack storage
|
||||
+ char stack_buf[4] = { 0 };
|
||||
+ __builtin_memcpy(stack_buf, static_buf, 4);
|
||||
+
|
||||
+ // static and stack both now contain ( 0, 'a', 'a', 0 }
|
||||
+
|
||||
+ // indirectly pass the stack storage to the length function
|
||||
+ char *s = (char *)stack_buf;
|
||||
+ print_name_len(s);
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
|
||||
index 55e82e7b638..da47046cc2a 100644
|
||||
--- a/gcc/tree-ssa-strlen.c
|
||||
+++ b/gcc/tree-ssa-strlen.c
|
||||
@@ -1200,8 +1200,11 @@ maybe_set_strlen_range (tree lhs, tree src)
|
||||
|| array_at_struct_end_p (src))
|
||||
return;
|
||||
|
||||
- tree type = TREE_TYPE (src);
|
||||
- if (tree size = TYPE_SIZE_UNIT (type))
|
||||
+ src = get_base_address (src);
|
||||
+ if (!DECL_P (src))
|
||||
+ return;
|
||||
+
|
||||
+ if (tree size = DECL_SIZE_UNIT (src))
|
||||
if (size && TREE_CODE (size) == INTEGER_CST)
|
||||
{
|
||||
wide_int max = wi::to_wide (size);
|
||||
@ -1,75 +0,0 @@
|
||||
From 6f989c5c6e5f909996a117bb24ecac936e7526c1 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Polacek <polacek@redhat.com>
|
||||
Date: Wed, 14 Jun 2023 17:09:15 -0400
|
||||
Subject: [PATCH] final: fix for TLSLD references [BZ#2213753]
|
||||
|
||||
Patch by Jakub Jelinek.
|
||||
---
|
||||
gcc/final.c | 17 +++++++++++++++++
|
||||
gcc/testsuite/g++.dg/tls/bz2213753.C | 26 ++++++++++++++++++++++++++
|
||||
2 files changed, 43 insertions(+)
|
||||
create mode 100644 gcc/testsuite/g++.dg/tls/bz2213753.C
|
||||
|
||||
diff --git a/gcc/final.c b/gcc/final.c
|
||||
index 5a65a8ce07c..c783fbb83d7 100644
|
||||
--- a/gcc/final.c
|
||||
+++ b/gcc/final.c
|
||||
@@ -1691,6 +1691,23 @@ get_some_local_dynamic_name ()
|
||||
}
|
||||
}
|
||||
|
||||
+ /* If all the TLSLD references from current function were DCEd, try harder and pick
|
||||
+ name of any TLSLD symbol in current TU. */
|
||||
+ varpool_node *node;
|
||||
+ if (!this_is_asm_operands)
|
||||
+ FOR_EACH_VARIABLE (node)
|
||||
+ if (DECL_THREAD_LOCAL_P (node->decl)
|
||||
+ && TREE_STATIC (node->decl)
|
||||
+ && decl_tls_model (node->decl) == TLS_MODEL_LOCAL_DYNAMIC
|
||||
+ && DECL_RTL_SET_P (node->decl))
|
||||
+ {
|
||||
+ rtx rtl = DECL_RTL (node->decl);
|
||||
+ if (MEM_P (rtl)
|
||||
+ && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF
|
||||
+ && SYMBOL_REF_TLS_MODEL (XEXP (rtl, 0)) == TLS_MODEL_LOCAL_DYNAMIC)
|
||||
+ return XSTR (XEXP (rtl, 0), 0);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/gcc/testsuite/g++.dg/tls/bz2213753.C b/gcc/testsuite/g++.dg/tls/bz2213753.C
|
||||
new file mode 100644
|
||||
index 00000000000..0c4742d8058
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/g++.dg/tls/bz2213753.C
|
||||
@@ -0,0 +1,26 @@
|
||||
+// RHBZ #2213753
|
||||
+// { dg-do compile { target c++11 } }
|
||||
+// { dg-require-effective-target fpic }
|
||||
+// { dg-require-effective-target shared }
|
||||
+// { dg-require-effective-target tls }
|
||||
+// { dg-options "-fPIC -O2" }
|
||||
+// { dg-add-options tls }
|
||||
+
|
||||
+struct A { ~A (); };
|
||||
+static thread_local int *t;
|
||||
+int a;
|
||||
+A::~A () { t = &a; }
|
||||
+long b;
|
||||
+
|
||||
+void *
|
||||
+foo ()
|
||||
+{
|
||||
+ void *c;
|
||||
+ if (t)
|
||||
+ {
|
||||
+ c = operator new (b);
|
||||
+ return c;
|
||||
+ }
|
||||
+ void *d = operator new (b);
|
||||
+ return d;
|
||||
+}
|
||||
--
|
||||
2.40.1
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
--- nvptx-tools/nvptx-as.c.jj 2017-01-20 12:40:18.000000000 +0100
|
||||
+++ nvptx-tools/nvptx-as.c 2017-01-20 12:43:53.864271442 +0100
|
||||
@@ -939,7 +939,7 @@ fork_execute (const char *prog, char *co
|
||||
fatal_error ("%s: %m", errmsg);
|
||||
}
|
||||
else
|
||||
- fatal_error (errmsg);
|
||||
+ fatal_error ("%s", errmsg);
|
||||
}
|
||||
do_wait (prog, pex);
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
--- nvptx-tools/configure.ac.jj 2017-01-13 12:48:31.000000000 +0100
|
||||
+++ nvptx-tools/configure.ac 2017-05-03 10:26:57.076092259 +0200
|
||||
@@ -66,6 +66,8 @@ CPPFLAGS=$save_CPPFLAGS
|
||||
LDFLAGS=$save_LDFLAGS
|
||||
LIBS=$save_LIBS
|
||||
|
||||
+AC_CHECK_DECLS(getopt)
|
||||
+
|
||||
AC_CONFIG_SUBDIRS([libiberty])
|
||||
AC_CONFIG_FILES([Makefile dejagnu.exp])
|
||||
AC_OUTPUT
|
||||
--- nvptx-tools/configure.jj 2017-01-13 12:48:54.000000000 +0100
|
||||
+++ nvptx-tools/configure 2017-05-03 10:27:13.503876809 +0200
|
||||
@@ -3963,6 +3963,18 @@ CPPFLAGS=$save_CPPFLAGS
|
||||
LDFLAGS=$save_LDFLAGS
|
||||
LIBS=$save_LIBS
|
||||
|
||||
+ac_fn_c_check_decl "$LINENO" "getopt" "ac_cv_have_decl_getopt" "$ac_includes_default"
|
||||
+if test "x$ac_cv_have_decl_getopt" = x""yes; then :
|
||||
+ ac_have_decl=1
|
||||
+else
|
||||
+ ac_have_decl=0
|
||||
+fi
|
||||
+
|
||||
+cat >>confdefs.h <<_ACEOF
|
||||
+#define HAVE_DECL_GETOPT $ac_have_decl
|
||||
+_ACEOF
|
||||
+
|
||||
+
|
||||
|
||||
|
||||
subdirs="$subdirs libiberty"
|
||||
@ -1,947 +0,0 @@
|
||||
--- nvptx-tools/configure.ac
|
||||
+++ nvptx-tools/configure.ac
|
||||
@@ -51,6 +51,7 @@ LIBS="$LIBS -lcuda"
|
||||
AC_CHECK_FUNCS([[cuGetErrorName] [cuGetErrorString]])
|
||||
AC_CHECK_DECLS([[cuGetErrorName], [cuGetErrorString]],
|
||||
[], [], [[#include <cuda.h>]])
|
||||
+AC_CHECK_HEADERS(unistd.h sys/stat.h)
|
||||
|
||||
AC_MSG_CHECKING([for extra programs to build requiring -lcuda])
|
||||
NVPTX_RUN=
|
||||
--- nvptx-tools/include/libiberty.h
|
||||
+++ nvptx-tools/include/libiberty.h
|
||||
@@ -390,6 +390,17 @@ extern void hex_init (void);
|
||||
/* Save files used for communication between processes. */
|
||||
#define PEX_SAVE_TEMPS 0x4
|
||||
|
||||
+/* Max number of alloca bytes per call before we must switch to malloc.
|
||||
+
|
||||
+ ?? Swiped from gnulib's regex_internal.h header. Is this actually
|
||||
+ the case? This number seems arbitrary, though sane.
|
||||
+
|
||||
+ The OS usually guarantees only one guard page at the bottom of the stack,
|
||||
+ and a page size can be as small as 4096 bytes. So we cannot safely
|
||||
+ allocate anything larger than 4096 bytes. Also care for the possibility
|
||||
+ of a few compiler-allocated temporary stack slots. */
|
||||
+#define MAX_ALLOCA_SIZE 4032
|
||||
+
|
||||
/* Prepare to execute one or more programs, with standard output of
|
||||
each program fed to standard input of the next.
|
||||
FLAGS As above.
|
||||
--- nvptx-tools/nvptx-as.c
|
||||
+++ nvptx-tools/nvptx-as.c
|
||||
@@ -30,6 +30,9 @@
|
||||
#include <string.h>
|
||||
#include <wait.h>
|
||||
#include <unistd.h>
|
||||
+#ifdef HAVE_SYS_STAT_H
|
||||
+#include <sys/stat.h>
|
||||
+#endif
|
||||
#include <errno.h>
|
||||
#define obstack_chunk_alloc malloc
|
||||
#define obstack_chunk_free free
|
||||
@@ -42,6 +45,38 @@
|
||||
|
||||
#include "version.h"
|
||||
|
||||
+#ifndef R_OK
|
||||
+#define R_OK 4
|
||||
+#define W_OK 2
|
||||
+#define X_OK 1
|
||||
+#endif
|
||||
+
|
||||
+#ifndef DIR_SEPARATOR
|
||||
+# define DIR_SEPARATOR '/'
|
||||
+#endif
|
||||
+
|
||||
+#if defined (_WIN32) || defined (__MSDOS__) \
|
||||
+ || defined (__DJGPP__) || defined (__OS2__)
|
||||
+# define HAVE_DOS_BASED_FILE_SYSTEM
|
||||
+# define HAVE_HOST_EXECUTABLE_SUFFIX
|
||||
+# define HOST_EXECUTABLE_SUFFIX ".exe"
|
||||
+# ifndef DIR_SEPARATOR_2
|
||||
+# define DIR_SEPARATOR_2 '\\'
|
||||
+# endif
|
||||
+# define PATH_SEPARATOR ';'
|
||||
+#else
|
||||
+# define PATH_SEPARATOR ':'
|
||||
+#endif
|
||||
+
|
||||
+#ifndef DIR_SEPARATOR_2
|
||||
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
|
||||
+#else
|
||||
+# define IS_DIR_SEPARATOR(ch) \
|
||||
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
|
||||
+#endif
|
||||
+
|
||||
+#define DIR_UP ".."
|
||||
+
|
||||
static const char *outname = NULL;
|
||||
|
||||
static void __attribute__ ((format (printf, 1, 2)))
|
||||
@@ -816,7 +851,7 @@ traverse (void **slot, void *data)
|
||||
}
|
||||
|
||||
static void
|
||||
-process (FILE *in, FILE *out)
|
||||
+process (FILE *in, FILE *out, int verify, const char *outname)
|
||||
{
|
||||
symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
|
||||
NULL);
|
||||
@@ -824,6 +859,18 @@ process (FILE *in, FILE *out)
|
||||
const char *input = read_file (in);
|
||||
Token *tok = tokenize (input);
|
||||
|
||||
+ /* By default, when ptxas is not in PATH, do minimalistic verification,
|
||||
+ just require that the first non-comment directive is .version. */
|
||||
+ if (verify < 0)
|
||||
+ {
|
||||
+ size_t i;
|
||||
+ for (i = 0; tok[i].kind == K_comment; i++)
|
||||
+ ;
|
||||
+ if (tok[i].kind != K_dotted || !is_keyword (&tok[i], "version"))
|
||||
+ fatal_error ("missing .version directive at start of file '%s'",
|
||||
+ outname);
|
||||
+ }
|
||||
+
|
||||
do
|
||||
tok = parse_file (tok);
|
||||
while (tok->kind);
|
||||
@@ -897,9 +944,83 @@ fork_execute (const char *prog, char *const *argv)
|
||||
do_wait (prog, pex);
|
||||
}
|
||||
|
||||
+/* Determine if progname is available in PATH. */
|
||||
+static bool
|
||||
+program_available (const char *progname)
|
||||
+{
|
||||
+ char *temp = getenv ("PATH");
|
||||
+ if (temp)
|
||||
+ {
|
||||
+ char *startp, *endp, *nstore, *alloc_ptr = NULL;
|
||||
+ size_t prefixlen = strlen (temp) + 1;
|
||||
+ size_t len;
|
||||
+ if (prefixlen < 2)
|
||||
+ prefixlen = 2;
|
||||
+
|
||||
+ len = prefixlen + strlen (progname) + 1;
|
||||
+#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
|
||||
+ len += strlen (HOST_EXECUTABLE_SUFFIX);
|
||||
+#endif
|
||||
+ if (len < MAX_ALLOCA_SIZE)
|
||||
+ nstore = (char *) alloca (len);
|
||||
+ else
|
||||
+ alloc_ptr = nstore = (char *) malloc (len);
|
||||
+
|
||||
+ startp = endp = temp;
|
||||
+ while (1)
|
||||
+ {
|
||||
+ if (*endp == PATH_SEPARATOR || *endp == 0)
|
||||
+ {
|
||||
+ if (endp == startp)
|
||||
+ {
|
||||
+ nstore[0] = '.';
|
||||
+ nstore[1] = DIR_SEPARATOR;
|
||||
+ nstore[2] = '\0';
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ memcpy (nstore, startp, endp - startp);
|
||||
+ if (! IS_DIR_SEPARATOR (endp[-1]))
|
||||
+ {
|
||||
+ nstore[endp - startp] = DIR_SEPARATOR;
|
||||
+ nstore[endp - startp + 1] = 0;
|
||||
+ }
|
||||
+ else
|
||||
+ nstore[endp - startp] = 0;
|
||||
+ }
|
||||
+ strcat (nstore, progname);
|
||||
+ if (! access (nstore, X_OK)
|
||||
+#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
|
||||
+ || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
|
||||
+#endif
|
||||
+ )
|
||||
+ {
|
||||
+#if defined (HAVE_SYS_STAT_H) && defined (S_ISREG)
|
||||
+ struct stat st;
|
||||
+ if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode))
|
||||
+#endif
|
||||
+ {
|
||||
+ free (alloc_ptr);
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (*endp == 0)
|
||||
+ break;
|
||||
+ endp = startp = endp + 1;
|
||||
+ }
|
||||
+ else
|
||||
+ endp++;
|
||||
+ }
|
||||
+ free (alloc_ptr);
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static struct option long_options[] = {
|
||||
{"traditional-format", no_argument, 0, 0 },
|
||||
{"save-temps", no_argument, 0, 0 },
|
||||
+ {"verify", no_argument, 0, 0 },
|
||||
{"no-verify", no_argument, 0, 0 },
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"version", no_argument, 0, 'V' },
|
||||
@@ -912,7 +1033,7 @@ main (int argc, char **argv)
|
||||
FILE *in = stdin;
|
||||
FILE *out = stdout;
|
||||
bool verbose __attribute__((unused)) = false;
|
||||
- bool verify = true;
|
||||
+ int verify = -1;
|
||||
const char *smver = "sm_30";
|
||||
|
||||
int o;
|
||||
@@ -923,7 +1044,9 @@ main (int argc, char **argv)
|
||||
{
|
||||
case 0:
|
||||
if (option_index == 2)
|
||||
- verify = false;
|
||||
+ verify = 1;
|
||||
+ else if (option_index == 3)
|
||||
+ verify = 0;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
@@ -948,7 +1071,8 @@ Usage: nvptx-none-as [option...] [asmfile]\n\
|
||||
Options:\n\
|
||||
-o FILE Write output to FILE\n\
|
||||
-v Be verbose\n\
|
||||
+ --verify Do verify output is acceptable to ptxas\n\
|
||||
--no-verify Do not verify output is acceptable to ptxas\n\
|
||||
--help Print this help and exit\n\
|
||||
--version Print version number and exit\n\
|
||||
\n\
|
||||
@@ -983,11 +1108,17 @@ This program has absolutely no warranty.\n",
|
||||
if (!in)
|
||||
fatal_error ("cannot open input ptx file");
|
||||
|
||||
- process (in, out);
|
||||
- if (outname)
|
||||
+ if (outname == NULL)
|
||||
+ verify = 0;
|
||||
+ else if (verify == -1)
|
||||
+ if (program_available ("ptxas"))
|
||||
+ verify = 1;
|
||||
+
|
||||
+ process (in, out, verify, outname);
|
||||
+ if (outname)
|
||||
fclose (out);
|
||||
|
||||
- if (verify && outname)
|
||||
+ if (verify > 0)
|
||||
{
|
||||
struct obstack argv_obstack;
|
||||
obstack_init (&argv_obstack);
|
||||
--- nvptx-tools/configure
|
||||
+++ nvptx-tools/configure
|
||||
@@ -168,7 +168,8 @@ test x\$exitcode = x0 || exit 1"
|
||||
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
|
||||
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
|
||||
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
|
||||
- test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
|
||||
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
|
||||
+test \$(( 1 + 1 )) = 2 || exit 1"
|
||||
if (eval "$as_required") 2>/dev/null; then :
|
||||
as_have_required=yes
|
||||
else
|
||||
@@ -552,11 +553,50 @@ PACKAGE_URL=
|
||||
|
||||
ac_unique_file="nvptx-tools"
|
||||
ac_unique_file="nvptx-as.c"
|
||||
+# Factoring default headers for most tests.
|
||||
+ac_includes_default="\
|
||||
+#include <stdio.h>
|
||||
+#ifdef HAVE_SYS_TYPES_H
|
||||
+# include <sys/types.h>
|
||||
+#endif
|
||||
+#ifdef HAVE_SYS_STAT_H
|
||||
+# include <sys/stat.h>
|
||||
+#endif
|
||||
+#ifdef STDC_HEADERS
|
||||
+# include <stdlib.h>
|
||||
+# include <stddef.h>
|
||||
+#else
|
||||
+# ifdef HAVE_STDLIB_H
|
||||
+# include <stdlib.h>
|
||||
+# endif
|
||||
+#endif
|
||||
+#ifdef HAVE_STRING_H
|
||||
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
|
||||
+# include <memory.h>
|
||||
+# endif
|
||||
+# include <string.h>
|
||||
+#endif
|
||||
+#ifdef HAVE_STRINGS_H
|
||||
+# include <strings.h>
|
||||
+#endif
|
||||
+#ifdef HAVE_INTTYPES_H
|
||||
+# include <inttypes.h>
|
||||
+#endif
|
||||
+#ifdef HAVE_STDINT_H
|
||||
+# include <stdint.h>
|
||||
+#endif
|
||||
+#ifdef HAVE_UNISTD_H
|
||||
+# include <unistd.h>
|
||||
+#endif"
|
||||
+
|
||||
enable_option_checking=no
|
||||
ac_subst_vars='LTLIBOBJS
|
||||
LIBOBJS
|
||||
subdirs
|
||||
NVPTX_RUN
|
||||
+EGREP
|
||||
+GREP
|
||||
+CPP
|
||||
CUDA_DRIVER_LDFLAGS
|
||||
CUDA_DRIVER_CPPFLAGS
|
||||
AR
|
||||
@@ -635,7 +675,8 @@ LIBS
|
||||
CPPFLAGS
|
||||
CXX
|
||||
CXXFLAGS
|
||||
-CCC'
|
||||
+CCC
|
||||
+CPP'
|
||||
ac_subdirs_all='libiberty'
|
||||
|
||||
# Initialize some variables set by options.
|
||||
@@ -1267,6 +1308,7 @@ Some influential environment variables:
|
||||
you have headers in a nonstandard directory <include dir>
|
||||
CXX C++ compiler command
|
||||
CXXFLAGS C++ compiler flags
|
||||
+ CPP C preprocessor
|
||||
|
||||
Use these variables to override the choices made by `configure' or to help
|
||||
it to find libraries and programs with nonstandard names/locations.
|
||||
@@ -1575,6 +1617,203 @@ $as_echo "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
||||
|
||||
} # ac_fn_c_check_decl
|
||||
+
|
||||
+# ac_fn_c_try_cpp LINENO
|
||||
+# ----------------------
|
||||
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
|
||||
+ac_fn_c_try_cpp ()
|
||||
+{
|
||||
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
|
||||
+case "(($ac_try" in
|
||||
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
+ *) ac_try_echo=$ac_try;;
|
||||
+esac
|
||||
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
+$as_echo "$ac_try_echo"; } >&5
|
||||
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
|
||||
+ ac_status=$?
|
||||
+ if test -s conftest.err; then
|
||||
+ grep -v '^ *+' conftest.err >conftest.er1
|
||||
+ cat conftest.er1 >&5
|
||||
+ mv -f conftest.er1 conftest.err
|
||||
+ fi
|
||||
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
+ test $ac_status = 0; } >/dev/null && {
|
||||
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
|
||||
+ test ! -s conftest.err
|
||||
+ }; then :
|
||||
+ ac_retval=0
|
||||
+else
|
||||
+ $as_echo "$as_me: failed program was:" >&5
|
||||
+sed 's/^/| /' conftest.$ac_ext >&5
|
||||
+
|
||||
+ ac_retval=1
|
||||
+fi
|
||||
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
||||
+ return $ac_retval
|
||||
+
|
||||
+} # ac_fn_c_try_cpp
|
||||
+
|
||||
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
|
||||
+# -------------------------------------------------------
|
||||
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
|
||||
+# the include files in INCLUDES and setting the cache variable VAR
|
||||
+# accordingly.
|
||||
+ac_fn_c_check_header_mongrel ()
|
||||
+{
|
||||
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
+ if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
+$as_echo_n "checking for $2... " >&6; }
|
||||
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+fi
|
||||
+eval ac_res=\$$3
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
+$as_echo "$ac_res" >&6; }
|
||||
+else
|
||||
+ # Is the header compilable?
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
|
||||
+$as_echo_n "checking $2 usability... " >&6; }
|
||||
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+$4
|
||||
+#include <$2>
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_compile "$LINENO"; then :
|
||||
+ ac_header_compiler=yes
|
||||
+else
|
||||
+ ac_header_compiler=no
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
|
||||
+$as_echo "$ac_header_compiler" >&6; }
|
||||
+
|
||||
+# Is the header present?
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
|
||||
+$as_echo_n "checking $2 presence... " >&6; }
|
||||
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+#include <$2>
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_cpp "$LINENO"; then :
|
||||
+ ac_header_preproc=yes
|
||||
+else
|
||||
+ ac_header_preproc=no
|
||||
+fi
|
||||
+rm -f conftest.err conftest.$ac_ext
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
|
||||
+$as_echo "$ac_header_preproc" >&6; }
|
||||
+
|
||||
+# So? What about this header?
|
||||
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
|
||||
+ yes:no: )
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
|
||||
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
|
||||
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
|
||||
+ ;;
|
||||
+ no:yes:* )
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
|
||||
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
|
||||
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
|
||||
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
|
||||
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
|
||||
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
|
||||
+ ;;
|
||||
+esac
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
+$as_echo_n "checking for $2... " >&6; }
|
||||
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ eval "$3=\$ac_header_compiler"
|
||||
+fi
|
||||
+eval ac_res=\$$3
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
+$as_echo "$ac_res" >&6; }
|
||||
+fi
|
||||
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
||||
+
|
||||
+} # ac_fn_c_check_header_mongrel
|
||||
+
|
||||
+# ac_fn_c_try_run LINENO
|
||||
+# ----------------------
|
||||
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
|
||||
+# that executables *can* be run.
|
||||
+ac_fn_c_try_run ()
|
||||
+{
|
||||
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
+ if { { ac_try="$ac_link"
|
||||
+case "(($ac_try" in
|
||||
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
+ *) ac_try_echo=$ac_try;;
|
||||
+esac
|
||||
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
+$as_echo "$ac_try_echo"; } >&5
|
||||
+ (eval "$ac_link") 2>&5
|
||||
+ ac_status=$?
|
||||
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
|
||||
+ { { case "(($ac_try" in
|
||||
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
+ *) ac_try_echo=$ac_try;;
|
||||
+esac
|
||||
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
+$as_echo "$ac_try_echo"; } >&5
|
||||
+ (eval "$ac_try") 2>&5
|
||||
+ ac_status=$?
|
||||
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
+ test $ac_status = 0; }; }; then :
|
||||
+ ac_retval=0
|
||||
+else
|
||||
+ $as_echo "$as_me: program exited with status $ac_status" >&5
|
||||
+ $as_echo "$as_me: failed program was:" >&5
|
||||
+sed 's/^/| /' conftest.$ac_ext >&5
|
||||
+
|
||||
+ ac_retval=$ac_status
|
||||
+fi
|
||||
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
|
||||
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
||||
+ return $ac_retval
|
||||
+
|
||||
+} # ac_fn_c_try_run
|
||||
+
|
||||
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
|
||||
+# -------------------------------------------------------
|
||||
+# Tests whether HEADER exists and can be compiled using the include files in
|
||||
+# INCLUDES, setting the cache variable VAR accordingly.
|
||||
+ac_fn_c_check_header_compile ()
|
||||
+{
|
||||
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
+$as_echo_n "checking for $2... " >&6; }
|
||||
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+$4
|
||||
+#include <$2>
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_compile "$LINENO"; then :
|
||||
+ eval "$3=yes"
|
||||
+else
|
||||
+ eval "$3=no"
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
+fi
|
||||
+eval ac_res=\$$3
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
+$as_echo "$ac_res" >&6; }
|
||||
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
||||
+
|
||||
+} # ac_fn_c_check_header_compile
|
||||
cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
@@ -3284,6 +3523,418 @@ cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_DECL_CUGETERRORSTRING $ac_have_decl
|
||||
_ACEOF
|
||||
|
||||
+ac_ext=c
|
||||
+ac_cpp='$CPP $CPPFLAGS'
|
||||
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
|
||||
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
|
||||
+# On Suns, sometimes $CPP names a directory.
|
||||
+if test -n "$CPP" && test -d "$CPP"; then
|
||||
+ CPP=
|
||||
+fi
|
||||
+if test -z "$CPP"; then
|
||||
+ if test "${ac_cv_prog_CPP+set}" = set; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ # Double quotes because CPP needs to be expanded
|
||||
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
|
||||
+ do
|
||||
+ ac_preproc_ok=false
|
||||
+for ac_c_preproc_warn_flag in '' yes
|
||||
+do
|
||||
+ # Use a header file that comes with gcc, so configuring glibc
|
||||
+ # with a fresh cross-compiler works.
|
||||
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
|
||||
+ # <limits.h> exists even on freestanding compilers.
|
||||
+ # On the NeXT, cc -E runs the code through the compiler's parser,
|
||||
+ # not just through cpp. "Syntax error" is here to catch this case.
|
||||
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+#ifdef __STDC__
|
||||
+# include <limits.h>
|
||||
+#else
|
||||
+# include <assert.h>
|
||||
+#endif
|
||||
+ Syntax error
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_cpp "$LINENO"; then :
|
||||
+
|
||||
+else
|
||||
+ # Broken: fails on valid input.
|
||||
+continue
|
||||
+fi
|
||||
+rm -f conftest.err conftest.$ac_ext
|
||||
+
|
||||
+ # OK, works on sane cases. Now check whether nonexistent headers
|
||||
+ # can be detected and how.
|
||||
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+#include <ac_nonexistent.h>
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_cpp "$LINENO"; then :
|
||||
+ # Broken: success on invalid input.
|
||||
+continue
|
||||
+else
|
||||
+ # Passes both tests.
|
||||
+ac_preproc_ok=:
|
||||
+break
|
||||
+fi
|
||||
+rm -f conftest.err conftest.$ac_ext
|
||||
+
|
||||
+done
|
||||
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
|
||||
+rm -f conftest.err conftest.$ac_ext
|
||||
+if $ac_preproc_ok; then :
|
||||
+ break
|
||||
+fi
|
||||
+
|
||||
+ done
|
||||
+ ac_cv_prog_CPP=$CPP
|
||||
+
|
||||
+fi
|
||||
+ CPP=$ac_cv_prog_CPP
|
||||
+else
|
||||
+ ac_cv_prog_CPP=$CPP
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
|
||||
+$as_echo "$CPP" >&6; }
|
||||
+ac_preproc_ok=false
|
||||
+for ac_c_preproc_warn_flag in '' yes
|
||||
+do
|
||||
+ # Use a header file that comes with gcc, so configuring glibc
|
||||
+ # with a fresh cross-compiler works.
|
||||
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
|
||||
+ # <limits.h> exists even on freestanding compilers.
|
||||
+ # On the NeXT, cc -E runs the code through the compiler's parser,
|
||||
+ # not just through cpp. "Syntax error" is here to catch this case.
|
||||
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+#ifdef __STDC__
|
||||
+# include <limits.h>
|
||||
+#else
|
||||
+# include <assert.h>
|
||||
+#endif
|
||||
+ Syntax error
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_cpp "$LINENO"; then :
|
||||
+
|
||||
+else
|
||||
+ # Broken: fails on valid input.
|
||||
+continue
|
||||
+fi
|
||||
+rm -f conftest.err conftest.$ac_ext
|
||||
+
|
||||
+ # OK, works on sane cases. Now check whether nonexistent headers
|
||||
+ # can be detected and how.
|
||||
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+#include <ac_nonexistent.h>
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_cpp "$LINENO"; then :
|
||||
+ # Broken: success on invalid input.
|
||||
+continue
|
||||
+else
|
||||
+ # Passes both tests.
|
||||
+ac_preproc_ok=:
|
||||
+break
|
||||
+fi
|
||||
+rm -f conftest.err conftest.$ac_ext
|
||||
+
|
||||
+done
|
||||
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
|
||||
+rm -f conftest.err conftest.$ac_ext
|
||||
+if $ac_preproc_ok; then :
|
||||
+
|
||||
+else
|
||||
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
+as_fn_error "C preprocessor \"$CPP\" fails sanity check
|
||||
+See \`config.log' for more details." "$LINENO" 5; }
|
||||
+fi
|
||||
+
|
||||
+ac_ext=c
|
||||
+ac_cpp='$CPP $CPPFLAGS'
|
||||
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
+
|
||||
+
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
|
||||
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
|
||||
+if test "${ac_cv_path_GREP+set}" = set; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ if test -z "$GREP"; then
|
||||
+ ac_path_GREP_found=false
|
||||
+ # Loop through the user's path and test for each of PROGNAME-LIST
|
||||
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
|
||||
+do
|
||||
+ IFS=$as_save_IFS
|
||||
+ test -z "$as_dir" && as_dir=.
|
||||
+ for ac_prog in grep ggrep; do
|
||||
+ for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
|
||||
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
|
||||
+# Check for GNU ac_path_GREP and select it if it is found.
|
||||
+ # Check for GNU $ac_path_GREP
|
||||
+case `"$ac_path_GREP" --version 2>&1` in
|
||||
+*GNU*)
|
||||
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
|
||||
+*)
|
||||
+ ac_count=0
|
||||
+ $as_echo_n 0123456789 >"conftest.in"
|
||||
+ while :
|
||||
+ do
|
||||
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
|
||||
+ mv "conftest.tmp" "conftest.in"
|
||||
+ cp "conftest.in" "conftest.nl"
|
||||
+ $as_echo 'GREP' >> "conftest.nl"
|
||||
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
|
||||
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
|
||||
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
|
||||
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
|
||||
+ # Best one so far, save it but keep looking for a better one
|
||||
+ ac_cv_path_GREP="$ac_path_GREP"
|
||||
+ ac_path_GREP_max=$ac_count
|
||||
+ fi
|
||||
+ # 10*(2^10) chars as input seems more than enough
|
||||
+ test $ac_count -gt 10 && break
|
||||
+ done
|
||||
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
|
||||
+esac
|
||||
+
|
||||
+ $ac_path_GREP_found && break 3
|
||||
+ done
|
||||
+ done
|
||||
+ done
|
||||
+IFS=$as_save_IFS
|
||||
+ if test -z "$ac_cv_path_GREP"; then
|
||||
+ as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
|
||||
+ fi
|
||||
+else
|
||||
+ ac_cv_path_GREP=$GREP
|
||||
+fi
|
||||
+
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
|
||||
+$as_echo "$ac_cv_path_GREP" >&6; }
|
||||
+ GREP="$ac_cv_path_GREP"
|
||||
+
|
||||
+
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
|
||||
+$as_echo_n "checking for egrep... " >&6; }
|
||||
+if test "${ac_cv_path_EGREP+set}" = set; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
|
||||
+ then ac_cv_path_EGREP="$GREP -E"
|
||||
+ else
|
||||
+ if test -z "$EGREP"; then
|
||||
+ ac_path_EGREP_found=false
|
||||
+ # Loop through the user's path and test for each of PROGNAME-LIST
|
||||
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
|
||||
+do
|
||||
+ IFS=$as_save_IFS
|
||||
+ test -z "$as_dir" && as_dir=.
|
||||
+ for ac_prog in egrep; do
|
||||
+ for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
|
||||
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
|
||||
+# Check for GNU ac_path_EGREP and select it if it is found.
|
||||
+ # Check for GNU $ac_path_EGREP
|
||||
+case `"$ac_path_EGREP" --version 2>&1` in
|
||||
+*GNU*)
|
||||
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
|
||||
+*)
|
||||
+ ac_count=0
|
||||
+ $as_echo_n 0123456789 >"conftest.in"
|
||||
+ while :
|
||||
+ do
|
||||
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
|
||||
+ mv "conftest.tmp" "conftest.in"
|
||||
+ cp "conftest.in" "conftest.nl"
|
||||
+ $as_echo 'EGREP' >> "conftest.nl"
|
||||
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
|
||||
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
|
||||
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
|
||||
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
|
||||
+ # Best one so far, save it but keep looking for a better one
|
||||
+ ac_cv_path_EGREP="$ac_path_EGREP"
|
||||
+ ac_path_EGREP_max=$ac_count
|
||||
+ fi
|
||||
+ # 10*(2^10) chars as input seems more than enough
|
||||
+ test $ac_count -gt 10 && break
|
||||
+ done
|
||||
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
|
||||
+esac
|
||||
+
|
||||
+ $ac_path_EGREP_found && break 3
|
||||
+ done
|
||||
+ done
|
||||
+ done
|
||||
+IFS=$as_save_IFS
|
||||
+ if test -z "$ac_cv_path_EGREP"; then
|
||||
+ as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
|
||||
+ fi
|
||||
+else
|
||||
+ ac_cv_path_EGREP=$EGREP
|
||||
+fi
|
||||
+
|
||||
+ fi
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
|
||||
+$as_echo "$ac_cv_path_EGREP" >&6; }
|
||||
+ EGREP="$ac_cv_path_EGREP"
|
||||
+
|
||||
+
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
|
||||
+$as_echo_n "checking for ANSI C header files... " >&6; }
|
||||
+if test "${ac_cv_header_stdc+set}" = set; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+#include <stdlib.h>
|
||||
+#include <stdarg.h>
|
||||
+#include <string.h>
|
||||
+#include <float.h>
|
||||
+
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+
|
||||
+ ;
|
||||
+ return 0;
|
||||
+}
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_compile "$LINENO"; then :
|
||||
+ ac_cv_header_stdc=yes
|
||||
+else
|
||||
+ ac_cv_header_stdc=no
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
+
|
||||
+if test $ac_cv_header_stdc = yes; then
|
||||
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
|
||||
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+#include <string.h>
|
||||
+
|
||||
+_ACEOF
|
||||
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||
+ $EGREP "memchr" >/dev/null 2>&1; then :
|
||||
+
|
||||
+else
|
||||
+ ac_cv_header_stdc=no
|
||||
+fi
|
||||
+rm -f conftest*
|
||||
+
|
||||
+fi
|
||||
+
|
||||
+if test $ac_cv_header_stdc = yes; then
|
||||
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
|
||||
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+_ACEOF
|
||||
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||
+ $EGREP "free" >/dev/null 2>&1; then :
|
||||
+
|
||||
+else
|
||||
+ ac_cv_header_stdc=no
|
||||
+fi
|
||||
+rm -f conftest*
|
||||
+
|
||||
+fi
|
||||
+
|
||||
+if test $ac_cv_header_stdc = yes; then
|
||||
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
|
||||
+ if test "$cross_compiling" = yes; then :
|
||||
+ :
|
||||
+else
|
||||
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+#include <ctype.h>
|
||||
+#include <stdlib.h>
|
||||
+#if ((' ' & 0x0FF) == 0x020)
|
||||
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
|
||||
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
|
||||
+#else
|
||||
+# define ISLOWER(c) \
|
||||
+ (('a' <= (c) && (c) <= 'i') \
|
||||
+ || ('j' <= (c) && (c) <= 'r') \
|
||||
+ || ('s' <= (c) && (c) <= 'z'))
|
||||
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
|
||||
+#endif
|
||||
+
|
||||
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+ int i;
|
||||
+ for (i = 0; i < 256; i++)
|
||||
+ if (XOR (islower (i), ISLOWER (i))
|
||||
+ || toupper (i) != TOUPPER (i))
|
||||
+ return 2;
|
||||
+ return 0;
|
||||
+}
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_run "$LINENO"; then :
|
||||
+
|
||||
+else
|
||||
+ ac_cv_header_stdc=no
|
||||
+fi
|
||||
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
|
||||
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
+fi
|
||||
+
|
||||
+fi
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
|
||||
+$as_echo "$ac_cv_header_stdc" >&6; }
|
||||
+if test $ac_cv_header_stdc = yes; then
|
||||
+
|
||||
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
|
||||
+
|
||||
+fi
|
||||
+
|
||||
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
|
||||
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
|
||||
+ inttypes.h stdint.h unistd.h
|
||||
+do :
|
||||
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
|
||||
+"
|
||||
+eval as_val=\$$as_ac_Header
|
||||
+ if test "x$as_val" = x""yes; then :
|
||||
+ cat >>confdefs.h <<_ACEOF
|
||||
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
||||
+_ACEOF
|
||||
+
|
||||
+fi
|
||||
+
|
||||
+done
|
||||
+
|
||||
+
|
||||
+for ac_header in unistd.h sys/stat.h
|
||||
+do :
|
||||
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||
+eval as_val=\$$as_ac_Header
|
||||
+ if test "x$as_val" = x""yes; then :
|
||||
+ cat >>confdefs.h <<_ACEOF
|
||||
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
||||
+_ACEOF
|
||||
+
|
||||
+fi
|
||||
+
|
||||
+done
|
||||
+
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for extra programs to build requiring -lcuda" >&5
|
||||
$as_echo_n "checking for extra programs to build requiring -lcuda... " >&6; }
|
||||
35
STAGE1-gcc
Normal file
35
STAGE1-gcc
Normal file
@ -0,0 +1,35 @@
|
||||
srpm gcc
|
||||
mcd $BUILDDIR/gcc
|
||||
|
||||
# These are for gcc cross-tools (politics sometime result in slightly
|
||||
# different arch names)
|
||||
GCC_CONFIGARGS="--prefix=$PREFIX
|
||||
--libdir=$PREFIX/lib${SUFFIX}
|
||||
--target=$TARGET
|
||||
${GCC_CONFIG_EXTRA}
|
||||
--enable-languages=c,c++
|
||||
--with-sysroot=$ROOTFS
|
||||
--with-build-sysroot=$ROOTFS
|
||||
--cache-file=config.cache
|
||||
--disable-bootstrap
|
||||
--enable-threads=posix
|
||||
--enable-64-bit-bfd
|
||||
--disable-lto
|
||||
$WITHPPL
|
||||
"
|
||||
|
||||
# prefill gcc cache
|
||||
echo 'lt_cv_shlibpath_overrides_runpath=no' > config.cache
|
||||
echo 'gcc_cv_libc_provides_ssp=yes' >> config.cache
|
||||
|
||||
if [ ! "$BUILDER_ARCH" = "$TARGET_ARCH" ]; then
|
||||
WITH_HEADERS="--with-headers=$ROOTFS/usr/include"
|
||||
fi
|
||||
|
||||
$SRC/gcc-*/configure $GCC_CONFIGARGS $WITH_HEADERS
|
||||
notparallel
|
||||
make $J
|
||||
make $J install
|
||||
mcd $ROOTFS/lib${SUFFIX}/gcc
|
||||
rsync -av $PREFIX/lib${SUFFIX}/gcc/ $ROOTFS/lib${SUFFIX}/gcc/
|
||||
rsync -av $PREFIX/$TARGET/lib/ $ROOTFS/lib${SUFFIX}/
|
||||
48
STAGE1-gcc-host
Normal file
48
STAGE1-gcc-host
Normal file
@ -0,0 +1,48 @@
|
||||
srpm gcc
|
||||
mcd $BUILDDIR/gcc-host
|
||||
|
||||
# These are for gcc cross-tools (politics sometime result in slightly
|
||||
# different arch names)
|
||||
GCC_CONFIGARGS="--prefix=$PREFIX
|
||||
--libdir=$PREFIX/lib${SUFFIX}
|
||||
--target=$TARGET
|
||||
${GCC_CONFIG_EXTRA}
|
||||
--enable-languages=c,c++
|
||||
--with-sysroot=$ROOTFS
|
||||
--with-build-sysroot=$ROOTFS
|
||||
--cache-file=config.cache
|
||||
--disable-bootstrap
|
||||
--enable-threads=posix
|
||||
--enable-64-bit-bfd
|
||||
--disable-lto
|
||||
$WITHPPL
|
||||
"
|
||||
|
||||
# prefill gcc cache
|
||||
echo 'lt_cv_shlibpath_overrides_runpath=no' > config.cache
|
||||
echo 'gcc_cv_libc_provides_ssp=yes' >> config.cache
|
||||
|
||||
if [ ! "$BUILDER_ARCH" = "$TARGET_ARCH" ]; then
|
||||
WITH_HEADERS="--with-headers=$ROOTFS/usr/include"
|
||||
fi
|
||||
|
||||
$SRC/gcc-*/configure $GCC_CONFIGARGS $WITH_HEADERS
|
||||
notparallel
|
||||
|
||||
# Pass gcc_cv_libc_provides_ssp down, because the config.cache
|
||||
# version is not passed down to the gcc subdir.
|
||||
make $J all-host gcc_cv_libc_provides_ssp=yes
|
||||
make $J install-host gcc_cv_libc_provides_ssp=yes
|
||||
|
||||
|
||||
if false; then
|
||||
mkdirp $ROOTFS/usr/lib${SUFFIX}
|
||||
for o in crt Scrt1 crti crtbegin crtbeginS crtend crtendS crtn
|
||||
do
|
||||
$TARGET-gcc -nostdlib -nostartfiles -c -x c /dev/null -c -o $ROOTFS/usr/lib${SUFFIX}/$o.o
|
||||
done
|
||||
for so in gcc gcc_s c
|
||||
do
|
||||
$TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $ROOTFS/usr/lib${SUFFIX}/lib$so.so
|
||||
done
|
||||
fi
|
||||
34
STAGE1-gcc-libgcc
Normal file
34
STAGE1-gcc-libgcc
Normal file
@ -0,0 +1,34 @@
|
||||
srpm gcc
|
||||
mcd $BUILDDIR/gcc-libgcc
|
||||
|
||||
# These are for gcc cross-tools (politics sometime result in slightly
|
||||
# different arch names)
|
||||
GCC_CONFIGARGS="--prefix=$PREFIX
|
||||
--libdir=$PREFIX/lib${SUFFIX}
|
||||
--target=$TARGET
|
||||
${GCC_CONFIG_EXTRA}
|
||||
--enable-languages=c,c++
|
||||
--with-sysroot=$ROOTFS
|
||||
--with-build-sysroot=$ROOTFS
|
||||
--cache-file=config.cache
|
||||
--disable-bootstrap
|
||||
--enable-threads=posix
|
||||
--enable-64-bit-bfd
|
||||
--disable-lto
|
||||
$WITHPPL
|
||||
"
|
||||
|
||||
# prefill gcc cache
|
||||
echo 'lt_cv_shlibpath_overrides_runpath=no' > config.cache
|
||||
echo 'gcc_cv_libc_provides_ssp=yes' >> config.cache
|
||||
|
||||
if [ ! "$BUILDER_ARCH" = "$TARGET_ARCH" ]; then
|
||||
WITH_HEADERS="--with-headers=$ROOTFS/usr/include"
|
||||
fi
|
||||
|
||||
$SRC/gcc-*/configure $GCC_CONFIGARGS $WITH_HEADERS
|
||||
notparallel
|
||||
# Pass gcc_cv_libc_provides_ssp down, because the config.cache
|
||||
# version is not passed down to the gcc subdir.
|
||||
make $J all-target-libgcc all-target-libssp gcc_cv_libc_provides_ssp=yes
|
||||
make $J install-target-libgcc install-target-libssp gcc_cv_libc_provides_ssp=yes
|
||||
28
STAGE1-t-gcc
Normal file
28
STAGE1-t-gcc
Normal file
@ -0,0 +1,28 @@
|
||||
srpm gcc
|
||||
mcd $BUILDDIR/t-gcc
|
||||
|
||||
GCC_TCONFIGARGS="--prefix=/usr
|
||||
--libdir=/usr/lib${SUFFIX}
|
||||
--with-sysroot=/
|
||||
--with-build-sysroot=$ROOTFS
|
||||
--build=$BUILD
|
||||
--host=$TARGET
|
||||
--target=$TARGET
|
||||
--disable-bootstrap
|
||||
--enable-werror=no
|
||||
--enable-cxx
|
||||
${GCC_CONFIG_EXTRA}
|
||||
--enable-languages=c,c++
|
||||
--enable-threads=posix
|
||||
--enable-linker-build-id
|
||||
"
|
||||
|
||||
$SRC/gcc-*/configure $GCC_TCONFIGARGS
|
||||
notparallel
|
||||
make $J
|
||||
make $J install DESTDIR=${ROOTFS}
|
||||
test -e ${ROOTFS}/usr/bin/cc && rm ${ROOTFS}/usr/bin/cc
|
||||
ln -s gcc ${ROOTFS}/usr/bin/cc
|
||||
mkdir -p ${ROOTFS}/usr/share/gdb/auto-load/usr/lib${SUFFIX}
|
||||
mv -f ${ROOTFS}/usr/lib${SUFFIX}/libstdc++*gdb.py* \
|
||||
${ROOTFS}/usr/share/gdb/auto-load/usr/lib${SUFFIX}
|
||||
16
gating.yaml
Normal file
16
gating.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
--- !Policy
|
||||
product_versions:
|
||||
- fedora-*
|
||||
decision_context: bodhi_update_push_stable
|
||||
subject_type: koji_build
|
||||
rules:
|
||||
- !PassingTestCaseRule {test_case_name: fedora-ci.koji-build.tier0.functional}
|
||||
--- !Policy
|
||||
product_versions:
|
||||
- rhel-9
|
||||
decision_context: osci_compose_gate
|
||||
rules:
|
||||
- !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier1-gating.functional}
|
||||
- !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier1-gating-p9.functional}
|
||||
- !PassingTestCaseRule {test_case_name: osci.brew-build.rebuild.validation}
|
||||
- !PassingTestCaseRule {test_case_name: osci.brew-build.revdeps.integration}
|
||||
63
gcc-RHEL-105072-1.patch
Normal file
63
gcc-RHEL-105072-1.patch
Normal file
@ -0,0 +1,63 @@
|
||||
commit 90986c5f0aa61cd22a9132486304ba5d12aae6c4
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Nov 22 13:30:23 2021 +0100
|
||||
|
||||
libgcc: Remove tbase member from struct unw_eh_callback_data
|
||||
|
||||
It is always a null pointer.
|
||||
|
||||
libgcc/ChangeLog
|
||||
|
||||
* unwind-dw2-fde-dip.c (struct unw_eh_callback_data): Remove
|
||||
tbase member.
|
||||
(base_from_cb_data): Adjust.
|
||||
(_Unwind_IteratePhdrCallback): Likewise.
|
||||
(_Unwind_Find_FDE): Likewise.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
|
||||
index 5095b6830bf79e2e..4a4d990f455e5c11 100644
|
||||
--- a/libgcc/unwind-dw2-fde-dip.c
|
||||
+++ b/libgcc/unwind-dw2-fde-dip.c
|
||||
@@ -104,7 +104,6 @@ static const fde * _Unwind_Find_registered_FDE (void *pc, struct dwarf_eh_bases
|
||||
struct unw_eh_callback_data
|
||||
{
|
||||
_Unwind_Ptr pc;
|
||||
- void *tbase;
|
||||
void *dbase;
|
||||
void *func;
|
||||
const fde *ret;
|
||||
@@ -154,7 +153,7 @@ base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data)
|
||||
return 0;
|
||||
|
||||
case DW_EH_PE_textrel:
|
||||
- return (_Unwind_Ptr) data->tbase;
|
||||
+ return 0;
|
||||
case DW_EH_PE_datarel:
|
||||
return (_Unwind_Ptr) data->dbase;
|
||||
default:
|
||||
@@ -431,7 +430,7 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
As soon as GLIBC will provide API so to notify that a library has been
|
||||
removed, we could cache this (and thus use search_object). */
|
||||
ob.pc_begin = NULL;
|
||||
- ob.tbase = data->tbase;
|
||||
+ ob.tbase = NULL;
|
||||
ob.dbase = data->dbase;
|
||||
ob.u.single = (fde *) eh_frame;
|
||||
ob.s.i = 0;
|
||||
@@ -461,7 +460,6 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
|
||||
return ret;
|
||||
|
||||
data.pc = (_Unwind_Ptr) pc;
|
||||
- data.tbase = NULL;
|
||||
data.dbase = NULL;
|
||||
data.func = NULL;
|
||||
data.ret = NULL;
|
||||
@@ -472,7 +470,7 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
|
||||
|
||||
if (data.ret)
|
||||
{
|
||||
- bases->tbase = data.tbase;
|
||||
+ bases->tbase = NULL;
|
||||
bases->dbase = data.dbase;
|
||||
bases->func = data.func;
|
||||
}
|
||||
51
gcc-RHEL-105072-10.patch
Normal file
51
gcc-RHEL-105072-10.patch
Normal file
@ -0,0 +1,51 @@
|
||||
commit 94ccaf62c378c3737f7e4b6a80e1160157119171
|
||||
Author: Thomas Neumann <tneumann@users.sourceforge.net>
|
||||
Date: Mon Sep 19 18:10:02 2022 +0200
|
||||
|
||||
Avoid depending on destructor order
|
||||
|
||||
In some scenarios (e.g., when mixing gcc and clang code), it can
|
||||
happen that frames are deregistered after the lookup structure
|
||||
has already been destroyed. That in itself would be fine, but
|
||||
it triggers an assert in __deregister_frame_info_bases that
|
||||
expects to find the frame.
|
||||
|
||||
To avoid that, we now remember that the btree as already been
|
||||
destroyed and disable the assert in that case.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
|
||||
* unwind-dw2-fde.c: (release_register_frames) Remember
|
||||
when the btree has been destroyed.
|
||||
(__deregister_frame_info_bases) Disable the assert when
|
||||
shutting down.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
|
||||
index f38efd3c09efc3e9..b0d07ccd53b30f4c 100644
|
||||
--- a/libgcc/unwind-dw2-fde.c
|
||||
+++ b/libgcc/unwind-dw2-fde.c
|
||||
@@ -48,6 +48,7 @@ typedef __UINTPTR_TYPE__ uintptr_type;
|
||||
#include "unwind-dw2-btree.h"
|
||||
|
||||
static struct btree registered_frames;
|
||||
+static bool in_shutdown;
|
||||
|
||||
static void
|
||||
release_registered_frames (void) __attribute__ ((destructor (110)));
|
||||
@@ -57,6 +58,7 @@ release_registered_frames (void)
|
||||
/* Release the b-tree and all frames. Frame releases that happen later are
|
||||
* silently ignored */
|
||||
btree_destroy (®istered_frames);
|
||||
+ in_shutdown = true;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -282,7 +284,7 @@ __deregister_frame_info_bases (const void *begin)
|
||||
__gthread_mutex_unlock (&object_mutex);
|
||||
#endif
|
||||
|
||||
- gcc_assert (ob);
|
||||
+ gcc_assert (in_shutdown || ob);
|
||||
return (void *) ob;
|
||||
}
|
||||
|
||||
42
gcc-RHEL-105072-11.patch
Normal file
42
gcc-RHEL-105072-11.patch
Normal file
@ -0,0 +1,42 @@
|
||||
commit 386ebf75f4c0342b1f823f4e4aba07abda3288d1
|
||||
Author: Thomas Neumann <tneumann@users.sourceforge.net>
|
||||
Date: Fri Sep 23 15:57:13 2022 +0200
|
||||
|
||||
fix assert in __deregister_frame_info_bases
|
||||
|
||||
When using the atomic fast path deregistering can fail during
|
||||
program shutdown if the lookup structures are already destroyed.
|
||||
The assert in __deregister_frame_info_bases takes that into
|
||||
account. In the non-fast-path case however is not aware of
|
||||
program shutdown, which caused a compiler error on such platforms.
|
||||
We fix that by introducing a constant for in_shutdown in
|
||||
non-fast-path builds.
|
||||
We also drop the destructor priority, as it is not supported on
|
||||
all platforms and we no longer rely upon the priority anyway.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
* unwind-dw2-fde.c: Introduce a constant for in_shutdown
|
||||
for the non-fast-path case. Drop destructor priority.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
|
||||
index b0d07ccd53b30f4c..27fea89dc314ccd0 100644
|
||||
--- a/libgcc/unwind-dw2-fde.c
|
||||
+++ b/libgcc/unwind-dw2-fde.c
|
||||
@@ -51,7 +51,7 @@ static struct btree registered_frames;
|
||||
static bool in_shutdown;
|
||||
|
||||
static void
|
||||
-release_registered_frames (void) __attribute__ ((destructor (110)));
|
||||
+release_registered_frames (void) __attribute__ ((destructor));
|
||||
static void
|
||||
release_registered_frames (void)
|
||||
{
|
||||
@@ -67,6 +67,8 @@ static void
|
||||
init_object (struct object *ob);
|
||||
|
||||
#else
|
||||
+/* Without fast path frame deregistration must always succeed. */
|
||||
+static const int in_shutdown = 0;
|
||||
|
||||
/* The unseen_objects list contains objects that have been registered
|
||||
but not yet categorized in any way. The seen_objects list has had
|
||||
1811
gcc-RHEL-105072-12.patch
Normal file
1811
gcc-RHEL-105072-12.patch
Normal file
File diff suppressed because it is too large
Load Diff
48
gcc-RHEL-105072-13.patch
Normal file
48
gcc-RHEL-105072-13.patch
Normal file
@ -0,0 +1,48 @@
|
||||
commit acdb24166d13d87c374e578d2ad5d58249171930
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Oct 17 11:09:17 2022 +0200
|
||||
|
||||
libgcc: Move cfa_how into potential padding in struct frame_state_reg_info
|
||||
|
||||
On many architectures, there is a padding gap after the how array
|
||||
member, and cfa_how can be moved there. This reduces the size of the
|
||||
struct and the amount of memory that uw_frame_state_for has to clear.
|
||||
|
||||
There is no measurable performance benefit from this on x86-64 (even
|
||||
though the memset goes from 120 to 112 bytes), but it seems to be a
|
||||
good idea to do anyway.
|
||||
|
||||
libgcc/
|
||||
|
||||
* unwind-dw2.h (struct frame_state_reg_info): Move cfa_how member
|
||||
and reduce its size.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2.h b/libgcc/unwind-dw2.h
|
||||
index 22241b1f0d14cffc..437c785efa4f297d 100644
|
||||
--- a/libgcc/unwind-dw2.h
|
||||
+++ b/libgcc/unwind-dw2.h
|
||||
@@ -50,6 +50,12 @@ typedef struct
|
||||
} reg[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
|
||||
unsigned char how[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
|
||||
|
||||
+ enum {
|
||||
+ CFA_UNSET,
|
||||
+ CFA_REG_OFFSET,
|
||||
+ CFA_EXP
|
||||
+ } cfa_how : 8;
|
||||
+
|
||||
/* Used to implement DW_CFA_remember_state. */
|
||||
struct frame_state_reg_info *prev;
|
||||
|
||||
@@ -58,11 +64,6 @@ typedef struct
|
||||
_Unwind_Sword cfa_offset;
|
||||
_Unwind_Word cfa_reg;
|
||||
const unsigned char *cfa_exp;
|
||||
- enum {
|
||||
- CFA_UNSET,
|
||||
- CFA_REG_OFFSET,
|
||||
- CFA_EXP
|
||||
- } cfa_how;
|
||||
} regs;
|
||||
|
||||
/* The PC described by the current frame state. */
|
||||
99
gcc-RHEL-105072-14.patch
Normal file
99
gcc-RHEL-105072-14.patch
Normal file
@ -0,0 +1,99 @@
|
||||
commit e724b0480bfa5ec04f39be8c7290330b495c59de
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Nov 4 10:18:03 2022 +0100
|
||||
|
||||
libgcc: Special-case BFD ld unwind table encodings in find_fde_tail
|
||||
|
||||
BFD ld (and the other linkers) only produce one encoding of these
|
||||
values. It is not necessary to use the general
|
||||
read_encoded_value_with_base decoding routine. This avoids the
|
||||
data-dependent branches in its implementation.
|
||||
|
||||
libgcc/
|
||||
|
||||
* unwind-dw2-fde-dip.c (find_fde_tail): Special-case encoding
|
||||
values actually used by BFD ld.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
|
||||
index 25f2e44c5823cf64..d4821d7d19950f15 100644
|
||||
--- a/libgcc/unwind-dw2-fde-dip.c
|
||||
+++ b/libgcc/unwind-dw2-fde-dip.c
|
||||
@@ -396,10 +396,21 @@ find_fde_tail (_Unwind_Ptr pc,
|
||||
if (hdr->version != 1)
|
||||
return NULL;
|
||||
|
||||
- p = read_encoded_value_with_base (hdr->eh_frame_ptr_enc,
|
||||
- base_from_cb_data (hdr->eh_frame_ptr_enc,
|
||||
- dbase),
|
||||
- p, &eh_frame);
|
||||
+ if (__builtin_expect (hdr->eh_frame_ptr_enc == (DW_EH_PE_sdata4
|
||||
+ | DW_EH_PE_pcrel), 1))
|
||||
+ {
|
||||
+ /* Specialized version of read_encoded_value_with_base, based on what
|
||||
+ BFD ld generates. */
|
||||
+ signed value __attribute__ ((mode (SI)));
|
||||
+ memcpy (&value, p, sizeof (value));
|
||||
+ p += sizeof (value);
|
||||
+ dbase = value; /* No adjustment because pcrel has base 0. */
|
||||
+ }
|
||||
+ else
|
||||
+ p = read_encoded_value_with_base (hdr->eh_frame_ptr_enc,
|
||||
+ base_from_cb_data (hdr->eh_frame_ptr_enc,
|
||||
+ dbase),
|
||||
+ p, &eh_frame);
|
||||
|
||||
/* We require here specific table encoding to speed things up.
|
||||
Also, DW_EH_PE_datarel here means using PT_GNU_EH_FRAME start
|
||||
@@ -409,10 +420,20 @@ find_fde_tail (_Unwind_Ptr pc,
|
||||
{
|
||||
_Unwind_Ptr fde_count;
|
||||
|
||||
- p = read_encoded_value_with_base (hdr->fde_count_enc,
|
||||
- base_from_cb_data (hdr->fde_count_enc,
|
||||
- dbase),
|
||||
- p, &fde_count);
|
||||
+ if (__builtin_expect (hdr->fde_count_enc == DW_EH_PE_udata4, 1))
|
||||
+ {
|
||||
+ /* Specialized version of read_encoded_value_with_base, based on
|
||||
+ what BFD ld generates. */
|
||||
+ unsigned value __attribute__ ((mode (SI)));
|
||||
+ memcpy (&value, p, sizeof (value));
|
||||
+ p += sizeof (value);
|
||||
+ fde_count = value;
|
||||
+ }
|
||||
+ else
|
||||
+ p = read_encoded_value_with_base (hdr->fde_count_enc,
|
||||
+ base_from_cb_data (hdr->fde_count_enc,
|
||||
+ dbase),
|
||||
+ p, &fde_count);
|
||||
/* Shouldn't happen. */
|
||||
if (fde_count == 0)
|
||||
return NULL;
|
||||
@@ -454,8 +475,25 @@ find_fde_tail (_Unwind_Ptr pc,
|
||||
f = (fde *) (table[mid].fde + data_base);
|
||||
f_enc = get_fde_encoding (f);
|
||||
f_enc_size = size_of_encoded_value (f_enc);
|
||||
- read_encoded_value_with_base (f_enc & 0x0f, 0,
|
||||
- &f->pc_begin[f_enc_size], &range);
|
||||
+
|
||||
+ /* BFD ld uses DW_EH_PE_sdata4 | DW_EH_PE_pcrel on non-FDPIC targets,
|
||||
+ so optimize for that.
|
||||
+
|
||||
+ This optimization is not valid for FDPIC targets. f_enc & 0x0f as
|
||||
+ passed to read_encoded_value_with_base masks away the base flags,
|
||||
+ but they are implicit for FDPIC. */
|
||||
+#ifndef __FDPIC__
|
||||
+ if (__builtin_expect (f_enc == (DW_EH_PE_sdata4 | DW_EH_PE_pcrel),
|
||||
+ 1))
|
||||
+ {
|
||||
+ signed value __attribute__ ((mode (SI)));
|
||||
+ memcpy (&value, &f->pc_begin[f_enc_size], sizeof (value));
|
||||
+ range = value;
|
||||
+ }
|
||||
+ else
|
||||
+#endif
|
||||
+ read_encoded_value_with_base (f_enc & 0x0f, 0,
|
||||
+ &f->pc_begin[f_enc_size], &range);
|
||||
_Unwind_Ptr func = table[mid].initial_loc + data_base;
|
||||
if (pc < table[mid].initial_loc + data_base + range)
|
||||
{
|
||||
337
gcc-RHEL-105072-15.patch
Normal file
337
gcc-RHEL-105072-15.patch
Normal file
@ -0,0 +1,337 @@
|
||||
commit 1c118c9970600117700cc12284587e0238de6bbe
|
||||
Author: Thomas Neumann <tneumann@users.sourceforge.net>
|
||||
Date: Tue Nov 22 08:41:54 2022 +0100
|
||||
|
||||
speed up end_fde_sort using radix sort
|
||||
|
||||
When registering a dynamic unwinding frame the fde list is sorted.
|
||||
Previously, we split the list into a sorted and an unsorted part,
|
||||
sorted the later using heap sort, and merged both. That can be
|
||||
quite slow due to the large number of (expensive) comparisons.
|
||||
|
||||
This patch replaces that logic with a radix sort instead. The
|
||||
radix sort uses the same amount of memory as the old logic,
|
||||
using the second list as auxiliary space, and it includes two
|
||||
techniques to speed up sorting: First, it computes the pointer
|
||||
addresses for blocks of values, reducing the decoding overhead.
|
||||
And it recognizes when the data has reached a sorted state,
|
||||
allowing for early termination. When running out of memory
|
||||
we fall back to pure heap sort, as before.
|
||||
|
||||
For this test program
|
||||
|
||||
\#include <cstdio>
|
||||
int main(int argc, char** argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
compiled with g++ -O -o hello -static hello.c we get with
|
||||
perf stat -r 200 on a 5950X the following performance numbers:
|
||||
|
||||
old logic:
|
||||
|
||||
0,20 msec task-clock
|
||||
930.834 cycles
|
||||
3.079.765 instructions
|
||||
0,00030478 +- 0,00000237 seconds time elapsed
|
||||
|
||||
new logic:
|
||||
|
||||
0,10 msec task-clock
|
||||
473.269 cycles
|
||||
1.239.077 instructions
|
||||
0,00021119 +- 0,00000168 seconds time elapsed
|
||||
|
||||
libgcc/ChangeLog:
|
||||
* unwind-dw2-fde.c: Use radix sort instead of split+sort+merge.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
|
||||
index 27fea89dc314ccd0..a0d9bfb9f7d34ec1 100644
|
||||
--- a/libgcc/unwind-dw2-fde.c
|
||||
+++ b/libgcc/unwind-dw2-fde.c
|
||||
@@ -456,22 +456,52 @@ fde_mixed_encoding_compare (struct object *ob, const fde *x, const fde *y)
|
||||
|
||||
typedef int (*fde_compare_t) (struct object *, const fde *, const fde *);
|
||||
|
||||
+// The extractor functions compute the pointer values for a block of
|
||||
+// fdes. The block processing hides the call overhead.
|
||||
|
||||
-/* This is a special mix of insertion sort and heap sort, optimized for
|
||||
- the data sets that actually occur. They look like
|
||||
- 101 102 103 127 128 105 108 110 190 111 115 119 125 160 126 129 130.
|
||||
- I.e. a linearly increasing sequence (coming from functions in the text
|
||||
- section), with additionally a few unordered elements (coming from functions
|
||||
- in gnu_linkonce sections) whose values are higher than the values in the
|
||||
- surrounding linear sequence (but not necessarily higher than the values
|
||||
- at the end of the linear sequence!).
|
||||
- The worst-case total run time is O(N) + O(n log (n)), where N is the
|
||||
- total number of FDEs and n is the number of erratic ones. */
|
||||
+static void
|
||||
+fde_unencoded_extract (struct object *ob __attribute__ ((unused)),
|
||||
+ _Unwind_Ptr *target, const fde **x, int count)
|
||||
+{
|
||||
+ for (int index = 0; index < count; ++index)
|
||||
+ memcpy (target + index, x[index]->pc_begin, sizeof (_Unwind_Ptr));
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+fde_single_encoding_extract (struct object *ob, _Unwind_Ptr *target,
|
||||
+ const fde **x, int count)
|
||||
+{
|
||||
+ _Unwind_Ptr base;
|
||||
+
|
||||
+ base = base_from_object (ob->s.b.encoding, ob);
|
||||
+ for (int index = 0; index < count; ++index)
|
||||
+ read_encoded_value_with_base (ob->s.b.encoding, base, x[index]->pc_begin,
|
||||
+ target + index);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+fde_mixed_encoding_extract (struct object *ob, _Unwind_Ptr *target,
|
||||
+ const fde **x, int count)
|
||||
+{
|
||||
+ for (int index = 0; index < count; ++index)
|
||||
+ {
|
||||
+ int encoding = get_fde_encoding (x[index]);
|
||||
+ read_encoded_value_with_base (encoding, base_from_object (encoding, ob),
|
||||
+ x[index]->pc_begin, target + index);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+typedef void (*fde_extractor_t) (struct object *, _Unwind_Ptr *, const fde **,
|
||||
+ int);
|
||||
+
|
||||
+// Data is is sorted using radix sort if possible, using an temporary
|
||||
+// auxiliary data structure of the same size as the input. When running
|
||||
+// out of memory do in-place heap sort.
|
||||
|
||||
struct fde_accumulator
|
||||
{
|
||||
struct fde_vector *linear;
|
||||
- struct fde_vector *erratic;
|
||||
+ struct fde_vector *aux;
|
||||
};
|
||||
|
||||
static inline int
|
||||
@@ -485,8 +515,8 @@ start_fde_sort (struct fde_accumulator *accu, size_t count)
|
||||
if ((accu->linear = malloc (size)))
|
||||
{
|
||||
accu->linear->count = 0;
|
||||
- if ((accu->erratic = malloc (size)))
|
||||
- accu->erratic->count = 0;
|
||||
+ if ((accu->aux = malloc (size)))
|
||||
+ accu->aux->count = 0;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
@@ -500,59 +530,6 @@ fde_insert (struct fde_accumulator *accu, const fde *this_fde)
|
||||
accu->linear->array[accu->linear->count++] = this_fde;
|
||||
}
|
||||
|
||||
-/* Split LINEAR into a linear sequence with low values and an erratic
|
||||
- sequence with high values, put the linear one (of longest possible
|
||||
- length) into LINEAR and the erratic one into ERRATIC. This is O(N).
|
||||
-
|
||||
- Because the longest linear sequence we are trying to locate within the
|
||||
- incoming LINEAR array can be interspersed with (high valued) erratic
|
||||
- entries. We construct a chain indicating the sequenced entries.
|
||||
- To avoid having to allocate this chain, we overlay it onto the space of
|
||||
- the ERRATIC array during construction. A final pass iterates over the
|
||||
- chain to determine what should be placed in the ERRATIC array, and
|
||||
- what is the linear sequence. This overlay is safe from aliasing. */
|
||||
-
|
||||
-static inline void
|
||||
-fde_split (struct object *ob, fde_compare_t fde_compare,
|
||||
- struct fde_vector *linear, struct fde_vector *erratic)
|
||||
-{
|
||||
- static const fde *marker;
|
||||
- size_t count = linear->count;
|
||||
- const fde *const *chain_end = ▮
|
||||
- size_t i, j, k;
|
||||
-
|
||||
- /* This should optimize out, but it is wise to make sure this assumption
|
||||
- is correct. Should these have different sizes, we cannot cast between
|
||||
- them and the overlaying onto ERRATIC will not work. */
|
||||
- gcc_assert (sizeof (const fde *) == sizeof (const fde **));
|
||||
-
|
||||
- for (i = 0; i < count; i++)
|
||||
- {
|
||||
- const fde *const *probe;
|
||||
-
|
||||
- for (probe = chain_end;
|
||||
- probe != &marker && fde_compare (ob, linear->array[i], *probe) < 0;
|
||||
- probe = chain_end)
|
||||
- {
|
||||
- chain_end = (const fde *const*) erratic->array[probe - linear->array];
|
||||
- erratic->array[probe - linear->array] = NULL;
|
||||
- }
|
||||
- erratic->array[i] = (const fde *) chain_end;
|
||||
- chain_end = &linear->array[i];
|
||||
- }
|
||||
-
|
||||
- /* Each entry in LINEAR which is part of the linear sequence we have
|
||||
- discovered will correspond to a non-NULL entry in the chain we built in
|
||||
- the ERRATIC array. */
|
||||
- for (i = j = k = 0; i < count; i++)
|
||||
- if (erratic->array[i])
|
||||
- linear->array[j++] = linear->array[i];
|
||||
- else
|
||||
- erratic->array[k++] = linear->array[i];
|
||||
- linear->count = j;
|
||||
- erratic->count = k;
|
||||
-}
|
||||
-
|
||||
#define SWAP(x,y) do { const fde * tmp = x; x = y; y = tmp; } while (0)
|
||||
|
||||
/* Convert a semi-heap to a heap. A semi-heap is a heap except possibly
|
||||
@@ -615,59 +592,116 @@ frame_heapsort (struct object *ob, fde_compare_t fde_compare,
|
||||
#undef SWAP
|
||||
}
|
||||
|
||||
-/* Merge V1 and V2, both sorted, and put the result into V1. */
|
||||
+// Radix sort data in V1 using V2 as aux memory. Runtime O(n).
|
||||
static inline void
|
||||
-fde_merge (struct object *ob, fde_compare_t fde_compare,
|
||||
- struct fde_vector *v1, struct fde_vector *v2)
|
||||
+fde_radixsort (struct object *ob, fde_extractor_t fde_extractor,
|
||||
+ struct fde_vector *v1, struct fde_vector *v2)
|
||||
{
|
||||
- size_t i1, i2;
|
||||
- const fde * fde2;
|
||||
-
|
||||
- i2 = v2->count;
|
||||
- if (i2 > 0)
|
||||
+#define FANOUTBITS 8
|
||||
+#define FANOUT (1 << FANOUTBITS)
|
||||
+#define BLOCKSIZE 128
|
||||
+ const unsigned rounds
|
||||
+ = (__CHAR_BIT__ * sizeof (_Unwind_Ptr) + FANOUTBITS - 1) / FANOUTBITS;
|
||||
+ const fde **a1 = v1->array, **a2 = v2->array;
|
||||
+ _Unwind_Ptr ptrs[BLOCKSIZE + 1];
|
||||
+ unsigned n = v1->count;
|
||||
+ for (unsigned round = 0; round != rounds; ++round)
|
||||
{
|
||||
- i1 = v1->count;
|
||||
- do
|
||||
+ unsigned counts[FANOUT] = {0};
|
||||
+ unsigned violations = 0;
|
||||
+
|
||||
+ // Count the number of elements per bucket and check if we are already
|
||||
+ // sorted.
|
||||
+ _Unwind_Ptr last = 0;
|
||||
+ for (unsigned i = 0; i < n;)
|
||||
+ {
|
||||
+ unsigned chunk = ((n - i) <= BLOCKSIZE) ? (n - i) : BLOCKSIZE;
|
||||
+ fde_extractor (ob, ptrs + 1, a1 + i, chunk);
|
||||
+ ptrs[0] = last;
|
||||
+ for (unsigned j = 0; j < chunk; ++j)
|
||||
+ {
|
||||
+ unsigned b = (ptrs[j + 1] >> (round * FANOUTBITS)) & (FANOUT - 1);
|
||||
+ counts[b]++;
|
||||
+ // Use summation instead of an if to eliminate branches.
|
||||
+ violations += ptrs[j + 1] < ptrs[j];
|
||||
+ }
|
||||
+ i += chunk;
|
||||
+ last = ptrs[chunk];
|
||||
+ }
|
||||
+
|
||||
+ // Stop if we are already sorted.
|
||||
+ if (!violations)
|
||||
+ {
|
||||
+ // The sorted data is in a1 now.
|
||||
+ a2 = a1;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ // Compute the prefix sum.
|
||||
+ unsigned sum = 0;
|
||||
+ for (unsigned i = 0; i != FANOUT; ++i)
|
||||
+ {
|
||||
+ unsigned s = sum;
|
||||
+ sum += counts[i];
|
||||
+ counts[i] = s;
|
||||
+ }
|
||||
+
|
||||
+ // Place all elements.
|
||||
+ for (unsigned i = 0; i < n;)
|
||||
{
|
||||
- i2--;
|
||||
- fde2 = v2->array[i2];
|
||||
- while (i1 > 0 && fde_compare (ob, v1->array[i1-1], fde2) > 0)
|
||||
+ unsigned chunk = ((n - i) <= BLOCKSIZE) ? (n - i) : BLOCKSIZE;
|
||||
+ fde_extractor (ob, ptrs, a1 + i, chunk);
|
||||
+ for (unsigned j = 0; j < chunk; ++j)
|
||||
{
|
||||
- v1->array[i1+i2] = v1->array[i1-1];
|
||||
- i1--;
|
||||
+ unsigned b = (ptrs[j] >> (round * FANOUTBITS)) & (FANOUT - 1);
|
||||
+ a2[counts[b]++] = a1[i + j];
|
||||
}
|
||||
- v1->array[i1+i2] = fde2;
|
||||
+ i += chunk;
|
||||
}
|
||||
- while (i2 > 0);
|
||||
- v1->count += v2->count;
|
||||
+
|
||||
+ // Swap a1 and a2.
|
||||
+ const fde **tmp = a1;
|
||||
+ a1 = a2;
|
||||
+ a2 = tmp;
|
||||
}
|
||||
+#undef BLOCKSIZE
|
||||
+#undef FANOUT
|
||||
+#undef FANOUTBITS
|
||||
+
|
||||
+ // The data is in a2 now, move in place if needed.
|
||||
+ if (a2 != v1->array)
|
||||
+ memcpy (v1->array, a2, sizeof (const fde *) * n);
|
||||
}
|
||||
|
||||
static inline void
|
||||
end_fde_sort (struct object *ob, struct fde_accumulator *accu, size_t count)
|
||||
{
|
||||
- fde_compare_t fde_compare;
|
||||
-
|
||||
gcc_assert (!accu->linear || accu->linear->count == count);
|
||||
|
||||
- if (ob->s.b.mixed_encoding)
|
||||
- fde_compare = fde_mixed_encoding_compare;
|
||||
- else if (ob->s.b.encoding == DW_EH_PE_absptr)
|
||||
- fde_compare = fde_unencoded_compare;
|
||||
- else
|
||||
- fde_compare = fde_single_encoding_compare;
|
||||
-
|
||||
- if (accu->erratic)
|
||||
+ if (accu->aux)
|
||||
{
|
||||
- fde_split (ob, fde_compare, accu->linear, accu->erratic);
|
||||
- gcc_assert (accu->linear->count + accu->erratic->count == count);
|
||||
- frame_heapsort (ob, fde_compare, accu->erratic);
|
||||
- fde_merge (ob, fde_compare, accu->linear, accu->erratic);
|
||||
- free (accu->erratic);
|
||||
+ fde_extractor_t fde_extractor;
|
||||
+ if (ob->s.b.mixed_encoding)
|
||||
+ fde_extractor = fde_mixed_encoding_extract;
|
||||
+ else if (ob->s.b.encoding == DW_EH_PE_absptr)
|
||||
+ fde_extractor = fde_unencoded_extract;
|
||||
+ else
|
||||
+ fde_extractor = fde_single_encoding_extract;
|
||||
+
|
||||
+ fde_radixsort (ob, fde_extractor, accu->linear, accu->aux);
|
||||
+ free (accu->aux);
|
||||
}
|
||||
else
|
||||
{
|
||||
- /* We've not managed to malloc an erratic array,
|
||||
+ fde_compare_t fde_compare;
|
||||
+ if (ob->s.b.mixed_encoding)
|
||||
+ fde_compare = fde_mixed_encoding_compare;
|
||||
+ else if (ob->s.b.encoding == DW_EH_PE_absptr)
|
||||
+ fde_compare = fde_unencoded_compare;
|
||||
+ else
|
||||
+ fde_compare = fde_single_encoding_compare;
|
||||
+
|
||||
+ /* We've not managed to malloc an aux array,
|
||||
so heap sort in the linear one. */
|
||||
frame_heapsort (ob, fde_compare, accu->linear);
|
||||
}
|
||||
143
gcc-RHEL-105072-16.patch
Normal file
143
gcc-RHEL-105072-16.patch
Normal file
@ -0,0 +1,143 @@
|
||||
commit 6e56633daae79f514b0e71f4d9849bcd8d9ce71f
|
||||
Author: Thomas Neumann <tneumann@users.sourceforge.net>
|
||||
Date: Fri Dec 9 18:23:44 2022 +0100
|
||||
|
||||
initialize fde objects lazily
|
||||
|
||||
When registering an unwind frame with __register_frame_info_bases
|
||||
we currently initialize that fde object eagerly. This has the
|
||||
advantage that it is immutable afterwards and we can safely
|
||||
access it from multiple threads, but it has the disadvantage
|
||||
that we pay the initialization cost even if the application
|
||||
never throws an exception.
|
||||
|
||||
This commit changes the logic to initialize the objects lazily.
|
||||
The objects themselves are inserted into the b-tree when
|
||||
registering the frame, but the sorted fde_vector is
|
||||
not constructed yet. Only on the first time that an
|
||||
exception tries to pass through the registered code the
|
||||
object is initialized. We notice that with a double checking,
|
||||
first doing a relaxed load of the sorted bit and then re-checking
|
||||
under a mutex when the object was not initialized yet.
|
||||
|
||||
Note that the check must implicitly be safe concering a concurrent
|
||||
frame deregistration, as trying the deregister a frame that is
|
||||
on the unwinding path of a concurrent exception is inherently racy.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
* unwind-dw2-fde.c: Initialize fde object lazily when
|
||||
the first exception tries to pass through.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
|
||||
index a0d9bfb9f7d34ec1..efcf9490469ad1a0 100644
|
||||
--- a/libgcc/unwind-dw2-fde.c
|
||||
+++ b/libgcc/unwind-dw2-fde.c
|
||||
@@ -63,8 +63,6 @@ release_registered_frames (void)
|
||||
|
||||
static void
|
||||
get_pc_range (const struct object *ob, uintptr_type *range);
|
||||
-static void
|
||||
-init_object (struct object *ob);
|
||||
|
||||
#else
|
||||
/* Without fast path frame deregistration must always succeed. */
|
||||
@@ -76,6 +74,7 @@ static const int in_shutdown = 0;
|
||||
by decreasing value of pc_begin. */
|
||||
static struct object *unseen_objects;
|
||||
static struct object *seen_objects;
|
||||
+#endif
|
||||
|
||||
#ifdef __GTHREAD_MUTEX_INIT
|
||||
static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
|
||||
@@ -103,7 +102,6 @@ init_object_mutex_once (void)
|
||||
static __gthread_mutex_t object_mutex;
|
||||
#endif
|
||||
#endif
|
||||
-#endif
|
||||
|
||||
/* Called from crtbegin.o to register the unwind info for an object. */
|
||||
|
||||
@@ -126,10 +124,7 @@ __register_frame_info_bases (const void *begin, struct object *ob,
|
||||
#endif
|
||||
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
- // Initialize eagerly to avoid locking later
|
||||
- init_object (ob);
|
||||
-
|
||||
- // And register the frame
|
||||
+ // Register the frame in the b-tree
|
||||
uintptr_type range[2];
|
||||
get_pc_range (ob, range);
|
||||
btree_insert (®istered_frames, range[0], range[1] - range[0], ob);
|
||||
@@ -180,10 +175,7 @@ __register_frame_info_table_bases (void *begin, struct object *ob,
|
||||
ob->s.b.encoding = DW_EH_PE_omit;
|
||||
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
- // Initialize eagerly to avoid locking later
|
||||
- init_object (ob);
|
||||
-
|
||||
- // And register the frame
|
||||
+ // Register the frame in the b-tree
|
||||
uintptr_type range[2];
|
||||
get_pc_range (ob, range);
|
||||
btree_insert (®istered_frames, range[0], range[1] - range[0], ob);
|
||||
@@ -926,7 +918,15 @@ init_object (struct object* ob)
|
||||
accu.linear->orig_data = ob->u.single;
|
||||
ob->u.sort = accu.linear;
|
||||
|
||||
+#ifdef ATOMIC_FDE_FAST_PATH
|
||||
+ // We must update the sorted bit with an atomic operation
|
||||
+ struct object tmp;
|
||||
+ tmp.s.b = ob->s.b;
|
||||
+ tmp.s.b.sorted = 1;
|
||||
+ __atomic_store (&(ob->s.b), &(tmp.s.b), __ATOMIC_RELEASE);
|
||||
+#else
|
||||
ob->s.b.sorted = 1;
|
||||
+#endif
|
||||
}
|
||||
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
@@ -1164,6 +1164,21 @@ search_object (struct object* ob, void *pc)
|
||||
}
|
||||
}
|
||||
|
||||
+#ifdef ATOMIC_FDE_FAST_PATH
|
||||
+
|
||||
+// Check if the object was already initialized
|
||||
+static inline bool
|
||||
+is_object_initialized (struct object *ob)
|
||||
+{
|
||||
+ // We have to use acquire atomics for the read, which
|
||||
+ // is a bit involved as we read from a bitfield
|
||||
+ struct object tmp;
|
||||
+ __atomic_load (&(ob->s.b), &(tmp.s.b), __ATOMIC_ACQUIRE);
|
||||
+ return tmp.s.b.sorted;
|
||||
+}
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
const fde *
|
||||
_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
|
||||
{
|
||||
@@ -1175,6 +1190,21 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
|
||||
if (!ob)
|
||||
return NULL;
|
||||
|
||||
+ // Initialize the object lazily
|
||||
+ if (!is_object_initialized (ob))
|
||||
+ {
|
||||
+ // Check again under mutex
|
||||
+ init_object_mutex_once ();
|
||||
+ __gthread_mutex_lock (&object_mutex);
|
||||
+
|
||||
+ if (!ob->s.b.sorted)
|
||||
+ {
|
||||
+ init_object (ob);
|
||||
+ }
|
||||
+
|
||||
+ __gthread_mutex_unlock (&object_mutex);
|
||||
+ }
|
||||
+
|
||||
f = search_object (ob, pc);
|
||||
#else
|
||||
|
||||
703
gcc-RHEL-105072-17.patch
Normal file
703
gcc-RHEL-105072-17.patch
Normal file
@ -0,0 +1,703 @@
|
||||
commit 8fdef16cd5d1b89359db3cd9a9768ab2d1b5081f
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Jan 3 16:47:32 2023 +0100
|
||||
|
||||
libgcc: Specialize execute_cfa_program in DWARF unwinder for alignments [redo]
|
||||
|
||||
The parameters fs->data_align and fs->code_align always have fixed
|
||||
values for a particular target in GCC-generated code. Specialize
|
||||
execute_cfa_program for these values, to avoid multiplications.
|
||||
|
||||
gcc/c-family/
|
||||
|
||||
* c-cppbuiltin.cc (c_cpp_builtins): Define
|
||||
__LIBGCC_DWARF_CIE_DATA_ALIGNMENT__.
|
||||
|
||||
libgcc/
|
||||
|
||||
* unwind-dw2-execute_cfa.h: New file. Extracted from
|
||||
the execute_cfa_program function in unwind-dw2.c.
|
||||
* unwind-dw2.c (execute_cfa_program_generic): New function.
|
||||
(execute_cfa_program_specialized): Likewise.
|
||||
(execute_cfa_program): Call execute_cfa_program_specialized
|
||||
or execute_cfa_program_generic, as appropriate.
|
||||
|
||||
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
|
||||
index 11e015bdb87b0f9b..a5369eb51b07f0ab 100644
|
||||
--- a/gcc/c-family/c-cppbuiltin.c
|
||||
+++ b/gcc/c-family/c-cppbuiltin.c
|
||||
@@ -1408,6 +1408,9 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||
#endif
|
||||
builtin_define_with_int_value ("__LIBGCC_DWARF_FRAME_REGISTERS__",
|
||||
DWARF_FRAME_REGISTERS);
|
||||
+ builtin_define_with_int_value ("__LIBGCC_DWARF_CIE_DATA_ALIGNMENT__",
|
||||
+ DWARF_CIE_DATA_ALIGNMENT);
|
||||
+
|
||||
#ifdef EH_RETURN_STACKADJ_RTX
|
||||
cpp_define (pfile, "__LIBGCC_EH_RETURN_STACKADJ_RTX__");
|
||||
#endif
|
||||
diff --git a/libgcc/unwind-dw2-execute_cfa.h b/libgcc/unwind-dw2-execute_cfa.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..dd97b7866686a361
|
||||
--- /dev/null
|
||||
+++ b/libgcc/unwind-dw2-execute_cfa.h
|
||||
@@ -0,0 +1,322 @@
|
||||
+/* DWARF2 exception handling CFA execution engine.
|
||||
+ Copyright (C) 1997-2022 Free Software Foundation, Inc.
|
||||
+
|
||||
+ This file is part of GCC.
|
||||
+
|
||||
+ GCC is free software; you can redistribute it and/or modify it
|
||||
+ under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 3, or (at your option)
|
||||
+ any later version.
|
||||
+
|
||||
+ GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
+ License for more details.
|
||||
+
|
||||
+ 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
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* This file is included from unwind-dw2.c to specialize the code for certain
|
||||
+ values of DATA_ALIGN and CODE_ALIGN. These macros must be defined prior to
|
||||
+ including this file. */
|
||||
+
|
||||
+{
|
||||
+ struct frame_state_reg_info *unused_rs = NULL;
|
||||
+
|
||||
+ /* Don't allow remember/restore between CIE and FDE programs. */
|
||||
+ fs->regs.prev = NULL;
|
||||
+
|
||||
+ /* The comparison with the return address uses < rather than <= because
|
||||
+ we are only interested in the effects of code before the call; for a
|
||||
+ noreturn function, the return address may point to unrelated code with
|
||||
+ a different stack configuration that we are not interested in. We
|
||||
+ assume that the call itself is unwind info-neutral; if not, or if
|
||||
+ there are delay instructions that adjust the stack, these must be
|
||||
+ reflected at the point immediately before the call insn.
|
||||
+ In signal frames, return address is after last completed instruction,
|
||||
+ so we add 1 to return address to make the comparison <=. */
|
||||
+ while (insn_ptr < insn_end
|
||||
+ && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
|
||||
+ {
|
||||
+ unsigned char insn = *insn_ptr++;
|
||||
+ _uleb128_t reg, utmp;
|
||||
+ _sleb128_t offset, stmp;
|
||||
+
|
||||
+ if ((insn & 0xc0) == DW_CFA_advance_loc)
|
||||
+ fs->pc += (insn & 0x3f) * CODE_ALIGN;
|
||||
+ else if ((insn & 0xc0) == DW_CFA_offset)
|
||||
+ {
|
||||
+ reg = insn & 0x3f;
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ offset = (_Unwind_Sword) utmp * DATA_ALIGN;
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ {
|
||||
+ fs->regs.how[reg] = REG_SAVED_OFFSET;
|
||||
+ fs->regs.reg[reg].loc.offset = offset;
|
||||
+ }
|
||||
+ }
|
||||
+ else if ((insn & 0xc0) == DW_CFA_restore)
|
||||
+ {
|
||||
+ reg = insn & 0x3f;
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ fs->regs.how[reg] = REG_UNSAVED;
|
||||
+ }
|
||||
+ else switch (insn)
|
||||
+ {
|
||||
+ case DW_CFA_set_loc:
|
||||
+ {
|
||||
+ _Unwind_Ptr pc;
|
||||
+
|
||||
+ insn_ptr = read_encoded_value (context, fs->fde_encoding,
|
||||
+ insn_ptr, &pc);
|
||||
+ fs->pc = (void *) pc;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_advance_loc1:
|
||||
+ fs->pc += read_1u (insn_ptr) * CODE_ALIGN;
|
||||
+ insn_ptr += 1;
|
||||
+ break;
|
||||
+ case DW_CFA_advance_loc2:
|
||||
+ fs->pc += read_2u (insn_ptr) * CODE_ALIGN;
|
||||
+ insn_ptr += 2;
|
||||
+ break;
|
||||
+ case DW_CFA_advance_loc4:
|
||||
+ fs->pc += read_4u (insn_ptr) * CODE_ALIGN;
|
||||
+ insn_ptr += 4;
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_offset_extended:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ offset = (_Unwind_Sword) utmp * DATA_ALIGN;
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ {
|
||||
+ fs->regs.how[reg] = REG_SAVED_OFFSET;
|
||||
+ fs->regs.reg[reg].loc.offset = offset;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_restore_extended:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
+ /* FIXME, this is wrong; the CIE might have said that the
|
||||
+ register was saved somewhere. */
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ fs->regs.how[reg] = REG_UNSAVED;
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_same_value:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ fs->regs.how[reg] = REG_UNSAVED;
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_undefined:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ fs->regs.how[reg] = REG_UNDEFINED;
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_nop:
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_register:
|
||||
+ {
|
||||
+ _uleb128_t reg2;
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®2);
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ {
|
||||
+ fs->regs.how[reg] = REG_SAVED_REG;
|
||||
+ fs->regs.reg[reg].loc.reg = (_Unwind_Word)reg2;
|
||||
+ }
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_remember_state:
|
||||
+ {
|
||||
+ struct frame_state_reg_info *new_rs;
|
||||
+ if (unused_rs)
|
||||
+ {
|
||||
+ new_rs = unused_rs;
|
||||
+ unused_rs = unused_rs->prev;
|
||||
+ }
|
||||
+ else
|
||||
+ new_rs = alloca (sizeof (struct frame_state_reg_info));
|
||||
+
|
||||
+ *new_rs = fs->regs;
|
||||
+ fs->regs.prev = new_rs;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_restore_state:
|
||||
+ {
|
||||
+ struct frame_state_reg_info *old_rs = fs->regs.prev;
|
||||
+ fs->regs = *old_rs;
|
||||
+ old_rs->prev = unused_rs;
|
||||
+ unused_rs = old_rs;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_def_cfa:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ fs->regs.cfa_reg = (_Unwind_Word)utmp;
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ fs->regs.cfa_offset = (_Unwind_Word)utmp;
|
||||
+ fs->regs.cfa_how = CFA_REG_OFFSET;
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_def_cfa_register:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ fs->regs.cfa_reg = (_Unwind_Word)utmp;
|
||||
+ fs->regs.cfa_how = CFA_REG_OFFSET;
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_def_cfa_offset:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ fs->regs.cfa_offset = utmp;
|
||||
+ /* cfa_how deliberately not set. */
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_def_cfa_expression:
|
||||
+ fs->regs.cfa_exp = insn_ptr;
|
||||
+ fs->regs.cfa_how = CFA_EXP;
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ insn_ptr += utmp;
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_expression:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ {
|
||||
+ fs->regs.how[reg] = REG_SAVED_EXP;
|
||||
+ fs->regs.reg[reg].loc.exp = insn_ptr;
|
||||
+ }
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ insn_ptr += utmp;
|
||||
+ break;
|
||||
+
|
||||
+ /* Dwarf3. */
|
||||
+ case DW_CFA_offset_extended_sf:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
+ insn_ptr = read_sleb128 (insn_ptr, &stmp);
|
||||
+ offset = stmp * DATA_ALIGN;
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ {
|
||||
+ fs->regs.how[reg] = REG_SAVED_OFFSET;
|
||||
+ fs->regs.reg[reg].loc.offset = offset;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_def_cfa_sf:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ fs->regs.cfa_reg = (_Unwind_Word)utmp;
|
||||
+ insn_ptr = read_sleb128 (insn_ptr, &stmp);
|
||||
+ fs->regs.cfa_offset = (_Unwind_Sword)stmp;
|
||||
+ fs->regs.cfa_how = CFA_REG_OFFSET;
|
||||
+ fs->regs.cfa_offset *= DATA_ALIGN;
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_def_cfa_offset_sf:
|
||||
+ insn_ptr = read_sleb128 (insn_ptr, &stmp);
|
||||
+ fs->regs.cfa_offset = (_Unwind_Sword)stmp;
|
||||
+ fs->regs.cfa_offset *= DATA_ALIGN;
|
||||
+ /* cfa_how deliberately not set. */
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_val_offset:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ offset = (_Unwind_Sword) utmp * DATA_ALIGN;
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ {
|
||||
+ fs->regs.how[reg] = REG_SAVED_VAL_OFFSET;
|
||||
+ fs->regs.reg[reg].loc.offset = offset;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_val_offset_sf:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
+ insn_ptr = read_sleb128 (insn_ptr, &stmp);
|
||||
+ offset = stmp * DATA_ALIGN;
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ {
|
||||
+ fs->regs.how[reg] = REG_SAVED_VAL_OFFSET;
|
||||
+ fs->regs.reg[reg].loc.offset = offset;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_val_expression:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ {
|
||||
+ fs->regs.how[reg] = REG_SAVED_VAL_EXP;
|
||||
+ fs->regs.reg[reg].loc.exp = insn_ptr;
|
||||
+ }
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ insn_ptr += utmp;
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_GNU_window_save:
|
||||
+#if defined (__aarch64__) && !defined (__ILP32__)
|
||||
+ /* This CFA is multiplexed with Sparc. On AArch64 it's used to toggle
|
||||
+ return address signing status. */
|
||||
+ reg = DWARF_REGNUM_AARCH64_RA_STATE;
|
||||
+ gcc_assert (fs->regs.how[reg] == REG_UNSAVED);
|
||||
+ fs->regs.reg[reg].loc.offset ^= 1;
|
||||
+#else
|
||||
+ /* ??? Hardcoded for SPARC register window configuration. */
|
||||
+ if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
|
||||
+ for (reg = 16; reg < 32; ++reg)
|
||||
+ {
|
||||
+ fs->regs.how[reg] = REG_SAVED_OFFSET;
|
||||
+ fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
|
||||
+ }
|
||||
+#endif
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_GNU_args_size:
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ context->args_size = (_Unwind_Word)utmp;
|
||||
+ break;
|
||||
+
|
||||
+ case DW_CFA_GNU_negative_offset_extended:
|
||||
+ /* Obsoleted by DW_CFA_offset_extended_sf, but used by
|
||||
+ older PowerPC code. */
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
+ offset = (_Unwind_Word) utmp * DATA_ALIGN;
|
||||
+ reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
+ if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
+ {
|
||||
+ fs->regs.how[reg] = REG_SAVED_OFFSET;
|
||||
+ fs->regs.reg[reg].loc.offset = -offset;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ gcc_unreachable ();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#undef DATA_ALIGN
|
||||
+#undef CODE_ALIGN
|
||||
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
|
||||
index daebcb8bf7d215fe..701552634c6e87c5 100644
|
||||
--- a/libgcc/unwind-dw2.c
|
||||
+++ b/libgcc/unwind-dw2.c
|
||||
@@ -947,302 +947,43 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
|
||||
instruction sequence to decode, current register information and
|
||||
CIE info, and the PC range to evaluate. */
|
||||
|
||||
+static void __attribute__ ((__noinline__))
|
||||
+execute_cfa_program_generic (const unsigned char *insn_ptr,
|
||||
+ const unsigned char *insn_end,
|
||||
+ struct _Unwind_Context *context,
|
||||
+ _Unwind_FrameState *fs)
|
||||
+{
|
||||
+#define DATA_ALIGN fs->data_align
|
||||
+#define CODE_ALIGN fs->code_align
|
||||
+#include "unwind-dw2-execute_cfa.h"
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+execute_cfa_program_specialized (const unsigned char *insn_ptr,
|
||||
+ const unsigned char *insn_end,
|
||||
+ struct _Unwind_Context *context,
|
||||
+ _Unwind_FrameState *fs)
|
||||
+{
|
||||
+#define DATA_ALIGN __LIBGCC_DWARF_CIE_DATA_ALIGNMENT__
|
||||
+ /* GCC always uses 1 even on architectures with a fixed instruction
|
||||
+ width. */
|
||||
+#define CODE_ALIGN 1
|
||||
+#include "unwind-dw2-execute_cfa.h"
|
||||
+}
|
||||
+
|
||||
static void
|
||||
execute_cfa_program (const unsigned char *insn_ptr,
|
||||
const unsigned char *insn_end,
|
||||
struct _Unwind_Context *context,
|
||||
_Unwind_FrameState *fs)
|
||||
{
|
||||
- struct frame_state_reg_info *unused_rs = NULL;
|
||||
-
|
||||
- /* Don't allow remember/restore between CIE and FDE programs. */
|
||||
- fs->regs.prev = NULL;
|
||||
-
|
||||
- /* The comparison with the return address uses < rather than <= because
|
||||
- we are only interested in the effects of code before the call; for a
|
||||
- noreturn function, the return address may point to unrelated code with
|
||||
- a different stack configuration that we are not interested in. We
|
||||
- assume that the call itself is unwind info-neutral; if not, or if
|
||||
- there are delay instructions that adjust the stack, these must be
|
||||
- reflected at the point immediately before the call insn.
|
||||
- In signal frames, return address is after last completed instruction,
|
||||
- so we add 1 to return address to make the comparison <=. */
|
||||
- while (insn_ptr < insn_end
|
||||
- && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
|
||||
- {
|
||||
- unsigned char insn = *insn_ptr++;
|
||||
- _uleb128_t reg, utmp;
|
||||
- _sleb128_t offset, stmp;
|
||||
-
|
||||
- if ((insn & 0xc0) == DW_CFA_advance_loc)
|
||||
- fs->pc += (insn & 0x3f) * fs->code_align;
|
||||
- else if ((insn & 0xc0) == DW_CFA_offset)
|
||||
- {
|
||||
- reg = insn & 0x3f;
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- offset = (_Unwind_Sword) utmp * fs->data_align;
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- {
|
||||
- fs->regs.how[reg] = REG_SAVED_OFFSET;
|
||||
- fs->regs.reg[reg].loc.offset = offset;
|
||||
- }
|
||||
- }
|
||||
- else if ((insn & 0xc0) == DW_CFA_restore)
|
||||
- {
|
||||
- reg = insn & 0x3f;
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- fs->regs.how[reg] = REG_UNSAVED;
|
||||
- }
|
||||
- else switch (insn)
|
||||
- {
|
||||
- case DW_CFA_set_loc:
|
||||
- {
|
||||
- _Unwind_Ptr pc;
|
||||
-
|
||||
- insn_ptr = read_encoded_value (context, fs->fde_encoding,
|
||||
- insn_ptr, &pc);
|
||||
- fs->pc = (void *) pc;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_advance_loc1:
|
||||
- fs->pc += read_1u (insn_ptr) * fs->code_align;
|
||||
- insn_ptr += 1;
|
||||
- break;
|
||||
- case DW_CFA_advance_loc2:
|
||||
- fs->pc += read_2u (insn_ptr) * fs->code_align;
|
||||
- insn_ptr += 2;
|
||||
- break;
|
||||
- case DW_CFA_advance_loc4:
|
||||
- fs->pc += read_4u (insn_ptr) * fs->code_align;
|
||||
- insn_ptr += 4;
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_offset_extended:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- offset = (_Unwind_Sword) utmp * fs->data_align;
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- {
|
||||
- fs->regs.how[reg] = REG_SAVED_OFFSET;
|
||||
- fs->regs.reg[reg].loc.offset = offset;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_restore_extended:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
- /* FIXME, this is wrong; the CIE might have said that the
|
||||
- register was saved somewhere. */
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- fs->regs.how[reg] = REG_UNSAVED;
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_same_value:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- fs->regs.how[reg] = REG_UNSAVED;
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_undefined:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- fs->regs.how[reg] = REG_UNDEFINED;
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_nop:
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_register:
|
||||
- {
|
||||
- _uleb128_t reg2;
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®2);
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- {
|
||||
- fs->regs.how[reg] = REG_SAVED_REG;
|
||||
- fs->regs.reg[reg].loc.reg = (_Unwind_Word)reg2;
|
||||
- }
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_remember_state:
|
||||
- {
|
||||
- struct frame_state_reg_info *new_rs;
|
||||
- if (unused_rs)
|
||||
- {
|
||||
- new_rs = unused_rs;
|
||||
- unused_rs = unused_rs->prev;
|
||||
- }
|
||||
- else
|
||||
- new_rs = alloca (sizeof (struct frame_state_reg_info));
|
||||
-
|
||||
- *new_rs = fs->regs;
|
||||
- fs->regs.prev = new_rs;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_restore_state:
|
||||
- {
|
||||
- struct frame_state_reg_info *old_rs = fs->regs.prev;
|
||||
- fs->regs = *old_rs;
|
||||
- old_rs->prev = unused_rs;
|
||||
- unused_rs = old_rs;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_def_cfa:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- fs->regs.cfa_reg = (_Unwind_Word)utmp;
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- fs->regs.cfa_offset = (_Unwind_Word)utmp;
|
||||
- fs->regs.cfa_how = CFA_REG_OFFSET;
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_def_cfa_register:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- fs->regs.cfa_reg = (_Unwind_Word)utmp;
|
||||
- fs->regs.cfa_how = CFA_REG_OFFSET;
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_def_cfa_offset:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- fs->regs.cfa_offset = utmp;
|
||||
- /* cfa_how deliberately not set. */
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_def_cfa_expression:
|
||||
- fs->regs.cfa_exp = insn_ptr;
|
||||
- fs->regs.cfa_how = CFA_EXP;
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- insn_ptr += utmp;
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_expression:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- {
|
||||
- fs->regs.how[reg] = REG_SAVED_EXP;
|
||||
- fs->regs.reg[reg].loc.exp = insn_ptr;
|
||||
- }
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- insn_ptr += utmp;
|
||||
- break;
|
||||
-
|
||||
- /* Dwarf3. */
|
||||
- case DW_CFA_offset_extended_sf:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
- insn_ptr = read_sleb128 (insn_ptr, &stmp);
|
||||
- offset = stmp * fs->data_align;
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- {
|
||||
- fs->regs.how[reg] = REG_SAVED_OFFSET;
|
||||
- fs->regs.reg[reg].loc.offset = offset;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_def_cfa_sf:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- fs->regs.cfa_reg = (_Unwind_Word)utmp;
|
||||
- insn_ptr = read_sleb128 (insn_ptr, &stmp);
|
||||
- fs->regs.cfa_offset = (_Unwind_Sword)stmp;
|
||||
- fs->regs.cfa_how = CFA_REG_OFFSET;
|
||||
- fs->regs.cfa_offset *= fs->data_align;
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_def_cfa_offset_sf:
|
||||
- insn_ptr = read_sleb128 (insn_ptr, &stmp);
|
||||
- fs->regs.cfa_offset = (_Unwind_Sword)stmp;
|
||||
- fs->regs.cfa_offset *= fs->data_align;
|
||||
- /* cfa_how deliberately not set. */
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_val_offset:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- offset = (_Unwind_Sword) utmp * fs->data_align;
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- {
|
||||
- fs->regs.how[reg] = REG_SAVED_VAL_OFFSET;
|
||||
- fs->regs.reg[reg].loc.offset = offset;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_val_offset_sf:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
- insn_ptr = read_sleb128 (insn_ptr, &stmp);
|
||||
- offset = stmp * fs->data_align;
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- {
|
||||
- fs->regs.how[reg] = REG_SAVED_VAL_OFFSET;
|
||||
- fs->regs.reg[reg].loc.offset = offset;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_val_expression:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- {
|
||||
- fs->regs.how[reg] = REG_SAVED_VAL_EXP;
|
||||
- fs->regs.reg[reg].loc.exp = insn_ptr;
|
||||
- }
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- insn_ptr += utmp;
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_GNU_window_save:
|
||||
-#if defined (__aarch64__) && !defined (__ILP32__)
|
||||
- /* This CFA is multiplexed with Sparc. On AArch64 it's used to toggle
|
||||
- return address signing status. */
|
||||
- reg = DWARF_REGNUM_AARCH64_RA_STATE;
|
||||
- gcc_assert (fs->regs.how[reg] == REG_UNSAVED);
|
||||
- fs->regs.reg[reg].loc.offset ^= 1;
|
||||
-#else
|
||||
- /* ??? Hardcoded for SPARC register window configuration. */
|
||||
- if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
|
||||
- for (reg = 16; reg < 32; ++reg)
|
||||
- {
|
||||
- fs->regs.how[reg] = REG_SAVED_OFFSET;
|
||||
- fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
|
||||
- }
|
||||
-#endif
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_GNU_args_size:
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- context->args_size = (_Unwind_Word)utmp;
|
||||
- break;
|
||||
-
|
||||
- case DW_CFA_GNU_negative_offset_extended:
|
||||
- /* Obsoleted by DW_CFA_offset_extended_sf, but used by
|
||||
- older PowerPC code. */
|
||||
- insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
- offset = (_Unwind_Word) utmp * fs->data_align;
|
||||
- reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
|
||||
- if (UNWIND_COLUMN_IN_RANGE (reg))
|
||||
- {
|
||||
- fs->regs.how[reg] = REG_SAVED_OFFSET;
|
||||
- fs->regs.reg[reg].loc.offset = -offset;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- gcc_unreachable ();
|
||||
- }
|
||||
- }
|
||||
+ if (fs->data_align == __LIBGCC_DWARF_CIE_DATA_ALIGNMENT__
|
||||
+ && fs->code_align == 1)
|
||||
+ execute_cfa_program_specialized (insn_ptr, insn_end, context, fs);
|
||||
+ else
|
||||
+ execute_cfa_program_generic (insn_ptr, insn_end, context, fs);
|
||||
}
|
||||
+
|
||||
|
||||
/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
|
||||
its caller and decode it into FS. This function also sets the
|
||||
146
gcc-RHEL-105072-18.patch
Normal file
146
gcc-RHEL-105072-18.patch
Normal file
@ -0,0 +1,146 @@
|
||||
commit c98cd1df22fbe0829149e346a1ba9bf1f0be8a40
|
||||
Author: Wilco Dijkstra <wilco.dijkstra@arm.com>
|
||||
Date: Tue Jan 3 15:57:46 2023 +0000
|
||||
|
||||
libgcc: Fix uninitialized RA signing on AArch64 [PR107678]
|
||||
|
||||
A recent change only initializes the regs.how[] during Dwarf unwinding
|
||||
which resulted in an uninitialized offset used in return address signing
|
||||
and random failures during unwinding. The fix is to encode the return
|
||||
address signing state in REG_UNSAVED and a new state REG_UNSAVED_ARCHEXT.
|
||||
|
||||
libgcc/
|
||||
PR target/107678
|
||||
* unwind-dw2.h (REG_UNSAVED_ARCHEXT): Add new enum.
|
||||
* unwind-dw2.c (uw_update_context_1): Add REG_UNSAVED_ARCHEXT case.
|
||||
* unwind-dw2-execute_cfa.h: Use REG_UNSAVED_ARCHEXT/REG_UNSAVED to
|
||||
encode the return address signing state.
|
||||
* config/aarch64/aarch64-unwind.h (aarch64_demangle_return_addr)
|
||||
Check current return address signing state.
|
||||
(aarch64_frob_update_contex): Remove.
|
||||
|
||||
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
|
||||
index 466e4235991485ea..2fddadc57564348f 100644
|
||||
--- a/libgcc/config/aarch64/aarch64-unwind.h
|
||||
+++ b/libgcc/config/aarch64/aarch64-unwind.h
|
||||
@@ -29,8 +29,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
|
||||
#define MD_DEMANGLE_RETURN_ADDR(context, fs, addr) \
|
||||
aarch64_demangle_return_addr (context, fs, addr)
|
||||
-#define MD_FROB_UPDATE_CONTEXT(context, fs) \
|
||||
- aarch64_frob_update_context (context, fs)
|
||||
|
||||
static inline int
|
||||
aarch64_cie_signed_with_b_key (struct _Unwind_Context *context)
|
||||
@@ -55,42 +53,28 @@ aarch64_cie_signed_with_b_key (struct _Unwind_Context *context)
|
||||
|
||||
static inline void *
|
||||
aarch64_demangle_return_addr (struct _Unwind_Context *context,
|
||||
- _Unwind_FrameState *fs ATTRIBUTE_UNUSED,
|
||||
+ _Unwind_FrameState *fs,
|
||||
_Unwind_Word addr_word)
|
||||
{
|
||||
void *addr = (void *)addr_word;
|
||||
- if (context->flags & RA_SIGNED_BIT)
|
||||
+ const int reg = DWARF_REGNUM_AARCH64_RA_STATE;
|
||||
+
|
||||
+ if (fs->regs.how[reg] == REG_UNSAVED)
|
||||
+ return addr;
|
||||
+
|
||||
+ /* Return-address signing state is toggled by DW_CFA_GNU_window_save (where
|
||||
+ REG_UNSAVED/REG_UNSAVED_ARCHEXT means RA signing is disabled/enabled),
|
||||
+ or set by a DW_CFA_expression. */
|
||||
+ if (fs->regs.how[reg] == REG_UNSAVED_ARCHEXT
|
||||
+ || (_Unwind_GetGR (context, reg) & 0x1) != 0)
|
||||
{
|
||||
_Unwind_Word salt = (_Unwind_Word) context->cfa;
|
||||
if (aarch64_cie_signed_with_b_key (context) != 0)
|
||||
return __builtin_aarch64_autib1716 (addr, salt);
|
||||
return __builtin_aarch64_autia1716 (addr, salt);
|
||||
}
|
||||
- else
|
||||
- return addr;
|
||||
-}
|
||||
-
|
||||
-/* Do AArch64 private initialization on CONTEXT based on frame info FS. Mark
|
||||
- CONTEXT as return address signed if bit 0 of DWARF_REGNUM_AARCH64_RA_STATE is
|
||||
- set. */
|
||||
-
|
||||
-static inline void
|
||||
-aarch64_frob_update_context (struct _Unwind_Context *context,
|
||||
- _Unwind_FrameState *fs)
|
||||
-{
|
||||
- const int reg = DWARF_REGNUM_AARCH64_RA_STATE;
|
||||
- int ra_signed;
|
||||
- if (fs->regs.how[reg] == REG_UNSAVED)
|
||||
- ra_signed = fs->regs.reg[reg].loc.offset & 0x1;
|
||||
- else
|
||||
- ra_signed = _Unwind_GetGR (context, reg) & 0x1;
|
||||
- if (ra_signed)
|
||||
- /* The flag is used for re-authenticating EH handler's address. */
|
||||
- context->flags |= RA_SIGNED_BIT;
|
||||
- else
|
||||
- context->flags &= ~RA_SIGNED_BIT;
|
||||
|
||||
- return;
|
||||
+ return addr;
|
||||
}
|
||||
|
||||
#endif /* defined AARCH64_UNWIND_H && defined __ILP32__ */
|
||||
diff --git a/libgcc/unwind-dw2-execute_cfa.h b/libgcc/unwind-dw2-execute_cfa.h
|
||||
index dd97b7866686a361..0166f85965d4a5ee 100644
|
||||
--- a/libgcc/unwind-dw2-execute_cfa.h
|
||||
+++ b/libgcc/unwind-dw2-execute_cfa.h
|
||||
@@ -278,10 +278,15 @@
|
||||
case DW_CFA_GNU_window_save:
|
||||
#if defined (__aarch64__) && !defined (__ILP32__)
|
||||
/* This CFA is multiplexed with Sparc. On AArch64 it's used to toggle
|
||||
- return address signing status. */
|
||||
+ return address signing status. REG_UNSAVED/REG_UNSAVED_ARCHEXT
|
||||
+ mean RA signing is disabled/enabled. */
|
||||
reg = DWARF_REGNUM_AARCH64_RA_STATE;
|
||||
- gcc_assert (fs->regs.how[reg] == REG_UNSAVED);
|
||||
- fs->regs.reg[reg].loc.offset ^= 1;
|
||||
+ gcc_assert (fs->regs.how[reg] == REG_UNSAVED
|
||||
+ || fs->regs.how[reg] == REG_UNSAVED_ARCHEXT);
|
||||
+ if (fs->regs.how[reg] == REG_UNSAVED)
|
||||
+ fs->regs.how[reg] = REG_UNSAVED_ARCHEXT;
|
||||
+ else
|
||||
+ fs->regs.how[reg] = REG_UNSAVED;
|
||||
#else
|
||||
/* ??? Hardcoded for SPARC register window configuration. */
|
||||
if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
|
||||
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
|
||||
index 701552634c6e87c5..280ec2eb4df3d2a2 100644
|
||||
--- a/libgcc/unwind-dw2.c
|
||||
+++ b/libgcc/unwind-dw2.c
|
||||
@@ -137,9 +137,6 @@ struct _Unwind_Context
|
||||
#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
|
||||
/* Context which has version/args_size/by_value fields. */
|
||||
#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
|
||||
- /* Bit reserved on AArch64, return address has been signed with A or B
|
||||
- key. */
|
||||
-#define RA_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
|
||||
_Unwind_Word flags;
|
||||
/* 0 for now, can be increased when further fields are added to
|
||||
struct _Unwind_Context. */
|
||||
@@ -1200,6 +1197,7 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
||||
{
|
||||
case REG_UNSAVED:
|
||||
case REG_UNDEFINED:
|
||||
+ case REG_UNSAVED_ARCHEXT:
|
||||
break;
|
||||
|
||||
case REG_SAVED_OFFSET:
|
||||
diff --git a/libgcc/unwind-dw2.h b/libgcc/unwind-dw2.h
|
||||
index 437c785efa4f297d..44f63e2eb31298d8 100644
|
||||
--- a/libgcc/unwind-dw2.h
|
||||
+++ b/libgcc/unwind-dw2.h
|
||||
@@ -29,6 +29,7 @@ enum {
|
||||
REG_SAVED_EXP,
|
||||
REG_SAVED_VAL_OFFSET,
|
||||
REG_SAVED_VAL_EXP,
|
||||
+ REG_UNSAVED_ARCHEXT, /* Target specific extension. */
|
||||
REG_UNDEFINED
|
||||
};
|
||||
|
||||
34
gcc-RHEL-105072-19.patch
Normal file
34
gcc-RHEL-105072-19.patch
Normal file
@ -0,0 +1,34 @@
|
||||
commit 9be9be828dc9020735bc7eacddd1ceae1aeedb1b
|
||||
Author: Sören Tempel <soeren+git@soeren-tempel.net>
|
||||
Date: Sun May 14 19:30:21 2023 +0200
|
||||
|
||||
fix assert in __deregister_frame_info_bases
|
||||
|
||||
The assertion in __deregister_frame_info_bases assumes that for every
|
||||
frame something was inserted into the lookup data structure by
|
||||
__register_frame_info_bases. Unfortunately, this does not necessarily
|
||||
hold true as the btree_insert call in __register_frame_info_bases will
|
||||
not insert anything for empty ranges. Therefore, we need to explicitly
|
||||
account for such empty ranges in the assertion as `ob` will be a null
|
||||
pointer for such ranges, hence causing the assertion to fail.
|
||||
|
||||
Signed-off-by: Sören Tempel <soeren@soeren-tempel.net>
|
||||
|
||||
libgcc/ChangeLog:
|
||||
* unwind-dw2-fde.c: Accept empty ranges when deregistering frames.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
|
||||
index efcf9490469ad1a0..fdf52396e8576b79 100644
|
||||
--- a/libgcc/unwind-dw2-fde.c
|
||||
+++ b/libgcc/unwind-dw2-fde.c
|
||||
@@ -278,7 +278,9 @@ __deregister_frame_info_bases (const void *begin)
|
||||
__gthread_mutex_unlock (&object_mutex);
|
||||
#endif
|
||||
|
||||
- gcc_assert (in_shutdown || ob);
|
||||
+ // If we didn't find anything in the lookup data structures then they
|
||||
+ // were either already destroyed or we tried to remove an empty range.
|
||||
+ gcc_assert (in_shutdown || ((range[1] - range[0]) == 0 || ob));
|
||||
return (void *) ob;
|
||||
}
|
||||
|
||||
147
gcc-RHEL-105072-2.patch
Normal file
147
gcc-RHEL-105072-2.patch
Normal file
@ -0,0 +1,147 @@
|
||||
commit f58bf16f672cda3ac55f92f12e258c817ece6e3c
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Nov 22 13:30:23 2021 +0100
|
||||
|
||||
libgcc: Remove dbase member from struct unw_eh_callback_data if NULL
|
||||
|
||||
Only bfin, frv, i386 and nios2 need this member at present.
|
||||
|
||||
libgcc/ChangeLog
|
||||
|
||||
* unwind-dw2-fde-dip.c (NEED_DBASE_MEMBER): Define.
|
||||
(struct unw_eh_callback_data): Make dbase member conditional.
|
||||
(unw_eh_callback_data_dbase): New function.
|
||||
(base_from_cb_data): Simplify for the non-dbase case.
|
||||
(_Unwind_IteratePhdrCallback): Adjust.
|
||||
(_Unwind_Find_FDE): Likewise.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
|
||||
index 4a4d990f455e5c11..3f302826d2d49074 100644
|
||||
--- a/libgcc/unwind-dw2-fde-dip.c
|
||||
+++ b/libgcc/unwind-dw2-fde-dip.c
|
||||
@@ -101,15 +101,35 @@ static const fde * _Unwind_Find_registered_FDE (void *pc, struct dwarf_eh_bases
|
||||
#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550)
|
||||
#endif
|
||||
|
||||
+#ifdef CRT_GET_RFIB_DATA
|
||||
+#define NEED_DBASE_MEMBER 1
|
||||
+#else
|
||||
+#define NEED_DBASE_MEMBER 0
|
||||
+#endif
|
||||
+
|
||||
struct unw_eh_callback_data
|
||||
{
|
||||
_Unwind_Ptr pc;
|
||||
+#if NEED_DBASE_MEMBER
|
||||
void *dbase;
|
||||
+#endif
|
||||
void *func;
|
||||
const fde *ret;
|
||||
int check_cache;
|
||||
};
|
||||
|
||||
+/* Returns DATA->dbase if available, else NULL. */
|
||||
+static inline _Unwind_Ptr
|
||||
+unw_eh_callback_data_dbase (const struct unw_eh_callback_data *data
|
||||
+ __attribute__ ((unused)))
|
||||
+{
|
||||
+#if NEED_DBASE_MEMBER
|
||||
+ return (_Unwind_Ptr) data->dbase;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
struct unw_eh_frame_hdr
|
||||
{
|
||||
unsigned char version;
|
||||
@@ -139,9 +159,11 @@ static struct frame_hdr_cache_element *frame_hdr_cache_head;
|
||||
/* Like base_of_encoded_value, but take the base from a struct
|
||||
unw_eh_callback_data instead of an _Unwind_Context. */
|
||||
|
||||
-static _Unwind_Ptr
|
||||
-base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data)
|
||||
+static inline _Unwind_Ptr
|
||||
+base_from_cb_data (unsigned char encoding __attribute__ ((unused)),
|
||||
+ _Unwind_Ptr dbase __attribute__ ((unused)))
|
||||
{
|
||||
+#if NEED_DBASE_MEMBER
|
||||
if (encoding == DW_EH_PE_omit)
|
||||
return 0;
|
||||
|
||||
@@ -155,10 +177,13 @@ base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data)
|
||||
case DW_EH_PE_textrel:
|
||||
return 0;
|
||||
case DW_EH_PE_datarel:
|
||||
- return (_Unwind_Ptr) data->dbase;
|
||||
+ return dbase;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
+#else /* !NEED_DBASE_MEMBER */
|
||||
+ return 0;
|
||||
+#endif
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -358,9 +383,10 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
+ _Unwind_Ptr dbase = unw_eh_callback_data_dbase (data);
|
||||
p = read_encoded_value_with_base (hdr->eh_frame_ptr_enc,
|
||||
base_from_cb_data (hdr->eh_frame_ptr_enc,
|
||||
- data),
|
||||
+ dbase),
|
||||
(const unsigned char *) (hdr + 1),
|
||||
&eh_frame);
|
||||
|
||||
@@ -374,7 +400,7 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
|
||||
p = read_encoded_value_with_base (hdr->fde_count_enc,
|
||||
base_from_cb_data (hdr->fde_count_enc,
|
||||
- data),
|
||||
+ dbase),
|
||||
p, &fde_count);
|
||||
/* Shouldn't happen. */
|
||||
if (fde_count == 0)
|
||||
@@ -431,7 +457,7 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
removed, we could cache this (and thus use search_object). */
|
||||
ob.pc_begin = NULL;
|
||||
ob.tbase = NULL;
|
||||
- ob.dbase = data->dbase;
|
||||
+ ob.dbase = (void *) dbase;
|
||||
ob.u.single = (fde *) eh_frame;
|
||||
ob.s.i = 0;
|
||||
ob.s.b.mixed_encoding = 1; /* Need to assume worst case. */
|
||||
@@ -442,7 +468,7 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
unsigned int encoding = get_fde_encoding (data->ret);
|
||||
|
||||
read_encoded_value_with_base (encoding,
|
||||
- base_from_cb_data (encoding, data),
|
||||
+ base_from_cb_data (encoding, dbase),
|
||||
data->ret->pc_begin, &func);
|
||||
data->func = (void *) func;
|
||||
}
|
||||
@@ -460,7 +486,9 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
|
||||
return ret;
|
||||
|
||||
data.pc = (_Unwind_Ptr) pc;
|
||||
+#if NEED_DBASE_MEMBER
|
||||
data.dbase = NULL;
|
||||
+#endif
|
||||
data.func = NULL;
|
||||
data.ret = NULL;
|
||||
data.check_cache = 1;
|
||||
@@ -471,7 +499,11 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
|
||||
if (data.ret)
|
||||
{
|
||||
bases->tbase = NULL;
|
||||
+#if NEED_DBASE_MEMBER
|
||||
bases->dbase = data.dbase;
|
||||
+#else
|
||||
+ bases->dbase = NULL;
|
||||
+#endif
|
||||
bases->func = data.func;
|
||||
}
|
||||
return data.ret;
|
||||
38
gcc-RHEL-105072-20.patch
Normal file
38
gcc-RHEL-105072-20.patch
Normal file
@ -0,0 +1,38 @@
|
||||
commit 30adfb85ff994c0faa0cc556ba46838b218263f5
|
||||
Author: Thomas Neumann <tneumann@users.sourceforge.net>
|
||||
Date: Mon May 15 14:59:22 2023 +0200
|
||||
|
||||
fix assert in non-atomic path
|
||||
|
||||
The non-atomic path does not have range information,
|
||||
we have to adjust the assert handle that case, too.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
* unwind-dw2-fde.c: Fix assert in non-atomic path.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
|
||||
index fdf52396e8576b79..9b0c229efa5427a9 100644
|
||||
--- a/libgcc/unwind-dw2-fde.c
|
||||
+++ b/libgcc/unwind-dw2-fde.c
|
||||
@@ -240,6 +240,7 @@ __deregister_frame_info_bases (const void *begin)
|
||||
|
||||
// And remove
|
||||
ob = btree_remove (®istered_frames, range[0]);
|
||||
+ bool empty_table = (range[1] - range[0]) == 0;
|
||||
#else
|
||||
init_object_mutex_once ();
|
||||
__gthread_mutex_lock (&object_mutex);
|
||||
@@ -276,11 +277,12 @@ __deregister_frame_info_bases (const void *begin)
|
||||
|
||||
out:
|
||||
__gthread_mutex_unlock (&object_mutex);
|
||||
+ const int empty_table = 0; // The non-atomic path stores all tables.
|
||||
#endif
|
||||
|
||||
// If we didn't find anything in the lookup data structures then they
|
||||
// were either already destroyed or we tried to remove an empty range.
|
||||
- gcc_assert (in_shutdown || ((range[1] - range[0]) == 0 || ob));
|
||||
+ gcc_assert (in_shutdown || (empty_table || ob));
|
||||
return (void *) ob;
|
||||
}
|
||||
|
||||
31
gcc-RHEL-105072-21.patch
Normal file
31
gcc-RHEL-105072-21.patch
Normal file
@ -0,0 +1,31 @@
|
||||
commit 5cf60b6ba111f4169305c7832b063b000e9ec36a
|
||||
Author: Thomas Neumann <tneumann@users.sourceforge.net>
|
||||
Date: Tue May 2 16:21:09 2023 +0200
|
||||
|
||||
release the sorted FDE array when deregistering a frame [PR109685]
|
||||
|
||||
The atomic fastpath bypasses the code that releases the sort
|
||||
array which was lazily allocated during unwinding. We now
|
||||
check after deregistering if there is an array to free.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
PR libgcc/109685
|
||||
* unwind-dw2-fde.c: Free sort array in atomic fast path.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
|
||||
index 9b0c229efa5427a9..0fd2fc54aa651350 100644
|
||||
--- a/libgcc/unwind-dw2-fde.c
|
||||
+++ b/libgcc/unwind-dw2-fde.c
|
||||
@@ -241,6 +241,12 @@ __deregister_frame_info_bases (const void *begin)
|
||||
// And remove
|
||||
ob = btree_remove (®istered_frames, range[0]);
|
||||
bool empty_table = (range[1] - range[0]) == 0;
|
||||
+
|
||||
+ // Deallocate the sort array if any.
|
||||
+ if (ob && ob->s.b.sorted)
|
||||
+ {
|
||||
+ free (ob->u.sort);
|
||||
+ }
|
||||
#else
|
||||
init_object_mutex_once ();
|
||||
__gthread_mutex_lock (&object_mutex);
|
||||
51
gcc-RHEL-105072-22.patch
Normal file
51
gcc-RHEL-105072-22.patch
Normal file
@ -0,0 +1,51 @@
|
||||
commit 38e88d41f50d844f1404172657ef7e8372014ef6
|
||||
Author: Thomas Neumann <tneumann@users.sourceforge.net>
|
||||
Date: Wed May 10 12:33:49 2023 +0200
|
||||
|
||||
fix radix sort on 32bit platforms [PR109670]
|
||||
|
||||
The radix sort uses two buffers, a1 for input and a2 for output.
|
||||
After every digit the role of the two buffers is swapped.
|
||||
When terminating the sort early the code made sure the output
|
||||
was in a2. However, when we run out of bits, as can happen on
|
||||
32bit platforms, the sorted result was in a1, as we had just
|
||||
swapped a1 and a2.
|
||||
This patch fixes the problem by unconditionally having a1 as
|
||||
output after every loop iteration.
|
||||
|
||||
This bug manifested itself only on 32bit platforms and even then
|
||||
only in some circumstances, as it needs frames where a swap
|
||||
is required due to differences in the top-most byte, which is
|
||||
affected by ASLR. The new logic was validated by exhaustive
|
||||
search over 32bit input values.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
PR libgcc/109670
|
||||
* unwind-dw2-fde.c: Fix radix sort buffer management.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
|
||||
index 0fd2fc54aa651350..41b8c2e9380bc45b 100644
|
||||
--- a/libgcc/unwind-dw2-fde.c
|
||||
+++ b/libgcc/unwind-dw2-fde.c
|
||||
@@ -634,8 +634,6 @@ fde_radixsort (struct object *ob, fde_extractor_t fde_extractor,
|
||||
// Stop if we are already sorted.
|
||||
if (!violations)
|
||||
{
|
||||
- // The sorted data is in a1 now.
|
||||
- a2 = a1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -670,9 +668,9 @@ fde_radixsort (struct object *ob, fde_extractor_t fde_extractor,
|
||||
#undef FANOUT
|
||||
#undef FANOUTBITS
|
||||
|
||||
- // The data is in a2 now, move in place if needed.
|
||||
- if (a2 != v1->array)
|
||||
- memcpy (v1->array, a2, sizeof (const fde *) * n);
|
||||
+ // The data is in a1 now, move in place if needed.
|
||||
+ if (a1 != v1->array)
|
||||
+ memcpy (v1->array, a1, sizeof (const fde *) * n);
|
||||
}
|
||||
|
||||
static inline void
|
||||
33
gcc-RHEL-105072-23.patch
Normal file
33
gcc-RHEL-105072-23.patch
Normal file
@ -0,0 +1,33 @@
|
||||
commit 49310a993308492348119f4033e4db0bda4fe46a
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Jun 6 11:01:07 2023 +0200
|
||||
|
||||
libgcc: Fix eh_frame fast path in find_fde_tail
|
||||
|
||||
The eh_frame value is only used by linear_search_fdes, not the binary
|
||||
search directly in find_fde_tail, so the bug is not immediately
|
||||
apparent with most programs.
|
||||
|
||||
Fixes commit e724b0480bfa5ec04f39be8c7290330b495c59de ("libgcc:
|
||||
Special-case BFD ld unwind table encodings in find_fde_tail").
|
||||
|
||||
libgcc/
|
||||
|
||||
PR libgcc/109712
|
||||
* unwind-dw2-fde-dip.c (find_fde_tail): Correct fast path for
|
||||
parsing eh_frame.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
|
||||
index d4821d7d19950f15..b46e95dc8f88ac5c 100644
|
||||
--- a/libgcc/unwind-dw2-fde-dip.c
|
||||
+++ b/libgcc/unwind-dw2-fde-dip.c
|
||||
@@ -403,8 +403,8 @@ find_fde_tail (_Unwind_Ptr pc,
|
||||
BFD ld generates. */
|
||||
signed value __attribute__ ((mode (SI)));
|
||||
memcpy (&value, p, sizeof (value));
|
||||
+ eh_frame = p + value;
|
||||
p += sizeof (value);
|
||||
- dbase = value; /* No adjustment because pcrel has base 0. */
|
||||
}
|
||||
else
|
||||
p = read_encoded_value_with_base (hdr->eh_frame_ptr_enc,
|
||||
28
gcc-RHEL-105072-24.patch
Normal file
28
gcc-RHEL-105072-24.patch
Normal file
@ -0,0 +1,28 @@
|
||||
commit 104b09005229ef48a79a33511ea192bb3ec3c415
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Jul 11 06:19:39 2023 +0200
|
||||
|
||||
libgcc: Fix -Wint-conversion warning in find_fde_tail
|
||||
|
||||
Fixes commit r14-1614-g49310a99330849 ("libgcc: Fix eh_frame fast path
|
||||
in find_fde_tail").
|
||||
|
||||
libgcc/
|
||||
|
||||
PR libgcc/110179
|
||||
* unwind-dw2-fde-dip.c (find_fde_tail): Add cast to avoid
|
||||
implicit conversion of pointer value to integer.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
|
||||
index b46e95dc8f88ac5c..e08154c1442d748f 100644
|
||||
--- a/libgcc/unwind-dw2-fde-dip.c
|
||||
+++ b/libgcc/unwind-dw2-fde-dip.c
|
||||
@@ -403,7 +403,7 @@ find_fde_tail (_Unwind_Ptr pc,
|
||||
BFD ld generates. */
|
||||
signed value __attribute__ ((mode (SI)));
|
||||
memcpy (&value, p, sizeof (value));
|
||||
- eh_frame = p + value;
|
||||
+ eh_frame = (_Unwind_Ptr) (p + value);
|
||||
p += sizeof (value);
|
||||
}
|
||||
else
|
||||
97
gcc-RHEL-105072-25.patch
Normal file
97
gcc-RHEL-105072-25.patch
Normal file
@ -0,0 +1,97 @@
|
||||
commit c46bded78f3733ad1312d141ebf1ae541032a48b
|
||||
Author: Thomas Neumann <thomas.neumann@in.tum.de>
|
||||
Date: Fri Aug 11 09:20:27 2023 -0600
|
||||
|
||||
preserve base pointer for __deregister_frame [PR110956]
|
||||
|
||||
Original bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110956
|
||||
Rainer Orth successfully tested the patch on Solaris with a full bootstrap.
|
||||
|
||||
Some uncommon unwinding table encodings need to access the base pointer
|
||||
for address computations. We do not have that information in calls to
|
||||
__deregister_frame_info_bases, and previously simply used nullptr as
|
||||
base pointer. That is usually fine, but for some Solaris i386 shared
|
||||
libraries that results in wrong address computations.
|
||||
|
||||
To fix this problem we now associate the unwinding object with
|
||||
the table pointer itself, which is always known, in addition to
|
||||
the PC range. When deregistering a frame, we first locate the object
|
||||
using the table pointer, and then use the base pointer stored within
|
||||
the object to compute the PC range.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
PR libgcc/110956
|
||||
* unwind-dw2-fde.c: Associate object with address of unwinding
|
||||
table.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
|
||||
index 41b8c2e9380bc45b..5d6fb29acd440563 100644
|
||||
--- a/libgcc/unwind-dw2-fde.c
|
||||
+++ b/libgcc/unwind-dw2-fde.c
|
||||
@@ -124,6 +124,9 @@ __register_frame_info_bases (const void *begin, struct object *ob,
|
||||
#endif
|
||||
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
+ // Register the object itself to know the base pointer on deregistration.
|
||||
+ btree_insert (®istered_frames, (uintptr_type) begin, 1, ob);
|
||||
+
|
||||
// Register the frame in the b-tree
|
||||
uintptr_type range[2];
|
||||
get_pc_range (ob, range);
|
||||
@@ -175,6 +178,9 @@ __register_frame_info_table_bases (void *begin, struct object *ob,
|
||||
ob->s.b.encoding = DW_EH_PE_omit;
|
||||
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
+ // Register the object itself to know the base pointer on deregistration.
|
||||
+ btree_insert (®istered_frames, (uintptr_type) begin, 1, ob);
|
||||
+
|
||||
// Register the frame in the b-tree
|
||||
uintptr_type range[2];
|
||||
get_pc_range (ob, range);
|
||||
@@ -225,22 +231,17 @@ __deregister_frame_info_bases (const void *begin)
|
||||
return ob;
|
||||
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
- // Find the corresponding PC range
|
||||
- struct object lookupob;
|
||||
- lookupob.tbase = 0;
|
||||
- lookupob.dbase = 0;
|
||||
- lookupob.u.single = begin;
|
||||
- lookupob.s.i = 0;
|
||||
- lookupob.s.b.encoding = DW_EH_PE_omit;
|
||||
-#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
|
||||
- lookupob.fde_end = NULL;
|
||||
-#endif
|
||||
- uintptr_type range[2];
|
||||
- get_pc_range (&lookupob, range);
|
||||
+ // Find the originally registered object to get the base pointer.
|
||||
+ ob = btree_remove (®istered_frames, (uintptr_type) begin);
|
||||
|
||||
- // And remove
|
||||
- ob = btree_remove (®istered_frames, range[0]);
|
||||
- bool empty_table = (range[1] - range[0]) == 0;
|
||||
+ // Remove the corresponding PC range.
|
||||
+ if (ob)
|
||||
+ {
|
||||
+ uintptr_type range[2];
|
||||
+ get_pc_range (ob, range);
|
||||
+ if (range[0] != range[1])
|
||||
+ btree_remove (®istered_frames, range[0]);
|
||||
+ }
|
||||
|
||||
// Deallocate the sort array if any.
|
||||
if (ob && ob->s.b.sorted)
|
||||
@@ -283,12 +284,11 @@ __deregister_frame_info_bases (const void *begin)
|
||||
|
||||
out:
|
||||
__gthread_mutex_unlock (&object_mutex);
|
||||
- const int empty_table = 0; // The non-atomic path stores all tables.
|
||||
#endif
|
||||
|
||||
// If we didn't find anything in the lookup data structures then they
|
||||
// were either already destroyed or we tried to remove an empty range.
|
||||
- gcc_assert (in_shutdown || (empty_table || ob));
|
||||
+ gcc_assert (in_shutdown || ob);
|
||||
return (void *) ob;
|
||||
}
|
||||
|
||||
112
gcc-RHEL-105072-26.patch
Normal file
112
gcc-RHEL-105072-26.patch
Normal file
@ -0,0 +1,112 @@
|
||||
commit a364148530c28645ce87adbc58a66c9f32a325ab
|
||||
Author: Thomas Neumann <tneumann@users.sourceforge.net>
|
||||
Date: Mon Mar 11 14:35:20 2024 +0100
|
||||
|
||||
handle unwind tables that are embedded within unwinding code [PR111731]
|
||||
|
||||
Original bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111731
|
||||
|
||||
The unwinding mechanism registers both the code range and the unwind
|
||||
table itself within a b-tree lookup structure. That data structure
|
||||
assumes that is consists of non-overlappping intervals. This
|
||||
becomes a problem if the unwinding table is embedded within the
|
||||
code itself, as now the intervals do overlap.
|
||||
|
||||
To fix this problem we now keep the unwind tables in a separate
|
||||
b-tree, which prevents the overlap.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
PR libgcc/111731
|
||||
* unwind-dw2-fde.c: Split unwind ranges if they contain the
|
||||
unwind table.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
|
||||
index 5d6fb29acd440563..421068b538abc66d 100644
|
||||
--- a/libgcc/unwind-dw2-fde.c
|
||||
+++ b/libgcc/unwind-dw2-fde.c
|
||||
@@ -48,6 +48,7 @@ typedef __UINTPTR_TYPE__ uintptr_type;
|
||||
#include "unwind-dw2-btree.h"
|
||||
|
||||
static struct btree registered_frames;
|
||||
+static struct btree registered_objects;
|
||||
static bool in_shutdown;
|
||||
|
||||
static void
|
||||
@@ -58,6 +59,7 @@ release_registered_frames (void)
|
||||
/* Release the b-tree and all frames. Frame releases that happen later are
|
||||
* silently ignored */
|
||||
btree_destroy (®istered_frames);
|
||||
+ btree_destroy (®istered_objects);
|
||||
in_shutdown = true;
|
||||
}
|
||||
|
||||
@@ -103,6 +105,21 @@ static __gthread_mutex_t object_mutex;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+#ifdef ATOMIC_FDE_FAST_PATH
|
||||
+// Register the pc range for a given object in the lookup structure.
|
||||
+static void
|
||||
+register_pc_range_for_object (uintptr_type begin, struct object *ob)
|
||||
+{
|
||||
+ // Register the object itself to know the base pointer on deregistration.
|
||||
+ btree_insert (®istered_objects, begin, 1, ob);
|
||||
+
|
||||
+ // Register the frame in the b-tree
|
||||
+ uintptr_type range[2];
|
||||
+ get_pc_range (ob, range);
|
||||
+ btree_insert (®istered_frames, range[0], range[1] - range[0], ob);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/* Called from crtbegin.o to register the unwind info for an object. */
|
||||
|
||||
void
|
||||
@@ -124,13 +141,7 @@ __register_frame_info_bases (const void *begin, struct object *ob,
|
||||
#endif
|
||||
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
- // Register the object itself to know the base pointer on deregistration.
|
||||
- btree_insert (®istered_frames, (uintptr_type) begin, 1, ob);
|
||||
-
|
||||
- // Register the frame in the b-tree
|
||||
- uintptr_type range[2];
|
||||
- get_pc_range (ob, range);
|
||||
- btree_insert (®istered_frames, range[0], range[1] - range[0], ob);
|
||||
+ register_pc_range_for_object ((uintptr_type) begin, ob);
|
||||
#else
|
||||
init_object_mutex_once ();
|
||||
__gthread_mutex_lock (&object_mutex);
|
||||
@@ -178,13 +189,7 @@ __register_frame_info_table_bases (void *begin, struct object *ob,
|
||||
ob->s.b.encoding = DW_EH_PE_omit;
|
||||
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
- // Register the object itself to know the base pointer on deregistration.
|
||||
- btree_insert (®istered_frames, (uintptr_type) begin, 1, ob);
|
||||
-
|
||||
- // Register the frame in the b-tree
|
||||
- uintptr_type range[2];
|
||||
- get_pc_range (ob, range);
|
||||
- btree_insert (®istered_frames, range[0], range[1] - range[0], ob);
|
||||
+ register_pc_range_for_object ((uintptr_type) begin, ob);
|
||||
#else
|
||||
init_object_mutex_once ();
|
||||
__gthread_mutex_lock (&object_mutex);
|
||||
@@ -232,7 +237,7 @@ __deregister_frame_info_bases (const void *begin)
|
||||
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
// Find the originally registered object to get the base pointer.
|
||||
- ob = btree_remove (®istered_frames, (uintptr_type) begin);
|
||||
+ ob = btree_remove (®istered_objects, (uintptr_type) begin);
|
||||
|
||||
// Remove the corresponding PC range.
|
||||
if (ob)
|
||||
@@ -240,7 +245,7 @@ __deregister_frame_info_bases (const void *begin)
|
||||
uintptr_type range[2];
|
||||
get_pc_range (ob, range);
|
||||
if (range[0] != range[1])
|
||||
- btree_remove (®istered_frames, range[0]);
|
||||
+ btree_remove (®istered_frames, range[0]);
|
||||
}
|
||||
|
||||
// Deallocate the sort array if any.
|
||||
299
gcc-RHEL-105072-27.patch
Normal file
299
gcc-RHEL-105072-27.patch
Normal file
@ -0,0 +1,299 @@
|
||||
commit 21109b37e8585a7a1b27650fcbf1749380016108
|
||||
Author: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Mon Mar 10 10:34:00 2025 +0100
|
||||
|
||||
libgcc: Fix up unwind-dw2-btree.h [PR119151]
|
||||
|
||||
The following testcase shows a bug in unwind-dw2-btree.h.
|
||||
In short, the header provides lock-free btree data structure (so no parent
|
||||
link on nodes, both insertion and deletion are done in top-down walks
|
||||
with some locking of just a few nodes at a time so that lookups can notice
|
||||
concurrent modifications and retry, non-leaf (inner) nodes contain keys
|
||||
which are initially the base address of the left-most leaf entry of the
|
||||
following child (or all ones if there is none) minus one, insertion ensures
|
||||
balancing of the tree to ensure [d/2, d] entries filled through aggressive
|
||||
splitting if it sees a full tree while walking, deletion performs various
|
||||
operations like merging neighbour trees, merging into parent or moving some
|
||||
nodes from neighbour to the current one).
|
||||
What differs from the textbook implementations is mostly that the leaf nodes
|
||||
don't include just address as a key, but address range, address + size
|
||||
(where we don't insert any ranges with zero size) and the lookups can be
|
||||
performed for any address in the [address, address + size) range. The keys
|
||||
on inner nodes are still just address-1, so the child covers all nodes
|
||||
where addr <= key unless it is covered already in children to the left.
|
||||
The user (static executables or JIT) should always ensure there is no
|
||||
overlap in between any of the ranges.
|
||||
|
||||
In the testcase a bunch of insertions are done, always followed by one
|
||||
removal, followed by one insertion of a range slightly different from the
|
||||
removed one. E.g. in the first case [&code[0x50], &code[0x59]] range
|
||||
is removed and then we insert [&code[0x4c], &code[0x53]] range instead.
|
||||
This is valid, it doesn't overlap anything. But the problem is that some
|
||||
non-leaf (inner) one used the &code[0x4f] key (after the 11 insertions
|
||||
completely correctly). On removal, nothing adjusts the keys on the parent
|
||||
nodes (it really can't in the top-down only walk, the keys could be many nodes
|
||||
above it and unlike insertion, removal only knows the start address, doesn't
|
||||
know the removed size and so will discover it only when reaching the leaf
|
||||
node which contains it; plus even if it knew the address and size, it still
|
||||
doesn't know what the second left-most leaf node will be (i.e. the one after
|
||||
removal)). And on insertion, if nodes aren't split at a level, nothing
|
||||
adjusts the inner keys either. If a range is inserted and is either fully
|
||||
bellow key (keys are - 1, so having address + size - 1 being equal to key is
|
||||
fine) or fully after key (i.e. address > key), it works just fine, but if
|
||||
the key is in a middle of the range like in this case, &code[0x4f] is in the
|
||||
middle of the [&code[0x4c], &code[0x53]] range, then insertion works fine
|
||||
(we only use size on the leaf nodes), and lookup of the addresses below
|
||||
the key work fine too (i.e. [&code[0x4c], &code[0x4f]] will succeed).
|
||||
The problem is with lookups after the key (i.e. [&code[0x50, &code[0x53]]),
|
||||
the lookup looks for them in different children of the btree and doesn't
|
||||
find an entry and returns NULL.
|
||||
|
||||
As users need to ensure non-overlapping entries at any time, the following
|
||||
patch fixes it by adjusting keys during insertion where we know not just
|
||||
the address but also size; if we find during the top-down walk a key
|
||||
which is in the middle of the range being inserted, we simply increase the
|
||||
key to be equal to address + size - 1 of the range being inserted.
|
||||
There can't be any existing leaf nodes overlapping the range in correct
|
||||
programs and the btree rebalancing done on deletion ensures we don't have
|
||||
any empty nodes which would also cause problems.
|
||||
|
||||
The patch adjusts the keys in two spots, once for the current node being
|
||||
walked (the last hunk in the header, with large comment trying to explain
|
||||
it) and once during inner node splitting in a parent node if we'd otherwise
|
||||
try to add that key in the middle of the range being inserted into the
|
||||
parent node (in that case it would be missed in the last hunk).
|
||||
The testcase covers both of those spots, so succeeds with GCC 12 (which
|
||||
didn't have btrees) and fails with vanilla GCC trunk and also fails if
|
||||
either the
|
||||
if (fence < base + size - 1)
|
||||
fence = iter->content.children[slot].separator = base + size - 1;
|
||||
or
|
||||
if (left_fence >= target && left_fence < target + size - 1)
|
||||
left_fence = target + size - 1;
|
||||
hunk is removed (of course, only with the current node sizes, i.e. up to
|
||||
15 children of inner nodes and up to 10 entries in leaf nodes).
|
||||
|
||||
2025-03-10 Jakub Jelinek <jakub@redhat.com>
|
||||
Michael Leuchtenburg <michael@slashhome.org>
|
||||
|
||||
PR libgcc/119151
|
||||
* unwind-dw2-btree.h (btree_split_inner): Add size argument. If
|
||||
left_fence is in the middle of [target,target + size - 1] range,
|
||||
increase it to target + size - 1.
|
||||
(btree_insert): Adjust btree_split_inner caller. If fence is smaller
|
||||
than base + size - 1, increase it and separator of the slot to
|
||||
base + size - 1.
|
||||
|
||||
* gcc.dg/pr119151.c: New test.
|
||||
|
||||
diff --git a/gcc/testsuite/gcc.dg/pr119151.c b/gcc/testsuite/gcc.dg/pr119151.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..6ef0f12ce9ae6c06
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.dg/pr119151.c
|
||||
@@ -0,0 +1,151 @@
|
||||
+/* PR libgcc/119151 */
|
||||
+/* Should be run just on targets which don't have _Unwind_Find_FDE in libc.so. */
|
||||
+/* { dg-do run { target { { x86_64-*-linux* aarch64*-*-linux* powerpc64*-*-linux* riscv*-*-linux* } && lp64 } } } */
|
||||
+/* { dg-options "-O2" } */
|
||||
+
|
||||
+struct object
|
||||
+{
|
||||
+ void *pc_begin, *tbase, *dbase, *single;
|
||||
+ __SIZE_TYPE__ i;
|
||||
+ void *fde_end, *next;
|
||||
+};
|
||||
+struct dwarf_eh_bases
|
||||
+{
|
||||
+ void *tbase, *dbase, *func;
|
||||
+};
|
||||
+extern void __register_frame_info (const void *, struct object *);
|
||||
+extern void *__deregister_frame_info (const void *);
|
||||
+extern const void *_Unwind_Find_FDE (void *, struct dwarf_eh_bases *);
|
||||
+#define DW_EH_PE_sdata8 0x0c
|
||||
+#define DW_EH_PE_pcrel 0x10
|
||||
+#define DW_CFA_def_cfa 0x0c
|
||||
+#define DW_CFA_offset 0x80
|
||||
+
|
||||
+struct __attribute__((aligned (8))) eh_frame_cie {
|
||||
+ unsigned len;
|
||||
+ unsigned tag;
|
||||
+ unsigned char version;
|
||||
+ unsigned char augmentation[3];
|
||||
+ unsigned char code_align_factor;
|
||||
+ unsigned char data_align_factor;
|
||||
+ unsigned char ra_column;
|
||||
+ unsigned char augmentation_size;
|
||||
+ unsigned char encoding;
|
||||
+ unsigned char def_cfa;
|
||||
+ unsigned char def_cfa_op1, def_cfa_op2;
|
||||
+ unsigned char offset;
|
||||
+ unsigned char offset_op;
|
||||
+};
|
||||
+struct __attribute__((aligned (8))) eh_frame_fde {
|
||||
+ unsigned len;
|
||||
+ unsigned cie_offset;
|
||||
+ unsigned long long begin, size;
|
||||
+ unsigned char augmentation;
|
||||
+};
|
||||
+struct eh_frame_cie_fde {
|
||||
+ struct eh_frame_cie cie;
|
||||
+ struct eh_frame_fde fde;
|
||||
+ unsigned int zero;
|
||||
+ struct object obj;
|
||||
+} eh_frame[256];
|
||||
+unsigned ehidx;
|
||||
+unsigned char code[0x800] __attribute__((aligned (8)));
|
||||
+
|
||||
+void *
|
||||
+register_range (void *addr, unsigned size)
|
||||
+{
|
||||
+ /* Fills in empty-ish CIE and FDE with pcrel sdata8 encoding so that
|
||||
+ we don't need to worry about lp64 large code models.
|
||||
+ We don't actually execute anything in code and only _Unwind_Find_FDE,
|
||||
+ don't actually try to unwind anything. */
|
||||
+ eh_frame[ehidx].cie.len
|
||||
+ = (unsigned) ((char *) &eh_frame[ehidx].fde
|
||||
+ - (char *) &eh_frame[ehidx].cie.tag);
|
||||
+ eh_frame[ehidx].cie.tag = 0;
|
||||
+ eh_frame[ehidx].cie.version = 3;
|
||||
+ __builtin_memcpy (eh_frame[ehidx].cie.augmentation, "zR", 3);
|
||||
+ eh_frame[ehidx].cie.code_align_factor = 1;
|
||||
+ eh_frame[ehidx].cie.data_align_factor = 0x78; /* sleb128 -8 */
|
||||
+ eh_frame[ehidx].cie.ra_column = 0x10;
|
||||
+ eh_frame[ehidx].cie.augmentation_size = 1;
|
||||
+ eh_frame[ehidx].cie.encoding = DW_EH_PE_pcrel | DW_EH_PE_sdata8;
|
||||
+ eh_frame[ehidx].cie.def_cfa = DW_CFA_def_cfa;
|
||||
+ eh_frame[ehidx].cie.def_cfa_op1 = 7;
|
||||
+ eh_frame[ehidx].cie.def_cfa_op2 = 8;
|
||||
+ eh_frame[ehidx].cie.offset = DW_CFA_offset + 0x10;
|
||||
+ eh_frame[ehidx].cie.offset_op = 1;
|
||||
+ eh_frame[ehidx].fde.len
|
||||
+ = (unsigned) ((char *) &eh_frame[ehidx].zero
|
||||
+ - (char *) &eh_frame[ehidx].fde.cie_offset);
|
||||
+ eh_frame[ehidx].fde.cie_offset
|
||||
+ = (unsigned) ((char *) &eh_frame[ehidx].fde.cie_offset
|
||||
+ - (char *) &eh_frame[ehidx].cie);
|
||||
+ eh_frame[ehidx].fde.begin
|
||||
+ = (__INTPTR_TYPE__) ((__UINTPTR_TYPE__) addr
|
||||
+ - (__UINTPTR_TYPE__) &eh_frame[ehidx].fde.begin);
|
||||
+ eh_frame[ehidx].fde.size = size;
|
||||
+ eh_frame[ehidx].fde.augmentation = 0;
|
||||
+ eh_frame[ehidx].zero = 0;
|
||||
+ __register_frame_info (&eh_frame[ehidx].cie, &eh_frame[ehidx].obj);
|
||||
+ ++ehidx;
|
||||
+ return &eh_frame[ehidx - 1].cie;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+unregister (void *eh_frame)
|
||||
+{
|
||||
+ __deregister_frame_info (eh_frame);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+ for (int i = 0; i < 0x50; i += 0x10)
|
||||
+ register_range (&code[i], 10);
|
||||
+ void *p = register_range (&code[0x50], 10);
|
||||
+ for (int i = 0x60; i < 0xb0; i += 0x10)
|
||||
+ register_range (&code[i], 10);
|
||||
+ unregister (p);
|
||||
+ register_range (&code[0x4c], 8);
|
||||
+ struct dwarf_eh_bases bases;
|
||||
+ const void *q = _Unwind_Find_FDE (&code[0x4c], &bases);
|
||||
+ const void *r = _Unwind_Find_FDE (&code[0x51], &bases);
|
||||
+ if (!q || q != r)
|
||||
+ __builtin_abort ();
|
||||
+ for (int i = 0; i <= 0xa0; i += 0x10)
|
||||
+ if (i != 0x50)
|
||||
+ {
|
||||
+ q = _Unwind_Find_FDE (&code[i], &bases);
|
||||
+ r = _Unwind_Find_FDE (&code[i + 9], &bases);
|
||||
+ if (!q || q != r)
|
||||
+ __builtin_abort ();
|
||||
+ }
|
||||
+ for (int i = 0xb0; i < 0x240; i += 0x10)
|
||||
+ register_range (&code[i], 10);
|
||||
+ p = register_range (&code[0x240], 10);
|
||||
+ for (int i = 0x250; i < 0x470; i += 0x10)
|
||||
+ register_range (&code[i], 10);
|
||||
+ void *s = register_range (&code[0x470], 10);
|
||||
+ for (int i = 0x480; i < 0x700; i += 0x10)
|
||||
+ register_range (&code[i], 10);
|
||||
+ unregister (p);
|
||||
+ register_range (&code[0x23c], 16);
|
||||
+ q = _Unwind_Find_FDE (&code[0x23d], &bases);
|
||||
+ r = _Unwind_Find_FDE (&code[0x24b], &bases);
|
||||
+ if (!q || q != r)
|
||||
+ __builtin_abort ();
|
||||
+ unregister (s);
|
||||
+ register_range (&code[0x46c], 16);
|
||||
+ q = _Unwind_Find_FDE (&code[0x46d], &bases);
|
||||
+ r = _Unwind_Find_FDE (&code[0x47b], &bases);
|
||||
+ if (!q || q != r)
|
||||
+ __builtin_abort ();
|
||||
+ for (int i = 0; i < 0x700; i += 0x10)
|
||||
+ if (i != 0x50 && i != 0x240 && i != 0x470)
|
||||
+ {
|
||||
+ q = _Unwind_Find_FDE (&code[i], &bases);
|
||||
+ r = _Unwind_Find_FDE (&code[i + 9], &bases);
|
||||
+ if (!q || q != r)
|
||||
+ __builtin_abort ();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/libgcc/unwind-dw2-btree.h b/libgcc/unwind-dw2-btree.h
|
||||
index ace507d9ffbdffb7..e3f3a11a7b5443d6 100644
|
||||
--- a/libgcc/unwind-dw2-btree.h
|
||||
+++ b/libgcc/unwind-dw2-btree.h
|
||||
@@ -474,7 +474,8 @@ btree_handle_root_split (struct btree *t, struct btree_node **node,
|
||||
// Split an inner node.
|
||||
static void
|
||||
btree_split_inner (struct btree *t, struct btree_node **inner,
|
||||
- struct btree_node **parent, uintptr_type target)
|
||||
+ struct btree_node **parent, uintptr_type target,
|
||||
+ uintptr_type size)
|
||||
{
|
||||
// Check for the root.
|
||||
btree_handle_root_split (t, inner, parent);
|
||||
@@ -490,6 +491,9 @@ btree_split_inner (struct btree *t, struct btree_node **inner,
|
||||
= left_inner->content.children[split + index];
|
||||
left_inner->entry_count = split;
|
||||
uintptr_type left_fence = btree_node_get_fence_key (left_inner);
|
||||
+ if (left_fence >= target && left_fence < target + size - 1)
|
||||
+ // See the PR119151 comment in btree_insert.
|
||||
+ left_fence = target + size - 1;
|
||||
btree_node_update_separator_after_split (*parent, right_fence, left_fence,
|
||||
right_inner);
|
||||
if (target <= left_fence)
|
||||
@@ -753,13 +757,28 @@ btree_insert (struct btree *t, uintptr_type base, uintptr_type size,
|
||||
{
|
||||
// Use eager splits to avoid lock coupling up.
|
||||
if (iter->entry_count == max_fanout_inner)
|
||||
- btree_split_inner (t, &iter, &parent, base);
|
||||
+ btree_split_inner (t, &iter, &parent, base, size);
|
||||
|
||||
unsigned slot = btree_node_find_inner_slot (iter, base);
|
||||
if (parent)
|
||||
btree_node_unlock_exclusive (parent);
|
||||
parent = iter;
|
||||
fence = iter->content.children[slot].separator;
|
||||
+ if (fence < base + size - 1)
|
||||
+ // The separator was set to the base - 1 of the leftmost leaf child
|
||||
+ // at some point but such an entry could have been removed afterwards.
|
||||
+ // As both insertion and removal are just walking down the tree with
|
||||
+ // only a few current nodes locked at a time, updating the separator
|
||||
+ // on removal is not possible, especially because btree_remove does
|
||||
+ // not know the size until it reaches leaf node. We must ensure that
|
||||
+ // the separator is not in a middle of some entry though, as
|
||||
+ // btree_lookup can look up any address in the entry's range and if
|
||||
+ // the separator is in the middle, addresses below it or equal to it
|
||||
+ // would be found while addresses above it would result in failed
|
||||
+ // lookup. Update the separator now. Assumption that users
|
||||
+ // ensure no overlapping registered ranges, there should be no
|
||||
+ // current entry for any address in the range. See PR119151.
|
||||
+ fence = iter->content.children[slot].separator = base + size - 1;
|
||||
iter = iter->content.children[slot].child;
|
||||
btree_node_lock_exclusive (iter);
|
||||
}
|
||||
204
gcc-RHEL-105072-3.patch
Normal file
204
gcc-RHEL-105072-3.patch
Normal file
@ -0,0 +1,204 @@
|
||||
commit 9488d24206687be80443dafdb2cdfc4ff3aca28c
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Nov 25 18:40:51 2021 +0100
|
||||
|
||||
libgcc: Split FDE search code from PT_GNU_EH_FRAME lookup
|
||||
|
||||
This allows switching to a different implementation for
|
||||
PT_GNU_EH_FRAME lookup in a subsequent commit.
|
||||
|
||||
This moves some of the PT_GNU_EH_FRAME parsing out of the glibc loader
|
||||
lock that is implied by dl_iterate_phdr. However, the FDE is already
|
||||
parsed outside the lock before this change, so this does not introduce
|
||||
additional crashes in case of a concurrent dlclose.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
|
||||
* unwind-dw2-fde-dip.c (struct unw_eh_callback_data): Add hdr.
|
||||
Remove func, ret.
|
||||
(find_fde_tail): New function. Split from
|
||||
_Unwind_IteratePhdrCallback. Move the result initialization
|
||||
from _Unwind_Find_FDE.
|
||||
(_Unwind_Find_FDE): Updated to call find_fde_tail.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
|
||||
index 3f302826d2d49074..fbb0fbdebb92d484 100644
|
||||
--- a/libgcc/unwind-dw2-fde-dip.c
|
||||
+++ b/libgcc/unwind-dw2-fde-dip.c
|
||||
@@ -113,8 +113,7 @@ struct unw_eh_callback_data
|
||||
#if NEED_DBASE_MEMBER
|
||||
void *dbase;
|
||||
#endif
|
||||
- void *func;
|
||||
- const fde *ret;
|
||||
+ const struct unw_eh_frame_hdr *hdr;
|
||||
int check_cache;
|
||||
};
|
||||
|
||||
@@ -197,10 +196,6 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
#else
|
||||
_Unwind_Ptr load_base;
|
||||
#endif
|
||||
- const unsigned char *p;
|
||||
- const struct unw_eh_frame_hdr *hdr;
|
||||
- _Unwind_Ptr eh_frame;
|
||||
- struct object ob;
|
||||
_Unwind_Ptr pc_low = 0, pc_high = 0;
|
||||
|
||||
struct ext_dl_phdr_info
|
||||
@@ -348,10 +343,8 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
return 0;
|
||||
|
||||
/* Read .eh_frame_hdr header. */
|
||||
- hdr = (const struct unw_eh_frame_hdr *)
|
||||
+ data->hdr = (const struct unw_eh_frame_hdr *)
|
||||
__RELOC_POINTER (p_eh_frame_hdr->p_vaddr, load_base);
|
||||
- if (hdr->version != 1)
|
||||
- return 1;
|
||||
|
||||
#ifdef CRT_GET_RFIB_DATA
|
||||
# if defined __i386__ || defined __nios2__
|
||||
@@ -383,12 +376,30 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
- _Unwind_Ptr dbase = unw_eh_callback_data_dbase (data);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+/* Find the FDE for the program counter PC, in a previously located
|
||||
+ PT_GNU_EH_FRAME data region. *BASES is updated if an FDE to return is
|
||||
+ found. */
|
||||
+
|
||||
+static const fde *
|
||||
+find_fde_tail (_Unwind_Ptr pc,
|
||||
+ const struct unw_eh_frame_hdr *hdr,
|
||||
+ _Unwind_Ptr dbase,
|
||||
+ struct dwarf_eh_bases *bases)
|
||||
+{
|
||||
+ const unsigned char *p = (const unsigned char *) (hdr + 1);
|
||||
+ _Unwind_Ptr eh_frame;
|
||||
+ struct object ob;
|
||||
+
|
||||
+ if (hdr->version != 1)
|
||||
+ return NULL;
|
||||
+
|
||||
p = read_encoded_value_with_base (hdr->eh_frame_ptr_enc,
|
||||
base_from_cb_data (hdr->eh_frame_ptr_enc,
|
||||
dbase),
|
||||
- (const unsigned char *) (hdr + 1),
|
||||
- &eh_frame);
|
||||
+ p, &eh_frame);
|
||||
|
||||
/* We require here specific table encoding to speed things up.
|
||||
Also, DW_EH_PE_datarel here means using PT_GNU_EH_FRAME start
|
||||
@@ -404,7 +415,7 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
p, &fde_count);
|
||||
/* Shouldn't happen. */
|
||||
if (fde_count == 0)
|
||||
- return 1;
|
||||
+ return NULL;
|
||||
if ((((_Unwind_Ptr) p) & 3) == 0)
|
||||
{
|
||||
struct fde_table {
|
||||
@@ -419,9 +430,9 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
_Unwind_Ptr range;
|
||||
|
||||
mid = fde_count - 1;
|
||||
- if (data->pc < table[0].initial_loc + data_base)
|
||||
- return 1;
|
||||
- else if (data->pc < table[mid].initial_loc + data_base)
|
||||
+ if (pc < table[0].initial_loc + data_base)
|
||||
+ return NULL;
|
||||
+ else if (pc < table[mid].initial_loc + data_base)
|
||||
{
|
||||
lo = 0;
|
||||
hi = mid;
|
||||
@@ -429,9 +440,9 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
while (lo < hi)
|
||||
{
|
||||
mid = (lo + hi) / 2;
|
||||
- if (data->pc < table[mid].initial_loc + data_base)
|
||||
+ if (pc < table[mid].initial_loc + data_base)
|
||||
hi = mid;
|
||||
- else if (data->pc >= table[mid + 1].initial_loc + data_base)
|
||||
+ else if (pc >= table[mid + 1].initial_loc + data_base)
|
||||
lo = mid + 1;
|
||||
else
|
||||
break;
|
||||
@@ -445,10 +456,16 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
f_enc_size = size_of_encoded_value (f_enc);
|
||||
read_encoded_value_with_base (f_enc & 0x0f, 0,
|
||||
&f->pc_begin[f_enc_size], &range);
|
||||
- if (data->pc < table[mid].initial_loc + data_base + range)
|
||||
- data->ret = f;
|
||||
- data->func = (void *) (table[mid].initial_loc + data_base);
|
||||
- return 1;
|
||||
+ _Unwind_Ptr func = table[mid].initial_loc + data_base;
|
||||
+ if (pc < table[mid].initial_loc + data_base + range)
|
||||
+ {
|
||||
+ bases->tbase = NULL;
|
||||
+ bases->dbase = (void *) dbase;
|
||||
+ bases->func = (void *) func;
|
||||
+ return f;
|
||||
+ }
|
||||
+ else
|
||||
+ return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,18 +478,20 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||
ob.u.single = (fde *) eh_frame;
|
||||
ob.s.i = 0;
|
||||
ob.s.b.mixed_encoding = 1; /* Need to assume worst case. */
|
||||
- data->ret = linear_search_fdes (&ob, (fde *) eh_frame, (void *) data->pc);
|
||||
- if (data->ret != NULL)
|
||||
+ const fde *entry = linear_search_fdes (&ob, (fde *) eh_frame, (void *) pc);
|
||||
+ if (entry != NULL)
|
||||
{
|
||||
_Unwind_Ptr func;
|
||||
- unsigned int encoding = get_fde_encoding (data->ret);
|
||||
+ unsigned int encoding = get_fde_encoding (entry);
|
||||
|
||||
read_encoded_value_with_base (encoding,
|
||||
base_from_cb_data (encoding, dbase),
|
||||
- data->ret->pc_begin, &func);
|
||||
- data->func = (void *) func;
|
||||
+ entry->pc_begin, &func);
|
||||
+ bases->tbase = NULL;
|
||||
+ bases->dbase = (void *) dbase;
|
||||
+ bases->func = (void *) func;
|
||||
}
|
||||
- return 1;
|
||||
+ return entry;
|
||||
}
|
||||
|
||||
const fde *
|
||||
@@ -489,24 +508,13 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
|
||||
#if NEED_DBASE_MEMBER
|
||||
data.dbase = NULL;
|
||||
#endif
|
||||
- data.func = NULL;
|
||||
- data.ret = NULL;
|
||||
data.check_cache = 1;
|
||||
|
||||
- if (dl_iterate_phdr (_Unwind_IteratePhdrCallback, &data) < 0)
|
||||
+ if (dl_iterate_phdr (_Unwind_IteratePhdrCallback, &data) <= 0)
|
||||
return NULL;
|
||||
|
||||
- if (data.ret)
|
||||
- {
|
||||
- bases->tbase = NULL;
|
||||
-#if NEED_DBASE_MEMBER
|
||||
- bases->dbase = data.dbase;
|
||||
-#else
|
||||
- bases->dbase = NULL;
|
||||
-#endif
|
||||
- bases->func = data.func;
|
||||
- }
|
||||
- return data.ret;
|
||||
+ _Unwind_Ptr dbase = unw_eh_callback_data_dbase (&data);
|
||||
+ return find_fde_tail ((_Unwind_Ptr) pc, data.hdr, dbase, bases);
|
||||
}
|
||||
|
||||
#else
|
||||
40
gcc-RHEL-105072-4.patch
Normal file
40
gcc-RHEL-105072-4.patch
Normal file
@ -0,0 +1,40 @@
|
||||
commit 790854ea7670f11c14d431c102a49181d2915965
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Jan 4 15:47:30 2022 +0100
|
||||
|
||||
libgcc: Use _dl_find_object in _Unwind_Find_FDE
|
||||
|
||||
libgcc/ChangeLog:
|
||||
|
||||
* unwind-dw2-fde-dip.c (_Unwind_Find_FDE): Call _dl_find_object
|
||||
if available.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
|
||||
index fbb0fbdebb92d484..b837d8e490425652 100644
|
||||
--- a/libgcc/unwind-dw2-fde-dip.c
|
||||
+++ b/libgcc/unwind-dw2-fde-dip.c
|
||||
@@ -504,6 +504,24 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
|
||||
if (ret != NULL)
|
||||
return ret;
|
||||
|
||||
+ /* Use DLFO_STRUCT_HAS_EH_DBASE as a proxy for the existence of a glibc-style
|
||||
+ _dl_find_object function. */
|
||||
+#ifdef DLFO_STRUCT_HAS_EH_DBASE
|
||||
+ {
|
||||
+ struct dl_find_object dlfo;
|
||||
+ if (_dl_find_object (pc, &dlfo) == 0)
|
||||
+ return find_fde_tail ((_Unwind_Ptr) pc, dlfo.dlfo_eh_frame,
|
||||
+# if DLFO_STRUCT_HAS_EH_DBASE
|
||||
+ (_Unwind_Ptr) dlfo.dlfo_eh_dbase,
|
||||
+# else
|
||||
+ NULL,
|
||||
+# endif
|
||||
+ bases);
|
||||
+ else
|
||||
+ return NULL;
|
||||
+ }
|
||||
+#endif /* DLFO_STRUCT_HAS_EH_DBASE */
|
||||
+
|
||||
data.pc = (_Unwind_Ptr) pc;
|
||||
#if NEED_DBASE_MEMBER
|
||||
data.dbase = NULL;
|
||||
27
gcc-RHEL-105072-5.patch
Normal file
27
gcc-RHEL-105072-5.patch
Normal file
@ -0,0 +1,27 @@
|
||||
commit ab2a2457780d224343ce05e7d8e2964c6a47fd83
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Jan 25 12:09:56 2022 +0100
|
||||
|
||||
libgcc: Fix _Unwind_Find_FDE for missing unwind data with glibc 2.35
|
||||
|
||||
_dl_find_object returns success even if no unwind information has been
|
||||
found, and dlfo_eh_frame is NULL.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
|
||||
PR libgcc/104207
|
||||
* unwind-dw2-fde-dip.c (_Unwind_Find_FDE): Add NULL check.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
|
||||
index b837d8e490425652..1744c91958013ebb 100644
|
||||
--- a/libgcc/unwind-dw2-fde-dip.c
|
||||
+++ b/libgcc/unwind-dw2-fde-dip.c
|
||||
@@ -509,7 +509,7 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
|
||||
#ifdef DLFO_STRUCT_HAS_EH_DBASE
|
||||
{
|
||||
struct dl_find_object dlfo;
|
||||
- if (_dl_find_object (pc, &dlfo) == 0)
|
||||
+ if (_dl_find_object (pc, &dlfo) == 0 && dlfo.dlfo_eh_frame != NULL)
|
||||
return find_fde_tail ((_Unwind_Ptr) pc, dlfo.dlfo_eh_frame,
|
||||
# if DLFO_STRUCT_HAS_EH_DBASE
|
||||
(_Unwind_Ptr) dlfo.dlfo_eh_dbase,
|
||||
28
gcc-RHEL-105072-6.patch
Normal file
28
gcc-RHEL-105072-6.patch
Normal file
@ -0,0 +1,28 @@
|
||||
commit 157cc4e0117756503c7c63df97cf31de7570b088
|
||||
Author: Xi Ruoyao <xry111@mengyan1223.wang>
|
||||
Date: Fri Feb 25 01:45:57 2022 +0800
|
||||
|
||||
libgcc: fix a warning calling find_fde_tail
|
||||
|
||||
The third parameter of find_fde_tail is an _Unwind_Ptr (which is an
|
||||
integer type instead of a pointer), but we are passing NULL to it. This
|
||||
causes a -Wint-conversion warning.
|
||||
|
||||
libgcc/
|
||||
|
||||
* unwind-dw2-fde-dip.c (_Unwind_Find_FDE): Call find_fde_tail
|
||||
with 0 instead of NULL.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
|
||||
index 1744c91958013ebb..25f2e44c5823cf64 100644
|
||||
--- a/libgcc/unwind-dw2-fde-dip.c
|
||||
+++ b/libgcc/unwind-dw2-fde-dip.c
|
||||
@@ -514,7 +514,7 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
|
||||
# if DLFO_STRUCT_HAS_EH_DBASE
|
||||
(_Unwind_Ptr) dlfo.dlfo_eh_dbase,
|
||||
# else
|
||||
- NULL,
|
||||
+ 0,
|
||||
# endif
|
||||
bases);
|
||||
else
|
||||
222
gcc-RHEL-105072-7.patch
Normal file
222
gcc-RHEL-105072-7.patch
Normal file
@ -0,0 +1,222 @@
|
||||
commit 0d344b557604e966dc7f91739881f03e1f221efd
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Thu Feb 10 17:42:56 2022 +0000
|
||||
|
||||
aarch64: Fix pac-ret with unusual dwarf in libgcc unwinder [PR104689]
|
||||
|
||||
The RA_SIGN_STATE dwarf pseudo-register is normally only set using the
|
||||
DW_CFA_AARCH64_negate_ra_state (== DW_CFA_window_save) operation which
|
||||
toggles the return address signedness state (the default state is 0).
|
||||
(It may be set by remember/restore_state CFI too, those save/restore
|
||||
the state of all registers.)
|
||||
|
||||
However RA_SIGN_STATE can be set directly via DW_CFA_val_expression too.
|
||||
GCC does not generate such CFI but some other compilers reportedly do.
|
||||
|
||||
Note: the toggle operation must not be mixed with other dwarf register
|
||||
rule CFI within the same CIE and FDE.
|
||||
|
||||
In libgcc we assume REG_UNSAVED means the RA_STATE is set using toggle
|
||||
operations, otherwise we assume its value is set by other CFI.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
|
||||
PR target/104689
|
||||
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
|
||||
Handle the !REG_UNSAVED case.
|
||||
* unwind-dw2.c (execute_cfa_program): Fail toggle if !REG_UNSAVED.
|
||||
|
||||
gcc/testsuite/ChangeLog:
|
||||
|
||||
PR target/104689
|
||||
* gcc.target/aarch64/pr104689.c: New test.
|
||||
|
||||
diff --git a/gcc/testsuite/gcc.target/aarch64/pr104689.c b/gcc/testsuite/gcc.target/aarch64/pr104689.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..3b7adbdfe7d6f969
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gcc.target/aarch64/pr104689.c
|
||||
@@ -0,0 +1,149 @@
|
||||
+/* PR target/104689. Unwind across pac-ret frames with unusual dwarf. */
|
||||
+/* { dg-do run } */
|
||||
+/* { dg-require-effective-target lp64 } */
|
||||
+/* { dg-options "-fexceptions -O2" } */
|
||||
+
|
||||
+#include <unwind.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+#define die() \
|
||||
+ do { \
|
||||
+ printf ("%s:%d: reached unexpectedly.\n", __FILE__, __LINE__); \
|
||||
+ fflush (stdout); \
|
||||
+ abort (); \
|
||||
+ } while (0)
|
||||
+
|
||||
+
|
||||
+/* Code to invoke unwinding with a logging callback. */
|
||||
+
|
||||
+static struct _Unwind_Exception exc;
|
||||
+
|
||||
+static _Unwind_Reason_Code
|
||||
+force_unwind_stop (int version, _Unwind_Action actions,
|
||||
+ _Unwind_Exception_Class exc_class,
|
||||
+ struct _Unwind_Exception *exc_obj,
|
||||
+ struct _Unwind_Context *context,
|
||||
+ void *stop_parameter)
|
||||
+{
|
||||
+ printf ("%s: CFA: %p PC: %p actions: %d\n",
|
||||
+ __func__,
|
||||
+ (void *)_Unwind_GetCFA (context),
|
||||
+ (void *)_Unwind_GetIP (context),
|
||||
+ (int)actions);
|
||||
+ if (actions & _UA_END_OF_STACK)
|
||||
+ die ();
|
||||
+ return _URC_NO_REASON;
|
||||
+}
|
||||
+
|
||||
+static void force_unwind (void)
|
||||
+{
|
||||
+#ifndef __USING_SJLJ_EXCEPTIONS__
|
||||
+ _Unwind_ForcedUnwind (&exc, force_unwind_stop, 0);
|
||||
+#else
|
||||
+ _Unwind_SjLj_ForcedUnwind (&exc, force_unwind_stop, 0);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Define functions with unusual pac-ret dwarf via top level asm. */
|
||||
+
|
||||
+#define STR(x) #x
|
||||
+#define DW_CFA_val_expression 0x16
|
||||
+#define RA_SIGN_STATE 34
|
||||
+#define DW_OP_lit0 0x30
|
||||
+#define DW_OP_lit1 0x31
|
||||
+
|
||||
+#define cfi_escape(a1, a2, a3, a4) \
|
||||
+ ".cfi_escape " STR(a1) ", " STR(a2) ", " STR(a3) ", " STR(a4)
|
||||
+
|
||||
+/* Bytes: 0x16 0x22 0x01 0x30 */
|
||||
+#define SET_RA_STATE_0 \
|
||||
+ cfi_escape (DW_CFA_val_expression, RA_SIGN_STATE, 1, DW_OP_lit0)
|
||||
+
|
||||
+/* Bytes: 0x16 0x22 0x01 0x31 */
|
||||
+#define SET_RA_STATE_1 \
|
||||
+ cfi_escape (DW_CFA_val_expression, RA_SIGN_STATE, 1, DW_OP_lit1)
|
||||
+
|
||||
+/* These function call their argument. */
|
||||
+void unusual_pac_ret (void *);
|
||||
+void unusual_no_pac_ret (void *);
|
||||
+
|
||||
+asm(""
|
||||
+".global unusual_pac_ret\n"
|
||||
+".type unusual_pac_ret, %function\n"
|
||||
+"unusual_pac_ret:\n"
|
||||
+" .cfi_startproc\n"
|
||||
+" " SET_RA_STATE_0 "\n"
|
||||
+" hint 25 // paciasp\n"
|
||||
+" " SET_RA_STATE_1 "\n"
|
||||
+" stp x29, x30, [sp, -16]!\n"
|
||||
+" .cfi_def_cfa_offset 16\n"
|
||||
+" .cfi_offset 29, -16\n"
|
||||
+" .cfi_offset 30, -8\n"
|
||||
+" mov x29, sp\n"
|
||||
+" blr x0\n"
|
||||
+" ldp x29, x30, [sp], 16\n"
|
||||
+" .cfi_restore 30\n"
|
||||
+" .cfi_restore 29\n"
|
||||
+" .cfi_def_cfa_offset 0\n"
|
||||
+" hint 29 // autiasp\n"
|
||||
+" " SET_RA_STATE_0 "\n"
|
||||
+" ret\n"
|
||||
+" .cfi_endproc\n");
|
||||
+
|
||||
+asm(""
|
||||
+".global unusual_no_pac_ret\n"
|
||||
+".type unusual_no_pac_ret, %function\n"
|
||||
+"unusual_no_pac_ret:\n"
|
||||
+" .cfi_startproc\n"
|
||||
+" " SET_RA_STATE_0 "\n"
|
||||
+" stp x29, x30, [sp, -16]!\n"
|
||||
+" .cfi_def_cfa_offset 16\n"
|
||||
+" .cfi_offset 29, -16\n"
|
||||
+" .cfi_offset 30, -8\n"
|
||||
+" mov x29, sp\n"
|
||||
+" blr x0\n"
|
||||
+" ldp x29, x30, [sp], 16\n"
|
||||
+" .cfi_restore 30\n"
|
||||
+" .cfi_restore 29\n"
|
||||
+" .cfi_def_cfa_offset 0\n"
|
||||
+" ret\n"
|
||||
+" .cfi_endproc\n");
|
||||
+
|
||||
+
|
||||
+/* Functions to create a call chain with mixed pac-ret dwarf. */
|
||||
+
|
||||
+__attribute__((target("branch-protection=pac-ret")))
|
||||
+static void f2_pac_ret (void)
|
||||
+{
|
||||
+ force_unwind ();
|
||||
+ die ();
|
||||
+}
|
||||
+
|
||||
+__attribute__((target("branch-protection=none")))
|
||||
+static void f1_no_pac_ret (void)
|
||||
+{
|
||||
+ unusual_pac_ret (f2_pac_ret);
|
||||
+ die ();
|
||||
+}
|
||||
+
|
||||
+__attribute__((noinline, target("branch-protection=pac-ret")))
|
||||
+static void f0_pac_ret (void)
|
||||
+{
|
||||
+ unusual_no_pac_ret (f1_no_pac_ret);
|
||||
+ die ();
|
||||
+}
|
||||
+
|
||||
+static void cleanup_handler (void *p)
|
||||
+{
|
||||
+ printf ("%s: Success.\n", __func__);
|
||||
+ exit (0);
|
||||
+}
|
||||
+
|
||||
+int main ()
|
||||
+{
|
||||
+ char dummy __attribute__((cleanup (cleanup_handler)));
|
||||
+ f0_pac_ret ();
|
||||
+ die ();
|
||||
+}
|
||||
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
|
||||
index b6faa9b495094d8e..3158af4c8c371fac 100644
|
||||
--- a/libgcc/config/aarch64/aarch64-unwind.h
|
||||
+++ b/libgcc/config/aarch64/aarch64-unwind.h
|
||||
@@ -78,7 +78,13 @@ static inline void
|
||||
aarch64_frob_update_context (struct _Unwind_Context *context,
|
||||
_Unwind_FrameState *fs)
|
||||
{
|
||||
- if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
|
||||
+ const int reg = DWARF_REGNUM_AARCH64_RA_STATE;
|
||||
+ int ra_signed;
|
||||
+ if (fs->regs.reg[reg].how == REG_UNSAVED)
|
||||
+ ra_signed = fs->regs.reg[reg].loc.offset & 0x1;
|
||||
+ else
|
||||
+ ra_signed = _Unwind_GetGR (context, reg) & 0x1;
|
||||
+ if (ra_signed)
|
||||
/* The flag is used for re-authenticating EH handler's address. */
|
||||
context->flags |= RA_SIGNED_BIT;
|
||||
else
|
||||
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
|
||||
index 41af7e23f47602ec..43d06531fce9bed1 100644
|
||||
--- a/libgcc/unwind-dw2.c
|
||||
+++ b/libgcc/unwind-dw2.c
|
||||
@@ -1204,7 +1204,9 @@ execute_cfa_program (const unsigned char *insn_ptr,
|
||||
#if defined (__aarch64__) && !defined (__ILP32__)
|
||||
/* This CFA is multiplexed with Sparc. On AArch64 it's used to toggle
|
||||
return address signing status. */
|
||||
- fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
|
||||
+ reg = DWARF_REGNUM_AARCH64_RA_STATE;
|
||||
+ gcc_assert (fs->regs.reg[reg].how == REG_UNSAVED);
|
||||
+ fs->regs.reg[reg].loc.offset ^= 1;
|
||||
#else
|
||||
/* ??? Hardcoded for SPARC register window configuration. */
|
||||
if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
|
||||
1354
gcc-RHEL-105072-8.patch
Normal file
1354
gcc-RHEL-105072-8.patch
Normal file
File diff suppressed because it is too large
Load Diff
377
gcc-RHEL-105072-9.patch
Normal file
377
gcc-RHEL-105072-9.patch
Normal file
@ -0,0 +1,377 @@
|
||||
commit d458f806afe07d1e06bdf275e94d05a716f41bf6
|
||||
Author: Thomas Neumann <tneumann@users.sourceforge.net>
|
||||
Date: Sun Sep 18 11:31:01 2022 +0200
|
||||
|
||||
Remove dependency on uintptr_t in libgcc
|
||||
|
||||
uintptr_t is no available for all targets, use __UINTPTR_TYPE__
|
||||
instead.
|
||||
|
||||
libgcc/ChangeLog:
|
||||
|
||||
* unwind-dw2-fde.c: Replace uintptr_t with typedef
|
||||
for __UINTPTR_TYPE__.
|
||||
* unwind-dw2-btree.h: Likewise.
|
||||
|
||||
diff --git a/libgcc/unwind-dw2-btree.h b/libgcc/unwind-dw2-btree.h
|
||||
index 8853f0eab486b847..ace507d9ffbdffb7 100644
|
||||
--- a/libgcc/unwind-dw2-btree.h
|
||||
+++ b/libgcc/unwind-dw2-btree.h
|
||||
@@ -39,7 +39,7 @@ struct version_lock
|
||||
// range. Even on 32 bit platforms that would require 1 billion
|
||||
// frame registrations within the time span of a few assembler
|
||||
// instructions.
|
||||
- uintptr_t version_lock;
|
||||
+ uintptr_type version_lock;
|
||||
};
|
||||
|
||||
#ifdef __GTHREAD_HAS_COND
|
||||
@@ -60,7 +60,7 @@ version_lock_initialize_locked_exclusive (struct version_lock *vl)
|
||||
static inline bool
|
||||
version_lock_try_lock_exclusive (struct version_lock *vl)
|
||||
{
|
||||
- uintptr_t state = __atomic_load_n (&(vl->version_lock), __ATOMIC_SEQ_CST);
|
||||
+ uintptr_type state = __atomic_load_n (&(vl->version_lock), __ATOMIC_SEQ_CST);
|
||||
if (state & 1)
|
||||
return false;
|
||||
return __atomic_compare_exchange_n (&(vl->version_lock), &state, state | 1,
|
||||
@@ -78,7 +78,7 @@ restart:
|
||||
|
||||
// We should virtually never get contention here, as frame
|
||||
// changes are rare.
|
||||
- uintptr_t state = __atomic_load_n (&(vl->version_lock), __ATOMIC_SEQ_CST);
|
||||
+ uintptr_type state = __atomic_load_n (&(vl->version_lock), __ATOMIC_SEQ_CST);
|
||||
if (!(state & 1))
|
||||
{
|
||||
if (__atomic_compare_exchange_n (&(vl->version_lock), &state, state | 1,
|
||||
@@ -134,8 +134,8 @@ static void
|
||||
version_lock_unlock_exclusive (struct version_lock *vl)
|
||||
{
|
||||
// increase version, reset exclusive lock bits
|
||||
- uintptr_t state = __atomic_load_n (&(vl->version_lock), __ATOMIC_SEQ_CST);
|
||||
- uintptr_t ns = (state + 4) & (~((uintptr_t) 3));
|
||||
+ uintptr_type state = __atomic_load_n (&(vl->version_lock), __ATOMIC_SEQ_CST);
|
||||
+ uintptr_type ns = (state + 4) & (~((uintptr_type) 3));
|
||||
state = __atomic_exchange_n (&(vl->version_lock), ns, __ATOMIC_SEQ_CST);
|
||||
|
||||
#ifdef __GTHREAD_HAS_COND
|
||||
@@ -152,9 +152,9 @@ version_lock_unlock_exclusive (struct version_lock *vl)
|
||||
// Acquire an optimistic "lock". Note that this does not lock at all, it
|
||||
// only allows for validation later.
|
||||
static inline bool
|
||||
-version_lock_lock_optimistic (const struct version_lock *vl, uintptr_t *lock)
|
||||
+version_lock_lock_optimistic (const struct version_lock *vl, uintptr_type *lock)
|
||||
{
|
||||
- uintptr_t state = __atomic_load_n (&(vl->version_lock), __ATOMIC_SEQ_CST);
|
||||
+ uintptr_type state = __atomic_load_n (&(vl->version_lock), __ATOMIC_SEQ_CST);
|
||||
*lock = state;
|
||||
|
||||
// Acquiring the lock fails when there is currently an exclusive lock.
|
||||
@@ -163,7 +163,7 @@ version_lock_lock_optimistic (const struct version_lock *vl, uintptr_t *lock)
|
||||
|
||||
// Validate a previously acquired "lock".
|
||||
static inline bool
|
||||
-version_lock_validate (const struct version_lock *vl, uintptr_t lock)
|
||||
+version_lock_validate (const struct version_lock *vl, uintptr_type lock)
|
||||
{
|
||||
// Prevent the reordering of non-atomic loads behind the atomic load.
|
||||
// Hans Boehm, Can Seqlocks Get Along with Programming Language Memory
|
||||
@@ -171,26 +171,26 @@ version_lock_validate (const struct version_lock *vl, uintptr_t lock)
|
||||
__atomic_thread_fence (__ATOMIC_ACQUIRE);
|
||||
|
||||
// Check that the node is still in the same state.
|
||||
- uintptr_t state = __atomic_load_n (&(vl->version_lock), __ATOMIC_SEQ_CST);
|
||||
+ uintptr_type state = __atomic_load_n (&(vl->version_lock), __ATOMIC_SEQ_CST);
|
||||
return (state == lock);
|
||||
}
|
||||
|
||||
// The largest possible separator value.
|
||||
-static const uintptr_t max_separator = ~((uintptr_t) (0));
|
||||
+static const uintptr_type max_separator = ~((uintptr_type) (0));
|
||||
|
||||
struct btree_node;
|
||||
|
||||
// Inner entry. The child tree contains all entries <= separator.
|
||||
struct inner_entry
|
||||
{
|
||||
- uintptr_t separator;
|
||||
+ uintptr_type separator;
|
||||
struct btree_node *child;
|
||||
};
|
||||
|
||||
// Leaf entry. Stores an object entry.
|
||||
struct leaf_entry
|
||||
{
|
||||
- uintptr_t base, size;
|
||||
+ uintptr_type base, size;
|
||||
struct object *ob;
|
||||
};
|
||||
|
||||
@@ -248,7 +248,7 @@ btree_node_needs_merge (const struct btree_node *n)
|
||||
}
|
||||
|
||||
// Get the fence key for inner nodes.
|
||||
-static inline uintptr_t
|
||||
+static inline uintptr_type
|
||||
btree_node_get_fence_key (const struct btree_node *n)
|
||||
{
|
||||
// For inner nodes we just return our right-most entry.
|
||||
@@ -257,7 +257,7 @@ btree_node_get_fence_key (const struct btree_node *n)
|
||||
|
||||
// Find the position for a slot in an inner node.
|
||||
static unsigned
|
||||
-btree_node_find_inner_slot (const struct btree_node *n, uintptr_t value)
|
||||
+btree_node_find_inner_slot (const struct btree_node *n, uintptr_type value)
|
||||
{
|
||||
for (unsigned index = 0, ec = n->entry_count; index != ec; ++index)
|
||||
if (n->content.children[index].separator >= value)
|
||||
@@ -267,7 +267,7 @@ btree_node_find_inner_slot (const struct btree_node *n, uintptr_t value)
|
||||
|
||||
// Find the position for a slot in a leaf node.
|
||||
static unsigned
|
||||
-btree_node_find_leaf_slot (const struct btree_node *n, uintptr_t value)
|
||||
+btree_node_find_leaf_slot (const struct btree_node *n, uintptr_type value)
|
||||
{
|
||||
for (unsigned index = 0, ec = n->entry_count; index != ec; ++index)
|
||||
if (n->content.entries[index].base + n->content.entries[index].size > value)
|
||||
@@ -299,14 +299,14 @@ btree_node_unlock_exclusive (struct btree_node *n)
|
||||
// Acquire an optimistic "lock". Note that this does not lock at all, it
|
||||
// only allows for validation later.
|
||||
static inline bool
|
||||
-btree_node_lock_optimistic (const struct btree_node *n, uintptr_t *lock)
|
||||
+btree_node_lock_optimistic (const struct btree_node *n, uintptr_type *lock)
|
||||
{
|
||||
return version_lock_lock_optimistic (&(n->version_lock), lock);
|
||||
}
|
||||
|
||||
// Validate a previously acquire lock.
|
||||
static inline bool
|
||||
-btree_node_validate (const struct btree_node *n, uintptr_t lock)
|
||||
+btree_node_validate (const struct btree_node *n, uintptr_type lock)
|
||||
{
|
||||
return version_lock_validate (&(n->version_lock), lock);
|
||||
}
|
||||
@@ -314,8 +314,8 @@ btree_node_validate (const struct btree_node *n, uintptr_t lock)
|
||||
// Insert a new separator after splitting.
|
||||
static void
|
||||
btree_node_update_separator_after_split (struct btree_node *n,
|
||||
- uintptr_t old_separator,
|
||||
- uintptr_t new_separator,
|
||||
+ uintptr_type old_separator,
|
||||
+ uintptr_type new_separator,
|
||||
struct btree_node *new_right)
|
||||
{
|
||||
unsigned slot = btree_node_find_inner_slot (n, old_separator);
|
||||
@@ -474,13 +474,13 @@ btree_handle_root_split (struct btree *t, struct btree_node **node,
|
||||
// Split an inner node.
|
||||
static void
|
||||
btree_split_inner (struct btree *t, struct btree_node **inner,
|
||||
- struct btree_node **parent, uintptr_t target)
|
||||
+ struct btree_node **parent, uintptr_type target)
|
||||
{
|
||||
// Check for the root.
|
||||
btree_handle_root_split (t, inner, parent);
|
||||
|
||||
// Create two inner node.
|
||||
- uintptr_t right_fence = btree_node_get_fence_key (*inner);
|
||||
+ uintptr_type right_fence = btree_node_get_fence_key (*inner);
|
||||
struct btree_node *left_inner = *inner;
|
||||
struct btree_node *right_inner = btree_allocate_node (t, true);
|
||||
unsigned split = left_inner->entry_count / 2;
|
||||
@@ -489,7 +489,7 @@ btree_split_inner (struct btree *t, struct btree_node **inner,
|
||||
right_inner->content.children[index]
|
||||
= left_inner->content.children[split + index];
|
||||
left_inner->entry_count = split;
|
||||
- uintptr_t left_fence = btree_node_get_fence_key (left_inner);
|
||||
+ uintptr_type left_fence = btree_node_get_fence_key (left_inner);
|
||||
btree_node_update_separator_after_split (*parent, right_fence, left_fence,
|
||||
right_inner);
|
||||
if (target <= left_fence)
|
||||
@@ -507,13 +507,14 @@ btree_split_inner (struct btree *t, struct btree_node **inner,
|
||||
// Split a leaf node.
|
||||
static void
|
||||
btree_split_leaf (struct btree *t, struct btree_node **leaf,
|
||||
- struct btree_node **parent, uintptr_t fence, uintptr_t target)
|
||||
+ struct btree_node **parent, uintptr_type fence,
|
||||
+ uintptr_type target)
|
||||
{
|
||||
// Check for the root.
|
||||
btree_handle_root_split (t, leaf, parent);
|
||||
|
||||
// Create two leaf nodes.
|
||||
- uintptr_t right_fence = fence;
|
||||
+ uintptr_type right_fence = fence;
|
||||
struct btree_node *left_leaf = *leaf;
|
||||
struct btree_node *right_leaf = btree_allocate_node (t, false);
|
||||
unsigned split = left_leaf->entry_count / 2;
|
||||
@@ -522,7 +523,7 @@ btree_split_leaf (struct btree *t, struct btree_node **leaf,
|
||||
right_leaf->content.entries[index]
|
||||
= left_leaf->content.entries[split + index];
|
||||
left_leaf->entry_count = split;
|
||||
- uintptr_t left_fence = right_leaf->content.entries[0].base - 1;
|
||||
+ uintptr_type left_fence = right_leaf->content.entries[0].base - 1;
|
||||
btree_node_update_separator_after_split (*parent, right_fence, left_fence,
|
||||
right_leaf);
|
||||
if (target <= left_fence)
|
||||
@@ -540,7 +541,7 @@ btree_split_leaf (struct btree *t, struct btree_node **leaf,
|
||||
// Merge (or balance) child nodes.
|
||||
static struct btree_node *
|
||||
btree_merge_node (struct btree *t, unsigned child_slot,
|
||||
- struct btree_node *parent, uintptr_t target)
|
||||
+ struct btree_node *parent, uintptr_type target)
|
||||
{
|
||||
// Choose the emptiest neighbor and lock both. The target child is already
|
||||
// locked.
|
||||
@@ -693,7 +694,7 @@ btree_merge_node (struct btree *t, unsigned child_slot,
|
||||
left_node->entry_count += to_shift;
|
||||
right_node->entry_count -= to_shift;
|
||||
}
|
||||
- uintptr_t left_fence;
|
||||
+ uintptr_type left_fence;
|
||||
if (btree_node_is_leaf (left_node))
|
||||
{
|
||||
left_fence = right_node->content.entries[0].base - 1;
|
||||
@@ -718,7 +719,7 @@ btree_merge_node (struct btree *t, unsigned child_slot,
|
||||
|
||||
// Insert an entry.
|
||||
static bool
|
||||
-btree_insert (struct btree *t, uintptr_t base, uintptr_t size,
|
||||
+btree_insert (struct btree *t, uintptr_type base, uintptr_type size,
|
||||
struct object *ob)
|
||||
{
|
||||
// Sanity check.
|
||||
@@ -747,7 +748,7 @@ btree_insert (struct btree *t, uintptr_t base, uintptr_t size,
|
||||
// But that is more difficult to implement and frame registration is
|
||||
// rare anyway, we use simple locking for now.
|
||||
|
||||
- uintptr_t fence = max_separator;
|
||||
+ uintptr_type fence = max_separator;
|
||||
while (btree_node_is_inner (iter))
|
||||
{
|
||||
// Use eager splits to avoid lock coupling up.
|
||||
@@ -790,7 +791,7 @@ btree_insert (struct btree *t, uintptr_t base, uintptr_t size,
|
||||
|
||||
// Remove an entry.
|
||||
static struct object *
|
||||
-btree_remove (struct btree *t, uintptr_t base)
|
||||
+btree_remove (struct btree *t, uintptr_type base)
|
||||
{
|
||||
// Access the root.
|
||||
version_lock_lock_exclusive (&(t->root_lock));
|
||||
@@ -838,7 +839,7 @@ btree_remove (struct btree *t, uintptr_t base)
|
||||
|
||||
// Find the corresponding entry for the given address.
|
||||
static struct object *
|
||||
-btree_lookup (const struct btree *t, uintptr_t target_addr)
|
||||
+btree_lookup (const struct btree *t, uintptr_type target_addr)
|
||||
{
|
||||
// Within this function many loads are relaxed atomic loads.
|
||||
// Use a macro to keep the code reasonable.
|
||||
@@ -867,7 +868,7 @@ btree_lookup (const struct btree *t, uintptr_t target_addr)
|
||||
|
||||
restart:
|
||||
struct btree_node *iter;
|
||||
- uintptr_t lock;
|
||||
+ uintptr_type lock;
|
||||
{
|
||||
// Accessing the root node requires defending against concurrent pointer
|
||||
// changes Thus we couple rootLock -> lock on root node -> validate rootLock
|
||||
@@ -878,7 +879,7 @@ restart:
|
||||
goto restart;
|
||||
if (!iter)
|
||||
return NULL;
|
||||
- uintptr_t child_lock;
|
||||
+ uintptr_type child_lock;
|
||||
if ((!btree_node_lock_optimistic (iter, &child_lock))
|
||||
|| (!version_lock_validate (&(t->root_lock), lock)))
|
||||
goto restart;
|
||||
@@ -910,7 +911,7 @@ restart:
|
||||
|
||||
// The node content can change at any point in time, thus we must
|
||||
// interleave parent and child checks.
|
||||
- uintptr_t child_lock;
|
||||
+ uintptr_type child_lock;
|
||||
if (!btree_node_lock_optimistic (child, &child_lock))
|
||||
goto restart;
|
||||
if (!btree_node_validate (iter, lock))
|
||||
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
|
||||
index a591faaa579b5883..f38efd3c09efc3e9 100644
|
||||
--- a/libgcc/unwind-dw2-fde.c
|
||||
+++ b/libgcc/unwind-dw2-fde.c
|
||||
@@ -42,6 +42,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+typedef __UINTPTR_TYPE__ uintptr_type;
|
||||
+
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
#include "unwind-dw2-btree.h"
|
||||
|
||||
@@ -58,7 +60,7 @@ release_registered_frames (void)
|
||||
}
|
||||
|
||||
static void
|
||||
-get_pc_range (const struct object *ob, uintptr_t *range);
|
||||
+get_pc_range (const struct object *ob, uintptr_type *range);
|
||||
static void
|
||||
init_object (struct object *ob);
|
||||
|
||||
@@ -124,7 +126,7 @@ __register_frame_info_bases (const void *begin, struct object *ob,
|
||||
init_object (ob);
|
||||
|
||||
// And register the frame
|
||||
- uintptr_t range[2];
|
||||
+ uintptr_type range[2];
|
||||
get_pc_range (ob, range);
|
||||
btree_insert (®istered_frames, range[0], range[1] - range[0], ob);
|
||||
#else
|
||||
@@ -178,7 +180,7 @@ __register_frame_info_table_bases (void *begin, struct object *ob,
|
||||
init_object (ob);
|
||||
|
||||
// And register the frame
|
||||
- uintptr_t range[2];
|
||||
+ uintptr_type range[2];
|
||||
get_pc_range (ob, range);
|
||||
btree_insert (®istered_frames, range[0], range[1] - range[0], ob);
|
||||
#else
|
||||
@@ -237,7 +239,7 @@ __deregister_frame_info_bases (const void *begin)
|
||||
#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
|
||||
lookupob.fde_end = NULL;
|
||||
#endif
|
||||
- uintptr_t range[2];
|
||||
+ uintptr_type range[2];
|
||||
get_pc_range (&lookupob, range);
|
||||
|
||||
// And remove
|
||||
@@ -677,7 +679,7 @@ end_fde_sort (struct object *ob, struct fde_accumulator *accu, size_t count)
|
||||
|
||||
static size_t
|
||||
classify_object_over_fdes (struct object *ob, const fde *this_fde,
|
||||
- uintptr_t *range)
|
||||
+ uintptr_type *range)
|
||||
{
|
||||
const struct dwarf_cie *last_cie = 0;
|
||||
size_t count = 0;
|
||||
@@ -892,11 +894,11 @@ init_object (struct object* ob)
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
/* Get the PC range for lookup */
|
||||
static void
|
||||
-get_pc_range (const struct object *ob, uintptr_t *range)
|
||||
+get_pc_range (const struct object *ob, uintptr_type *range)
|
||||
{
|
||||
// It is safe to cast to non-const object* here as
|
||||
// classify_object_over_fdes does not modify ob in query mode.
|
||||
- struct object *ncob = (struct object *) (uintptr_t) ob;
|
||||
+ struct object *ncob = (struct object *) (uintptr_type) ob;
|
||||
range[0] = range[1] = 0;
|
||||
if (ob->s.b.sorted)
|
||||
{
|
||||
@@ -1131,7 +1133,7 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
|
||||
const fde *f = NULL;
|
||||
|
||||
#ifdef ATOMIC_FDE_FAST_PATH
|
||||
- ob = btree_lookup (®istered_frames, (uintptr_t) pc);
|
||||
+ ob = btree_lookup (®istered_frames, (uintptr_type) pc);
|
||||
if (!ob)
|
||||
return NULL;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -96,10 +96,10 @@ Date: Wed Oct 6 14:33:59 2021 -0400
|
||||
* c-c++-common/Wbidi-chars-17.c: New test.
|
||||
|
||||
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
|
||||
index f591b39be5a..cf922812198 100644
|
||||
index 8a4cd634f77..3976fc368db 100644
|
||||
--- a/gcc/c-family/c.opt
|
||||
+++ b/gcc/c-family/c.opt
|
||||
@@ -334,6 +334,30 @@ Wbad-function-cast
|
||||
@@ -374,6 +374,30 @@ Wbad-function-cast
|
||||
C ObjC Var(warn_bad_function_cast) Warning
|
||||
Warn about casting functions to incompatible types.
|
||||
|
||||
@ -131,22 +131,23 @@ index f591b39be5a..cf922812198 100644
|
||||
C ObjC C++ ObjC++ Var(warn_bool_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
|
||||
Warn about boolean expression compared with an integer value different from true/false.
|
||||
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
|
||||
index 78ca7738df2..cc85c53aede 100644
|
||||
index 6070288856c..a22758d18ee 100644
|
||||
--- a/gcc/doc/invoke.texi
|
||||
+++ b/gcc/doc/invoke.texi
|
||||
@@ -264,7 +264,8 @@ Objective-C and Objective-C++ Dialects}.
|
||||
-Walloc-zero -Walloc-size-larger-than=@var{n}
|
||||
-Walloca -Walloca-larger-than=@var{n} @gol
|
||||
-Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol
|
||||
--Wno-attributes -Wbool-compare -Wbool-operation @gol
|
||||
+-Wno-attributes -Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]} @gol
|
||||
@@ -325,7 +325,9 @@ Objective-C and Objective-C++ Dialects}.
|
||||
-Warith-conversion @gol
|
||||
-Warray-bounds -Warray-bounds=@var{n} @gol
|
||||
-Wno-attributes -Wattribute-alias=@var{n} -Wno-attribute-alias @gol
|
||||
--Wno-attribute-warning -Wbool-compare -Wbool-operation @gol
|
||||
+-Wno-attribute-warning @gol
|
||||
+-Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]} @gol
|
||||
+-Wbool-compare -Wbool-operation @gol
|
||||
-Wno-builtin-declaration-mismatch @gol
|
||||
-Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat @gol
|
||||
-Wc++-compat -Wc++11-compat -Wc++14-compat @gol
|
||||
@@ -5606,6 +5607,23 @@ Warn about declarations using the @code{alias} and similar attributes whose
|
||||
target is incompatible with the type of the alias. @xref{Function Attributes,
|
||||
,Declaring Attributes of Functions}.
|
||||
-Wc11-c2x-compat @gol
|
||||
@@ -7557,6 +7559,23 @@ Attributes considered include @code{alloc_align}, @code{alloc_size},
|
||||
This is the default. You can disable these warnings with either
|
||||
@option{-Wno-attribute-alias} or @option{-Wattribute-alias=0}.
|
||||
|
||||
+@item -Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]}
|
||||
+@opindex Wbidi-chars=
|
||||
@ -221,15 +222,19 @@ index 00000000000..3f851b69e65
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-11.c b/gcc/testsuite/c-c++-common/Wbidi-chars-11.c
|
||||
new file mode 100644
|
||||
index 00000000000..44d044d82de
|
||||
index 00000000000..270ce2368a9
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-11.c
|
||||
@@ -0,0 +1,9 @@
|
||||
@@ -0,0 +1,13 @@
|
||||
+/* PR preprocessor/103026 */
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-Wbidi-chars=unpaired" } */
|
||||
+/* Test that we warn when mixing UCN and UTF-8. */
|
||||
+
|
||||
+int LRE__PDF_\u202c;
|
||||
+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
|
||||
+int LRE_\u202a_PDF__;
|
||||
+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
|
||||
+const char *s1 = "LRE__PDF_\u202c";
|
||||
+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
|
||||
+const char *s2 = "LRE_\u202a_PDF_";
|
||||
@ -493,10 +498,10 @@ index 00000000000..9dc7edb6e64
|
||||
+}
|
||||
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-4.c b/gcc/testsuite/c-c++-common/Wbidi-chars-4.c
|
||||
new file mode 100644
|
||||
index 00000000000..49f856b9bfe
|
||||
index 00000000000..639e5c62e88
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-4.c
|
||||
@@ -0,0 +1,172 @@
|
||||
@@ -0,0 +1,188 @@
|
||||
+/* PR preprocessor/103026 */
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-Wbidi-chars=any -Wno-multichar -Wno-overflow" } */
|
||||
@ -640,6 +645,22 @@ index 00000000000..49f856b9bfe
|
||||
+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
|
||||
+}
|
||||
+
|
||||
+int abc;
|
||||
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
|
||||
+int AX;
|
||||
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
|
||||
+int A\u202cY;
|
||||
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
|
||||
+int A\u202CY2;
|
||||
@ -671,10 +692,10 @@ index 00000000000..49f856b9bfe
|
||||
+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
|
||||
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-5.c b/gcc/testsuite/c-c++-common/Wbidi-chars-5.c
|
||||
new file mode 100644
|
||||
index 00000000000..f5776806c79
|
||||
index 00000000000..68cb053144b
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-5.c
|
||||
@@ -0,0 +1,172 @@
|
||||
@@ -0,0 +1,188 @@
|
||||
+/* PR preprocessor/103026 */
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-Wbidi-chars=unpaired -Wno-multichar -Wno-overflow" } */
|
||||
@ -818,6 +839,22 @@ index 00000000000..f5776806c79
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+}
|
||||
+
|
||||
+int abc;
|
||||
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int abc;
|
||||
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int AX;
|
||||
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int A\u202cY;
|
||||
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int A\u202CY2;
|
||||
@ -849,10 +886,10 @@ index 00000000000..f5776806c79
|
||||
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
|
||||
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-6.c b/gcc/testsuite/c-c++-common/Wbidi-chars-6.c
|
||||
new file mode 100644
|
||||
index 00000000000..a65d6faf60e
|
||||
index 00000000000..0ce6fff2dee
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-6.c
|
||||
@@ -0,0 +1,130 @@
|
||||
@@ -0,0 +1,155 @@
|
||||
+/* PR preprocessor/103026 */
|
||||
+/* { dg-do compile } */
|
||||
+/* { dg-options "-Wbidi-chars=unpaired" } */
|
||||
@ -963,24 +1000,49 @@ index 00000000000..a65d6faf60e
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+}
|
||||
+
|
||||
+int aLREbPDI;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int A\u202aB\u2069C;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int aRLEbPDI;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int a\u202bB\u2069c;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int aLRObPDI;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int a\u202db\u2069c2;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int aRLObPDI;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int a\u202eb\u2069;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int aLRIbPDF;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int a\u2066b\u202c;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int aRLIbPDFc
|
||||
+;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
|
||||
+int a\u2067b\u202c;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int aFSIbPDF;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int a\u2068b\u202c;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int aFSIbPD\u202C;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int aFSI\u2068bPDF_;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int aLREbPDFb;
|
||||
+int A\u202aB\u202c;
|
||||
+int a_LRE_LRE_b_PDF_PDF;
|
||||
+int A\u202aA\u202aB\u202cB\u202c;
|
||||
+int aPDFbLREadPDF;
|
||||
+int a_\u202C_\u202a_\u202c;
|
||||
+int a_LRE_b_PDF_c_LRE_PDF;
|
||||
+int a_\u202a_\u202c_\u202a_\u202c_;
|
||||
+int a_LRE_b_PDF_c_LRE;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
+int a_\u202a_\u202c_\u202a_;
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-7.c b/gcc/testsuite/c-c++-common/Wbidi-chars-7.c
|
||||
@ -1053,11 +1115,11 @@ index 00000000000..e2af1b1ca97
|
||||
+int lre_\u202a; const char *s4 = "PDF\u202c";
|
||||
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
|
||||
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
|
||||
index 3ad52d5e01e..e0dcb7f0529 100644
|
||||
index 176f8c5bbce..112b9c24751 100644
|
||||
--- a/libcpp/include/cpplib.h
|
||||
+++ b/libcpp/include/cpplib.h
|
||||
@@ -305,6 +305,17 @@ enum cpp_normalize_level {
|
||||
normalized_none
|
||||
@@ -319,6 +319,17 @@ enum cpp_main_search
|
||||
CMS_system, /* Search the system INCLUDE path. */
|
||||
};
|
||||
|
||||
+/* The possible bidirectional control characters checking levels, from least
|
||||
@ -1074,7 +1136,7 @@ index 3ad52d5e01e..e0dcb7f0529 100644
|
||||
/* This structure is nested inside struct cpp_reader, and
|
||||
carries all the options visible to the command line. */
|
||||
struct cpp_options
|
||||
@@ -506,6 +517,10 @@ struct cpp_options
|
||||
@@ -539,6 +550,10 @@ struct cpp_options
|
||||
/* True if warn about differences between C++98 and C++11. */
|
||||
bool cpp_warn_cxx11_compat;
|
||||
|
||||
@ -1085,21 +1147,21 @@ index 3ad52d5e01e..e0dcb7f0529 100644
|
||||
/* Dependency generation. */
|
||||
struct
|
||||
{
|
||||
@@ -1063,7 +1078,8 @@ enum {
|
||||
CPP_W_PEDANTIC,
|
||||
@@ -643,7 +658,8 @@ enum cpp_warning_reason {
|
||||
CPP_W_C90_C99_COMPAT,
|
||||
CPP_W_C11_C2X_COMPAT,
|
||||
CPP_W_CXX11_COMPAT,
|
||||
- CPP_W_EXPANSION_TO_DEFINED
|
||||
+ CPP_W_EXPANSION_TO_DEFINED,
|
||||
+ CPP_W_BIDIRECTIONAL
|
||||
};
|
||||
|
||||
/* Output a diagnostic of some kind. */
|
||||
/* Callback for header lookup for HEADER, which is the name of a
|
||||
diff --git a/libcpp/init.c b/libcpp/init.c
|
||||
index ca3fbaa5c05..5c15da82ff8 100644
|
||||
index 5a424e23553..f9a8f5f088f 100644
|
||||
--- a/libcpp/init.c
|
||||
+++ b/libcpp/init.c
|
||||
@@ -208,6 +208,7 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
|
||||
@@ -223,6 +223,7 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
|
||||
= ENABLE_CANONICAL_SYSTEM_HEADERS;
|
||||
CPP_OPTION (pfile, ext_numeric_literals) = 1;
|
||||
CPP_OPTION (pfile, warn_date_time) = 0;
|
||||
@ -1108,13 +1170,13 @@ index ca3fbaa5c05..5c15da82ff8 100644
|
||||
/* Default CPP arithmetic to something sensible for the host for the
|
||||
benefit of dumb users like fix-header. */
|
||||
diff --git a/libcpp/internal.h b/libcpp/internal.h
|
||||
index 4f74f995cec..53b4c0f4af7 100644
|
||||
index 8577cab6c83..0ce0246c5a2 100644
|
||||
--- a/libcpp/internal.h
|
||||
+++ b/libcpp/internal.h
|
||||
@@ -576,6 +576,13 @@ struct cpp_reader
|
||||
/* If non-null, the lexer will use this location for the next token
|
||||
instead of getting a location from the linemap. */
|
||||
source_location *forced_token_location_p;
|
||||
@@ -597,6 +597,13 @@ struct cpp_reader
|
||||
/* Location identifying the main source file -- intended to be line
|
||||
zero of said file. */
|
||||
location_t main_loc;
|
||||
+
|
||||
+ /* Returns true iff we should warn about UTF-8 bidirectional control
|
||||
+ characters. */
|
||||
@ -1126,7 +1188,7 @@ index 4f74f995cec..53b4c0f4af7 100644
|
||||
|
||||
/* Character classes. Based on the more primitive macros in safe-ctype.h.
|
||||
diff --git a/libcpp/lex.c b/libcpp/lex.c
|
||||
index a408f912c5c..ea7f75e842e 100644
|
||||
index fa2253d41c3..6a4fbce6030 100644
|
||||
--- a/libcpp/lex.c
|
||||
+++ b/libcpp/lex.c
|
||||
@@ -1164,6 +1164,324 @@ _cpp_process_line_notes (cpp_reader *pfile, int in_comment)
|
||||
@ -1134,12 +1196,12 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
}
|
||||
|
||||
+namespace bidi {
|
||||
+ enum kind {
|
||||
+ enum class kind {
|
||||
+ NONE, LRE, RLE, LRO, RLO, LRI, RLI, FSI, PDF, PDI, LTR, RTL
|
||||
+ };
|
||||
+
|
||||
+ /* All the UTF-8 encodings of bidi characters start with E2. */
|
||||
+ const uchar utf8_start = 0xe2;
|
||||
+ constexpr uchar utf8_start = 0xe2;
|
||||
+
|
||||
+ /* A vector holding currently open bidi contexts. We use a char for
|
||||
+ each context, its LSB is 1 if it represents a PDF context, 0 if it
|
||||
@ -1165,7 +1227,7 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+ /* Return the context of the Ith element. */
|
||||
+ kind ctx_at (unsigned int i)
|
||||
+ {
|
||||
+ return (vec[i] & 1) ? PDF : PDI;
|
||||
+ return (vec[i] & 1) ? kind::PDF : kind::PDI;
|
||||
+ }
|
||||
+
|
||||
+ /* Return which context is currently opened. */
|
||||
@ -1173,7 +1235,7 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+ {
|
||||
+ unsigned int len = vec.count ();
|
||||
+ if (len == 0)
|
||||
+ return NONE;
|
||||
+ return kind::NONE;
|
||||
+ return ctx_at (len - 1);
|
||||
+ }
|
||||
+
|
||||
@ -1191,40 +1253,40 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+ {
|
||||
+ switch (k)
|
||||
+ {
|
||||
+ case LRE:
|
||||
+ case RLE:
|
||||
+ case LRO:
|
||||
+ case RLO:
|
||||
+ case kind::LRE:
|
||||
+ case kind::RLE:
|
||||
+ case kind::LRO:
|
||||
+ case kind::RLO:
|
||||
+ vec.push (ucn_p ? 3u : 1u);
|
||||
+ break;
|
||||
+ case LRI:
|
||||
+ case RLI:
|
||||
+ case FSI:
|
||||
+ case kind::LRI:
|
||||
+ case kind::RLI:
|
||||
+ case kind::FSI:
|
||||
+ vec.push (ucn_p ? 2u : 0u);
|
||||
+ break;
|
||||
+ /* PDF terminates the scope of the last LRE, RLE, LRO, or RLO
|
||||
+ whose scope has not yet been terminated. */
|
||||
+ case PDF:
|
||||
+ if (current_ctx () == PDF)
|
||||
+ case kind::PDF:
|
||||
+ if (current_ctx () == kind::PDF)
|
||||
+ pop ();
|
||||
+ break;
|
||||
+ /* PDI terminates the scope of the last LRI, RLI, or FSI whose
|
||||
+ scope has not yet been terminated, as well as the scopes of
|
||||
+ any subsequent LREs, RLEs, LROs, or RLOs whose scopes have not
|
||||
+ yet been terminated. */
|
||||
+ case PDI:
|
||||
+ case kind::PDI:
|
||||
+ for (int i = vec.count () - 1; i >= 0; --i)
|
||||
+ if (ctx_at (i) == PDI)
|
||||
+ if (ctx_at (i) == kind::PDI)
|
||||
+ {
|
||||
+ vec.truncate (i);
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ case LTR:
|
||||
+ case RTL:
|
||||
+ case kind::LTR:
|
||||
+ case kind::RTL:
|
||||
+ /* These aren't popped by a PDF/PDI. */
|
||||
+ break;
|
||||
+ [[likely]] case NONE:
|
||||
+ [[likely]] case kind::NONE:
|
||||
+ break;
|
||||
+ default:
|
||||
+ abort ();
|
||||
@ -1236,27 +1298,27 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+ {
|
||||
+ switch (k)
|
||||
+ {
|
||||
+ case LRE:
|
||||
+ case kind::LRE:
|
||||
+ return "U+202A (LEFT-TO-RIGHT EMBEDDING)";
|
||||
+ case RLE:
|
||||
+ case kind::RLE:
|
||||
+ return "U+202B (RIGHT-TO-LEFT EMBEDDING)";
|
||||
+ case LRO:
|
||||
+ case kind::LRO:
|
||||
+ return "U+202D (LEFT-TO-RIGHT OVERRIDE)";
|
||||
+ case RLO:
|
||||
+ case kind::RLO:
|
||||
+ return "U+202E (RIGHT-TO-LEFT OVERRIDE)";
|
||||
+ case LRI:
|
||||
+ case kind::LRI:
|
||||
+ return "U+2066 (LEFT-TO-RIGHT ISOLATE)";
|
||||
+ case RLI:
|
||||
+ case kind::RLI:
|
||||
+ return "U+2067 (RIGHT-TO-LEFT ISOLATE)";
|
||||
+ case FSI:
|
||||
+ case kind::FSI:
|
||||
+ return "U+2068 (FIRST STRONG ISOLATE)";
|
||||
+ case PDF:
|
||||
+ case kind::PDF:
|
||||
+ return "U+202C (POP DIRECTIONAL FORMATTING)";
|
||||
+ case PDI:
|
||||
+ case kind::PDI:
|
||||
+ return "U+2069 (POP DIRECTIONAL ISOLATE)";
|
||||
+ case LTR:
|
||||
+ case kind::LTR:
|
||||
+ return "U+200E (LEFT-TO-RIGHT MARK)";
|
||||
+ case RTL:
|
||||
+ case kind::RTL:
|
||||
+ return "U+200F (RIGHT-TO-LEFT MARK)";
|
||||
+ default:
|
||||
+ abort ();
|
||||
@ -1275,19 +1337,19 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+ switch (p[2])
|
||||
+ {
|
||||
+ case 0xaa:
|
||||
+ return bidi::LRE;
|
||||
+ return bidi::kind::LRE;
|
||||
+ case 0xab:
|
||||
+ return bidi::RLE;
|
||||
+ return bidi::kind::RLE;
|
||||
+ case 0xac:
|
||||
+ return bidi::PDF;
|
||||
+ return bidi::kind::PDF;
|
||||
+ case 0xad:
|
||||
+ return bidi::LRO;
|
||||
+ return bidi::kind::LRO;
|
||||
+ case 0xae:
|
||||
+ return bidi::RLO;
|
||||
+ return bidi::kind::RLO;
|
||||
+ case 0x8e:
|
||||
+ return bidi::LTR;
|
||||
+ return bidi::kind::LTR;
|
||||
+ case 0x8f:
|
||||
+ return bidi::RTL;
|
||||
+ return bidi::kind::RTL;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
@ -1295,18 +1357,18 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+ switch (p[2])
|
||||
+ {
|
||||
+ case 0xa6:
|
||||
+ return bidi::LRI;
|
||||
+ return bidi::kind::LRI;
|
||||
+ case 0xa7:
|
||||
+ return bidi::RLI;
|
||||
+ return bidi::kind::RLI;
|
||||
+ case 0xa8:
|
||||
+ return bidi::FSI;
|
||||
+ return bidi::kind::FSI;
|
||||
+ case 0xa9:
|
||||
+ return bidi::PDI;
|
||||
+ return bidi::kind::PDI;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return bidi::NONE;
|
||||
+ return bidi::kind::NONE;
|
||||
+}
|
||||
+
|
||||
+/* Parse a UCN where P points just past \u or \U and return its bidi code. */
|
||||
@ -1322,32 +1384,32 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+ if (is_U)
|
||||
+ {
|
||||
+ if (p[0] != '0' || p[1] != '0' || p[2] != '0' || p[3] != '0')
|
||||
+ return bidi::NONE;
|
||||
+ return bidi::kind::NONE;
|
||||
+ /* Skip 4B so we can treat \u and \U the same below. */
|
||||
+ p += 4;
|
||||
+ }
|
||||
+
|
||||
+ /* All code points we are looking for start with 20xx. */
|
||||
+ if (p[0] != '2' || p[1] != '0')
|
||||
+ return bidi::NONE;
|
||||
+ return bidi::kind::NONE;
|
||||
+ else if (p[2] == '2')
|
||||
+ switch (p[3])
|
||||
+ {
|
||||
+ case 'a':
|
||||
+ case 'A':
|
||||
+ return bidi::LRE;
|
||||
+ return bidi::kind::LRE;
|
||||
+ case 'b':
|
||||
+ case 'B':
|
||||
+ return bidi::RLE;
|
||||
+ return bidi::kind::RLE;
|
||||
+ case 'c':
|
||||
+ case 'C':
|
||||
+ return bidi::PDF;
|
||||
+ return bidi::kind::PDF;
|
||||
+ case 'd':
|
||||
+ case 'D':
|
||||
+ return bidi::LRO;
|
||||
+ return bidi::kind::LRO;
|
||||
+ case 'e':
|
||||
+ case 'E':
|
||||
+ return bidi::RLO;
|
||||
+ return bidi::kind::RLO;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
@ -1355,13 +1417,13 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+ switch (p[3])
|
||||
+ {
|
||||
+ case '6':
|
||||
+ return bidi::LRI;
|
||||
+ return bidi::kind::LRI;
|
||||
+ case '7':
|
||||
+ return bidi::RLI;
|
||||
+ return bidi::kind::RLI;
|
||||
+ case '8':
|
||||
+ return bidi::FSI;
|
||||
+ return bidi::kind::FSI;
|
||||
+ case '9':
|
||||
+ return bidi::PDI;
|
||||
+ return bidi::kind::PDI;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
@ -1370,15 +1432,15 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+ {
|
||||
+ case 'e':
|
||||
+ case 'E':
|
||||
+ return bidi::LTR;
|
||||
+ return bidi::kind::LTR;
|
||||
+ case 'f':
|
||||
+ case 'F':
|
||||
+ return bidi::RTL;
|
||||
+ return bidi::kind::RTL;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return bidi::NONE;
|
||||
+ return bidi::kind::NONE;
|
||||
+}
|
||||
+
|
||||
+/* We're closing a bidi context, that is, we've encountered a newline,
|
||||
@ -1393,7 +1455,7 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+ if (CPP_OPTION (pfile, cpp_warn_bidirectional) == bidirectional_unpaired
|
||||
+ && bidi::vec.count () > 0)
|
||||
+ {
|
||||
+ const source_location loc
|
||||
+ const location_t loc
|
||||
+ = linemap_position_for_column (pfile->line_table,
|
||||
+ CPP_BUF_COLUMN (pfile->buffer, p));
|
||||
+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0,
|
||||
@ -1413,14 +1475,14 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+maybe_warn_bidi_on_char (cpp_reader *pfile, const uchar *p, bidi::kind kind,
|
||||
+ bool ucn_p)
|
||||
+{
|
||||
+ if (__builtin_expect (kind == bidi::NONE, 1))
|
||||
+ if (__builtin_expect (kind == bidi::kind::NONE, 1))
|
||||
+ return;
|
||||
+
|
||||
+ const unsigned char warn_bidi = CPP_OPTION (pfile, cpp_warn_bidirectional);
|
||||
+ const auto warn_bidi = CPP_OPTION (pfile, cpp_warn_bidirectional);
|
||||
+
|
||||
+ if (warn_bidi != bidirectional_none)
|
||||
+ {
|
||||
+ const source_location loc
|
||||
+ const location_t loc
|
||||
+ = linemap_position_for_column (pfile->line_table,
|
||||
+ CPP_BUF_COLUMN (pfile->buffer, p));
|
||||
+ /* It seems excessive to warn about a PDI/PDF that is closing
|
||||
@ -1437,7 +1499,7 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
+ }
|
||||
+ else if (warn_bidi == bidirectional_any)
|
||||
+ {
|
||||
+ if (kind == bidi::PDF || kind == bidi::PDI)
|
||||
+ if (kind == bidi::kind::PDF || kind == bidi::kind::PDI)
|
||||
+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0,
|
||||
+ "\"%s\" is closing an unopened context",
|
||||
+ bidi::to_str (kind));
|
||||
@ -1501,7 +1563,7 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
@@ -1233,9 +1565,31 @@ skip_line_comment (cpp_reader *pfile)
|
||||
{
|
||||
cpp_buffer *buffer = pfile->buffer;
|
||||
source_location orig_line = pfile->line_table->highest_line;
|
||||
location_t orig_line = pfile->line_table->highest_line;
|
||||
+ const bool warn_bidi_p = pfile->warn_bidi_p ();
|
||||
|
||||
- while (*buffer->cur != '\n')
|
||||
@ -1532,9 +1594,9 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
|
||||
_cpp_process_line_notes (pfile, true);
|
||||
return orig_line != pfile->line_table->highest_line;
|
||||
@@ -1315,11 +1669,13 @@ warn_about_normalization (cpp_reader *pfile,
|
||||
@@ -1346,11 +1700,13 @@ static const cppchar_t utf8_signifier = 0xC0;
|
||||
|
||||
/* Returns TRUE if the sequence starting at buffer->cur is invalid in
|
||||
/* Returns TRUE if the sequence starting at buffer->cur is valid in
|
||||
an identifier. FIRST is TRUE if this starts an identifier. */
|
||||
+
|
||||
static bool
|
||||
@ -1546,20 +1608,35 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
|
||||
if (*buffer->cur == '$')
|
||||
{
|
||||
@@ -1343,6 +1699,12 @@ forms_identifier_p (cpp_reader *pfile, int first,
|
||||
{
|
||||
@@ -1373,6 +1729,13 @@ forms_identifier_p (cpp_reader *pfile, int first,
|
||||
cppchar_t s;
|
||||
buffer->cur += 2;
|
||||
+ if (warn_bidi_p)
|
||||
+ {
|
||||
+ bidi::kind kind = get_bidi_ucn (buffer->cur,
|
||||
+ buffer->cur[-1] == 'U');
|
||||
+ maybe_warn_bidi_on_char (pfile, buffer->cur, kind, /*ucn_p=*/true);
|
||||
+ }
|
||||
if (_cpp_valid_ucn (pfile, &buffer->cur, buffer->rlimit, 1 + !first,
|
||||
state, &s, NULL, NULL))
|
||||
return true;
|
||||
@@ -1450,6 +1812,7 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn,
|
||||
if (*buffer->cur >= utf8_signifier)
|
||||
{
|
||||
+ if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0)
|
||||
+ && warn_bidi_p)
|
||||
+ {
|
||||
+ bidi::kind kind = get_bidi_utf8 (buffer->cur);
|
||||
+ maybe_warn_bidi_on_char (pfile, buffer->cur, kind,
|
||||
+ /*ucn_p=*/false);
|
||||
+ }
|
||||
if (_cpp_valid_utf8 (pfile, &buffer->cur, buffer->rlimit, 1 + !first,
|
||||
state, &s))
|
||||
return true;
|
||||
@@ -1381,6 +1744,13 @@ forms_identifier_p (cpp_reader *pfile, int first,
|
||||
&& (buffer->cur[1] == 'u' || buffer->cur[1] == 'U'))
|
||||
{
|
||||
buffer->cur += 2;
|
||||
+ if (warn_bidi_p)
|
||||
+ {
|
||||
+ bidi::kind kind = get_bidi_ucn (buffer->cur,
|
||||
+ buffer->cur[-1] == 'U');
|
||||
+ maybe_warn_bidi_on_char (pfile, buffer->cur, kind,
|
||||
+ /*ucn_p=*/true);
|
||||
+ }
|
||||
if (_cpp_valid_ucn (pfile, &buffer->cur, buffer->rlimit, 1 + !first,
|
||||
state, &s, NULL, NULL))
|
||||
return true;
|
||||
@@ -1489,6 +1859,7 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn,
|
||||
const uchar *cur;
|
||||
unsigned int len;
|
||||
unsigned int hash = HT_HASHSTEP (0, *base);
|
||||
@ -1567,7 +1644,7 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
|
||||
cur = pfile->buffer->cur;
|
||||
if (! starts_ucn)
|
||||
@@ -1472,6 +1835,8 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn,
|
||||
@@ -1512,6 +1883,8 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn,
|
||||
pfile->buffer->cur++;
|
||||
}
|
||||
} while (forms_identifier_p (pfile, false, nst));
|
||||
@ -1576,31 +1653,31 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
result = _cpp_interpret_identifier (pfile, base,
|
||||
pfile->buffer->cur - base);
|
||||
*spelling = cpp_lookup (pfile, base, pfile->buffer->cur - base);
|
||||
@@ -1673,6 +2038,7 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base,
|
||||
_cpp_buff *first_buff = NULL, *last_buff = NULL;
|
||||
size_t raw_prefix_start;
|
||||
_cpp_line_note *note = &pfile->buffer->notes[pfile->buffer->cur_note];
|
||||
@@ -1758,6 +2131,7 @@ static void
|
||||
lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
|
||||
{
|
||||
const uchar *pos = base;
|
||||
+ const bool warn_bidi_p = pfile->warn_bidi_p ();
|
||||
|
||||
type = (*base == 'L' ? CPP_WSTRING :
|
||||
*base == 'U' ? CPP_STRING32 :
|
||||
@@ -1909,8 +2275,15 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base,
|
||||
cur = base = pfile->buffer->cur;
|
||||
/* 'tis a pity this information isn't passed down from the lexer's
|
||||
initial categorization of the token. */
|
||||
@@ -1994,8 +2368,15 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
|
||||
pos = base = pfile->buffer->cur;
|
||||
note = &pfile->buffer->notes[pfile->buffer->cur_note];
|
||||
}
|
||||
+ else if (__builtin_expect ((unsigned char) c == bidi::utf8_start, 0)
|
||||
+ && warn_bidi_p)
|
||||
+ maybe_warn_bidi_on_char (pfile, cur - 1, get_bidi_utf8 (cur - 1),
|
||||
+ maybe_warn_bidi_on_char (pfile, pos - 1, get_bidi_utf8 (pos - 1),
|
||||
+ /*ucn_p=*/false);
|
||||
}
|
||||
|
||||
+ if (warn_bidi_p)
|
||||
+ maybe_warn_bidi_on_close (pfile, cur);
|
||||
+ maybe_warn_bidi_on_close (pfile, pos);
|
||||
+
|
||||
if (CPP_OPTION (pfile, user_literals))
|
||||
{
|
||||
/* If a string format macro, say from inttypes.h, is placed touching
|
||||
@@ -2005,15 +2378,27 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
|
||||
@@ -2090,15 +2471,27 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
|
||||
else
|
||||
terminator = '>', type = CPP_HEADER_NAME;
|
||||
|
||||
@ -1630,7 +1707,7 @@ index a408f912c5c..ea7f75e842e 100644
|
||||
else if (c == '\n')
|
||||
{
|
||||
cur--;
|
||||
@@ -2030,6 +2415,11 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
|
||||
@@ -2115,6 +2508,11 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
|
||||
}
|
||||
else if (c == '\0')
|
||||
saw_NUL = true;
|
||||
79
gcc11-Wmismatched-dealloc-doc.patch
Normal file
79
gcc11-Wmismatched-dealloc-doc.patch
Normal file
@ -0,0 +1,79 @@
|
||||
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
|
||||
index 3419483c532..a2a6b1c98be 100644
|
||||
--- a/gcc/doc/invoke.texi
|
||||
+++ b/gcc/doc/invoke.texi
|
||||
@@ -255,7 +255,7 @@ in the following sections.
|
||||
-Wno-inherited-variadic-ctor -Wno-init-list-lifetime @gol
|
||||
-Winvalid-imported-macros @gol
|
||||
-Wno-invalid-offsetof -Wno-literal-suffix @gol
|
||||
--Wno-mismatched-new-delete -Wmismatched-tags @gol
|
||||
+-Wmismatched-new-delete -Wmismatched-tags @gol
|
||||
-Wmultiple-inheritance -Wnamespaces -Wnarrowing @gol
|
||||
-Wnoexcept -Wnoexcept-type -Wnon-virtual-dtor @gol
|
||||
-Wpessimizing-move -Wno-placement-new -Wplacement-new=@var{n} @gol
|
||||
@@ -3966,7 +3966,7 @@ The warning is inactive inside a system header file, such as the STL, so
|
||||
one can still use the STL. One may also instantiate or specialize
|
||||
templates.
|
||||
|
||||
-@item -Wno-mismatched-new-delete @r{(C++ and Objective-C++ only)}
|
||||
+@item -Wmismatched-new-delete @r{(C++ and Objective-C++ only)}
|
||||
@opindex Wmismatched-new-delete
|
||||
@opindex Wno-mismatched-new-delete
|
||||
Warn for mismatches between calls to @code{operator new} or @code{operator
|
||||
@@ -3998,7 +3998,7 @@ The related option @option{-Wmismatched-dealloc} diagnoses mismatches
|
||||
involving allocation and deallocation functions other than @code{operator
|
||||
new} and @code{operator delete}.
|
||||
|
||||
-@option{-Wmismatched-new-delete} is enabled by default.
|
||||
+@option{-Wmismatched-new-delete} is included in @option{-Wall}.
|
||||
|
||||
@item -Wmismatched-tags @r{(C++ and Objective-C++ only)}
|
||||
@opindex Wmismatched-tags
|
||||
@@ -5543,6 +5543,8 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
|
||||
-Wmemset-elt-size @gol
|
||||
-Wmemset-transposed-args @gol
|
||||
-Wmisleading-indentation @r{(only for C/C++)} @gol
|
||||
+-Wmismatched-dealloc @gol
|
||||
+-Wmismatched-new-delete @r{(only for C/C++)} @gol
|
||||
-Wmissing-attributes @gol
|
||||
-Wmissing-braces @r{(only for C/ObjC)} @gol
|
||||
-Wmultistatement-macros @gol
|
||||
@@ -6428,7 +6430,7 @@ Ignoring the warning can result in poorly optimized code.
|
||||
disable the warning, but this is not recommended and should be done only
|
||||
when non-existent profile data is justified.
|
||||
|
||||
-@item -Wno-mismatched-dealloc
|
||||
+@item -Wmismatched-dealloc
|
||||
@opindex Wmismatched-dealloc
|
||||
@opindex Wno-mismatched-dealloc
|
||||
|
||||
@@ -6461,7 +6463,7 @@ void f (void)
|
||||
In C++, the related option @option{-Wmismatched-new-delete} diagnoses
|
||||
mismatches involving either @code{operator new} or @code{operator delete}.
|
||||
|
||||
-Option @option{-Wmismatched-dealloc} is enabled by default.
|
||||
+Option @option{-Wmismatched-dealloc} is included in @option{-Wall}.
|
||||
|
||||
@item -Wmultistatement-macros
|
||||
@opindex Wmultistatement-macros
|
||||
@@ -7951,9 +7953,9 @@ Warnings controlled by the option can be disabled either by specifying
|
||||
Disable @option{-Wframe-larger-than=} warnings. The option is equivalent
|
||||
to @option{-Wframe-larger-than=}@samp{SIZE_MAX} or larger.
|
||||
|
||||
-@item -Wno-free-nonheap-object
|
||||
-@opindex Wno-free-nonheap-object
|
||||
+@item -Wfree-nonheap-object
|
||||
@opindex Wfree-nonheap-object
|
||||
+@opindex Wno-free-nonheap-object
|
||||
Warn when attempting to deallocate an object that was either not allocated
|
||||
on the heap, or by using a pointer that was not returned from a prior call
|
||||
to the corresponding allocation function. For example, because the call
|
||||
@@ -7970,7 +7972,7 @@ void f (char *p)
|
||||
@}
|
||||
@end smallexample
|
||||
|
||||
-@option{-Wfree-nonheap-object} is enabled by default.
|
||||
+@option{-Wfree-nonheap-object} is included in @option{-Wall}.
|
||||
|
||||
@item -Wstack-usage=@var{byte-size}
|
||||
@opindex Wstack-usage
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
--- gcc/configure.ac.jj 2017-02-13 12:20:53.000000000 +0100
|
||||
+++ gcc/configure.ac 2017-02-25 12:42:32.859175403 +0100
|
||||
@@ -481,7 +481,7 @@ AC_ARG_ENABLE(build-format-warnings,
|
||||
@@ -480,7 +480,7 @@ AC_ARG_ENABLE(build-format-warnings,
|
||||
AS_HELP_STRING([--disable-build-format-warnings],[don't use -Wformat while building GCC]),
|
||||
[],[enable_build_format_warnings=yes])
|
||||
AS_IF([test $enable_build_format_warnings = no],
|
||||
@ -13,7 +13,7 @@
|
||||
+ [wf_opt="-Wno-format -Wno-format-security"],[wf_opt=])
|
||||
ACX_PROG_CXX_WARNING_OPTS(
|
||||
m4_quote(m4_do([-W -Wall -Wno-narrowing -Wwrite-strings ],
|
||||
[-Wcast-qual $wf_opt])), [loose_warn])
|
||||
[-Wcast-qual -Wno-error=format-diag $wf_opt])),
|
||||
--- gcc/configure.jj 2017-02-13 12:20:52.000000000 +0100
|
||||
+++ gcc/configure 2017-02-25 12:42:50.041946391 +0100
|
||||
@@ -6647,7 +6647,7 @@ else
|
||||
297
gcc11-bind-now.patch
Normal file
297
gcc11-bind-now.patch
Normal file
@ -0,0 +1,297 @@
|
||||
From 36362544fb039599c0eb58d839e90ffb5410ad27 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Polacek <polacek@redhat.com>
|
||||
Date: Wed, 9 Feb 2022 15:18:43 -0500
|
||||
Subject: [PATCH] configure: Implement --enable-host-bind-now
|
||||
|
||||
As promised in the --enable-host-pie patch, this patch adds another
|
||||
configure option, --enable-host-bind-now, which adds -z now when linking
|
||||
the compiler executables in order to extend hardening. BIND_NOW with RELRO
|
||||
allows the GOT to be marked RO; this prevents GOT modification attacks.
|
||||
|
||||
This option does not affect linking of target libraries; you can use
|
||||
LDFLAGS_FOR_TARGET=-Wl,-z,relro,-z,now to enable RELRO/BIND_NOW.
|
||||
|
||||
Bootstrapped/regtested on x86_64-pc-linux-gnu (with the option enabled vs
|
||||
not enabled). I suppose this is GCC 13 material, but maybe I'll get some
|
||||
comments anyway.
|
||||
|
||||
c++tools/ChangeLog:
|
||||
|
||||
* configure.ac (--enable-host-bind-now): New check.
|
||||
* configure: Regenerate.
|
||||
|
||||
gcc/ChangeLog:
|
||||
|
||||
* configure.ac (--enable-host-bind-now): New check. Add
|
||||
-Wl,-z,now to LD_PICFLAG if --enable-host-bind-now.
|
||||
* configure: Regenerate.
|
||||
* doc/install.texi: Document --enable-host-bind-now.
|
||||
|
||||
lto-plugin/ChangeLog:
|
||||
|
||||
* configure.ac (--enable-host-bind-now): New check. Link with
|
||||
-z,now.
|
||||
* configure: Regenerate.
|
||||
---
|
||||
c++tools/configure | 11 +++++++++++
|
||||
c++tools/configure.ac | 7 +++++++
|
||||
gcc/configure | 20 ++++++++++++++++++--
|
||||
gcc/configure.ac | 13 ++++++++++++-
|
||||
gcc/doc/install.texi | 6 ++++++
|
||||
lto-plugin/configure | 20 ++++++++++++++++++--
|
||||
lto-plugin/configure.ac | 11 +++++++++++
|
||||
7 files changed, 83 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/c++tools/configure b/c++tools/configure
|
||||
index c1aceb8404a..25432b5040d 100755
|
||||
--- a/c++tools/configure
|
||||
+++ b/c++tools/configure
|
||||
@@ -631,6 +631,7 @@ ac_ct_CC
|
||||
GREP
|
||||
CXXCPP
|
||||
LD_PICFLAG
|
||||
+enable_host_bind_now
|
||||
PICFLAG
|
||||
MAINTAINER
|
||||
CXX_AUX_TOOLS
|
||||
@@ -704,6 +705,7 @@ enable_c___tools
|
||||
enable_checking
|
||||
enable_default_pie
|
||||
enable_host_pie
|
||||
+enable_host_bind_now
|
||||
with_gcc_major_version_only
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
@@ -1336,6 +1338,7 @@ Optional Features:
|
||||
yes,no,all,none,release.
|
||||
--enable-default-pie enable Position Independent Executable as default
|
||||
--enable-host-pie build host code as PIE
|
||||
+ --enable-host-bind-now link host code as BIND_NOW
|
||||
|
||||
Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
@@ -3009,6 +3012,14 @@ fi
|
||||
|
||||
|
||||
|
||||
+# Enable --enable-host-bind-now
|
||||
+# Check whether --enable-host-bind-now was given.
|
||||
+if test "${enable_host_bind_now+set}" = set; then :
|
||||
+ enableval=$enable_host_bind_now; LD_PICFLAG="$LD_PICFLAG -Wl,-z,now"
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+
|
||||
|
||||
# Check if O_CLOEXEC is defined by fcntl
|
||||
|
||||
diff --git a/c++tools/configure.ac b/c++tools/configure.ac
|
||||
index 1e42689f2eb..d3f23f66f00 100644
|
||||
--- a/c++tools/configure.ac
|
||||
+++ b/c++tools/configure.ac
|
||||
@@ -110,6 +110,13 @@ AC_ARG_ENABLE(host-pie,
|
||||
[build host code as PIE])],
|
||||
[PICFLAG=-fPIE; LD_PICFLAG=-pie], [])
|
||||
AC_SUBST(PICFLAG)
|
||||
+
|
||||
+# Enable --enable-host-bind-now
|
||||
+AC_ARG_ENABLE(host-bind-now,
|
||||
+[AS_HELP_STRING([--enable-host-bind-now],
|
||||
+ [link host code as BIND_NOW])],
|
||||
+[LD_PICFLAG="$LD_PICFLAG -Wl,-z,now"], [])
|
||||
+AC_SUBST(enable_host_bind_now)
|
||||
AC_SUBST(LD_PICFLAG)
|
||||
|
||||
# Check if O_CLOEXEC is defined by fcntl
|
||||
diff --git a/gcc/configure b/gcc/configure
|
||||
index 2ded5d4c50b..5671dc7dcf4 100755
|
||||
--- a/gcc/configure
|
||||
+++ b/gcc/configure
|
||||
@@ -635,6 +635,7 @@ CET_HOST_FLAGS
|
||||
LD_PICFLAG
|
||||
PICFLAG
|
||||
enable_default_pie
|
||||
+enable_host_bind_now
|
||||
enable_host_pie
|
||||
enable_host_shared
|
||||
enable_plugin
|
||||
@@ -1023,6 +1024,7 @@ enable_version_specific_runtime_libs
|
||||
enable_plugin
|
||||
enable_host_shared
|
||||
enable_host_pie
|
||||
+enable_host_bind_now
|
||||
enable_libquadmath_support
|
||||
with_linker_hash_style
|
||||
with_diagnostics_color
|
||||
@@ -1786,6 +1788,7 @@ Optional Features:
|
||||
--enable-plugin enable plugin support
|
||||
--enable-host-shared build host code as shared libraries
|
||||
--enable-host-pie build host code as PIE
|
||||
+ --enable-host-bind-now link host code as BIND_NOW
|
||||
--disable-libquadmath-support
|
||||
disable libquadmath support for Fortran
|
||||
--enable-default-pie enable Position Independent Executable as default
|
||||
@@ -32109,6 +32112,14 @@ fi
|
||||
|
||||
|
||||
|
||||
+# Enable --enable-host-bind-now
|
||||
+# Check whether --enable-host-bind-now was given.
|
||||
+if test "${enable_host_bind_now+set}" = set; then :
|
||||
+ enableval=$enable_host_bind_now;
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+
|
||||
# Check whether --enable-libquadmath-support was given.
|
||||
if test "${enable_libquadmath_support+set}" = set; then :
|
||||
enableval=$enable_libquadmath_support; ENABLE_LIBQUADMATH_SUPPORT=$enableval
|
||||
@@ -32295,6 +32306,8 @@ else
|
||||
PICFLAG=
|
||||
fi
|
||||
|
||||
+
|
||||
+
|
||||
if test x$enable_host_pie = xyes; then
|
||||
LD_PICFLAG=-pie
|
||||
elif test x$gcc_cv_no_pie = xyes; then
|
||||
@@ -32303,6 +32316,9 @@ else
|
||||
LD_PICFLAG=
|
||||
fi
|
||||
|
||||
+if test x$enable_host_bind_now = xyes; then
|
||||
+ LD_PICFLAG="$LD_PICFLAG -Wl,-z,now"
|
||||
+fi
|
||||
|
||||
|
||||
|
||||
diff --git a/gcc/configure.ac b/gcc/configure.ac
|
||||
index dca995aeec7..6017bcbc8c6 100644
|
||||
--- a/gcc/configure.ac
|
||||
+++ b/gcc/configure.ac
|
||||
@@ -7497,6 +7497,12 @@ AC_ARG_ENABLE(host-pie,
|
||||
[build host code as PIE])])
|
||||
AC_SUBST(enable_host_pie)
|
||||
|
||||
+# Enable --enable-host-bind-now
|
||||
+AC_ARG_ENABLE(host-bind-now,
|
||||
+[AS_HELP_STRING([--enable-host-bind-now],
|
||||
+ [link host code as BIND_NOW])])
|
||||
+AC_SUBST(enable_host_bind_now)
|
||||
+
|
||||
AC_ARG_ENABLE(libquadmath-support,
|
||||
[AS_HELP_STRING([--disable-libquadmath-support],
|
||||
[disable libquadmath support for Fortran])],
|
||||
@@ -7638,6 +7644,8 @@ else
|
||||
PICFLAG=
|
||||
fi
|
||||
|
||||
+AC_SUBST([PICFLAG])
|
||||
+
|
||||
if test x$enable_host_pie = xyes; then
|
||||
LD_PICFLAG=-pie
|
||||
elif test x$gcc_cv_no_pie = xyes; then
|
||||
@@ -7646,7 +7654,10 @@ else
|
||||
LD_PICFLAG=
|
||||
fi
|
||||
|
||||
-AC_SUBST([PICFLAG])
|
||||
+if test x$enable_host_bind_now = xyes; then
|
||||
+ LD_PICFLAG="$LD_PICFLAG -Wl,-z,now"
|
||||
+fi
|
||||
+
|
||||
AC_SUBST([LD_PICFLAG])
|
||||
|
||||
# Enable Intel CET on Intel CET enabled host if jit is enabled.
|
||||
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
|
||||
index 9747f832a75..b59af198d3e 100644
|
||||
--- a/gcc/doc/install.texi
|
||||
+++ b/gcc/doc/install.texi
|
||||
@@ -1041,6 +1041,12 @@ protection against Return Oriented Programming (ROP) attacks.
|
||||
in which case @option{-fPIC} is used when compiling, and @option{-pie} when
|
||||
linking.
|
||||
|
||||
+@item --enable-host-bind-now
|
||||
+Specify that the @emph{host} executables should be linked with the option
|
||||
+@option{-Wl,-z,now}, which means that the dynamic linker will resolve all
|
||||
+symbols when the executables are started, and that in turn allows RELRO to
|
||||
+mark the GOT read-only, resulting in better security.
|
||||
+
|
||||
@item @anchor{with-gnu-as}--with-gnu-as
|
||||
Specify that the compiler should assume that the
|
||||
assembler it finds is the GNU assembler. However, this does not modify
|
||||
diff --git a/lto-plugin/configure b/lto-plugin/configure
|
||||
index baa84adbb6c..669ccaede52 100755
|
||||
--- a/lto-plugin/configure
|
||||
+++ b/lto-plugin/configure
|
||||
@@ -656,6 +656,7 @@ accel_dir_suffix
|
||||
gcc_build_dir
|
||||
CET_HOST_FLAGS
|
||||
ac_lto_plugin_ldflags
|
||||
+enable_host_bind_now
|
||||
ac_lto_plugin_warn_cflags
|
||||
EGREP
|
||||
GREP
|
||||
@@ -771,6 +772,7 @@ enable_maintainer_mode
|
||||
with_libiberty
|
||||
enable_dependency_tracking
|
||||
enable_largefile
|
||||
+enable_host_bind_now
|
||||
enable_cet
|
||||
with_gcc_major_version_only
|
||||
enable_shared
|
||||
@@ -1418,6 +1420,7 @@ Optional Features:
|
||||
--disable-dependency-tracking
|
||||
speeds up one-time build
|
||||
--disable-largefile omit support for large files
|
||||
+ --enable-host-bind-now link host code as BIND_NOW
|
||||
--enable-cet enable Intel CET in host libraries [default=auto]
|
||||
--enable-shared[=PKGS] build shared libraries [default=yes]
|
||||
--enable-static[=PKGS] build static libraries [default=yes]
|
||||
@@ -5662,6 +5665,19 @@ if test "x$have_static_libgcc" = xyes; then
|
||||
ac_lto_plugin_ldflags="-Wc,-static-libgcc"
|
||||
fi
|
||||
|
||||
+# Enable --enable-host-bind-now
|
||||
+# Check whether --enable-host-bind-now was given.
|
||||
+if test "${enable_host_bind_now+set}" = set; then :
|
||||
+ enableval=$enable_host_bind_now;
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+
|
||||
+if test x$enable_host_bind_now = xyes; then
|
||||
+ ac_lto_plugin_ldflags="$ac_lto_plugin_ldflags -Wl,-z,now"
|
||||
+fi
|
||||
+
|
||||
+
|
||||
|
||||
# Check whether --enable-cet was given.
|
||||
if test "${enable_cet+set}" = set; then :
|
||||
diff --git a/lto-plugin/configure.ac b/lto-plugin/configure.ac
|
||||
index 7e6f729e9dc..5d5fea8fe70 100644
|
||||
--- a/lto-plugin/configure.ac
|
||||
+++ b/lto-plugin/configure.ac
|
||||
@@ -25,6 +25,17 @@ LDFLAGS="$saved_LDFLAGS"
|
||||
if test "x$have_static_libgcc" = xyes; then
|
||||
ac_lto_plugin_ldflags="-Wc,-static-libgcc"
|
||||
fi
|
||||
+
|
||||
+# Enable --enable-host-bind-now
|
||||
+AC_ARG_ENABLE(host-bind-now,
|
||||
+[AS_HELP_STRING([--enable-host-bind-now],
|
||||
+ [link host code as BIND_NOW])])
|
||||
+AC_SUBST(enable_host_bind_now)
|
||||
+
|
||||
+if test x$enable_host_bind_now = xyes; then
|
||||
+ ac_lto_plugin_ldflags="$ac_lto_plugin_ldflags -Wl,-z,now"
|
||||
+fi
|
||||
+
|
||||
AC_SUBST(ac_lto_plugin_ldflags)
|
||||
|
||||
GCC_CET_HOST_FLAGS(CET_HOST_FLAGS)
|
||||
|
||||
base-commit: bf799d3409cb9a189114a6c9ff5b7cd123915764
|
||||
--
|
||||
2.34.1
|
||||
|
||||
20
gcc11-d-shared-libphobos.patch
Normal file
20
gcc11-d-shared-libphobos.patch
Normal file
@ -0,0 +1,20 @@
|
||||
2019-01-17 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* d-spec.cc (lang_specific_driver): Make -shared-libphobos
|
||||
the default rather than -static-libphobos.
|
||||
|
||||
--- gcc/d/d-spec.cc.jj 2019-01-01 12:37:49.502444257 +0100
|
||||
+++ gcc/d/d-spec.cc 2019-01-17 17:09:45.364949246 +0100
|
||||
@@ -408,9 +408,9 @@ lang_specific_driver (cl_decoded_option
|
||||
/* Add `-lgphobos' if we haven't already done so. */
|
||||
if (phobos_library != PHOBOS_NOLINK)
|
||||
{
|
||||
- /* Default to static linking. */
|
||||
- if (phobos_library != PHOBOS_DYNAMIC)
|
||||
- phobos_library = PHOBOS_STATIC;
|
||||
+ /* Default to shared linking. */
|
||||
+ if (phobos_library != PHOBOS_STATIC)
|
||||
+ phobos_library = PHOBOS_DYNAMIC;
|
||||
|
||||
#ifdef HAVE_LD_STATIC_DYNAMIC
|
||||
if (phobos_library == PHOBOS_STATIC && !static_link)
|
||||
32
gcc11-dejagnu-multiline.patch
Normal file
32
gcc11-dejagnu-multiline.patch
Normal file
@ -0,0 +1,32 @@
|
||||
commit 14c7757e9b751781360737f53b71f851fc356d3d
|
||||
Author: Jeff Law <jeffreyalaw@gmail.com>
|
||||
Date: Fri Oct 29 11:30:15 2021 -0400
|
||||
|
||||
Avoid overly-greedy match in dejagnu regexp.
|
||||
|
||||
Occasionally I've been seeing failures with the multi-line diagnostics. It's never been clear what's causing the spurious failures, though I have long suspected a greedy regexp match.
|
||||
|
||||
It happened again yesterday with a local change that in no way should affect diagnostics, so I finally went searching and found that sure enough the multi-line diagnostics had a ".*" in their regexp. According to the comments, the .* is primarily to catch any dg directives that may appear -- ie it should eat to EOL, but not multiple lines. But a .* can indeed match a newline and cause it to eat multiple lines.
|
||||
|
||||
The fix is simple. [^\r\n]* will eat to EOL, but not further.
|
||||
|
||||
Regression tested on x86_64 and on our internal target.
|
||||
|
||||
gcc/testsuite
|
||||
|
||||
* lib/multiline.exp (_build_multiline_regex): Use a better
|
||||
regexp than .* to match up to EOL.
|
||||
|
||||
diff --git a/gcc/testsuite/lib/multiline.exp b/gcc/testsuite/lib/multiline.exp
|
||||
index 0e151b6d222..86387f8209b 100644
|
||||
--- a/gcc/testsuite/lib/multiline.exp
|
||||
+++ b/gcc/testsuite/lib/multiline.exp
|
||||
@@ -331,7 +331,7 @@ proc _build_multiline_regex { multiline index } {
|
||||
# Support arbitrary followup text on each non-empty line,
|
||||
# to deal with comments containing containing DejaGnu
|
||||
# directives.
|
||||
- append rexp ".*"
|
||||
+ append rexp "\[^\\n\\r\]*"
|
||||
}
|
||||
}
|
||||
append rexp "\n"
|
||||
69
gcc11-detect-sapphirerapids.patch
Normal file
69
gcc11-detect-sapphirerapids.patch
Normal file
@ -0,0 +1,69 @@
|
||||
commit 63dd214dce603f4f99e2cb272255b6c2b4308c3d
|
||||
Author: Cui,Lili <lili.cui@intel.com>
|
||||
Date: Mon Nov 7 11:25:41 2022 +0800
|
||||
|
||||
Remove AVX512_VP2INTERSECT from PTA_SAPPHIRERAPIDS
|
||||
|
||||
gcc/ChangeLog:
|
||||
|
||||
* config/i386/driver-i386.cc (host_detect_local_cpu):
|
||||
Move sapphirerapids out of AVX512_VP2INTERSECT.
|
||||
* config/i386/i386.h: Remove AVX512_VP2INTERSECT from PTA_SAPPHIRERAPIDS
|
||||
* doc/invoke.texi: Remove AVX512_VP2INTERSECT from SAPPHIRERAPIDS
|
||||
|
||||
(cherry picked from commit d644dfe36d9733c767af62d37250253ced6efd8c)
|
||||
|
||||
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
|
||||
index f844a168ddb..90f84aba4ee 100644
|
||||
--- a/gcc/config/i386/driver-i386.c
|
||||
+++ b/gcc/config/i386/driver-i386.c
|
||||
@@ -574,15 +574,12 @@ const char *host_detect_local_cpu (int argc, const char **argv)
|
||||
/* This is unknown family 0x6 CPU. */
|
||||
if (has_feature (FEATURE_AVX))
|
||||
{
|
||||
+ /* Assume Tiger Lake */
|
||||
if (has_feature (FEATURE_AVX512VP2INTERSECT))
|
||||
- {
|
||||
- if (has_feature (FEATURE_TSXLDTRK))
|
||||
- /* Assume Sapphire Rapids. */
|
||||
- cpu = "sapphirerapids";
|
||||
- else
|
||||
- /* Assume Tiger Lake */
|
||||
- cpu = "tigerlake";
|
||||
- }
|
||||
+ cpu = "tigerlake";
|
||||
+ /* Assume Sapphire Rapids. */
|
||||
+ else if (has_feature (FEATURE_TSXLDTRK))
|
||||
+ cpu = "sapphirerapids";
|
||||
/* Assume Cooper Lake */
|
||||
else if (has_feature (FEATURE_AVX512BF16))
|
||||
cpu = "cooperlake";
|
||||
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
|
||||
index ac0e5da623c..e03279bcf39 100644
|
||||
--- a/gcc/config/i386/i386.h
|
||||
+++ b/gcc/config/i386/i386.h
|
||||
@@ -2562,7 +2562,7 @@ constexpr wide_int_bitmask PTA_ICELAKE_SERVER = PTA_ICELAKE_CLIENT
|
||||
constexpr wide_int_bitmask PTA_TIGERLAKE = PTA_ICELAKE_CLIENT | PTA_MOVDIRI
|
||||
| PTA_MOVDIR64B | PTA_CLWB | PTA_AVX512VP2INTERSECT | PTA_KL | PTA_WIDEKL;
|
||||
constexpr wide_int_bitmask PTA_SAPPHIRERAPIDS = PTA_ICELAKE_SERVER | PTA_MOVDIRI
|
||||
- | PTA_MOVDIR64B | PTA_AVX512VP2INTERSECT | PTA_ENQCMD | PTA_CLDEMOTE
|
||||
+ | PTA_MOVDIR64B | PTA_ENQCMD | PTA_CLDEMOTE
|
||||
| PTA_PTWRITE | PTA_WAITPKG | PTA_SERIALIZE | PTA_TSXLDTRK | PTA_AMX_TILE
|
||||
| PTA_AMX_INT8 | PTA_AMX_BF16 | PTA_UINTR | PTA_AVXVNNI | PTA_AVX512BF16;
|
||||
constexpr wide_int_bitmask PTA_KNL = PTA_BROADWELL | PTA_AVX512PF
|
||||
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
|
||||
index 3419483c532..6b3afb827a5 100644
|
||||
--- a/gcc/doc/invoke.texi
|
||||
+++ b/gcc/doc/invoke.texi
|
||||
@@ -30236,9 +30236,9 @@ Intel sapphirerapids CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3,
|
||||
SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE,
|
||||
RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW,
|
||||
AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ,
|
||||
-AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2
|
||||
+AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2,
|
||||
VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, PCONFIG, WBNOINVD, CLWB,
|
||||
-MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG,
|
||||
+MOVDIRI, MOVDIR64B, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG,
|
||||
SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI and
|
||||
AVX512BF16 instruction set support.
|
||||
|
||||
83
gcc11-dg-ice-fixes.patch
Normal file
83
gcc11-dg-ice-fixes.patch
Normal file
@ -0,0 +1,83 @@
|
||||
diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-1.c b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-1.c
|
||||
index 8c3884bdc00..141f089d4f8 100644
|
||||
--- a/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-1.c
|
||||
+++ b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-1.c
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Test OpenACC 'kernels' construct decomposition. */
|
||||
|
||||
/* { dg-additional-options "-fopt-info-omp-all" } */
|
||||
-/* { dg-additional-options "-fchecking --param=openacc-kernels=decompose" } */
|
||||
+/* { dg-additional-options "-fno-report-bug -fchecking --param=openacc-kernels=decompose" } */
|
||||
/* { dg-ice "TODO" }
|
||||
{ dg-prune-output "during GIMPLE pass: omplower" } */
|
||||
|
||||
diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-2.c b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-2.c
|
||||
index 8bf60a9a509..a07e0a42116 100644
|
||||
--- a/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-2.c
|
||||
+++ b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-2.c
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Test OpenACC 'kernels' construct decomposition. */
|
||||
|
||||
-/* { dg-additional-options "-fchecking --param=openacc-kernels=decompose" } */
|
||||
+/* { dg-additional-options "-fno-report-bug -fchecking --param=openacc-kernels=decompose" } */
|
||||
/* { dg-ice "TODO" }
|
||||
{ dg-prune-output "during GIMPLE pass: omplower" } */
|
||||
|
||||
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
|
||||
index eae0d8c377b..ed37f95e865 100644
|
||||
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
|
||||
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
|
||||
@@ -1,6 +1,6 @@
|
||||
// PR c++/52830
|
||||
// { dg-do compile { target c++11 } }
|
||||
-// { dg-additional-options "-fchecking" }
|
||||
+// { dg-additional-options "-fchecking -fno-report-bug" }
|
||||
// { dg-ice "comptypes" }
|
||||
|
||||
template<bool b> struct eif { typedef void type; };
|
||||
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-88982.C b/gcc/testsuite/g++.dg/cpp0x/vt-88982.C
|
||||
index 7a868233d73..45307a63483 100644
|
||||
--- a/gcc/testsuite/g++.dg/cpp0x/vt-88982.C
|
||||
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-88982.C
|
||||
@@ -1,6 +1,6 @@
|
||||
// PR c++/88982
|
||||
// { dg-do compile { target c++11 } }
|
||||
-// { dg-additional-options "-fchecking" }
|
||||
+// { dg-additional-options "-fchecking -fno-report-bug" }
|
||||
// { dg-ice "tsubst_pack_expansion" }
|
||||
|
||||
template<typename...Ts> struct A {
|
||||
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn61.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn61.C
|
||||
index bed5ea0cfc0..cb235bf891a 100644
|
||||
--- a/gcc/testsuite/g++.dg/cpp1y/auto-fn61.C
|
||||
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn61.C
|
||||
@@ -1,6 +1,6 @@
|
||||
// PR c++/88003
|
||||
// { dg-do compile { target c++14 } }
|
||||
-// { dg-additional-options "-fchecking" }
|
||||
+// { dg-additional-options "-fchecking -fno-report-bug" }
|
||||
// { dg-ice "poplevel_class" }
|
||||
|
||||
auto test() {
|
||||
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda26.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda26.C
|
||||
index 0cdb400d21c..8f17cca31dd 100644
|
||||
--- a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda26.C
|
||||
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda26.C
|
||||
@@ -1,6 +1,6 @@
|
||||
// PR c++/87765
|
||||
// { dg-do compile { target c++17 } }
|
||||
-// { dg-additional-options "-fchecking" }
|
||||
+// { dg-additional-options "-fchecking -fno-report-bug" }
|
||||
// { dg-ice "cxx_eval_constant_expression" }
|
||||
|
||||
template <int N>
|
||||
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-vla-kernels-decompose-ice-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-vla-kernels-decompose-ice-1.c
|
||||
index 0777b612b63..53abbe2db83 100644
|
||||
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-vla-kernels-decompose-ice-1.c
|
||||
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/declare-vla-kernels-decompose-ice-1.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* { dg-additional-options "--param=openacc-kernels=decompose" } */
|
||||
+/* { dg-additional-options "--param=openacc-kernels=decompose -fno-report-bug" } */
|
||||
/* Hopefully, this is the same issue as '../../../gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-1.c'.
|
||||
{ dg-ice "TODO" }
|
||||
TODO { dg-prune-output "during GIMPLE pass: omplower" }
|
||||
@ -0,0 +1,74 @@
|
||||
From 59a72acbccf4c81a04b4d09760fc8b16992de106 Mon Sep 17 00:00:00 2001
|
||||
From: Xi Ruoyao <xry111@xry111.site>
|
||||
Date: Sat, 24 Sep 2022 15:16:57 +0800
|
||||
Subject: aarch64: testsuite: disable stack protector for tests relying on
|
||||
stack offset
|
||||
|
||||
Stack protector needs a guard value on the stack and change the stack
|
||||
layout. So we need to disable it for those tests, to avoid test failure
|
||||
with --enable-default-ssp.
|
||||
|
||||
gcc/testsuite/ChangeLog:
|
||||
|
||||
* gcc.target/aarch64/shrink_wrap_1.c (dg-options): Add
|
||||
-fno-stack-protector.
|
||||
* gcc.target/aarch64/stack-check-cfa-1.c (dg-options): Add
|
||||
-fno-stack-protector.
|
||||
* gcc.target/aarch64/stack-check-cfa-2.c (dg-options): Add
|
||||
-fno-stack-protector.
|
||||
* gcc.target/aarch64/test_frame_17.c (dg-options): Add
|
||||
-fno-stack-protector.
|
||||
---
|
||||
gcc/testsuite/gcc.target/aarch64/shrink_wrap_1.c | 2 +-
|
||||
gcc/testsuite/gcc.target/aarch64/stack-check-cfa-1.c | 2 +-
|
||||
gcc/testsuite/gcc.target/aarch64/stack-check-cfa-2.c | 2 +-
|
||||
gcc/testsuite/gcc.target/aarch64/test_frame_17.c | 2 +-
|
||||
4 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/gcc/testsuite/gcc.target/aarch64/shrink_wrap_1.c b/gcc/testsuite/gcc.target/aarch64/shrink_wrap_1.c
|
||||
index ab7cd74ec3b4..067220c04a08 100644
|
||||
--- a/gcc/testsuite/gcc.target/aarch64/shrink_wrap_1.c
|
||||
+++ b/gcc/testsuite/gcc.target/aarch64/shrink_wrap_1.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile { target { aarch64*-*-* } } } */
|
||||
-/* { dg-options "-O2" } */
|
||||
+/* { dg-options "-O2 -fno-stack-protector" } */
|
||||
/* { dg-final { check-function-bodies "**" "" } } */
|
||||
|
||||
/*
|
||||
diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-1.c b/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-1.c
|
||||
index 6885894a97e0..412a9ed1aab0 100644
|
||||
--- a/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-1.c
|
||||
+++ b/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-1.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
-/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16 -funwind-tables" } */
|
||||
+/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16 -funwind-tables -fno-stack-protector" } */
|
||||
/* { dg-require-effective-target supports_stack_clash_protection } */
|
||||
|
||||
#define SIZE 128*1024
|
||||
diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-2.c b/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-2.c
|
||||
index 5796a53be067..e440569a0785 100644
|
||||
--- a/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-2.c
|
||||
+++ b/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-2.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
-/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16 -funwind-tables" } */
|
||||
+/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16 -funwind-tables -fno-stack-protector" } */
|
||||
/* { dg-require-effective-target supports_stack_clash_protection } */
|
||||
|
||||
#define SIZE 1280*1024 + 512
|
||||
diff --git a/gcc/testsuite/gcc.target/aarch64/test_frame_17.c b/gcc/testsuite/gcc.target/aarch64/test_frame_17.c
|
||||
index 44f132911286..5d432ad0854e 100644
|
||||
--- a/gcc/testsuite/gcc.target/aarch64/test_frame_17.c
|
||||
+++ b/gcc/testsuite/gcc.target/aarch64/test_frame_17.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
-/* { dg-options "-O2" } */
|
||||
+/* { dg-options "-O2 -fno-stack-protector" } */
|
||||
|
||||
/* Test reuse of stack adjustment temporaries. */
|
||||
|
||||
--
|
||||
cgit
|
||||
|
||||
244
gcc11-fix-failures-with-default-SSP.patch
Normal file
244
gcc11-fix-failures-with-default-SSP.patch
Normal file
@ -0,0 +1,244 @@
|
||||
From 90c31ff339015ddd89ac519656fbd23a36ee6271 Mon Sep 17 00:00:00 2001
|
||||
From: Allan McRae <allan@archlinux.org>
|
||||
Date: Fri, 28 Jan 2022 12:44:08 -0500
|
||||
Subject: testsuite/70230 - fix failures with default SSP\
|
||||
|
||||
Configuring with --enable-default-ssp triggers various testsuite
|
||||
failures. These contain asm statements that are not compatible with
|
||||
-fstack-protector. Adding -fno-stack-protector to dg-options to
|
||||
work around this issue.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR testsuite/70230
|
||||
* gcc.dg/asan/use-after-scope-4.c (dg-options): Add
|
||||
-fno-stack-protector.
|
||||
* gcc.dg/stack-usage-1.c: Likewise
|
||||
* gcc.dg/superblock.c: Likewise
|
||||
* gcc.target/i386/avx-vzeroupper-17.c: Likewise
|
||||
* gcc.target/i386/cleanup-1.c: Likewise
|
||||
* gcc.target/i386/cleanup-2.c: Likewise
|
||||
* gcc.target/i386/interrupt-redzone-1.c: Likewise
|
||||
* gcc.target/i386/interrupt-redzone-2.c: Likewise
|
||||
* gcc.target/i386/pr79793-1.c: Likewise
|
||||
* gcc.target/i386/pr79793-2.c: Likewise
|
||||
* gcc.target/i386/shrink_wrap_1.c: Likewise
|
||||
* gcc.target/i386/stack-check-11.c: Likewise
|
||||
* gcc.target/i386/stack-check-18.c: Likewise
|
||||
* gcc.target/i386/stack-check-19.c: Likewise
|
||||
* gcc.target/i386/stackalign/pr88483-1.c: Likewise
|
||||
* gcc.target/i386/stackalign/pr88483-2.c: Likewise
|
||||
* gcc.target/i386/sw-1.c: Likewise
|
||||
|
||||
Backported to gcc 11 by dmalcolm@redhat.com
|
||||
This was r12-6922-g90c31ff339015d, modifying the change to sw-1.c
|
||||
to avoid the change from r12-2671-gdadbb1a886af95.
|
||||
|
||||
---
|
||||
gcc/testsuite/gcc.dg/asan/use-after-scope-4.c | 1 +
|
||||
gcc/testsuite/gcc.dg/stack-usage-1.c | 2 +-
|
||||
gcc/testsuite/gcc.dg/superblock.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/avx-vzeroupper-17.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/cleanup-1.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/cleanup-2.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/interrupt-redzone-1.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/interrupt-redzone-2.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/pr79793-1.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/pr79793-2.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/shrink_wrap_1.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/stack-check-11.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/stack-check-18.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/stack-check-19.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/stackalign/pr88483-1.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/stackalign/pr88483-2.c | 2 +-
|
||||
gcc/testsuite/gcc.target/i386/sw-1.c | 2 +-
|
||||
17 files changed, 17 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-4.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-4.c
|
||||
index 44dc79535d2a..e1486e75045f 100644
|
||||
--- a/gcc/testsuite/gcc.dg/asan/use-after-scope-4.c
|
||||
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-4.c
|
||||
@@ -1,4 +1,5 @@
|
||||
// { dg-do run }
|
||||
+/* { dg-options "-fno-stack-protector" } */
|
||||
|
||||
#define FN(NAME) \
|
||||
NAME (void) \
|
||||
diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c
|
||||
index 93cfe7c01639..1d7d1fee4351 100644
|
||||
--- a/gcc/testsuite/gcc.dg/stack-usage-1.c
|
||||
+++ b/gcc/testsuite/gcc.dg/stack-usage-1.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
-/* { dg-options "-fstack-usage" } */
|
||||
+/* { dg-options "-fstack-usage -fno-stack-protector" } */
|
||||
/* nvptx doesn't have a reg allocator, and hence no stack usage data. */
|
||||
/* { dg-skip-if "" { nvptx-*-* } } */
|
||||
|
||||
diff --git a/gcc/testsuite/gcc.dg/superblock.c b/gcc/testsuite/gcc.dg/superblock.c
|
||||
index 2b2fa9e154fb..6b4419adaf59 100644
|
||||
--- a/gcc/testsuite/gcc.dg/superblock.c
|
||||
+++ b/gcc/testsuite/gcc.dg/superblock.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
-/* { dg-options "-O2 -fno-asynchronous-unwind-tables -fsched2-use-superblocks -fdump-rtl-sched2 -fdump-rtl-bbro" } */
|
||||
+/* { dg-options "-O2 -fno-asynchronous-unwind-tables -fsched2-use-superblocks -fdump-rtl-sched2 -fdump-rtl-bbro -fno-stack-protector" } */
|
||||
/* { dg-require-effective-target scheduling } */
|
||||
|
||||
typedef int aligned __attribute__ ((aligned (64)));
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-17.c b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-17.c
|
||||
index 6dc0dc053214..d677e6f10e01 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-17.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-17.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile { target lp64 } } */
|
||||
-/* { dg-options "-O2 -mavx -mabi=ms -dp" } */
|
||||
+/* { dg-options "-O2 -mavx -mabi=ms -dp -fno-stack-protector" } */
|
||||
|
||||
typedef float __m256 __attribute__ ((__vector_size__ (32), __may_alias__));
|
||||
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/cleanup-1.c b/gcc/testsuite/gcc.target/i386/cleanup-1.c
|
||||
index dcfcc4edb5fa..6e7544c6b7ac 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/cleanup-1.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/cleanup-1.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do run { target *-*-linux* *-*-gnu* } } */
|
||||
-/* { dg-options "-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2" } */
|
||||
+/* { dg-options "-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2 -fno-stack-protector" } */
|
||||
/* Test complex CFA value expressions. */
|
||||
|
||||
#include <unwind.h>
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/cleanup-2.c b/gcc/testsuite/gcc.target/i386/cleanup-2.c
|
||||
index 7e60323373b8..a24daba73da2 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/cleanup-2.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/cleanup-2.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do run { target { *-*-linux* && { ! ia32 } } } } */
|
||||
-/* { dg-options "-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2" } */
|
||||
+/* { dg-options "-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2 -fno-stack-protector" } */
|
||||
/* Test complex CFA value expressions. */
|
||||
|
||||
#include <unwind.h>
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-redzone-1.c b/gcc/testsuite/gcc.target/i386/interrupt-redzone-1.c
|
||||
index 10098848c506..0c412db427e3 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/interrupt-redzone-1.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/interrupt-redzone-1.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile { target { ! ia32 } } } */
|
||||
-/* { dg-options "-O2 -mgeneral-regs-only -mno-cld -mred-zone" } */
|
||||
+/* { dg-options "-O2 -mgeneral-regs-only -mno-cld -mred-zone -fno-stack-protector" } */
|
||||
|
||||
void
|
||||
__attribute__((interrupt))
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-redzone-2.c b/gcc/testsuite/gcc.target/i386/interrupt-redzone-2.c
|
||||
index 2577f43c9168..caea99665f23 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/interrupt-redzone-2.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/interrupt-redzone-2.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile { target { ! ia32 } } } */
|
||||
-/* { dg-options "-O2 -mgeneral-regs-only -mno-cld -mred-zone" } */
|
||||
+/* { dg-options "-O2 -mgeneral-regs-only -mno-cld -mred-zone -fno-stack-protector" } */
|
||||
|
||||
void
|
||||
__attribute__((interrupt))
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/pr79793-1.c b/gcc/testsuite/gcc.target/i386/pr79793-1.c
|
||||
index 1cc67a83ba39..102d63afe8d9 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/pr79793-1.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/pr79793-1.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
|
||||
-/* { dg-options "-O2 -mgeneral-regs-only -mtune=generic" } */
|
||||
+/* { dg-options "-O2 -mgeneral-regs-only -mtune=generic -fno-stack-protector" } */
|
||||
|
||||
void
|
||||
__attribute__ ((interrupt))
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/pr79793-2.c b/gcc/testsuite/gcc.target/i386/pr79793-2.c
|
||||
index e1e6463e120a..30f22bea9884 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/pr79793-2.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/pr79793-2.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
|
||||
-/* { dg-options "-O2 -mgeneral-regs-only -mtune=generic" } */
|
||||
+/* { dg-options "-O2 -mgeneral-regs-only -mtune=generic -fno-stack-protector" } */
|
||||
|
||||
typedef unsigned int uword_t __attribute__ ((mode (__word__)));
|
||||
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/shrink_wrap_1.c b/gcc/testsuite/gcc.target/i386/shrink_wrap_1.c
|
||||
index 94dadd6cdbd8..4b286671e90b 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/shrink_wrap_1.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/shrink_wrap_1.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile { target { ! ia32 } } } */
|
||||
-/* { dg-options "-O2 -fdump-rtl-pro_and_epilogue" } */
|
||||
+/* { dg-options "-O2 -fdump-rtl-pro_and_epilogue -fno-stack-protector" } */
|
||||
|
||||
enum machine_mode
|
||||
{
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/stack-check-11.c b/gcc/testsuite/gcc.target/i386/stack-check-11.c
|
||||
index 90ab6023b422..48341cedcd4b 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/stack-check-11.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/stack-check-11.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
-/* { dg-options "-O2 -fstack-clash-protection -mtune=generic" } */
|
||||
+/* { dg-options "-O2 -fstack-clash-protection -mtune=generic -fno-stack-protector" } */
|
||||
/* { dg-require-effective-target supports_stack_clash_protection } */
|
||||
|
||||
#include <stdint.h>
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/stack-check-18.c b/gcc/testsuite/gcc.target/i386/stack-check-18.c
|
||||
index 1cf4bbcfafb5..a0aab4a98238 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/stack-check-18.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/stack-check-18.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
-/* { dg-options "-O2 -fstack-clash-protection -mtune=generic -fdump-rtl-expand" } */
|
||||
+/* { dg-options "-O2 -fstack-clash-protection -mtune=generic -fdump-rtl-expand -fno-stack-protector" } */
|
||||
/* { dg-require-effective-target supports_stack_clash_protection } */
|
||||
/* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */
|
||||
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/stack-check-19.c b/gcc/testsuite/gcc.target/i386/stack-check-19.c
|
||||
index bf6af5ffc3e9..94c75dcb47ce 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/stack-check-19.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/stack-check-19.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
-/* { dg-options "-O2 -fstack-clash-protection -mtune=generic -fdump-rtl-expand" } */
|
||||
+/* { dg-options "-O2 -fstack-clash-protection -mtune=generic -fdump-rtl-expand -fno-stack-protector" } */
|
||||
/* { dg-require-effective-target supports_stack_clash_protection } */
|
||||
/* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */
|
||||
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/stackalign/pr88483-1.c b/gcc/testsuite/gcc.target/i386/stackalign/pr88483-1.c
|
||||
index c8bb0832fe26..11ecdd52aa15 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/stackalign/pr88483-1.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/stackalign/pr88483-1.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
-/* { dg-options "-O2 -mavx2" } */
|
||||
+/* { dg-options "-O2 -mavx2 -fno-stack-protector" } */
|
||||
|
||||
struct B
|
||||
{
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/stackalign/pr88483-2.c b/gcc/testsuite/gcc.target/i386/stackalign/pr88483-2.c
|
||||
index e94fa1d18fad..33174fa29dec 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/stackalign/pr88483-2.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/stackalign/pr88483-2.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
-/* { dg-options "-O2 -mavx512f" } */
|
||||
+/* { dg-options "-O2 -mavx512f -fno-stack-protector" } */
|
||||
|
||||
struct B
|
||||
{
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/sw-1.c b/gcc/testsuite/gcc.target/i386/sw-1.c
|
||||
index a9c89fca4ec4..b0432279644a 100644
|
||||
--- a/gcc/testsuite/gcc.target/i386/sw-1.c
|
||||
+++ b/gcc/testsuite/gcc.target/i386/sw-1.c
|
||||
@@ -1,4 +1,4 @@
|
||||
/* { dg-do compile } */
|
||||
-/* { dg-options "-O2 -mtune=generic -fshrink-wrap -fdump-rtl-pro_and_epilogue" } */
|
||||
+/* { dg-options "-O2 -mtune=generic -fshrink-wrap -fdump-rtl-pro_and_epilogue -fno-stack-protector" } */
|
||||
/* { dg-skip-if "No shrink-wrapping preformed" { x86_64-*-mingw* } } */
|
||||
|
||||
--
|
||||
cgit
|
||||
|
||||
@ -1,21 +1,22 @@
|
||||
2017-01-20 Jakub Jelinek <jakub@redhat.com>
|
||||
2019-01-17 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.c (offload_targets_default): New variable.
|
||||
(process_command): Set it if -foffload is defaulted.
|
||||
(driver::maybe_putenv_OFFLOAD_TARGETS): Add OFFLOAD_TARGET_DEFAULT=1
|
||||
into environment if -foffload has been defaulted.
|
||||
* lto-wrapper.c (OFFLOAD_TARGET_DEFAULT_ENV): Define.
|
||||
(compile_images_for_offload_targets): If OFFLOAD_TARGET_DEFAULT
|
||||
(compile_offload_image): If OFFLOAD_TARGET_DEFAULT
|
||||
is in the environment, don't fail if corresponding mkoffload
|
||||
can't be found. Free and clear offload_names if no valid offload
|
||||
is found.
|
||||
can't be found.
|
||||
(compile_images_for_offload_targets): Likewise. Free and clear
|
||||
offload_names if no valid offload is found.
|
||||
libgomp/
|
||||
* target.c (gomp_load_plugin_for_device): If a plugin can't be
|
||||
dlopened, assume it has no devices silently.
|
||||
|
||||
--- gcc/gcc.c.jj 2017-01-17 10:28:40.000000000 +0100
|
||||
+++ gcc/gcc.c 2017-01-20 16:26:29.649962902 +0100
|
||||
@@ -290,6 +290,10 @@ static const char *spec_host_machine = D
|
||||
@@ -319,6 +319,10 @@ static const char *spec_host_machine = D
|
||||
|
||||
static char *offload_targets = NULL;
|
||||
|
||||
@ -26,7 +27,7 @@ libgomp/
|
||||
/* Nonzero if cross-compiling.
|
||||
When -b is used, the value comes from the `specs' file. */
|
||||
|
||||
@@ -4457,7 +4461,10 @@ process_command (unsigned int decoded_op
|
||||
@@ -4828,7 +4832,10 @@ process_command (unsigned int decoded_op
|
||||
/* If the user didn't specify any, default to all configured offload
|
||||
targets. */
|
||||
if (ENABLE_OFFLOADING && offload_targets == NULL)
|
||||
@ -36,14 +37,14 @@ libgomp/
|
||||
+ offload_targets_default = true;
|
||||
+ }
|
||||
|
||||
if (output_file
|
||||
&& strcmp (output_file, "-") != 0
|
||||
@@ -7693,6 +7700,8 @@ driver::maybe_putenv_OFFLOAD_TARGETS ()
|
||||
/* Handle -gtoggle as it would later in toplev.c:process_options to
|
||||
make the debug-level-gt spec function work as expected. */
|
||||
@@ -8494,6 +8501,8 @@ driver::maybe_putenv_OFFLOAD_TARGETS ()
|
||||
obstack_grow (&collect_obstack, offload_targets,
|
||||
strlen (offload_targets) + 1);
|
||||
xputenv (XOBFINISH (&collect_obstack, char *));
|
||||
+ if (offload_targets_default)
|
||||
+ xputenv ("OFFLOAD_TARGET_DEFAULT=1");
|
||||
+ xputenv ("OFFLOAD_TARGET_DEFAULT=1");
|
||||
}
|
||||
|
||||
free (offload_targets);
|
||||
@ -55,55 +56,53 @@ libgomp/
|
||||
#define OFFLOAD_TARGET_NAMES_ENV "OFFLOAD_TARGET_NAMES"
|
||||
+#define OFFLOAD_TARGET_DEFAULT_ENV "OFFLOAD_TARGET_DEFAULT"
|
||||
|
||||
enum lto_mode_d {
|
||||
LTO_MODE_NONE, /* Not doing LTO. */
|
||||
@@ -790,8 +791,10 @@ compile_images_for_offload_targets (unsi
|
||||
/* By default there is no special suffix for target executables. */
|
||||
#ifdef TARGET_EXECUTABLE_SUFFIX
|
||||
@@ -906,6 +907,12 @@ compile_offload_image (const char *targe
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (!compiler && getenv (OFFLOAD_TARGET_DEFAULT_ENV))
|
||||
+ {
|
||||
+ free_array_of_ptrs ((void **) paths, n_paths);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
if (!compiler)
|
||||
fatal_error (input_location,
|
||||
"could not find %s in %s (consider using %<-B%>)",
|
||||
@@ -975,6 +982,7 @@ compile_images_for_offload_targets (unsi
|
||||
if (!target_names)
|
||||
return;
|
||||
unsigned num_targets = parse_env_var (target_names, &names, NULL);
|
||||
+ const char *target_names_default = getenv (OFFLOAD_TARGET_DEFAULT_ENV);
|
||||
+ int next_name_entry = 0;
|
||||
|
||||
int next_name_entry = 0;
|
||||
+ bool hsa_seen = false;
|
||||
const char *compiler_path = getenv ("COMPILER_PATH");
|
||||
if (!compiler_path)
|
||||
goto out;
|
||||
@@ -804,18 +807,32 @@ compile_images_for_offload_targets (unsi
|
||||
/* HSA does not use LTO-like streaming and a different compiler, skip
|
||||
it. */
|
||||
if (strcmp (names[i], "hsa") == 0)
|
||||
- continue;
|
||||
+ {
|
||||
+ hsa_seen = true;
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
offload_names[next_name_entry]
|
||||
@@ -985,13 +993,19 @@ compile_images_for_offload_targets (unsi
|
||||
offload_names = XCNEWVEC (char *, num_targets + 1);
|
||||
for (unsigned i = 0; i < num_targets; i++)
|
||||
{
|
||||
- offload_names[i]
|
||||
+ offload_names[next_name_entry]
|
||||
= compile_offload_image (names[i], compiler_path, in_argc, in_argv,
|
||||
compiler_opts, compiler_opt_count,
|
||||
linker_opts, linker_opt_count);
|
||||
if (!offload_names[next_name_entry])
|
||||
- if (!offload_names[i])
|
||||
- fatal_error (input_location,
|
||||
- "problem with building target image for %s\n", names[i]);
|
||||
+ {
|
||||
+ if (target_names_default != NULL)
|
||||
+ continue;
|
||||
+ fatal_error (input_location,
|
||||
+ "problem with building target image for %s\n",
|
||||
+ names[i]);
|
||||
+ }
|
||||
next_name_entry++;
|
||||
}
|
||||
|
||||
+ if (next_name_entry == 0 && !hsa_seen)
|
||||
- "problem with building target image for %s", names[i]);
|
||||
+ if (!offload_names[next_name_entry])
|
||||
+ continue;
|
||||
+ next_name_entry++;
|
||||
+ }
|
||||
+
|
||||
+ if (next_name_entry == 0)
|
||||
+ {
|
||||
+ free (offload_names);
|
||||
+ offload_names = NULL;
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
out:
|
||||
free_array_of_ptrs ((void **) names, num_targets);
|
||||
}
|
||||
--- libgomp/target.c.jj 2017-01-01 12:45:52.000000000 +0100
|
||||
+++ libgomp/target.c 2017-01-20 20:12:13.756710875 +0100
|
||||
@@ -2356,7 +2356,7 @@ gomp_load_plugin_for_device (struct gomp
|
||||
181
gcc11-fortran-fdec-add-missing-indexes.patch
Normal file
181
gcc11-fortran-fdec-add-missing-indexes.patch
Normal file
@ -0,0 +1,181 @@
|
||||
From 7001d522d0273658d9e1fb12ca104d56bfcae34d Mon Sep 17 00:00:00 2001
|
||||
From: Mark Eggleston <markeggleston@gcc.gnu.org>
|
||||
Date: Fri, 22 Jan 2021 15:06:08 +0000
|
||||
Subject: [PATCH 10/10] Fill in missing array dimensions using the lower bound
|
||||
|
||||
Use -fdec-add-missing-indexes to enable feature. Also enabled by fdec.
|
||||
---
|
||||
gcc/fortran/lang.opt | 8 ++++++++
|
||||
gcc/fortran/options.c | 1 +
|
||||
gcc/fortran/resolve.c | 24 ++++++++++++++++++++++++
|
||||
gcc/testsuite/gfortran.dg/array_6.f90 | 23 +++++++++++++++++++++++
|
||||
gcc/testsuite/gfortran.dg/array_7.f90 | 23 +++++++++++++++++++++++
|
||||
gcc/testsuite/gfortran.dg/array_8.f90 | 23 +++++++++++++++++++++++
|
||||
6 files changed, 102 insertions(+)
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/array_6.f90
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/array_7.f90
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/array_8.f90
|
||||
|
||||
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
|
||||
index 019c798cf09..f27de88ea3f 100644
|
||||
--- a/gcc/fortran/lang.opt
|
||||
+++ b/gcc/fortran/lang.opt
|
||||
@@ -281,6 +281,10 @@ Wmissing-include-dirs
|
||||
Fortran
|
||||
; Documented in C/C++
|
||||
|
||||
+Wmissing-index
|
||||
+Fortran Var(warn_missing_index) Warning LangEnabledBy(Fortran,Wall)
|
||||
+Warn that the lower bound of a missing index will be used.
|
||||
+
|
||||
Wuse-without-only
|
||||
Fortran Var(warn_use_without_only) Warning
|
||||
Warn about USE statements that have no ONLY qualifier.
|
||||
@@ -460,6 +464,10 @@ fdec
|
||||
Fortran Var(flag_dec)
|
||||
Enable all DEC language extensions.
|
||||
|
||||
+fdec-add-missing-indexes
|
||||
+Fortran Var(flag_dec_add_missing_indexes)
|
||||
+Enable the addition of missing indexes using their lower bounds.
|
||||
+
|
||||
fdec-blank-format-item
|
||||
Fortran Var(flag_dec_blank_format_item)
|
||||
Enable the use of blank format items in format strings.
|
||||
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
|
||||
index 050f56fdc25..c3b2822685d 100644
|
||||
--- a/gcc/fortran/options.c
|
||||
+++ b/gcc/fortran/options.c
|
||||
@@ -84,6 +84,7 @@ set_dec_flags (int value)
|
||||
SET_BITFLAG (flag_dec_non_logical_if, value, value);
|
||||
SET_BITFLAG (flag_dec_promotion, value, value);
|
||||
SET_BITFLAG (flag_dec_sequence, value, value);
|
||||
+ SET_BITFLAG (flag_dec_add_missing_indexes, value, value);
|
||||
}
|
||||
|
||||
/* Finalize DEC flags. */
|
||||
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
|
||||
index fe7d0cc5944..0efeedab46e 100644
|
||||
--- a/gcc/fortran/resolve.c
|
||||
+++ b/gcc/fortran/resolve.c
|
||||
@@ -4806,6 +4806,30 @@ compare_spec_to_ref (gfc_array_ref *ar)
|
||||
if (ar->type == AR_FULL)
|
||||
return true;
|
||||
|
||||
+ if (flag_dec_add_missing_indexes && as->rank > ar->dimen)
|
||||
+ {
|
||||
+ /* Add in the missing dimensions, assuming they are the lower bound
|
||||
+ of that dimension if not specified. */
|
||||
+ int j;
|
||||
+ if (warn_missing_index)
|
||||
+ {
|
||||
+ gfc_warning (OPT_Wmissing_index, "Using the lower bound for "
|
||||
+ "unspecified dimensions in array reference at %L",
|
||||
+ &ar->where);
|
||||
+ }
|
||||
+ /* Other parts of the code iterate ar->start and ar->end from 0 to
|
||||
+ ar->dimen, so it is safe to assume slots from ar->dimen upwards
|
||||
+ are unused (i.e. there are no gaps; the specified indexes are
|
||||
+ contiguous and start at zero. */
|
||||
+ for(j = ar->dimen; j <= as->rank; j++)
|
||||
+ {
|
||||
+ ar->start[j] = gfc_copy_expr (as->lower[j]);
|
||||
+ ar->end[j] = gfc_copy_expr (as->lower[j]);
|
||||
+ ar->dimen_type[j] = DIMEN_ELEMENT;
|
||||
+ }
|
||||
+ ar->dimen = as->rank;
|
||||
+ }
|
||||
+
|
||||
if (as->rank != ar->dimen)
|
||||
{
|
||||
gfc_error ("Rank mismatch in array reference at %L (%d/%d)",
|
||||
diff --git a/gcc/testsuite/gfortran.dg/array_6.f90 b/gcc/testsuite/gfortran.dg/array_6.f90
|
||||
new file mode 100644
|
||||
index 00000000000..5c26e18ab3e
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/array_6.f90
|
||||
@@ -0,0 +1,23 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec -Wmissing-index" }!
|
||||
+! Checks that under-specified arrays (referencing arrays with fewer
|
||||
+! dimensions than the array spec) generates a warning.
|
||||
+!
|
||||
+! Contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
+! Updated by Mark Eggleston <mark.eggleston@codethink.co.uk>
|
||||
+!
|
||||
+
|
||||
+program under_specified_array
|
||||
+ integer chessboard(8,8)
|
||||
+ integer chessboard3d(8,8,3:5)
|
||||
+ chessboard(3,1) = 5
|
||||
+ chessboard(3,2) = 55
|
||||
+ chessboard3d(4,1,3) = 6
|
||||
+ chessboard3d(4,1,4) = 66
|
||||
+ chessboard3d(4,4,3) = 7
|
||||
+ chessboard3d(4,4,4) = 77
|
||||
+
|
||||
+ if (chessboard(3).ne.5) stop 1 ! { dg-warning "Using the lower bound for unspecified dimensions in array reference" }
|
||||
+ if (chessboard3d(4).ne.6) stop 2 ! { dg-warning "Using the lower bound for unspecified dimensions in array reference" }
|
||||
+ if (chessboard3d(4,4).ne.7) stop 3 ! { dg-warning "Using the lower bound for unspecified dimensions in array reference" }
|
||||
+end program
|
||||
diff --git a/gcc/testsuite/gfortran.dg/array_7.f90 b/gcc/testsuite/gfortran.dg/array_7.f90
|
||||
new file mode 100644
|
||||
index 00000000000..5588a5bd02d
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/array_7.f90
|
||||
@@ -0,0 +1,23 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec-add-missing-indexes -Wmissing-index" }!
|
||||
+! Checks that under-specified arrays (referencing arrays with fewer
|
||||
+! dimensions than the array spec) generates a warning.
|
||||
+!
|
||||
+! Contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
+! Updated by Mark Eggleston <mark.eggleston@codethink.co.uk>
|
||||
+!
|
||||
+
|
||||
+program under_specified_array
|
||||
+ integer chessboard(8,8)
|
||||
+ integer chessboard3d(8,8,3:5)
|
||||
+ chessboard(3,1) = 5
|
||||
+ chessboard(3,2) = 55
|
||||
+ chessboard3d(4,1,3) = 6
|
||||
+ chessboard3d(4,1,4) = 66
|
||||
+ chessboard3d(4,4,3) = 7
|
||||
+ chessboard3d(4,4,4) = 77
|
||||
+
|
||||
+ if (chessboard(3).ne.5) stop 1 ! { dg-warning "Using the lower bound for unspecified dimensions in array reference" }
|
||||
+ if (chessboard3d(4).ne.6) stop 2 ! { dg-warning "Using the lower bound for unspecified dimensions in array reference" }
|
||||
+ if (chessboard3d(4,4).ne.7) stop 3 ! { dg-warning "Using the lower bound for unspecified dimensions in array reference" }
|
||||
+end program
|
||||
diff --git a/gcc/testsuite/gfortran.dg/array_8.f90 b/gcc/testsuite/gfortran.dg/array_8.f90
|
||||
new file mode 100644
|
||||
index 00000000000..f0d2ef5e37d
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/array_8.f90
|
||||
@@ -0,0 +1,23 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-fdec -fno-dec-add-missing-indexes" }!
|
||||
+! Checks that under-specified arrays (referencing arrays with fewer
|
||||
+! dimensions than the array spec) generates a warning.
|
||||
+!
|
||||
+! Contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
+! Updated by Mark Eggleston <mark.eggleston@codethink.co.uk>
|
||||
+!
|
||||
+
|
||||
+program under_specified_array
|
||||
+ integer chessboard(8,8)
|
||||
+ integer chessboard3d(8,8,3:5)
|
||||
+ chessboard(3,1) = 5
|
||||
+ chessboard(3,2) = 55
|
||||
+ chessboard3d(4,1,3) = 6
|
||||
+ chessboard3d(4,1,4) = 66
|
||||
+ chessboard3d(4,4,3) = 7
|
||||
+ chessboard3d(4,4,4) = 77
|
||||
+
|
||||
+ if (chessboard(3).ne.5) stop 1 ! { dg-error "Rank mismatch" }
|
||||
+ if (chessboard3d(4).ne.6) stop 2 ! { dg-error "Rank mismatch" }
|
||||
+ if (chessboard3d(4,4).ne.7) stop 3 ! { dg-error "Rank mismatch" }
|
||||
+end program
|
||||
--
|
||||
2.27.0
|
||||
|
||||
215
gcc11-fortran-fdec-duplicates.patch
Normal file
215
gcc11-fortran-fdec-duplicates.patch
Normal file
@ -0,0 +1,215 @@
|
||||
From 23b1fcb104c666429451ffaf936f8da5fcd3d43a Mon Sep 17 00:00:00 2001
|
||||
From: Mark Eggleston <markeggleston@gcc.gnu.org>
|
||||
Date: Fri, 22 Jan 2021 12:29:47 +0000
|
||||
Subject: [PATCH 01/10] Allow duplicate declarations.
|
||||
|
||||
Enabled by -fdec-duplicates and -fdec.
|
||||
|
||||
Some fixes by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
Addition of -fdec-duplicates by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
---
|
||||
gcc/fortran/lang.opt | 4 ++++
|
||||
gcc/fortran/options.c | 1 +
|
||||
gcc/fortran/symbol.c | 21 +++++++++++++++++--
|
||||
.../gfortran.dg/duplicate_type_4.f90 | 13 ++++++++++++
|
||||
.../gfortran.dg/duplicate_type_5.f90 | 13 ++++++++++++
|
||||
.../gfortran.dg/duplicate_type_6.f90 | 13 ++++++++++++
|
||||
.../gfortran.dg/duplicate_type_7.f90 | 13 ++++++++++++
|
||||
.../gfortran.dg/duplicate_type_8.f90 | 12 +++++++++++
|
||||
.../gfortran.dg/duplicate_type_9.f90 | 12 +++++++++++
|
||||
9 files changed, 100 insertions(+), 2 deletions(-)
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/duplicate_type_4.f90
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/duplicate_type_5.f90
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/duplicate_type_6.f90
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/duplicate_type_7.f90
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/duplicate_type_8.f90
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/duplicate_type_9.f90
|
||||
|
||||
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
|
||||
index 2b1977c523b..52bd522051e 100644
|
||||
--- a/gcc/fortran/lang.opt
|
||||
+++ b/gcc/fortran/lang.opt
|
||||
@@ -469,6 +469,10 @@ Fortran Var(flag_dec_char_conversions)
|
||||
Enable the use of character literals in assignments and data statements
|
||||
for non-character variables.
|
||||
|
||||
+fdec-duplicates
|
||||
+Fortran Var(flag_dec_duplicates)
|
||||
+Allow varibles to be duplicated in the type specification matches.
|
||||
+
|
||||
fdec-include
|
||||
Fortran Var(flag_dec_include)
|
||||
Enable legacy parsing of INCLUDE as statement.
|
||||
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
|
||||
index 3a0b98bf1ec..f19ba87f8a0 100644
|
||||
--- a/gcc/fortran/options.c
|
||||
+++ b/gcc/fortran/options.c
|
||||
@@ -77,6 +77,7 @@ set_dec_flags (int value)
|
||||
SET_BITFLAG (flag_dec_format_defaults, value, value);
|
||||
SET_BITFLAG (flag_dec_blank_format_item, value, value);
|
||||
SET_BITFLAG (flag_dec_char_conversions, value, value);
|
||||
+ SET_BITFLAG (flag_dec_duplicates, value, value);
|
||||
}
|
||||
|
||||
/* Finalize DEC flags. */
|
||||
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
|
||||
index 3b988d1be22..9843175cc2a 100644
|
||||
--- a/gcc/fortran/symbol.c
|
||||
+++ b/gcc/fortran/symbol.c
|
||||
@@ -1995,6 +1995,8 @@ gfc_add_type (gfc_symbol *sym, gfc_typespec *ts, locus *where)
|
||||
if (sym->attr.result && type == BT_UNKNOWN && sym->ns->proc_name)
|
||||
type = sym->ns->proc_name->ts.type;
|
||||
|
||||
+ flavor = sym->attr.flavor;
|
||||
+
|
||||
if (type != BT_UNKNOWN && !(sym->attr.function && sym->attr.implicit_type)
|
||||
&& !(gfc_state_stack->previous && gfc_state_stack->previous->previous
|
||||
&& gfc_state_stack->previous->previous->state == COMP_SUBMODULE)
|
||||
@@ -2007,6 +2009,23 @@ gfc_add_type (gfc_symbol *sym, gfc_typespec *ts, locus *where)
|
||||
else if (sym->attr.function && sym->attr.result)
|
||||
gfc_error ("Symbol %qs at %L already has basic type of %s",
|
||||
sym->ns->proc_name->name, where, gfc_basic_typename (type));
|
||||
+ else if (flag_dec_duplicates)
|
||||
+ {
|
||||
+ /* Ignore temporaries and class/procedure names */
|
||||
+ if (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS
|
||||
+ || sym->ts.type == BT_PROCEDURE)
|
||||
+ return false;
|
||||
+
|
||||
+ if (gfc_compare_types (&sym->ts, ts)
|
||||
+ && (flavor == FL_UNKNOWN || flavor == FL_VARIABLE
|
||||
+ || flavor == FL_PROCEDURE))
|
||||
+ {
|
||||
+ return gfc_notify_std (GFC_STD_LEGACY,
|
||||
+ "Symbol '%qs' at %L already has "
|
||||
+ "basic type of %s", sym->name, where,
|
||||
+ gfc_basic_typename (type));
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
gfc_error ("Symbol %qs at %L already has basic type of %s", sym->name,
|
||||
where, gfc_basic_typename (type));
|
||||
@@ -2020,8 +2039,6 @@ gfc_add_type (gfc_symbol *sym, gfc_typespec *ts, locus *where)
|
||||
return false;
|
||||
}
|
||||
|
||||
- flavor = sym->attr.flavor;
|
||||
-
|
||||
if (flavor == FL_PROGRAM || flavor == FL_BLOCK_DATA || flavor == FL_MODULE
|
||||
|| flavor == FL_LABEL
|
||||
|| (flavor == FL_PROCEDURE && sym->attr.subroutine)
|
||||
diff --git a/gcc/testsuite/gfortran.dg/duplicate_type_4.f90 b/gcc/testsuite/gfortran.dg/duplicate_type_4.f90
|
||||
new file mode 100644
|
||||
index 00000000000..cdd29ea8846
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/duplicate_type_4.f90
|
||||
@@ -0,0 +1,13 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-std=f95" }
|
||||
+
|
||||
+! PR fortran/30239
|
||||
+! Check for errors when a symbol gets declared a type twice, even if it
|
||||
+! is the same.
|
||||
+
|
||||
+INTEGER FUNCTION foo ()
|
||||
+ IMPLICIT NONE
|
||||
+ INTEGER :: x
|
||||
+ INTEGER :: x ! { dg-error "basic type of" }
|
||||
+ x = 42
|
||||
+END FUNCTION foo
|
||||
diff --git a/gcc/testsuite/gfortran.dg/duplicate_type_5.f90 b/gcc/testsuite/gfortran.dg/duplicate_type_5.f90
|
||||
new file mode 100644
|
||||
index 00000000000..00f931809aa
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/duplicate_type_5.f90
|
||||
@@ -0,0 +1,13 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec" }
|
||||
+!
|
||||
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+
|
||||
+program test
|
||||
+ implicit none
|
||||
+ integer :: x
|
||||
+ integer :: x
|
||||
+ x = 42
|
||||
+ if (x /= 42) stop 1
|
||||
+end program test
|
||||
diff --git a/gcc/testsuite/gfortran.dg/duplicate_type_6.f90 b/gcc/testsuite/gfortran.dg/duplicate_type_6.f90
|
||||
new file mode 100644
|
||||
index 00000000000..f0df27e323c
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/duplicate_type_6.f90
|
||||
@@ -0,0 +1,13 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-std=legacy -fdec-duplicates" }
|
||||
+!
|
||||
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+
|
||||
+program test
|
||||
+ implicit none
|
||||
+ integer :: x
|
||||
+ integer :: x
|
||||
+ x = 42
|
||||
+ if (x /= 42) stop 1
|
||||
+end program test
|
||||
diff --git a/gcc/testsuite/gfortran.dg/duplicate_type_7.f90 b/gcc/testsuite/gfortran.dg/duplicate_type_7.f90
|
||||
new file mode 100644
|
||||
index 00000000000..f32472ff586
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/duplicate_type_7.f90
|
||||
@@ -0,0 +1,13 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec-duplicates" }
|
||||
+!
|
||||
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+
|
||||
+program test
|
||||
+ implicit none
|
||||
+ integer :: x
|
||||
+ integer :: x! { dg-warning "Legacy Extension" }
|
||||
+ x = 42
|
||||
+ if (x /= 42) stop 1
|
||||
+end program test
|
||||
diff --git a/gcc/testsuite/gfortran.dg/duplicate_type_8.f90 b/gcc/testsuite/gfortran.dg/duplicate_type_8.f90
|
||||
new file mode 100644
|
||||
index 00000000000..23c94add179
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/duplicate_type_8.f90
|
||||
@@ -0,0 +1,12 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-fdec -fno-dec-duplicates" }
|
||||
+!
|
||||
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+
|
||||
+integer function foo ()
|
||||
+ implicit none
|
||||
+ integer :: x
|
||||
+ integer :: x ! { dg-error "basic type of" }
|
||||
+ x = 42
|
||||
+end function foo
|
||||
diff --git a/gcc/testsuite/gfortran.dg/duplicate_type_9.f90 b/gcc/testsuite/gfortran.dg/duplicate_type_9.f90
|
||||
new file mode 100644
|
||||
index 00000000000..d5edee4d8ee
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/duplicate_type_9.f90
|
||||
@@ -0,0 +1,12 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-fdec-duplicates -fno-dec-duplicates" }
|
||||
+!
|
||||
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+
|
||||
+integer function foo ()
|
||||
+ implicit none
|
||||
+ integer :: x
|
||||
+ integer :: x ! { dg-error "basic type of" }
|
||||
+ x = 42
|
||||
+end function foo
|
||||
--
|
||||
2.27.0
|
||||
|
||||
78
gcc11-fortran-fdec-ichar.patch
Normal file
78
gcc11-fortran-fdec-ichar.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From f883ac209b0feea860354cb4ef7ff06dc8063fab Mon Sep 17 00:00:00 2001
|
||||
From: Mark Eggleston <markeggleston@gcc.gnu.org>
|
||||
Date: Fri, 22 Jan 2021 12:53:35 +0000
|
||||
Subject: [PATCH 03/10] Allow more than one character as argument to ICHAR
|
||||
|
||||
Use -fdec to enable.
|
||||
---
|
||||
gcc/fortran/check.c | 2 +-
|
||||
gcc/fortran/simplify.c | 4 ++--
|
||||
.../gfortran.dg/dec_ichar_with_string_1.f | 21 +++++++++++++++++++
|
||||
3 files changed, 24 insertions(+), 3 deletions(-)
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_ichar_with_string_1.f
|
||||
|
||||
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
|
||||
index 82db8e4e1b2..623c1cc470e 100644
|
||||
--- a/gcc/fortran/check.c
|
||||
+++ b/gcc/fortran/check.c
|
||||
@@ -3157,7 +3157,7 @@ gfc_check_ichar_iachar (gfc_expr *c, gfc_expr *kind)
|
||||
else
|
||||
return true;
|
||||
|
||||
- if (i != 1)
|
||||
+ if (i != 1 && !flag_dec)
|
||||
{
|
||||
gfc_error ("Argument of %s at %L must be of length one",
|
||||
gfc_current_intrinsic, &c->where);
|
||||
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
|
||||
index 23317a2e2d9..9900572424f 100644
|
||||
--- a/gcc/fortran/simplify.c
|
||||
+++ b/gcc/fortran/simplify.c
|
||||
@@ -3261,7 +3261,7 @@ gfc_simplify_iachar (gfc_expr *e, gfc_expr *kind)
|
||||
if (e->expr_type != EXPR_CONSTANT)
|
||||
return NULL;
|
||||
|
||||
- if (e->value.character.length != 1)
|
||||
+ if (e->value.character.length != 1 && !flag_dec)
|
||||
{
|
||||
gfc_error ("Argument of IACHAR at %L must be of length one", &e->where);
|
||||
return &gfc_bad_expr;
|
||||
@@ -3459,7 +3459,7 @@ gfc_simplify_ichar (gfc_expr *e, gfc_expr *kind)
|
||||
if (e->expr_type != EXPR_CONSTANT)
|
||||
return NULL;
|
||||
|
||||
- if (e->value.character.length != 1)
|
||||
+ if (e->value.character.length != 1 && !flag_dec)
|
||||
{
|
||||
gfc_error ("Argument of ICHAR at %L must be of length one", &e->where);
|
||||
return &gfc_bad_expr;
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_ichar_with_string_1.f b/gcc/testsuite/gfortran.dg/dec_ichar_with_string_1.f
|
||||
new file mode 100644
|
||||
index 00000000000..85efccecc0f
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_ichar_with_string_1.f
|
||||
@@ -0,0 +1,21 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec" }
|
||||
+!
|
||||
+! Test ICHAR and IACHAR with more than one character as argument
|
||||
+!
|
||||
+! Test case contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM ichar_more_than_one_character
|
||||
+ CHARACTER*4 st/'Test'/
|
||||
+ INTEGER i
|
||||
+
|
||||
+ i = ICHAR(st)
|
||||
+ if (i.NE.84) STOP 1
|
||||
+ i = IACHAR(st)
|
||||
+ if (i.NE.84) STOP 2
|
||||
+ i = ICHAR('Test')
|
||||
+ if (i.NE.84) STOP 3
|
||||
+ i = IACHAR('Test')
|
||||
+ if (i.NE.84) STOP 4
|
||||
+ END
|
||||
--
|
||||
2.27.0
|
||||
|
||||
158
gcc11-fortran-fdec-non-integer-index.patch
Normal file
158
gcc11-fortran-fdec-non-integer-index.patch
Normal file
@ -0,0 +1,158 @@
|
||||
From 67aef262311d6a746786ee0f59748ccaa7e1e711 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Eggleston <markeggleston@gcc.gnu.org>
|
||||
Date: Fri, 22 Jan 2021 13:09:54 +0000
|
||||
Subject: [PATCH 04/10] Allow non-integer substring indexes
|
||||
|
||||
Use -fdec-non-integer-index compiler flag to enable. Also enabled by -fdec.
|
||||
---
|
||||
gcc/fortran/lang.opt | 4 ++++
|
||||
gcc/fortran/options.c | 1 +
|
||||
gcc/fortran/resolve.c | 20 +++++++++++++++++++
|
||||
.../dec_not_integer_substring_indexes_1.f | 18 +++++++++++++++++
|
||||
.../dec_not_integer_substring_indexes_2.f | 18 +++++++++++++++++
|
||||
.../dec_not_integer_substring_indexes_3.f | 18 +++++++++++++++++
|
||||
6 files changed, 79 insertions(+)
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_1.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_2.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_3.f
|
||||
|
||||
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
|
||||
index c4da248f07c..d527c106bd6 100644
|
||||
--- a/gcc/fortran/lang.opt
|
||||
+++ b/gcc/fortran/lang.opt
|
||||
@@ -489,6 +489,10 @@ fdec-math
|
||||
Fortran Var(flag_dec_math)
|
||||
Enable legacy math intrinsics for compatibility.
|
||||
|
||||
+fdec-non-integer-index
|
||||
+Fortran Var(flag_dec_non_integer_index)
|
||||
+Enable support for non-integer substring indexes.
|
||||
+
|
||||
fdec-structure
|
||||
Fortran Var(flag_dec_structure)
|
||||
Enable support for DEC STRUCTURE/RECORD.
|
||||
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
|
||||
index f19ba87f8a0..9a042f64881 100644
|
||||
--- a/gcc/fortran/options.c
|
||||
+++ b/gcc/fortran/options.c
|
||||
@@ -78,6 +78,7 @@ set_dec_flags (int value)
|
||||
SET_BITFLAG (flag_dec_blank_format_item, value, value);
|
||||
SET_BITFLAG (flag_dec_char_conversions, value, value);
|
||||
SET_BITFLAG (flag_dec_duplicates, value, value);
|
||||
+ SET_BITFLAG (flag_dec_non_integer_index, value, value);
|
||||
}
|
||||
|
||||
/* Finalize DEC flags. */
|
||||
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
|
||||
index 4b90cb59902..bc0df0fdb99 100644
|
||||
--- a/gcc/fortran/resolve.c
|
||||
+++ b/gcc/fortran/resolve.c
|
||||
@@ -5131,6 +5131,16 @@ gfc_resolve_substring (gfc_ref *ref, bool *equal_length)
|
||||
if (!gfc_resolve_expr (ref->u.ss.start))
|
||||
return false;
|
||||
|
||||
+ /* In legacy mode, allow non-integer string indexes by converting */
|
||||
+ if (flag_dec_non_integer_index && ref->u.ss.start->ts.type != BT_INTEGER
|
||||
+ && gfc_numeric_ts (&ref->u.ss.start->ts))
|
||||
+ {
|
||||
+ gfc_typespec t;
|
||||
+ t.type = BT_INTEGER;
|
||||
+ t.kind = ref->u.ss.start->ts.kind;
|
||||
+ gfc_convert_type_warn (ref->u.ss.start, &t, 2, 1);
|
||||
+ }
|
||||
+
|
||||
if (ref->u.ss.start->ts.type != BT_INTEGER)
|
||||
{
|
||||
gfc_error ("Substring start index at %L must be of type INTEGER",
|
||||
@@ -5160,6 +5170,16 @@ gfc_resolve_substring (gfc_ref *ref, bool *equal_length)
|
||||
if (!gfc_resolve_expr (ref->u.ss.end))
|
||||
return false;
|
||||
|
||||
+ /* Non-integer string index endings, as for start */
|
||||
+ if (flag_dec_non_integer_index && ref->u.ss.end->ts.type != BT_INTEGER
|
||||
+ && gfc_numeric_ts (&ref->u.ss.end->ts))
|
||||
+ {
|
||||
+ gfc_typespec t;
|
||||
+ t.type = BT_INTEGER;
|
||||
+ t.kind = ref->u.ss.end->ts.kind;
|
||||
+ gfc_convert_type_warn (ref->u.ss.end, &t, 2, 1);
|
||||
+ }
|
||||
+
|
||||
if (ref->u.ss.end->ts.type != BT_INTEGER)
|
||||
{
|
||||
gfc_error ("Substring end index at %L must be of type INTEGER",
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_1.f b/gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_1.f
|
||||
new file mode 100644
|
||||
index 00000000000..0be28abaa4b
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_1.f
|
||||
@@ -0,0 +1,18 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec" }
|
||||
+!
|
||||
+! Test not integer substring indexes
|
||||
+!
|
||||
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM not_integer_substring_indexes
|
||||
+ CHARACTER*5 st/'Tests'/
|
||||
+ REAL ir/1.0/
|
||||
+ REAL ir2/4.0/
|
||||
+
|
||||
+ if (st(ir:4).ne.'Test') stop 1
|
||||
+ if (st(1:ir2).ne.'Test') stop 2
|
||||
+ if (st(1.0:4).ne.'Test') stop 3
|
||||
+ if (st(1:4.0).ne.'Test') stop 4
|
||||
+ if (st(2.5:4).ne.'est') stop 5
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_2.f b/gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_2.f
|
||||
new file mode 100644
|
||||
index 00000000000..3cf05296d0c
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_2.f
|
||||
@@ -0,0 +1,18 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec-non-integer-index" }
|
||||
+!
|
||||
+! Test not integer substring indexes
|
||||
+!
|
||||
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM not_integer_substring_indexes
|
||||
+ CHARACTER*5 st/'Tests'/
|
||||
+ REAL ir/1.0/
|
||||
+ REAL ir2/4.0/
|
||||
+
|
||||
+ if (st(ir:4).ne.'Test') stop 1
|
||||
+ if (st(1:ir2).ne.'Test') stop 2
|
||||
+ if (st(1.0:4).ne.'Test') stop 3
|
||||
+ if (st(1:4.0).ne.'Test') stop 4
|
||||
+ if (st(2.5:4).ne.'est') stop 5
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_3.f b/gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_3.f
|
||||
new file mode 100644
|
||||
index 00000000000..703de995897
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_not_integer_substring_indexes_3.f
|
||||
@@ -0,0 +1,18 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-fdec -fno-dec-non-integer-index" }
|
||||
+!
|
||||
+! Test not integer substring indexes
|
||||
+!
|
||||
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM not_integer_substring_indexes
|
||||
+ CHARACTER*5 st/'Tests'/
|
||||
+ REAL ir/1.0/
|
||||
+ REAL ir2/4.0/
|
||||
+
|
||||
+ if (st(ir:4).ne.'Test') stop 1 ! { dg-error "Substring start index" }
|
||||
+ if (st(1:ir2).ne.'Test') stop 2 ! { dg-error "Substring end index" }
|
||||
+ if (st(1.0:4).ne.'Test') stop 3 ! { dg-error "Substring start index" }
|
||||
+ if (st(1:4.0).ne.'Test') stop 4 ! { dg-error "Substring end index" }
|
||||
+ if (st(2.5:4).ne.'est') stop 5 ! { dg-error "Substring start index" }
|
||||
+ END
|
||||
--
|
||||
2.27.0
|
||||
|
||||
378
gcc11-fortran-fdec-non-logical-if.patch
Normal file
378
gcc11-fortran-fdec-non-logical-if.patch
Normal file
@ -0,0 +1,378 @@
|
||||
From cc87ddb841017bb0976b05091733609ee17d7f05 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Eggleston <markeggleston@gcc.gnu.org>
|
||||
Date: Fri, 22 Jan 2021 13:15:17 +0000
|
||||
Subject: [PATCH 07/10] Allow non-logical expressions in IF statements
|
||||
|
||||
Use -fdec-non-logical-if to enable feature. Also enabled using -fdec.
|
||||
---
|
||||
gcc/fortran/lang.opt | 4 ++
|
||||
gcc/fortran/options.c | 1 +
|
||||
gcc/fortran/resolve.c | 60 ++++++++++++++++---
|
||||
...gical_expressions_if_statements_blocks_1.f | 25 ++++++++
|
||||
...gical_expressions_if_statements_blocks_2.f | 25 ++++++++
|
||||
...gical_expressions_if_statements_blocks_3.f | 25 ++++++++
|
||||
...gical_expressions_if_statements_blocks_4.f | 45 ++++++++++++++
|
||||
...gical_expressions_if_statements_blocks_5.f | 45 ++++++++++++++
|
||||
...gical_expressions_if_statements_blocks_6.f | 45 ++++++++++++++
|
||||
9 files changed, 266 insertions(+), 9 deletions(-)
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_1.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_2.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_3.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_4.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_5.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_6.f
|
||||
|
||||
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
|
||||
index 4a269ebb22d..d886c2f33ed 100644
|
||||
--- a/gcc/fortran/lang.opt
|
||||
+++ b/gcc/fortran/lang.opt
|
||||
@@ -497,6 +497,10 @@ fdec-override-kind
|
||||
Fortran Var(flag_dec_override_kind)
|
||||
Enable support for per variable kind specification.
|
||||
|
||||
+fdec-non-logical-if
|
||||
+Fortran Var(flag_dec_non_logical_if)
|
||||
+Enable support for non-logical expressions in if statements.
|
||||
+
|
||||
fdec-old-init
|
||||
Fortran Var(flag_dec_old_init)
|
||||
Enable support for old style initializers in derived types.
|
||||
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
|
||||
index edbab483b36..a946c86790a 100644
|
||||
--- a/gcc/fortran/options.c
|
||||
+++ b/gcc/fortran/options.c
|
||||
@@ -81,6 +81,7 @@ set_dec_flags (int value)
|
||||
SET_BITFLAG (flag_dec_non_integer_index, value, value);
|
||||
SET_BITFLAG (flag_dec_old_init, value, value);
|
||||
SET_BITFLAG (flag_dec_override_kind, value, value);
|
||||
+ SET_BITFLAG (flag_dec_non_logical_if, value, value);
|
||||
}
|
||||
|
||||
/* Finalize DEC flags. */
|
||||
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
|
||||
index bc0df0fdb99..07dd039f3bf 100644
|
||||
--- a/gcc/fortran/resolve.c
|
||||
+++ b/gcc/fortran/resolve.c
|
||||
@@ -10789,10 +10789,31 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
|
||||
switch (b->op)
|
||||
{
|
||||
case EXEC_IF:
|
||||
- if (t && b->expr1 != NULL
|
||||
- && (b->expr1->ts.type != BT_LOGICAL || b->expr1->rank != 0))
|
||||
- gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
|
||||
- &b->expr1->where);
|
||||
+ if (t && b->expr1 != NULL)
|
||||
+ {
|
||||
+ if (flag_dec_non_logical_if && b->expr1->ts.type != BT_LOGICAL)
|
||||
+ {
|
||||
+ gfc_expr* cast;
|
||||
+ cast = gfc_ne (b->expr1,
|
||||
+ gfc_get_int_expr (1, &gfc_current_locus, 0),
|
||||
+ INTRINSIC_NE);
|
||||
+ if (cast == NULL)
|
||||
+ gfc_internal_error ("gfc_resolve_blocks(): Failed to cast "
|
||||
+ "to LOGICAL in IF");
|
||||
+ b->expr1 = cast;
|
||||
+ if (warn_conversion_extra)
|
||||
+ {
|
||||
+ gfc_warning (OPT_Wconversion_extra, "Non-LOGICAL type in"
|
||||
+ " IF statement condition %L will be true if"
|
||||
+ " it evaluates to nonzero",
|
||||
+ &b->expr1->where);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((b->expr1->ts.type != BT_LOGICAL || b->expr1->rank != 0))
|
||||
+ gfc_error ("IF clause at %L requires a scalar LOGICAL "
|
||||
+ "expression", &b->expr1->where);
|
||||
+ }
|
||||
break;
|
||||
|
||||
case EXEC_WHERE:
|
||||
@@ -12093,11 +12114,32 @@ start:
|
||||
break;
|
||||
|
||||
case EXEC_IF:
|
||||
- if (t && code->expr1 != NULL
|
||||
- && (code->expr1->ts.type != BT_LOGICAL
|
||||
- || code->expr1->rank != 0))
|
||||
- gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
|
||||
- &code->expr1->where);
|
||||
+ if (t && code->expr1 != NULL)
|
||||
+ {
|
||||
+ if (flag_dec_non_logical_if
|
||||
+ && code->expr1->ts.type != BT_LOGICAL)
|
||||
+ {
|
||||
+ gfc_expr* cast;
|
||||
+ cast = gfc_ne (code->expr1,
|
||||
+ gfc_get_int_expr (1, &gfc_current_locus, 0),
|
||||
+ INTRINSIC_NE);
|
||||
+ if (cast == NULL)
|
||||
+ gfc_internal_error ("gfc_resolve_code(): Failed to cast "
|
||||
+ "to LOGICAL in IF");
|
||||
+ code->expr1 = cast;
|
||||
+ if (warn_conversion_extra)
|
||||
+ {
|
||||
+ gfc_warning (OPT_Wconversion_extra, "Non-LOGICAL type in"
|
||||
+ " IF statement condition %L will be true if"
|
||||
+ " it evaluates to nonzero",
|
||||
+ &code->expr1->where);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (code->expr1->ts.type != BT_LOGICAL || code->expr1->rank != 0)
|
||||
+ gfc_error ("IF clause at %L requires a scalar LOGICAL "
|
||||
+ "expression", &code->expr1->where);
|
||||
+ }
|
||||
break;
|
||||
|
||||
case EXEC_CALL:
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_1.f b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_1.f
|
||||
new file mode 100644
|
||||
index 00000000000..0101db893ca
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_1.f
|
||||
@@ -0,0 +1,25 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec -Wconversion-extra" }
|
||||
+!
|
||||
+! Allow logical expressions in if statements and blocks
|
||||
+!
|
||||
+! Contributed by Francisco Redondo Marchena <francisco.marchema@codethink.co.uk>
|
||||
+! and Jeff Law <law@redhat.com>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM logical_exp_if_st_bl
|
||||
+ INTEGER ipos/1/
|
||||
+ INTEGER ineg/0/
|
||||
+
|
||||
+ ! Test non logical variables
|
||||
+ if (ineg) STOP 1 ! { dg-warning "if it evaluates to nonzero" }
|
||||
+ if (0) STOP 2 ! { dg-warning "if it evaluates to nonzero" }
|
||||
+
|
||||
+ ! Test non logical expressions in if statements
|
||||
+ if (MOD(ipos, 1)) STOP 3 ! { dg-warning "if it evaluates to nonzero" }
|
||||
+
|
||||
+ ! Test non logical expressions in if blocks
|
||||
+ if (MOD(2 * ipos, 2)) then ! { dg-warning "if it evaluates to nonzero" }
|
||||
+ STOP 4
|
||||
+ endif
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_2.f b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_2.f
|
||||
new file mode 100644
|
||||
index 00000000000..876f4e09508
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_2.f
|
||||
@@ -0,0 +1,25 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec-non-logical-if -Wconversion-extra" }
|
||||
+!
|
||||
+! Allow logical expressions in if statements and blocks
|
||||
+!
|
||||
+! Contributed by Francisco Redondo Marchena <francisco.marchema@codethink.co.uk>
|
||||
+! and Jeff Law <law@redhat.com>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM logical_exp_if_st_bl
|
||||
+ INTEGER ipos/1/
|
||||
+ INTEGER ineg/0/
|
||||
+
|
||||
+ ! Test non logical variables
|
||||
+ if (ineg) STOP 1 ! { dg-warning "if it evaluates to nonzero" }
|
||||
+ if (0) STOP 2 ! { dg-warning "if it evaluates to nonzero" }
|
||||
+
|
||||
+ ! Test non logical expressions in if statements
|
||||
+ if (MOD(ipos, 1)) STOP 3 ! { dg-warning "if it evaluates to nonzero" }
|
||||
+
|
||||
+ ! Test non logical expressions in if blocks
|
||||
+ if (MOD(2 * ipos, 2)) then ! { dg-warning "if it evaluates to nonzero" }
|
||||
+ STOP 4
|
||||
+ endif
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_3.f b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_3.f
|
||||
new file mode 100644
|
||||
index 00000000000..35cb4c51b8d
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_3.f
|
||||
@@ -0,0 +1,25 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-fdec -fno-dec-non-logical-if" }
|
||||
+!
|
||||
+! Allow logical expressions in if statements and blocks
|
||||
+!
|
||||
+! Contributed by Francisco Redondo Marchena <francisco.marchema@codethink.co.uk>
|
||||
+! and Jeff Law <law@redhat.com>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM logical_exp_if_st_bl
|
||||
+ INTEGER ipos/1/
|
||||
+ INTEGER ineg/0/
|
||||
+
|
||||
+ ! Test non logical variables
|
||||
+ if (ineg) STOP 1 ! { dg-error "IF clause at" }
|
||||
+ if (0) STOP 2 ! { dg-error "IF clause at" }
|
||||
+
|
||||
+ ! Test non logical expressions in if statements
|
||||
+ if (MOD(ipos, 1)) STOP 3 ! { dg-error "IF clause at" }
|
||||
+
|
||||
+ ! Test non logical expressions in if blocks
|
||||
+ if (MOD(2 * ipos, 2)) then ! { dg-error "IF clause at" }
|
||||
+ STOP 4
|
||||
+ endif
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_4.f b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_4.f
|
||||
new file mode 100644
|
||||
index 00000000000..7b60b60827f
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_4.f
|
||||
@@ -0,0 +1,45 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec -Wconversion-extra" }
|
||||
+!
|
||||
+! Contributed by Francisco Redondo Marchena <francisco.marchema@codethink.co.uk>
|
||||
+! and Jeff Law <law@redhat.com>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ function othersub1()
|
||||
+ integer*4 othersub1
|
||||
+ othersub1 = 9
|
||||
+ end
|
||||
+
|
||||
+ function othersub2()
|
||||
+ integer*4 othersub2
|
||||
+ othersub2 = 0
|
||||
+ end
|
||||
+
|
||||
+ program MAIN
|
||||
+ integer*4 othersub1
|
||||
+ integer*4 othersub2
|
||||
+ integer a /1/
|
||||
+ integer b /2/
|
||||
+
|
||||
+ if (othersub1()) then ! { dg-warning "if it evaluates to nonzero" }
|
||||
+ write(*,*) "OK"
|
||||
+ else
|
||||
+ stop 1
|
||||
+ end if
|
||||
+ if (othersub2()) then ! { dg-warning "if it evaluates to nonzero" }
|
||||
+ stop 2
|
||||
+ else
|
||||
+ write(*,*) "OK"
|
||||
+ end if
|
||||
+ if (a-b) then ! { dg-warning "if it evaluates to nonzero" }
|
||||
+ write(*,*) "OK"
|
||||
+ else
|
||||
+ stop 3
|
||||
+ end if
|
||||
+ if (b-(a+1)) then ! { dg-warning "if it evaluates to nonzero" }
|
||||
+ stop 3
|
||||
+ else
|
||||
+ write(*,*) "OK"
|
||||
+ end if
|
||||
+ end
|
||||
+
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_5.f b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_5.f
|
||||
new file mode 100644
|
||||
index 00000000000..80336f48ca1
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_5.f
|
||||
@@ -0,0 +1,45 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec-non-logical-if -Wconversion-extra" }
|
||||
+!
|
||||
+! Contributed by Francisco Redondo Marchena <francisco.marchema@codethink.co.uk>
|
||||
+! and Jeff Law <law@redhat.com>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ function othersub1()
|
||||
+ integer*4 othersub1
|
||||
+ othersub1 = 9
|
||||
+ end
|
||||
+
|
||||
+ function othersub2()
|
||||
+ integer*4 othersub2
|
||||
+ othersub2 = 0
|
||||
+ end
|
||||
+
|
||||
+ program MAIN
|
||||
+ integer*4 othersub1
|
||||
+ integer*4 othersub2
|
||||
+ integer a /1/
|
||||
+ integer b /2/
|
||||
+
|
||||
+ if (othersub1()) then ! { dg-warning "Non-LOGICAL type in IF statement" }
|
||||
+ write(*,*) "OK"
|
||||
+ else
|
||||
+ stop 1
|
||||
+ end if
|
||||
+ if (othersub2()) then ! { dg-warning "Non-LOGICAL type in IF statement" }
|
||||
+ stop 2
|
||||
+ else
|
||||
+ write(*,*) "OK"
|
||||
+ end if
|
||||
+ if (a-b) then ! { dg-warning "Non-LOGICAL type in IF statement" }
|
||||
+ write(*,*) "OK"
|
||||
+ else
|
||||
+ stop 3
|
||||
+ end if
|
||||
+ if (b-(a+1)) then ! { dg-warning "Non-LOGICAL type in IF statement" }
|
||||
+ stop 3
|
||||
+ else
|
||||
+ write(*,*) "OK"
|
||||
+ end if
|
||||
+ end
|
||||
+
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_6.f b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_6.f
|
||||
new file mode 100644
|
||||
index 00000000000..e1125ca717a
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_logical_expressions_if_statements_blocks_6.f
|
||||
@@ -0,0 +1,45 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-fdec -fno-dec-non-logical-if" }
|
||||
+!
|
||||
+! Contributed by Francisco Redondo Marchena <francisco.marchema@codethink.co.uk>
|
||||
+! and Jeff Law <law@redhat.com>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ function othersub1()
|
||||
+ integer*4 othersub1
|
||||
+ othersub1 = 9
|
||||
+ end
|
||||
+
|
||||
+ function othersub2()
|
||||
+ integer*4 othersub2
|
||||
+ othersub2 = 0
|
||||
+ end
|
||||
+
|
||||
+ program MAIN
|
||||
+ integer*4 othersub1
|
||||
+ integer*4 othersub2
|
||||
+ integer a /1/
|
||||
+ integer b /2/
|
||||
+
|
||||
+ if (othersub1()) then ! { dg-error "IF clause at" }
|
||||
+ write(*,*) "OK"
|
||||
+ else
|
||||
+ stop 1
|
||||
+ end if
|
||||
+ if (othersub2()) then ! { dg-error "IF clause at" }
|
||||
+ stop 2
|
||||
+ else
|
||||
+ write(*,*) "OK"
|
||||
+ end if
|
||||
+ if (a-b) then ! { dg-error "IF clause at" }
|
||||
+ write(*,*) "OK"
|
||||
+ else
|
||||
+ stop 3
|
||||
+ end if
|
||||
+ if (b-(a+1)) then ! { dg-error "IF clause at" }
|
||||
+ stop 3
|
||||
+ else
|
||||
+ write(*,*) "OK"
|
||||
+ end if
|
||||
+ end
|
||||
+
|
||||
--
|
||||
2.27.0
|
||||
|
||||
185
gcc11-fortran-fdec-old-init.patch
Normal file
185
gcc11-fortran-fdec-old-init.patch
Normal file
@ -0,0 +1,185 @@
|
||||
From 8bcc0f85ed1718c0dd9033ad4a34df181aabaffe Mon Sep 17 00:00:00 2001
|
||||
From: Mark Eggleston <markeggleston@gcc.gnu.org>
|
||||
Date: Fri, 22 Jan 2021 13:11:06 +0000
|
||||
Subject: [PATCH 05/10] Allow old-style initializers in derived types
|
||||
|
||||
This allows simple declarations in derived types and structures, such as:
|
||||
LOGICAL*1 NIL /0/
|
||||
Only single value expressions are allowed at the moment.
|
||||
|
||||
Use -fdec-old-init to enable. Also enabled by -fdec.
|
||||
---
|
||||
gcc/fortran/decl.c | 27 +++++++++++++++----
|
||||
gcc/fortran/lang.opt | 4 +++
|
||||
gcc/fortran/options.c | 1 +
|
||||
...ec_derived_types_initialised_old_style_1.f | 25 +++++++++++++++++
|
||||
...ec_derived_types_initialised_old_style_2.f | 25 +++++++++++++++++
|
||||
...ec_derived_types_initialised_old_style_3.f | 26 ++++++++++++++++++
|
||||
6 files changed, 103 insertions(+), 5 deletions(-)
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_1.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_2.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_3.f
|
||||
|
||||
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
|
||||
index 723915822f3..5c8c1b7981b 100644
|
||||
--- a/gcc/fortran/decl.c
|
||||
+++ b/gcc/fortran/decl.c
|
||||
@@ -2827,12 +2827,29 @@ variable_decl (int elem)
|
||||
but not components of derived types. */
|
||||
else if (gfc_current_state () == COMP_DERIVED)
|
||||
{
|
||||
- gfc_error ("Invalid old style initialization for derived type "
|
||||
- "component at %C");
|
||||
- m = MATCH_ERROR;
|
||||
- goto cleanup;
|
||||
+ if (flag_dec_old_init)
|
||||
+ {
|
||||
+ /* Attempt to match an old-style initializer which is a simple
|
||||
+ integer or character expression; this will not work with
|
||||
+ multiple values. */
|
||||
+ m = gfc_match_init_expr (&initializer);
|
||||
+ if (m == MATCH_ERROR)
|
||||
+ goto cleanup;
|
||||
+ else if (m == MATCH_YES)
|
||||
+ {
|
||||
+ m = gfc_match ("/");
|
||||
+ if (m != MATCH_YES)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ gfc_error ("Invalid old style initialization for derived type "
|
||||
+ "component at %C");
|
||||
+ m = MATCH_ERROR;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
}
|
||||
-
|
||||
/* For structure components, read the initializer as a special
|
||||
expression and let the rest of this function apply the initializer
|
||||
as usual. */
|
||||
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
|
||||
index d527c106bd6..25cc948699b 100644
|
||||
--- a/gcc/fortran/lang.opt
|
||||
+++ b/gcc/fortran/lang.opt
|
||||
@@ -493,6 +493,10 @@ fdec-non-integer-index
|
||||
Fortran Var(flag_dec_non_integer_index)
|
||||
Enable support for non-integer substring indexes.
|
||||
|
||||
+fdec-old-init
|
||||
+Fortran Var(flag_dec_old_init)
|
||||
+Enable support for old style initializers in derived types.
|
||||
+
|
||||
fdec-structure
|
||||
Fortran Var(flag_dec_structure)
|
||||
Enable support for DEC STRUCTURE/RECORD.
|
||||
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
|
||||
index 9a042f64881..d6bd36c3a8a 100644
|
||||
--- a/gcc/fortran/options.c
|
||||
+++ b/gcc/fortran/options.c
|
||||
@@ -79,6 +79,7 @@ set_dec_flags (int value)
|
||||
SET_BITFLAG (flag_dec_char_conversions, value, value);
|
||||
SET_BITFLAG (flag_dec_duplicates, value, value);
|
||||
SET_BITFLAG (flag_dec_non_integer_index, value, value);
|
||||
+ SET_BITFLAG (flag_dec_old_init, value, value);
|
||||
}
|
||||
|
||||
/* Finalize DEC flags. */
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_1.f b/gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_1.f
|
||||
new file mode 100644
|
||||
index 00000000000..eac4f9bfcf1
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_1.f
|
||||
@@ -0,0 +1,25 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec" }
|
||||
+!
|
||||
+! Test old style initializers in derived types
|
||||
+!
|
||||
+! Contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM spec_in_var
|
||||
+ TYPE STRUCT1
|
||||
+ INTEGER*4 ID /8/
|
||||
+ INTEGER*4 TYPE /5/
|
||||
+ INTEGER*8 DEFVAL /0/
|
||||
+ CHARACTER*(5) NAME /'tests'/
|
||||
+ LOGICAL*1 NIL /0/
|
||||
+ END TYPE STRUCT1
|
||||
+
|
||||
+ TYPE (STRUCT1) SINST
|
||||
+
|
||||
+ IF(SINST%ID.NE.8) STOP 1
|
||||
+ IF(SINST%TYPE.NE.5) STOP 2
|
||||
+ IF(SINST%DEFVAL.NE.0) STOP 3
|
||||
+ IF(SINST%NAME.NE.'tests') STOP 4
|
||||
+ IF(SINST%NIL) STOP 5
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_2.f b/gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_2.f
|
||||
new file mode 100644
|
||||
index 00000000000..d904c8b2974
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_2.f
|
||||
@@ -0,0 +1,25 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-std=legacy -fdec-old-init" }
|
||||
+!
|
||||
+! Test old style initializers in derived types
|
||||
+!
|
||||
+! Contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM spec_in_var
|
||||
+ TYPE STRUCT1
|
||||
+ INTEGER*4 ID /8/
|
||||
+ INTEGER*4 TYPE /5/
|
||||
+ INTEGER*8 DEFVAL /0/
|
||||
+ CHARACTER*(5) NAME /'tests'/
|
||||
+ LOGICAL*1 NIL /0/
|
||||
+ END TYPE STRUCT1
|
||||
+
|
||||
+ TYPE (STRUCT1) SINST
|
||||
+
|
||||
+ IF(SINST%ID.NE.8) STOP 1
|
||||
+ IF(SINST%TYPE.NE.5) STOP 2
|
||||
+ IF(SINST%DEFVAL.NE.0) STOP 3
|
||||
+ IF(SINST%NAME.NE.'tests') STOP 4
|
||||
+ IF(SINST%NIL) STOP 5
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_3.f b/gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_3.f
|
||||
new file mode 100644
|
||||
index 00000000000..58c2b4b66cf
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_derived_types_initialised_old_style_3.f
|
||||
@@ -0,0 +1,26 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-std=legacy -fdec -fno-dec-old-init" }
|
||||
+!
|
||||
+! Test old style initializers in derived types
|
||||
+!
|
||||
+! Contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+
|
||||
+ PROGRAM spec_in_var
|
||||
+ TYPE STRUCT1
|
||||
+ INTEGER*4 ID /8/ ! { dg-error "Invalid old style initialization" }
|
||||
+ INTEGER*4 TYPE /5/ ! { dg-error "Invalid old style initialization" }
|
||||
+ INTEGER*8 DEFVAL /0/ ! { dg-error "Invalid old style initialization" }
|
||||
+ CHARACTER*(5) NAME /'tests'/ ! { dg-error "Invalid old style initialization" }
|
||||
+ LOGICAL*1 NIL /0/ ! { dg-error "Invalid old style initialization" }
|
||||
+ END TYPE STRUCT1
|
||||
+
|
||||
+ TYPE (STRUCT1) SINST
|
||||
+
|
||||
+ IF(SINST%ID.NE.8) STOP 1 ! { dg-error "'id' at \\(1\\) is not a member" }
|
||||
+ IF(SINST%TYPE.NE.5) STOP 2 ! { dg-error "'type' at \\(1\\) is not a member" }
|
||||
+ IF(SINST%DEFVAL.NE.0) STOP 3 ! { dg-error "'defval' at \\(1\\) is not a member" }
|
||||
+ IF(SINST%NAME.NE.'tests') STOP 4 ! { dg-error "'name' at \\(1\\) is not a member" }
|
||||
+ IF(SINST%NIL) STOP 5 ! { dg-error "'nil' at \\(1\\) is not a member" }
|
||||
+ END
|
||||
--
|
||||
2.27.0
|
||||
|
||||
588
gcc11-fortran-fdec-override-kind.patch
Normal file
588
gcc11-fortran-fdec-override-kind.patch
Normal file
@ -0,0 +1,588 @@
|
||||
From 786869fd62813e80da9b6545a295d53c36275c19 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Eggleston <markeggleston@gcc.gnu.org>
|
||||
Date: Fri, 22 Jan 2021 13:12:14 +0000
|
||||
Subject: [PATCH 06/10] Allow string length and kind to be specified on a per
|
||||
variable basis.
|
||||
|
||||
This allows kind/length to be mixed with array specification in
|
||||
declarations.
|
||||
|
||||
e.g.
|
||||
|
||||
INTEGER*4 x*2, y*8
|
||||
CHARACTER names*20(10)
|
||||
REAL v(100)*8, vv*4(50)
|
||||
|
||||
The per-variable size overrides the kind or length specified for the type.
|
||||
|
||||
Use -fdec-override-kind to enable. Also enabled by -fdec.
|
||||
|
||||
Note: this feature is a merger of two previously separate features.
|
||||
|
||||
Now accepts named constants as kind parameters:
|
||||
|
||||
INTEGER A
|
||||
PARAMETER (A=2)
|
||||
INTEGER B*(A)
|
||||
|
||||
Contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
|
||||
Now rejects invalid kind parameters and prints error messages:
|
||||
|
||||
INTEGER X*3
|
||||
|
||||
caused an internal compiler error.
|
||||
|
||||
Contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
---
|
||||
gcc/fortran/decl.c | 156 ++++++++++++++----
|
||||
gcc/fortran/lang.opt | 4 +
|
||||
gcc/fortran/options.c | 1 +
|
||||
.../dec_mixed_char_array_declaration_1.f | 13 ++
|
||||
.../dec_mixed_char_array_declaration_2.f | 13 ++
|
||||
.../dec_mixed_char_array_declaration_3.f | 13 ++
|
||||
.../gfortran.dg/dec_spec_in_variable_1.f | 31 ++++
|
||||
.../gfortran.dg/dec_spec_in_variable_2.f | 31 ++++
|
||||
.../gfortran.dg/dec_spec_in_variable_3.f | 31 ++++
|
||||
.../gfortran.dg/dec_spec_in_variable_4.f | 14 ++
|
||||
.../gfortran.dg/dec_spec_in_variable_5.f | 19 +++
|
||||
.../gfortran.dg/dec_spec_in_variable_6.f | 19 +++
|
||||
.../gfortran.dg/dec_spec_in_variable_7.f | 15 ++
|
||||
.../gfortran.dg/dec_spec_in_variable_8.f | 14 ++
|
||||
14 files changed, 340 insertions(+), 34 deletions(-)
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_1.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_2.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_3.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_spec_in_variable_1.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_spec_in_variable_2.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_spec_in_variable_3.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_spec_in_variable_4.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_spec_in_variable_5.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_spec_in_variable_6.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_spec_in_variable_7.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_spec_in_variable_8.f
|
||||
|
||||
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
|
||||
index 5c8c1b7981b..f7dc9d8263d 100644
|
||||
--- a/gcc/fortran/decl.c
|
||||
+++ b/gcc/fortran/decl.c
|
||||
@@ -1213,6 +1213,54 @@ syntax:
|
||||
return MATCH_ERROR;
|
||||
}
|
||||
|
||||
+/* This matches the nonstandard kind given after a variable name, like:
|
||||
+ INTEGER x*2, y*4
|
||||
+ The per-variable kind will override any kind given in the type
|
||||
+ declaration.
|
||||
+*/
|
||||
+
|
||||
+static match
|
||||
+match_per_symbol_kind (int *length)
|
||||
+{
|
||||
+ match m;
|
||||
+ gfc_expr *expr = NULL;
|
||||
+
|
||||
+ m = gfc_match_char ('*');
|
||||
+ if (m != MATCH_YES)
|
||||
+ return m;
|
||||
+
|
||||
+ m = gfc_match_small_literal_int (length, NULL);
|
||||
+ if (m == MATCH_YES || m == MATCH_ERROR)
|
||||
+ return m;
|
||||
+
|
||||
+ if (gfc_match_char ('(') == MATCH_NO)
|
||||
+ return MATCH_ERROR;
|
||||
+
|
||||
+ m = gfc_match_expr (&expr);
|
||||
+ if (m == MATCH_YES)
|
||||
+ {
|
||||
+ m = MATCH_ERROR; // Assume error
|
||||
+ if (gfc_expr_check_typed (expr, gfc_current_ns, false))
|
||||
+ {
|
||||
+ if ((expr->expr_type == EXPR_CONSTANT)
|
||||
+ && (expr->ts.type == BT_INTEGER))
|
||||
+ {
|
||||
+ *length = mpz_get_si(expr->value.integer);
|
||||
+ m = MATCH_YES;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (m == MATCH_YES)
|
||||
+ {
|
||||
+ if (gfc_match_char (')') == MATCH_NO)
|
||||
+ m = MATCH_ERROR;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (expr != NULL)
|
||||
+ gfc_free_expr (expr);
|
||||
+ return m;
|
||||
+}
|
||||
|
||||
/* Special subroutine for finding a symbol. Check if the name is found
|
||||
in the current name space. If not, and we're compiling a function or
|
||||
@@ -2443,6 +2491,35 @@ check_function_name (char *name)
|
||||
}
|
||||
|
||||
|
||||
+static match
|
||||
+match_character_length_clause (gfc_charlen **cl, bool *cl_deferred, int elem)
|
||||
+{
|
||||
+ gfc_expr* char_len;
|
||||
+ char_len = NULL;
|
||||
+
|
||||
+ match m = match_char_length (&char_len, cl_deferred, false);
|
||||
+ if (m == MATCH_YES)
|
||||
+ {
|
||||
+ *cl = gfc_new_charlen (gfc_current_ns, NULL);
|
||||
+ (*cl)->length = char_len;
|
||||
+ }
|
||||
+ else if (m == MATCH_NO)
|
||||
+ {
|
||||
+ if (elem > 1
|
||||
+ && (current_ts.u.cl->length == NULL
|
||||
+ || current_ts.u.cl->length->expr_type != EXPR_CONSTANT))
|
||||
+ {
|
||||
+ *cl = gfc_new_charlen (gfc_current_ns, NULL);
|
||||
+ (*cl)->length = gfc_copy_expr (current_ts.u.cl->length);
|
||||
+ }
|
||||
+ else
|
||||
+ *cl = current_ts.u.cl;
|
||||
+
|
||||
+ *cl_deferred = current_ts.deferred;
|
||||
+ }
|
||||
+ return m;
|
||||
+}
|
||||
+
|
||||
/* Match a variable name with an optional initializer. When this
|
||||
subroutine is called, a variable is expected to be parsed next.
|
||||
Depending on what is happening at the moment, updates either the
|
||||
@@ -2453,7 +2530,7 @@ variable_decl (int elem)
|
||||
{
|
||||
char name[GFC_MAX_SYMBOL_LEN + 1];
|
||||
static unsigned int fill_id = 0;
|
||||
- gfc_expr *initializer, *char_len;
|
||||
+ gfc_expr *initializer;
|
||||
gfc_array_spec *as;
|
||||
gfc_array_spec *cp_as; /* Extra copy for Cray Pointees. */
|
||||
gfc_charlen *cl;
|
||||
@@ -2462,11 +2539,15 @@ variable_decl (int elem)
|
||||
match m;
|
||||
bool t;
|
||||
gfc_symbol *sym;
|
||||
+ match cl_match;
|
||||
+ match kind_match;
|
||||
+ int overridden_kind;
|
||||
char c;
|
||||
|
||||
initializer = NULL;
|
||||
as = NULL;
|
||||
cp_as = NULL;
|
||||
+ kind_match = MATCH_NO;
|
||||
|
||||
/* When we get here, we've just matched a list of attributes and
|
||||
maybe a type and a double colon. The next thing we expect to see
|
||||
@@ -2519,6 +2600,28 @@ variable_decl (int elem)
|
||||
|
||||
var_locus = gfc_current_locus;
|
||||
|
||||
+
|
||||
+ cl = NULL;
|
||||
+ cl_deferred = false;
|
||||
+ cl_match = MATCH_NO;
|
||||
+
|
||||
+ /* Check for a character length clause before an array clause */
|
||||
+ if (flag_dec_override_kind)
|
||||
+ {
|
||||
+ if (current_ts.type == BT_CHARACTER)
|
||||
+ {
|
||||
+ cl_match = match_character_length_clause (&cl, &cl_deferred, elem);
|
||||
+ if (cl_match == MATCH_ERROR)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ kind_match = match_per_symbol_kind (&overridden_kind);
|
||||
+ if (kind_match == MATCH_ERROR)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Now we could see the optional array spec. or character length. */
|
||||
m = gfc_match_array_spec (&as, true, true);
|
||||
if (m == MATCH_ERROR)
|
||||
@@ -2667,40 +2770,12 @@ variable_decl (int elem)
|
||||
}
|
||||
}
|
||||
|
||||
- char_len = NULL;
|
||||
- cl = NULL;
|
||||
- cl_deferred = false;
|
||||
-
|
||||
- if (current_ts.type == BT_CHARACTER)
|
||||
+ /* Second chance for a character length clause */
|
||||
+ if (cl_match == MATCH_NO && current_ts.type == BT_CHARACTER)
|
||||
{
|
||||
- switch (match_char_length (&char_len, &cl_deferred, false))
|
||||
- {
|
||||
- case MATCH_YES:
|
||||
- cl = gfc_new_charlen (gfc_current_ns, NULL);
|
||||
-
|
||||
- cl->length = char_len;
|
||||
- break;
|
||||
-
|
||||
- /* Non-constant lengths need to be copied after the first
|
||||
- element. Also copy assumed lengths. */
|
||||
- case MATCH_NO:
|
||||
- if (elem > 1
|
||||
- && (current_ts.u.cl->length == NULL
|
||||
- || current_ts.u.cl->length->expr_type != EXPR_CONSTANT))
|
||||
- {
|
||||
- cl = gfc_new_charlen (gfc_current_ns, NULL);
|
||||
- cl->length = gfc_copy_expr (current_ts.u.cl->length);
|
||||
- }
|
||||
- else
|
||||
- cl = current_ts.u.cl;
|
||||
-
|
||||
- cl_deferred = current_ts.deferred;
|
||||
-
|
||||
- break;
|
||||
-
|
||||
- case MATCH_ERROR:
|
||||
- goto cleanup;
|
||||
- }
|
||||
+ m = match_character_length_clause (&cl, &cl_deferred, elem);
|
||||
+ if (m == MATCH_ERROR)
|
||||
+ goto cleanup;
|
||||
}
|
||||
|
||||
/* The dummy arguments and result of the abreviated form of MODULE
|
||||
@@ -2802,6 +2877,19 @@ variable_decl (int elem)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
+ if (kind_match == MATCH_YES)
|
||||
+ {
|
||||
+ gfc_find_symbol (name, gfc_current_ns, 1, &sym);
|
||||
+ /* sym *must* be found at this point */
|
||||
+ sym->ts.kind = overridden_kind;
|
||||
+ if (gfc_validate_kind (sym->ts.type, sym->ts.kind, true) < 0)
|
||||
+ {
|
||||
+ gfc_error ("Kind %d not supported for type %s at %C",
|
||||
+ sym->ts.kind, gfc_basic_typename (sym->ts.type));
|
||||
+ return MATCH_ERROR;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (!check_function_name (name))
|
||||
{
|
||||
m = MATCH_ERROR;
|
||||
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
|
||||
index 25cc948699b..4a269ebb22d 100644
|
||||
--- a/gcc/fortran/lang.opt
|
||||
+++ b/gcc/fortran/lang.opt
|
||||
@@ -493,6 +493,10 @@ fdec-non-integer-index
|
||||
Fortran Var(flag_dec_non_integer_index)
|
||||
Enable support for non-integer substring indexes.
|
||||
|
||||
+fdec-override-kind
|
||||
+Fortran Var(flag_dec_override_kind)
|
||||
+Enable support for per variable kind specification.
|
||||
+
|
||||
fdec-old-init
|
||||
Fortran Var(flag_dec_old_init)
|
||||
Enable support for old style initializers in derived types.
|
||||
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
|
||||
index d6bd36c3a8a..edbab483b36 100644
|
||||
--- a/gcc/fortran/options.c
|
||||
+++ b/gcc/fortran/options.c
|
||||
@@ -80,6 +80,7 @@ set_dec_flags (int value)
|
||||
SET_BITFLAG (flag_dec_duplicates, value, value);
|
||||
SET_BITFLAG (flag_dec_non_integer_index, value, value);
|
||||
SET_BITFLAG (flag_dec_old_init, value, value);
|
||||
+ SET_BITFLAG (flag_dec_override_kind, value, value);
|
||||
}
|
||||
|
||||
/* Finalize DEC flags. */
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_1.f b/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_1.f
|
||||
new file mode 100644
|
||||
index 00000000000..706ea4112a4
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_1.f
|
||||
@@ -0,0 +1,13 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec" }
|
||||
+!
|
||||
+! Test character declaration with mixed string length and array specification
|
||||
+!
|
||||
+! Contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM character_declaration
|
||||
+ CHARACTER ASPEC_SLENGTH*2 (5) /'01','02','03','04','05'/
|
||||
+ CHARACTER SLENGTH_ASPEC(5)*2 /'01','02','03','04','05'/
|
||||
+ if (ASPEC_SLENGTH(3).NE.SLENGTH_ASPEC(3)) STOP 1
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_2.f b/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_2.f
|
||||
new file mode 100644
|
||||
index 00000000000..26d2acf01de
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_2.f
|
||||
@@ -0,0 +1,13 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec-override-kind" }
|
||||
+!
|
||||
+! Test character declaration with mixed string length and array specification
|
||||
+!
|
||||
+! Contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM character_declaration
|
||||
+ CHARACTER ASPEC_SLENGTH*2 (5) /'01','02','03','04','05'/
|
||||
+ CHARACTER SLENGTH_ASPEC(5)*2 /'01','02','03','04','05'/
|
||||
+ if (ASPEC_SLENGTH(3).NE.SLENGTH_ASPEC(3)) STOP 1
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_3.f b/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_3.f
|
||||
new file mode 100644
|
||||
index 00000000000..76e4f0bdb93
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_mixed_char_array_declaration_3.f
|
||||
@@ -0,0 +1,13 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-fdec-override-kind -fno-dec-override-kind" }
|
||||
+!
|
||||
+! Test character declaration with mixed string length and array specification
|
||||
+!
|
||||
+! Contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM character_declaration
|
||||
+ CHARACTER ASPEC_SLENGTH*2 (5) /'01','02','03','04','05'/ ! { dg-error "Syntax error" }
|
||||
+ CHARACTER SLENGTH_ASPEC(5)*2 /'01','02','03','04','05'/
|
||||
+ if (ASPEC_SLENGTH(3).NE.SLENGTH_ASPEC(3)) STOP 1 ! { dg-error " Operands of comparison operator" }
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_spec_in_variable_1.f b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_1.f
|
||||
new file mode 100644
|
||||
index 00000000000..edd0f5874b7
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_1.f
|
||||
@@ -0,0 +1,31 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec" }
|
||||
+!
|
||||
+! Test kind specification in variable not in type
|
||||
+!
|
||||
+! Contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ program spec_in_var
|
||||
+ integer*8 ai*1, bi*4, ci
|
||||
+ real*4 ar*4, br*8, cr
|
||||
+
|
||||
+ ai = 1
|
||||
+ ar = 1.0
|
||||
+ bi = 2
|
||||
+ br = 2.0
|
||||
+ ci = 3
|
||||
+ cr = 3.0
|
||||
+
|
||||
+ if (ai .ne. 1) stop 1
|
||||
+ if (abs(ar - 1.0) > 1.0D-6) stop 2
|
||||
+ if (bi .ne. 2) stop 3
|
||||
+ if (abs(br - 2.0) > 1.0D-6) stop 4
|
||||
+ if (ci .ne. 3) stop 5
|
||||
+ if (abs(cr - 3.0) > 1.0D-6) stop 6
|
||||
+ if (kind(ai) .ne. 1) stop 7
|
||||
+ if (kind(ar) .ne. 4) stop 8
|
||||
+ if (kind(bi) .ne. 4) stop 9
|
||||
+ if (kind(br) .ne. 8) stop 10
|
||||
+ if (kind(ci) .ne. 8) stop 11
|
||||
+ if (kind(cr) .ne. 4) stop 12
|
||||
+ end
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_spec_in_variable_2.f b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_2.f
|
||||
new file mode 100644
|
||||
index 00000000000..bfaba584dbb
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_2.f
|
||||
@@ -0,0 +1,31 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec-override-kind" }
|
||||
+!
|
||||
+! Test kind specification in variable not in type
|
||||
+!
|
||||
+! Contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ program spec_in_var
|
||||
+ integer*8 ai*1, bi*4, ci
|
||||
+ real*4 ar*4, br*8, cr
|
||||
+
|
||||
+ ai = 1
|
||||
+ ar = 1.0
|
||||
+ bi = 2
|
||||
+ br = 2.0
|
||||
+ ci = 3
|
||||
+ cr = 3.0
|
||||
+
|
||||
+ if (ai .ne. 1) stop 1
|
||||
+ if (abs(ar - 1.0) > 1.0D-6) stop 2
|
||||
+ if (bi .ne. 2) stop 3
|
||||
+ if (abs(br - 2.0) > 1.0D-6) stop 4
|
||||
+ if (ci .ne. 3) stop 5
|
||||
+ if (abs(cr - 3.0) > 1.0D-6) stop 6
|
||||
+ if (kind(ai) .ne. 1) stop 7
|
||||
+ if (kind(ar) .ne. 4) stop 8
|
||||
+ if (kind(bi) .ne. 4) stop 9
|
||||
+ if (kind(br) .ne. 8) stop 10
|
||||
+ if (kind(ci) .ne. 8) stop 11
|
||||
+ if (kind(cr) .ne. 4) stop 12
|
||||
+ end
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_spec_in_variable_3.f b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_3.f
|
||||
new file mode 100644
|
||||
index 00000000000..5ff434e7466
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_3.f
|
||||
@@ -0,0 +1,31 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-fdec -fno-dec-override-kind" }
|
||||
+!
|
||||
+! Test kind specification in variable not in type
|
||||
+!
|
||||
+! Contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ program spec_in_var
|
||||
+ integer*8 ai*1, bi*4, ci ! { dg-error "Syntax error" }
|
||||
+ real*4 ar*4, br*8, cr ! { dg-error "Syntax error" }
|
||||
+
|
||||
+ ai = 1
|
||||
+ ar = 1.0
|
||||
+ bi = 2
|
||||
+ br = 2.0
|
||||
+ ci = 3
|
||||
+ cr = 3.0
|
||||
+
|
||||
+ if (ai .ne. 1) stop 1
|
||||
+ if (abs(ar - 1.0) > 1.0D-6) stop 2
|
||||
+ if (bi .ne. 2) stop 3
|
||||
+ if (abs(br - 2.0) > 1.0D-6) stop 4
|
||||
+ if (ci .ne. 3) stop 5
|
||||
+ if (abs(cr - 3.0) > 1.0D-6) stop 6
|
||||
+ if (kind(ai) .ne. 1) stop 7
|
||||
+ if (kind(ar) .ne. 4) stop 8
|
||||
+ if (kind(bi) .ne. 4) stop 9
|
||||
+ if (kind(br) .ne. 8) stop 10
|
||||
+ if (kind(ci) .ne. 8) stop 11
|
||||
+ if (kind(cr) .ne. 4) stop 12
|
||||
+ end
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_spec_in_variable_4.f b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_4.f
|
||||
new file mode 100644
|
||||
index 00000000000..c01980e8b9d
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_4.f
|
||||
@@ -0,0 +1,14 @@
|
||||
+! { dg-do compile }
|
||||
+!
|
||||
+! Test kind specification in variable not in type. The per variable
|
||||
+! kind specification is not enabled so these should fail
|
||||
+!
|
||||
+! Contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ program spec_in_var
|
||||
+ integer a
|
||||
+ parameter(a=2)
|
||||
+ integer b*(a) ! { dg-error "Syntax error" }
|
||||
+ real c*(8) ! { dg-error "Syntax error" }
|
||||
+ logical d*1_1 ! { dg-error "Syntax error" }
|
||||
+ end
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_spec_in_variable_5.f b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_5.f
|
||||
new file mode 100644
|
||||
index 00000000000..e2f39da3f4f
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_5.f
|
||||
@@ -0,0 +1,19 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec-override-kind" }
|
||||
+!
|
||||
+! Test kind specification in variable not in type
|
||||
+!
|
||||
+! Contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ program spec_in_var
|
||||
+ integer a
|
||||
+ parameter(a=2)
|
||||
+ integer b*(a)
|
||||
+ real c*(8)
|
||||
+ logical d*(1_1)
|
||||
+ character e*(a)
|
||||
+ if (kind(b).ne.2) stop 1
|
||||
+ if (kind(c).ne.8) stop 2
|
||||
+ if (kind(d).ne.1) stop 3
|
||||
+ if (len(e).ne.2) stop 4
|
||||
+ end
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_spec_in_variable_6.f b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_6.f
|
||||
new file mode 100644
|
||||
index 00000000000..569747874e3
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_6.f
|
||||
@@ -0,0 +1,19 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec" }
|
||||
+!
|
||||
+! Test kind specification in variable not in type
|
||||
+!
|
||||
+! Contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ program spec_in_var
|
||||
+ integer a
|
||||
+ parameter(a=2)
|
||||
+ integer b*(a)
|
||||
+ real c*(8)
|
||||
+ logical d*(1_1)
|
||||
+ character e*(a)
|
||||
+ if (kind(b).ne.2) stop 1
|
||||
+ if (kind(c).ne.8) stop 2
|
||||
+ if (kind(d).ne.1) stop 3
|
||||
+ if (len(e).ne.2) stop 4
|
||||
+ end
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_spec_in_variable_7.f b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_7.f
|
||||
new file mode 100644
|
||||
index 00000000000..b975bfd15c5
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_7.f
|
||||
@@ -0,0 +1,15 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-fdec -fno-dec-override-kind" }
|
||||
+!
|
||||
+! Test kind specification in variable not in type as the per variable
|
||||
+! kind specification is not enables these should fail
|
||||
+!
|
||||
+! Contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ program spec_in_var
|
||||
+ integer a
|
||||
+ parameter(a=2)
|
||||
+ integer b*(a) ! { dg-error "Syntax error" }
|
||||
+ real c*(8) ! { dg-error "Syntax error" }
|
||||
+ logical d*1_1 ! { dg-error "Syntax error" }
|
||||
+ end
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_spec_in_variable_8.f b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_8.f
|
||||
new file mode 100644
|
||||
index 00000000000..85732e0bd85
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_spec_in_variable_8.f
|
||||
@@ -0,0 +1,14 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-fdec" }
|
||||
+!
|
||||
+! Check that invalid kind values are rejected.
|
||||
+!
|
||||
+! Contributed by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ program spec_in_var
|
||||
+ integer a
|
||||
+ parameter(a=3)
|
||||
+ integer b*(a) ! { dg-error "Kind 3 not supported" }
|
||||
+ real c*(78) ! { dg-error "Kind 78 not supported" }
|
||||
+ logical d*(*) ! { dg-error "Invalid character" }
|
||||
+ end
|
||||
--
|
||||
2.27.0
|
||||
|
||||
2093
gcc11-fortran-fdec-promotion.patch
Normal file
2093
gcc11-fortran-fdec-promotion.patch
Normal file
File diff suppressed because it is too large
Load Diff
262
gcc11-fortran-fdec-sequence.patch
Normal file
262
gcc11-fortran-fdec-sequence.patch
Normal file
@ -0,0 +1,262 @@
|
||||
From bb76446db10c21860a4e19569ce3e350d8a2b59f Mon Sep 17 00:00:00 2001
|
||||
From: Mark Eggleston <markeggleston@gcc.gnu.org>
|
||||
Date: Fri, 22 Jan 2021 15:00:44 +0000
|
||||
Subject: [PATCH 09/10] Add the SEQUENCE attribute by default if it's not
|
||||
present.
|
||||
|
||||
Use -fdec-sequence to enable this feature. Also enabled by -fdec.
|
||||
---
|
||||
gcc/fortran/lang.opt | 4 ++
|
||||
gcc/fortran/options.c | 1 +
|
||||
gcc/fortran/resolve.c | 13 ++++-
|
||||
...dd_SEQUENCE_to_COMMON_block_by_default_1.f | 57 +++++++++++++++++++
|
||||
...dd_SEQUENCE_to_COMMON_block_by_default_2.f | 57 +++++++++++++++++++
|
||||
...dd_SEQUENCE_to_COMMON_block_by_default_3.f | 57 +++++++++++++++++++
|
||||
6 files changed, 186 insertions(+), 3 deletions(-)
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_1.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_2.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_3.f
|
||||
|
||||
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
|
||||
index 4ca2f93f2df..019c798cf09 100644
|
||||
--- a/gcc/fortran/lang.opt
|
||||
+++ b/gcc/fortran/lang.opt
|
||||
@@ -509,6 +509,10 @@ fdec-promotion
|
||||
Fortran Var(flag_dec_promotion)
|
||||
Add support for type promotion in intrinsic arguments.
|
||||
|
||||
+fdec-sequence
|
||||
+Fortran Var(flag_dec_sequence)
|
||||
+Add the SEQUENCE attribute by default if it's not present.
|
||||
+
|
||||
fdec-structure
|
||||
Fortran Var(flag_dec_structure)
|
||||
Enable support for DEC STRUCTURE/RECORD.
|
||||
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
|
||||
index 15079c7e95a..050f56fdc25 100644
|
||||
--- a/gcc/fortran/options.c
|
||||
+++ b/gcc/fortran/options.c
|
||||
@@ -83,6 +83,7 @@ set_dec_flags (int value)
|
||||
SET_BITFLAG (flag_dec_override_kind, value, value);
|
||||
SET_BITFLAG (flag_dec_non_logical_if, value, value);
|
||||
SET_BITFLAG (flag_dec_promotion, value, value);
|
||||
+ SET_BITFLAG (flag_dec_sequence, value, value);
|
||||
}
|
||||
|
||||
/* Finalize DEC flags. */
|
||||
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
|
||||
index 07dd039f3bf..fe7d0cc5944 100644
|
||||
--- a/gcc/fortran/resolve.c
|
||||
+++ b/gcc/fortran/resolve.c
|
||||
@@ -978,9 +978,16 @@ resolve_common_vars (gfc_common_head *common_block, bool named_common)
|
||||
|
||||
if (!(csym->ts.u.derived->attr.sequence
|
||||
|| csym->ts.u.derived->attr.is_bind_c))
|
||||
- gfc_error_now ("Derived type variable %qs in COMMON at %L "
|
||||
- "has neither the SEQUENCE nor the BIND(C) "
|
||||
- "attribute", csym->name, &csym->declared_at);
|
||||
+ {
|
||||
+ if (flag_dec_sequence)
|
||||
+ /* Assume sequence. */
|
||||
+ csym->ts.u.derived->attr.sequence = 1;
|
||||
+ else
|
||||
+ gfc_error_now ("Derived type variable '%s' in COMMON at %L "
|
||||
+ "has neither the SEQUENCE nor the BIND(C) "
|
||||
+ "attribute", csym->name, &csym->declared_at);
|
||||
+ }
|
||||
+
|
||||
if (csym->ts.u.derived->attr.alloc_comp)
|
||||
gfc_error_now ("Derived type variable %qs in COMMON at %L "
|
||||
"has an ultimate component that is "
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_1.f b/gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_1.f
|
||||
new file mode 100644
|
||||
index 00000000000..fe7b39625eb
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_1.f
|
||||
@@ -0,0 +1,57 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec" }
|
||||
+!
|
||||
+! Test add default SEQUENCE attribute derived types appearing in
|
||||
+! COMMON blocks and EQUIVALENCE statements.
|
||||
+!
|
||||
+! Contributed by Francisco Redondo Marchena <francisco.marchena@codethink.co.uk>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ MODULE SEQ
|
||||
+ TYPE STRUCT1
|
||||
+ INTEGER*4 ID
|
||||
+ INTEGER*4 TYPE
|
||||
+ INTEGER*8 DEFVAL
|
||||
+ CHARACTER*(4) NAME
|
||||
+ LOGICAL*1 NIL
|
||||
+ END TYPE STRUCT1
|
||||
+ END MODULE
|
||||
+
|
||||
+ SUBROUTINE A
|
||||
+ USE SEQ
|
||||
+ TYPE (STRUCT1) S
|
||||
+ COMMON /BLOCK1/ S
|
||||
+ IF (S%ID.NE.5) STOP 1
|
||||
+ IF (S%TYPE.NE.1000) STOP 2
|
||||
+ IF (S%DEFVAL.NE.-99) STOP 3
|
||||
+ IF (S%NAME.NE."JANE") STOP 4
|
||||
+ IF (S%NIL.NEQV..FALSE.) STOP 5
|
||||
+ END SUBROUTINE
|
||||
+
|
||||
+ PROGRAM sequence_att_common
|
||||
+ USE SEQ
|
||||
+ IMPLICIT NONE
|
||||
+ TYPE (STRUCT1) S1
|
||||
+ TYPE (STRUCT1) S2
|
||||
+ TYPE (STRUCT1) S3
|
||||
+
|
||||
+ EQUIVALENCE (S1,S2)
|
||||
+ COMMON /BLOCK1/ S3
|
||||
+
|
||||
+ S1%ID = 5
|
||||
+ S1%TYPE = 1000
|
||||
+ S1%DEFVAL = -99
|
||||
+ S1%NAME = "JANE"
|
||||
+ S1%NIL = .FALSE.
|
||||
+
|
||||
+ IF (S2%ID.NE.5) STOP 1
|
||||
+ IF (S2%TYPE.NE.1000) STOP 2
|
||||
+ IF (S2%DEFVAL.NE.-99) STOP 3
|
||||
+ IF (S2%NAME.NE."JANE") STOP 4
|
||||
+ IF (S2%NIL.NEQV..FALSE.) STOP 5
|
||||
+
|
||||
+ S3 = S1
|
||||
+
|
||||
+ CALL A
|
||||
+
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_2.f b/gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_2.f
|
||||
new file mode 100644
|
||||
index 00000000000..83512f0f3a2
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_2.f
|
||||
@@ -0,0 +1,57 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-fdec-sequence" }
|
||||
+!
|
||||
+! Test add default SEQUENCE attribute derived types appearing in
|
||||
+! COMMON blocks and EQUIVALENCE statements.
|
||||
+!
|
||||
+! Contributed by Francisco Redondo Marchena <francisco.marchena@codethink.co.uk>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ MODULE SEQ
|
||||
+ TYPE STRUCT1
|
||||
+ INTEGER*4 ID
|
||||
+ INTEGER*4 TYPE
|
||||
+ INTEGER*8 DEFVAL
|
||||
+ CHARACTER*(4) NAME
|
||||
+ LOGICAL*1 NIL
|
||||
+ END TYPE STRUCT1
|
||||
+ END MODULE
|
||||
+
|
||||
+ SUBROUTINE A
|
||||
+ USE SEQ
|
||||
+ TYPE (STRUCT1) S
|
||||
+ COMMON /BLOCK1/ S
|
||||
+ IF (S%ID.NE.5) STOP 1
|
||||
+ IF (S%TYPE.NE.1000) STOP 2
|
||||
+ IF (S%DEFVAL.NE.-99) STOP 3
|
||||
+ IF (S%NAME.NE."JANE") STOP 4
|
||||
+ IF (S%NIL.NEQV..FALSE.) STOP 5
|
||||
+ END SUBROUTINE
|
||||
+
|
||||
+ PROGRAM sequence_att_common
|
||||
+ USE SEQ
|
||||
+ IMPLICIT NONE
|
||||
+ TYPE (STRUCT1) S1
|
||||
+ TYPE (STRUCT1) S2
|
||||
+ TYPE (STRUCT1) S3
|
||||
+
|
||||
+ EQUIVALENCE (S1,S2)
|
||||
+ COMMON /BLOCK1/ S3
|
||||
+
|
||||
+ S1%ID = 5
|
||||
+ S1%TYPE = 1000
|
||||
+ S1%DEFVAL = -99
|
||||
+ S1%NAME = "JANE"
|
||||
+ S1%NIL = .FALSE.
|
||||
+
|
||||
+ IF (S2%ID.NE.5) STOP 1
|
||||
+ IF (S2%TYPE.NE.1000) STOP 2
|
||||
+ IF (S2%DEFVAL.NE.-99) STOP 3
|
||||
+ IF (S2%NAME.NE."JANE") STOP 4
|
||||
+ IF (S2%NIL.NEQV..FALSE.) STOP 5
|
||||
+
|
||||
+ S3 = S1
|
||||
+
|
||||
+ CALL A
|
||||
+
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_3.f b/gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_3.f
|
||||
new file mode 100644
|
||||
index 00000000000..26cd59f9090
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/dec_add_SEQUENCE_to_COMMON_block_by_default_3.f
|
||||
@@ -0,0 +1,57 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-fdec -fno-dec-sequence" }
|
||||
+!
|
||||
+! Test add default SEQUENCE attribute derived types appearing in
|
||||
+! COMMON blocks and EQUIVALENCE statements.
|
||||
+!
|
||||
+! Contributed by Francisco Redondo Marchena <francisco.marchena@codethink.co.uk>
|
||||
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ MODULE SEQ
|
||||
+ TYPE STRUCT1
|
||||
+ INTEGER*4 ID
|
||||
+ INTEGER*4 TYPE
|
||||
+ INTEGER*8 DEFVAL
|
||||
+ CHARACTER*(4) NAME
|
||||
+ LOGICAL*1 NIL
|
||||
+ END TYPE STRUCT1
|
||||
+ END MODULE
|
||||
+
|
||||
+ SUBROUTINE A
|
||||
+ USE SEQ
|
||||
+ TYPE (STRUCT1) S ! { dg-error "Derived type variable" }
|
||||
+ COMMON /BLOCK1/ S
|
||||
+ IF (S%ID.NE.5) STOP 1
|
||||
+ IF (S%TYPE.NE.1000) STOP 2
|
||||
+ IF (S%DEFVAL.NE.-99) STOP 3
|
||||
+ IF (S%NAME.NE."JANE") STOP 4
|
||||
+ IF (S%NIL.NEQV..FALSE.) STOP 5
|
||||
+ END SUBROUTINE
|
||||
+
|
||||
+ PROGRAM sequence_att_common
|
||||
+ USE SEQ
|
||||
+ IMPLICIT NONE
|
||||
+ TYPE (STRUCT1) S1
|
||||
+ TYPE (STRUCT1) S2
|
||||
+ TYPE (STRUCT1) S3 ! { dg-error "Derived type variable" }
|
||||
+
|
||||
+ EQUIVALENCE (S1,S2) ! { dg-error "Derived type variable" }
|
||||
+ COMMON /BLOCK1/ S3
|
||||
+
|
||||
+ S1%ID = 5
|
||||
+ S1%TYPE = 1000
|
||||
+ S1%DEFVAL = -99
|
||||
+ S1%NAME = "JANE"
|
||||
+ S1%NIL = .FALSE.
|
||||
+
|
||||
+ IF (S2%ID.NE.5) STOP 1
|
||||
+ IF (S2%TYPE.NE.1000) STOP 2
|
||||
+ IF (S2%DEFVAL.NE.-99) STOP 3
|
||||
+ IF (S2%NAME.NE."JANE") STOP 4
|
||||
+ IF (S2%NIL.NEQV..FALSE.) STOP 5
|
||||
+
|
||||
+ S3 = S1
|
||||
+
|
||||
+ CALL A
|
||||
+
|
||||
+ END
|
||||
--
|
||||
2.27.0
|
||||
|
||||
305
gcc11-fortran-flogical-as-integer.patch
Normal file
305
gcc11-fortran-flogical-as-integer.patch
Normal file
@ -0,0 +1,305 @@
|
||||
From 9b45f3063dfd2b893e7963a4828c1b0afecdc68a Mon Sep 17 00:00:00 2001
|
||||
From: Mark Eggleston <markeggleston@gcc.gnu.org>
|
||||
Date: Fri, 22 Jan 2021 12:41:46 +0000
|
||||
Subject: [PATCH 02/10] Convert LOGICAL to INTEGER for arithmetic ops, and vice
|
||||
versa
|
||||
|
||||
We allow converting LOGICAL types to INTEGER when doing arithmetic
|
||||
operations, and converting INTEGER types to LOGICAL for use in
|
||||
boolean operations.
|
||||
|
||||
This feature is enabled with the -flogical-as-integer flag.
|
||||
|
||||
Note: using this feature will disable bitwise logical operations enabled by
|
||||
-fdec.
|
||||
---
|
||||
gcc/fortran/lang.opt | 4 ++
|
||||
gcc/fortran/resolve.c | 55 ++++++++++++++++++-
|
||||
.../logical_to_integer_and_vice_versa_1.f | 31 +++++++++++
|
||||
.../logical_to_integer_and_vice_versa_2.f | 31 +++++++++++
|
||||
.../logical_to_integer_and_vice_versa_3.f | 33 +++++++++++
|
||||
.../logical_to_integer_and_vice_versa_4.f | 33 +++++++++++
|
||||
6 files changed, 186 insertions(+), 1 deletion(-)
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_1.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_2.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_3.f
|
||||
create mode 100644 gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_4.f
|
||||
|
||||
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
|
||||
index 52bd522051e..c4da248f07c 100644
|
||||
--- a/gcc/fortran/lang.opt
|
||||
+++ b/gcc/fortran/lang.opt
|
||||
@@ -497,6 +497,10 @@ fdec-static
|
||||
Fortran Var(flag_dec_static)
|
||||
Enable DEC-style STATIC and AUTOMATIC attributes.
|
||||
|
||||
+flogical-as-integer
|
||||
+Fortran Var(flag_logical_as_integer)
|
||||
+Convert from integer to logical or logical to integer for arithmetic operations.
|
||||
+
|
||||
fdefault-double-8
|
||||
Fortran Var(flag_default_double)
|
||||
Set the default double precision kind to an 8 byte wide type.
|
||||
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
|
||||
index c075d0fa0c4..4b90cb59902 100644
|
||||
--- a/gcc/fortran/resolve.c
|
||||
+++ b/gcc/fortran/resolve.c
|
||||
@@ -3915,7 +3915,6 @@ lookup_uop_fuzzy (const char *op, gfc_symtree *uop)
|
||||
return gfc_closest_fuzzy_match (op, candidates);
|
||||
}
|
||||
|
||||
-
|
||||
/* Callback finding an impure function as an operand to an .and. or
|
||||
.or. expression. Remember the last function warned about to
|
||||
avoid double warnings when recursing. */
|
||||
@@ -3975,6 +3974,22 @@ convert_hollerith_to_character (gfc_expr *e)
|
||||
}
|
||||
}
|
||||
|
||||
+/* If E is a logical, convert it to an integer and issue a warning
|
||||
+ for the conversion. */
|
||||
+
|
||||
+static void
|
||||
+convert_integer_to_logical (gfc_expr *e)
|
||||
+{
|
||||
+ if (e->ts.type == BT_INTEGER)
|
||||
+ {
|
||||
+ /* Convert to LOGICAL */
|
||||
+ gfc_typespec t;
|
||||
+ t.type = BT_LOGICAL;
|
||||
+ t.kind = 1;
|
||||
+ gfc_convert_type_warn (e, &t, 2, 1);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* Convert to numeric and issue a warning for the conversion. */
|
||||
|
||||
static void
|
||||
@@ -3987,6 +4002,22 @@ convert_to_numeric (gfc_expr *a, gfc_expr *b)
|
||||
gfc_convert_type_warn (a, &t, 2, 1);
|
||||
}
|
||||
|
||||
+/* If E is a logical, convert it to an integer and issue a warning
|
||||
+ for the conversion. */
|
||||
+
|
||||
+static void
|
||||
+convert_logical_to_integer (gfc_expr *e)
|
||||
+{
|
||||
+ if (e->ts.type == BT_LOGICAL)
|
||||
+ {
|
||||
+ /* Convert to INTEGER */
|
||||
+ gfc_typespec t;
|
||||
+ t.type = BT_INTEGER;
|
||||
+ t.kind = 1;
|
||||
+ gfc_convert_type_warn (e, &t, 2, 1);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* Resolve an operator expression node. This can involve replacing the
|
||||
operation with a user defined function call. */
|
||||
|
||||
@@ -4072,6 +4103,12 @@ resolve_operator (gfc_expr *e)
|
||||
case INTRINSIC_TIMES:
|
||||
case INTRINSIC_DIVIDE:
|
||||
case INTRINSIC_POWER:
|
||||
+ if (flag_logical_as_integer)
|
||||
+ {
|
||||
+ convert_logical_to_integer (op1);
|
||||
+ convert_logical_to_integer (op2);
|
||||
+ }
|
||||
+
|
||||
if (gfc_numeric_ts (&op1->ts) && gfc_numeric_ts (&op2->ts))
|
||||
{
|
||||
gfc_type_convert_binary (e, 1);
|
||||
@@ -4108,6 +4145,13 @@ resolve_operator (gfc_expr *e)
|
||||
case INTRINSIC_OR:
|
||||
case INTRINSIC_EQV:
|
||||
case INTRINSIC_NEQV:
|
||||
+
|
||||
+ if (flag_logical_as_integer)
|
||||
+ {
|
||||
+ convert_integer_to_logical (op1);
|
||||
+ convert_integer_to_logical (op2);
|
||||
+ }
|
||||
+
|
||||
if (op1->ts.type == BT_LOGICAL && op2->ts.type == BT_LOGICAL)
|
||||
{
|
||||
e->ts.type = BT_LOGICAL;
|
||||
@@ -4158,6 +4202,9 @@ resolve_operator (gfc_expr *e)
|
||||
goto simplify_op;
|
||||
}
|
||||
|
||||
+ if (flag_logical_as_integer)
|
||||
+ convert_integer_to_logical (op1);
|
||||
+
|
||||
if (op1->ts.type == BT_LOGICAL)
|
||||
{
|
||||
e->ts.type = BT_LOGICAL;
|
||||
@@ -4198,6 +4245,12 @@ resolve_operator (gfc_expr *e)
|
||||
convert_hollerith_to_character (op2);
|
||||
}
|
||||
|
||||
+ if (flag_logical_as_integer)
|
||||
+ {
|
||||
+ convert_logical_to_integer (op1);
|
||||
+ convert_logical_to_integer (op2);
|
||||
+ }
|
||||
+
|
||||
if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
|
||||
&& op1->ts.kind == op2->ts.kind)
|
||||
{
|
||||
diff --git a/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_1.f b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_1.f
|
||||
new file mode 100644
|
||||
index 00000000000..938a91d9e9a
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_1.f
|
||||
@@ -0,0 +1,31 @@
|
||||
+! { dg-do run }
|
||||
+! { dg-options "-std=legacy -flogical-as-integer" }
|
||||
+!
|
||||
+! Test conversion between logical and integer for logical operators
|
||||
+!
|
||||
+! Test case contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
|
||||
+! Modified for -flogical-as-integer by Mark Eggleston
|
||||
+! <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+ PROGRAM logical_integer_conversion
|
||||
+ LOGICAL lpos /.true./
|
||||
+ INTEGER ineg/0/
|
||||
+ INTEGER ires
|
||||
+ LOGICAL lres
|
||||
+
|
||||
+ ! Test Logicals converted to Integers
|
||||
+ if ((lpos.AND.ineg).EQ.1) STOP 3
|
||||
+ if ((ineg.AND.lpos).NE.0) STOP 4
|
||||
+ ires = (.true..AND.0)
|
||||
+ if (ires.NE.0) STOP 5
|
||||
+ ires = (1.AND..false.)
|
||||
+ if (ires.EQ.1) STOP 6
|
||||
+
|
||||
+ ! Test Integers converted to Logicals
|
||||
+ if (lpos.EQ.ineg) STOP 7
|
||||
+ if (ineg.EQ.lpos) STOP 8
|
||||
+ lres = (.true..EQ.0)
|
||||
+ if (lres) STOP 9
|
||||
+ lres = (1.EQ..false.)
|
||||
+ if (lres) STOP 10
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_2.f b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_2.f
|
||||
new file mode 100644
|
||||
index 00000000000..9f146202ba5
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_2.f
|
||||
@@ -0,0 +1,31 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-std=legacy -flogical-as-integer -fno-logical-as-integer" }
|
||||
+!
|
||||
+! Based on logical_to_integer_and_vice_versa_1.f but with option disabled
|
||||
+! to test for error messages.
|
||||
+!
|
||||
+! Test case contributed by by Mark Eggleston <mark.eggleston@codethink.com>
|
||||
+!
|
||||
+!
|
||||
+ PROGRAM logical_integer_conversion
|
||||
+ LOGICAL lpos /.true./
|
||||
+ INTEGER ineg/0/
|
||||
+ INTEGER ires
|
||||
+ LOGICAL lres
|
||||
+
|
||||
+ ! Test Logicals converted to Integers
|
||||
+ if ((lpos.AND.ineg).EQ.1) STOP 3 ! { dg-error "Operands of logical operator" }
|
||||
+ if ((ineg.AND.lpos).NE.0) STOP 4 ! { dg-error "Operands of logical operator" }
|
||||
+ ires = (.true..AND.0) ! { dg-error "Operands of logical operator" }
|
||||
+ if (ires.NE.0) STOP 5
|
||||
+ ires = (1.AND..false.) ! { dg-error "Operands of logical operator" }
|
||||
+ if (ires.EQ.1) STOP 6
|
||||
+
|
||||
+ ! Test Integers converted to Logicals
|
||||
+ if (lpos.EQ.ineg) STOP 7 ! { dg-error "Operands of comparison operator" }
|
||||
+ if (ineg.EQ.lpos) STOP 8 ! { dg-error "Operands of comparison operator" }
|
||||
+ lres = (.true..EQ.0) ! { dg-error "Operands of comparison operator" }
|
||||
+ if (lres) STOP 9
|
||||
+ lres = (1.EQ..false.) ! { dg-error "Operands of comparison operator" }
|
||||
+ if (lres) STOP 10
|
||||
+ END
|
||||
diff --git a/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_3.f b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_3.f
|
||||
new file mode 100644
|
||||
index 00000000000..446873eb2dc
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_3.f
|
||||
@@ -0,0 +1,33 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-std=legacy -flogical-as-integer" }
|
||||
+!
|
||||
+! Test conversion between logical and integer for logical operators
|
||||
+!
|
||||
+ program test
|
||||
+ logical f /.false./
|
||||
+ logical t /.true./
|
||||
+ real x
|
||||
+
|
||||
+ x = 7.7
|
||||
+ x = x + t*3.0
|
||||
+ if (abs(x - 10.7).gt.0.00001) stop 1
|
||||
+ x = x + .false.*5.0
|
||||
+ if (abs(x - 10.7).gt.0.00001) stop 2
|
||||
+ x = x - .true.*5.0
|
||||
+ if (abs(x - 5.7).gt.0.00001) stop 3
|
||||
+ x = x + t
|
||||
+ if (abs(x - 6.7).gt.0.00001) stop 4
|
||||
+ x = x + f
|
||||
+ if (abs(x - 6.7).gt.0.00001) stop 5
|
||||
+ x = x - t
|
||||
+ if (abs(x - 5.7).gt.0.00001) stop 6
|
||||
+ x = x - f
|
||||
+ if (abs(x - 5.7).gt.0.00001) stop 7
|
||||
+ x = x**.true.
|
||||
+ if (abs(x - 5.7).gt.0.00001) stop 8
|
||||
+ x = x**.false.
|
||||
+ if (abs(x - 1.0).gt.0.00001) stop 9
|
||||
+ x = x/t
|
||||
+ if (abs(x - 1.0).gt.0.00001) stop 10
|
||||
+ if ((x/.false.).le.huge(x)) stop 11
|
||||
+ end
|
||||
diff --git a/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_4.f b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_4.f
|
||||
new file mode 100644
|
||||
index 00000000000..4301a4988d8
|
||||
--- /dev/null
|
||||
+++ b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_4.f
|
||||
@@ -0,0 +1,33 @@
|
||||
+! { dg-do compile }
|
||||
+! { dg-options "-std=legacy -flogical-as-integer -fno-logical-as-integer" }
|
||||
+!
|
||||
+! Test conversion between logical and integer for logical operators
|
||||
+!
|
||||
+ program test
|
||||
+ logical f /.false./
|
||||
+ logical t /.true./
|
||||
+ real x
|
||||
+
|
||||
+ x = 7.7
|
||||
+ x = x + t*3.0 ! { dg-error "Operands of binary numeric" }
|
||||
+ if (abs(x - 10.7).gt.0.00001) stop 1
|
||||
+ x = x + .false.*5.0 ! { dg-error "Operands of binary numeric" }
|
||||
+ if (abs(x - 10.7).gt.0.00001) stop 2
|
||||
+ x = x - .true.*5.0 ! { dg-error "Operands of binary numeric" }
|
||||
+ if (abs(x - 5.7).gt.0.00001) stop 3
|
||||
+ x = x + t ! { dg-error "Operands of binary numeric" }
|
||||
+ if (abs(x - 6.7).gt.0.00001) stop 4
|
||||
+ x = x + f ! { dg-error "Operands of binary numeric" }
|
||||
+ if (abs(x - 6.7).gt.0.00001) stop 5
|
||||
+ x = x - t ! { dg-error "Operands of binary numeric" }
|
||||
+ if (abs(x - 5.7).gt.0.00001) stop 6
|
||||
+ x = x - f ! { dg-error "Operands of binary numeric" }
|
||||
+ if (abs(x - 5.7).gt.0.00001) stop 7
|
||||
+ x = x**.true. ! { dg-error "Operands of binary numeric" }
|
||||
+ if (abs(x - 5.7).gt.0.00001) stop 8
|
||||
+ x = x**.false. ! { dg-error "Operands of binary numeric" }
|
||||
+ if (abs(x - 1.0).gt.0.00001) stop 9
|
||||
+ x = x/t ! { dg-error "Operands of binary numeric" }
|
||||
+ if (abs(x - 1.0).gt.0.00001) stop 10
|
||||
+ if ((x/.false.).le.huge(x)) stop 11 ! { dg-error "Operands of binary numeric" }
|
||||
+ end
|
||||
--
|
||||
2.27.0
|
||||
|
||||
52
gcc11-gcov-show-branches-and-calls.patch
Normal file
52
gcc11-gcov-show-branches-and-calls.patch
Normal file
@ -0,0 +1,52 @@
|
||||
diff --git a/gcc/gcov.c b/gcc/gcov.c
|
||||
index cf0a49d8c30..e9cd2f5505d 100644
|
||||
--- a/gcc/gcov.c
|
||||
+++ b/gcc/gcov.c
|
||||
@@ -1497,11 +1497,16 @@ generate_results (const char *file_name)
|
||||
memset (&coverage, 0, sizeof (coverage));
|
||||
coverage.name = fn->get_name ();
|
||||
add_line_counts (flag_function_summary ? &coverage : NULL, fn);
|
||||
- if (flag_function_summary)
|
||||
- {
|
||||
- function_summary (&coverage);
|
||||
- fnotice (stdout, "\n");
|
||||
- }
|
||||
+
|
||||
+ if (!flag_function_summary)
|
||||
+ continue;
|
||||
+
|
||||
+ for (const block_info& block : fn->blocks)
|
||||
+ for (arc_info *arc = block.succ; arc; arc = arc->succ_next)
|
||||
+ add_branch_counts (&coverage, arc);
|
||||
+
|
||||
+ function_summary (&coverage);
|
||||
+ fnotice (stdout, "\n");
|
||||
}
|
||||
|
||||
name_map needle;
|
||||
@@ -2480,6 +2485,25 @@ function_summary (const coverage_info *coverage)
|
||||
{
|
||||
fnotice (stdout, "%s '%s'\n", "Function", coverage->name);
|
||||
executed_summary (coverage->lines, coverage->lines_executed);
|
||||
+
|
||||
+ if (coverage->branches)
|
||||
+ {
|
||||
+ fnotice (stdout, "Branches executed:%s of %d\n",
|
||||
+ format_gcov (coverage->branches_executed, coverage->branches, 2),
|
||||
+ coverage->branches);
|
||||
+ fnotice (stdout, "Taken at least once:%s of %d\n",
|
||||
+ format_gcov (coverage->branches_taken, coverage->branches, 2),
|
||||
+ coverage->branches);
|
||||
+ }
|
||||
+ else
|
||||
+ fnotice (stdout, "No branches\n");
|
||||
+
|
||||
+ if (coverage->calls)
|
||||
+ fnotice (stdout, "Calls executed:%s of %d\n",
|
||||
+ format_gcov (coverage->calls_executed, coverage->calls, 2),
|
||||
+ coverage->calls);
|
||||
+ else
|
||||
+ fnotice (stdout, "No calls\n");
|
||||
}
|
||||
|
||||
/* Output summary info for a file. */
|
||||
@ -1,8 +1,8 @@
|
||||
--- libada/Makefile.in.jj 2009-01-14 12:07:35.000000000 +0100
|
||||
+++ libada/Makefile.in 2009-01-15 14:25:33.000000000 +0100
|
||||
@@ -66,18 +66,40 @@ libsubdir := $(libdir)/gcc/$(target_nonc
|
||||
--- libada/Makefile.in.jj 2019-01-09 13:01:18.015608205 +0100
|
||||
+++ libada/Makefile.in 2019-01-11 18:16:23.441726931 +0100
|
||||
@@ -71,18 +71,40 @@ version := $(shell @get_gcc_base_ver@ $(
|
||||
libsubdir := $(libdir)/gcc/$(target_noncanonical)/$(version)$(MULTISUBDIR)
|
||||
ADA_RTS_DIR=$(GCC_DIR)/ada/rts$(subst /,_,$(MULTISUBDIR))
|
||||
ADA_RTS_SUBDIR=./rts$(subst /,_,$(MULTISUBDIR))
|
||||
|
||||
+DEFAULTMULTIFLAGS :=
|
||||
+ifeq ($(MULTISUBDIR),)
|
||||
@ -45,17 +45,17 @@
|
||||
"PICFLAG_FOR_TARGET=$(PICFLAG)" \
|
||||
"THREAD_KIND=$(THREAD_KIND)" \
|
||||
"TRACE=$(TRACE)" \
|
||||
@@ -88,7 +110,7 @@ LIBADA_FLAGS_TO_PASS = \
|
||||
@@ -93,7 +115,7 @@ LIBADA_FLAGS_TO_PASS = \
|
||||
"exeext=.exeext.should.not.be.used " \
|
||||
'CC=the.host.compiler.should.not.be.needed' \
|
||||
"GCC_FOR_TARGET=$(CC)" \
|
||||
- "CFLAGS=$(CFLAGS)"
|
||||
+ "CFLAGS=$(CFLAGS) $(DEFAULTMULTIFLAGS)"
|
||||
|
||||
# Rules to build gnatlib.
|
||||
.PHONY: gnatlib gnatlib-plain gnatlib-sjlj gnatlib-zcx gnatlib-shared osconstool
|
||||
--- config-ml.in.jj 2010-06-30 09:50:44.000000000 +0200
|
||||
+++ config-ml.in 2010-07-02 21:24:17.994211151 +0200
|
||||
.PHONY: libada gnatlib gnatlib-shared gnatlib-sjlj gnatlib-zcx osconstool
|
||||
|
||||
--- config-ml.in.jj 2019-01-09 12:50:16.646501448 +0100
|
||||
+++ config-ml.in 2019-01-11 18:16:23.442726914 +0100
|
||||
@@ -511,6 +511,8 @@ multi-do:
|
||||
ADAFLAGS="$(ADAFLAGS) $${flags}" \
|
||||
prefix="$(prefix)" \
|
||||
@ -63,42 +63,44 @@
|
||||
+ mandir="$(mandir)" \
|
||||
+ infodir="$(infodir)" \
|
||||
GOCFLAGS="$(GOCFLAGS) $${flags}" \
|
||||
GDCFLAGS="$(GDCFLAGS) $${flags}" \
|
||||
CXXFLAGS="$(CXXFLAGS) $${flags}" \
|
||||
LIBCFLAGS="$(LIBCFLAGS) $${flags}" \
|
||||
--- libcpp/macro.c.jj 2015-01-14 11:01:34.000000000 +0100
|
||||
+++ libcpp/macro.c 2015-01-14 14:22:19.286949884 +0100
|
||||
@@ -2947,8 +2947,6 @@ create_iso_definition (cpp_reader *pfile
|
||||
cpp_token *token;
|
||||
const cpp_token *ctoken;
|
||||
--- libcpp/macro.c.jj 2019-01-09 13:01:21.420552123 +0100
|
||||
+++ libcpp/macro.c 2019-01-11 18:18:17.736876285 +0100
|
||||
@@ -3256,8 +3256,6 @@ static cpp_macro *
|
||||
create_iso_definition (cpp_reader *pfile)
|
||||
{
|
||||
bool following_paste_op = false;
|
||||
- const char *paste_op_error_msg =
|
||||
- N_("'##' cannot appear at either end of a macro expansion");
|
||||
unsigned int num_extra_tokens = 0;
|
||||
|
||||
/* Get the first token of the expansion (or the '(' of a
|
||||
@@ -3059,7 +3057,8 @@ create_iso_definition (cpp_reader *pfile
|
||||
unsigned nparms = 0;
|
||||
cpp_hashnode **params = NULL;
|
||||
@@ -3382,7 +3380,9 @@ create_iso_definition (cpp_reader *pfile
|
||||
function-like macros, but not at the end. */
|
||||
if (following_paste_op)
|
||||
{
|
||||
- cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
|
||||
+ cpp_error (pfile, CPP_DL_ERROR,
|
||||
+ "'##' cannot appear at either end of a macro expansion");
|
||||
return false;
|
||||
+ "'##' cannot appear at either end of a macro "
|
||||
+ "expansion");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
@@ -3072,7 +3071,8 @@ create_iso_definition (cpp_reader *pfile
|
||||
if (!vaopt_tracker.completed ())
|
||||
@@ -3397,7 +3397,9 @@ create_iso_definition (cpp_reader *pfile
|
||||
function-like macros, but not at the beginning. */
|
||||
if (macro->count == 1)
|
||||
{
|
||||
- cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
|
||||
+ cpp_error (pfile, CPP_DL_ERROR,
|
||||
+ "'##' cannot appear at either end of a macro expansion");
|
||||
return false;
|
||||
+ "'##' cannot appear at either end of a macro "
|
||||
+ "expansion");
|
||||
goto out;
|
||||
}
|
||||
|
||||
--- libcpp/expr.c.jj 2015-01-14 11:01:34.000000000 +0100
|
||||
+++ libcpp/expr.c 2015-01-14 14:35:52.851002344 +0100
|
||||
@@ -672,16 +672,17 @@ cpp_classify_number (cpp_reader *pfile,
|
||||
--- libcpp/expr.c.jj 2019-01-09 13:01:22.415535734 +0100
|
||||
+++ libcpp/expr.c 2019-01-11 18:16:23.444726882 +0100
|
||||
@@ -803,16 +803,17 @@ cpp_classify_number (cpp_reader *pfile,
|
||||
if ((result & CPP_N_WIDTH) == CPP_N_LARGE
|
||||
&& CPP_OPTION (pfile, cpp_warn_long_long))
|
||||
{
|
||||
@ -121,4 +123,4 @@
|
||||
+ : N_("use of C99 long long integer constant"));
|
||||
}
|
||||
|
||||
result |= CPP_N_INTEGER;
|
||||
if ((result & CPP_N_SIZE_T) == CPP_N_SIZE_T
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user