Compare commits

...

No commits in common. "c8" and "c9s-RHEL-105416" have entirely different histories.

137 changed files with 18794 additions and 26206 deletions

1
.fmf/version Normal file
View File

@ -0,0 +1 @@
1

View File

@ -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
View File

@ -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

View File

@ -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++);
+}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
;;

View File

@ -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) && \

View File

@ -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

View File

@ -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

View File

@ -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" }

View File

@ -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;

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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;
+}

View File

@ -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 ();
+}

View File

@ -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

View File

@ -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)
;

View File

@ -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. */

View File

@ -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;
+ }
+}

View File

@ -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;
+ }
+ }
+ }
+}

View File

@ -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,

View File

@ -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

View File

@ -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*] } {

View File

@ -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 } */

View File

@ -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" } } */

View File

@ -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

View File

@ -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;

View File

@ -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 ();
+}

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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"

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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 (&registered_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
View 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

File diff suppressed because it is too large Load Diff

48
gcc-RHEL-105072-13.patch Normal file
View 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
View 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
View 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 = &marker;
- 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
View 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 (&registered_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 (&registered_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
View 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, &reg);
+ 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, &reg);
+ /* 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);
+ 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);
+ 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, &reg);
+ insn_ptr = read_uleb128 (insn_ptr, &reg2);
+ 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);
+ 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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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);
+ 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, &reg);
+ 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, &reg);
- 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, &reg);
- /* 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);
- 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);
- 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, &reg);
- insn_ptr = read_uleb128 (insn_ptr, &reg2);
- 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);
- 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, &reg);
- 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, &reg);
- 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, &reg);
- 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);
- 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, &reg);
- 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
View 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
View 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
View 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
View 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 (&registered_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
View 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 (&registered_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
View 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
View 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
View 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
View 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 (&registered_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 (&registered_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 (&registered_frames, (uintptr_type) begin);
- // And remove
- ob = btree_remove (&registered_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 (&registered_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
View 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 (&registered_frames);
+ btree_destroy (&registered_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 (&registered_objects, begin, 1, ob);
+
+ // Register the frame in the b-tree
+ uintptr_type range[2];
+ get_pc_range (ob, range);
+ btree_insert (&registered_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 (&registered_frames, (uintptr_type) begin, 1, ob);
-
- // Register the frame in the b-tree
- uintptr_type range[2];
- get_pc_range (ob, range);
- btree_insert (&registered_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 (&registered_frames, (uintptr_type) begin, 1, ob);
-
- // Register the frame in the b-tree
- uintptr_type range[2];
- get_pc_range (ob, range);
- btree_insert (&registered_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 (&registered_frames, (uintptr_type) begin);
+ ob = btree_remove (&registered_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 (&registered_frames, range[0]);
+ btree_remove (&registered_frames, range[0]);
}
// Deallocate the sort array if any.

299
gcc-RHEL-105072-27.patch Normal file
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

377
gcc-RHEL-105072-9.patch Normal file
View 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 (&registered_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 (&registered_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 (&registered_frames, (uintptr_t) pc);
+ ob = btree_lookup (&registered_frames, (uintptr_type) pc);
if (!ob)
return NULL;

File diff suppressed because it is too large Load Diff

View File

@ -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;

View 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

View File

@ -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
View 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

View 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)

View 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"

View 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
View 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" }

View File

@ -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

View 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

View File

@ -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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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. */

View 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