summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/conf/distro/include/maintainers.inc2
-rw-r--r--meta/recipes-devtools/gcc/gcc-14.3.inc (renamed from meta/recipes-devtools/gcc/gcc-14.2.inc)11
-rw-r--r--meta/recipes-devtools/gcc/gcc-cross-canadian_14.3.bb (renamed from meta/recipes-devtools/gcc/gcc-cross-canadian_14.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc-cross_14.3.bb (renamed from meta/recipes-devtools/gcc/gcc-cross_14.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc-crosssdk_14.3.bb (renamed from meta/recipes-devtools/gcc/gcc-crosssdk_14.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc-runtime_14.3.bb (renamed from meta/recipes-devtools/gcc/gcc-runtime_14.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc-sanitizers_14.3.bb (renamed from meta/recipes-devtools/gcc/gcc-sanitizers_14.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc-source_14.3.bb (renamed from meta/recipes-devtools/gcc/gcc-source_14.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc/0001-arm-Fix-LDRD-register-overlap-PR117675.patch148
-rw-r--r--meta/recipes-devtools/gcc/gcc/0026-gcc-Fix-c-tweak-for-Wrange-loop-construct.patch114
-rw-r--r--meta/recipes-devtools/gcc/gcc/0027-gcc-backport-patch-to-fix-data-relocation-to-ENDBR-s.patch447
-rw-r--r--meta/recipes-devtools/gcc/gcc/0028-fix-incorrect-preprocessor-line-numbers.patch475
-rw-r--r--meta/recipes-devtools/gcc/gcc/gcc.git-ab884fffe3fc82a710bea66ad651720d71c938b8.patch549
-rw-r--r--meta/recipes-devtools/gcc/gcc_14.3.bb (renamed from meta/recipes-devtools/gcc/gcc_14.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/libgcc-initial_14.3.bb (renamed from meta/recipes-devtools/gcc/libgcc-initial_14.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/libgcc_14.3.bb (renamed from meta/recipes-devtools/gcc/libgcc_14.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/libgfortran_14.3.bb (renamed from meta/recipes-devtools/gcc/libgfortran_14.2.bb)0
17 files changed, 4 insertions, 1742 deletions
diff --git a/meta/conf/distro/include/maintainers.inc b/meta/conf/distro/include/maintainers.inc
index f1bff80586..9fe11282d9 100644
--- a/meta/conf/distro/include/maintainers.inc
+++ b/meta/conf/distro/include/maintainers.inc
@@ -194,7 +194,7 @@ RECIPE_MAINTAINER:pn-gcc-cross-canadian-${TRANSLATED_TARGET_ARCH} = "Khem Raj <r
194RECIPE_MAINTAINER:pn-gcc-crosssdk-${SDK_SYS} = "Khem Raj <raj.khem@gmail.com>" 194RECIPE_MAINTAINER:pn-gcc-crosssdk-${SDK_SYS} = "Khem Raj <raj.khem@gmail.com>"
195RECIPE_MAINTAINER:pn-gcc-runtime = "Khem Raj <raj.khem@gmail.com>" 195RECIPE_MAINTAINER:pn-gcc-runtime = "Khem Raj <raj.khem@gmail.com>"
196RECIPE_MAINTAINER:pn-gcc-sanitizers = "Khem Raj <raj.khem@gmail.com>" 196RECIPE_MAINTAINER:pn-gcc-sanitizers = "Khem Raj <raj.khem@gmail.com>"
197RECIPE_MAINTAINER:pn-gcc-source-14.2.0 = "Khem Raj <raj.khem@gmail.com>" 197RECIPE_MAINTAINER:pn-gcc-source-14.3.0 = "Khem Raj <raj.khem@gmail.com>"
198RECIPE_MAINTAINER:pn-gconf = "Ross Burton <ross.burton@arm.com>" 198RECIPE_MAINTAINER:pn-gconf = "Ross Burton <ross.burton@arm.com>"
199RECIPE_MAINTAINER:pn-gcr = "Unassigned <unassigned@yoctoproject.org>" 199RECIPE_MAINTAINER:pn-gcr = "Unassigned <unassigned@yoctoproject.org>"
200RECIPE_MAINTAINER:pn-gdb = "Khem Raj <raj.khem@gmail.com>" 200RECIPE_MAINTAINER:pn-gdb = "Khem Raj <raj.khem@gmail.com>"
diff --git a/meta/recipes-devtools/gcc/gcc-14.2.inc b/meta/recipes-devtools/gcc/gcc-14.3.inc
index fa9003f604..ca2f2e2a13 100644
--- a/meta/recipes-devtools/gcc/gcc-14.2.inc
+++ b/meta/recipes-devtools/gcc/gcc-14.3.inc
@@ -2,11 +2,11 @@ require gcc-common.inc
2 2
3# Third digit in PV should be incremented after a minor release 3# Third digit in PV should be incremented after a minor release
4 4
5PV = "14.2.0" 5PV = "14.3.0"
6 6
7# BINV should be incremented to a revision after a minor gcc release 7# BINV should be incremented to a revision after a minor gcc release
8 8
9BINV = "14.2.0" 9BINV = "14.3.0"
10 10
11FILESEXTRAPATHS =. "${FILE_DIRNAME}/gcc:${FILE_DIRNAME}/gcc/backport:" 11FILESEXTRAPATHS =. "${FILE_DIRNAME}/gcc:${FILE_DIRNAME}/gcc/backport:"
12 12
@@ -40,7 +40,7 @@ LIC_FILES_CHKSUM = "\
40RELEASE ?= "${PV}" 40RELEASE ?= "${PV}"
41BASEURI ?= "${GNU_MIRROR}/gcc/gcc-${PV}/gcc-${PV}.tar.xz" 41BASEURI ?= "${GNU_MIRROR}/gcc/gcc-${PV}/gcc-${PV}.tar.xz"
42SOURCEDIR ?= "gcc-${PV}" 42SOURCEDIR ?= "gcc-${PV}"
43SRC_URI[sha256sum] = "a7b39bc69cbf9e25826c5a60ab26477001f7c08d85cec04bc0e29cabed6f3cc9" 43SRC_URI[sha256sum] = "e0dc77297625631ac8e50fa92fffefe899a4eb702592da5c32ef04e2293aca3a"
44 44
45SRC_URI = "${BASEURI} \ 45SRC_URI = "${BASEURI} \
46 file://0001-gcc-4.3.1-ARCH_FLAGS_FOR_TARGET.patch \ 46 file://0001-gcc-4.3.1-ARCH_FLAGS_FOR_TARGET.patch \
@@ -68,11 +68,6 @@ SRC_URI = "${BASEURI} \
68 file://0023-Fix-install-path-of-linux64.h.patch \ 68 file://0023-Fix-install-path-of-linux64.h.patch \
69 file://0024-Avoid-hardcoded-build-paths-into-ppc-libgcc.patch \ 69 file://0024-Avoid-hardcoded-build-paths-into-ppc-libgcc.patch \
70 file://0025-gcc-testsuite-tweaks-for-mips-OE.patch \ 70 file://0025-gcc-testsuite-tweaks-for-mips-OE.patch \
71 file://0026-gcc-Fix-c-tweak-for-Wrange-loop-construct.patch \
72 file://0027-gcc-backport-patch-to-fix-data-relocation-to-ENDBR-s.patch \
73 file://gcc.git-ab884fffe3fc82a710bea66ad651720d71c938b8.patch \
74 file://0001-arm-Fix-LDRD-register-overlap-PR117675.patch \
75 file://0028-fix-incorrect-preprocessor-line-numbers.patch \
76" 71"
77 72
78S = "${TMPDIR}/work-shared/gcc-${PV}-${PR}/${SOURCEDIR}" 73S = "${TMPDIR}/work-shared/gcc-${PV}-${PR}/${SOURCEDIR}"
diff --git a/meta/recipes-devtools/gcc/gcc-cross-canadian_14.2.bb b/meta/recipes-devtools/gcc/gcc-cross-canadian_14.3.bb
index bf53c5cd78..bf53c5cd78 100644
--- a/meta/recipes-devtools/gcc/gcc-cross-canadian_14.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-cross-canadian_14.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc-cross_14.2.bb b/meta/recipes-devtools/gcc/gcc-cross_14.3.bb
index b43cca0c52..b43cca0c52 100644
--- a/meta/recipes-devtools/gcc/gcc-cross_14.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-cross_14.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc-crosssdk_14.2.bb b/meta/recipes-devtools/gcc/gcc-crosssdk_14.3.bb
index 40a6c4feff..40a6c4feff 100644
--- a/meta/recipes-devtools/gcc/gcc-crosssdk_14.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-crosssdk_14.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc-runtime_14.2.bb b/meta/recipes-devtools/gcc/gcc-runtime_14.3.bb
index dd430b57eb..dd430b57eb 100644
--- a/meta/recipes-devtools/gcc/gcc-runtime_14.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-runtime_14.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc-sanitizers_14.2.bb b/meta/recipes-devtools/gcc/gcc-sanitizers_14.3.bb
index 8bda2ccad6..8bda2ccad6 100644
--- a/meta/recipes-devtools/gcc/gcc-sanitizers_14.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-sanitizers_14.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc-source_14.2.bb b/meta/recipes-devtools/gcc/gcc-source_14.3.bb
index be11fa2fcc..be11fa2fcc 100644
--- a/meta/recipes-devtools/gcc/gcc-source_14.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-source_14.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc/0001-arm-Fix-LDRD-register-overlap-PR117675.patch b/meta/recipes-devtools/gcc/gcc/0001-arm-Fix-LDRD-register-overlap-PR117675.patch
deleted file mode 100644
index e3d887a135..0000000000
--- a/meta/recipes-devtools/gcc/gcc/0001-arm-Fix-LDRD-register-overlap-PR117675.patch
+++ /dev/null
@@ -1,148 +0,0 @@
1From 9366c328518766d896155388726055624716c0af Mon Sep 17 00:00:00 2001
2From: Wilco Dijkstra <wilco.dijkstra@arm.com>
3Date: Tue, 10 Dec 2024 14:22:48 +0000
4Subject: [PATCH] arm: Fix LDRD register overlap [PR117675]
5
6The register indexed variants of LDRD have complex register overlap constraints
7which makes them hard to use without using output_move_double (which can't be
8used for atomics as it doesn't guarantee to emit atomic LDRD/STRD when required).
9Add a new predicate and constraint for plain LDRD/STRD with base or base+imm.
10This blocks register indexing and fixes PR117675.
11
12gcc:
13 PR target/117675
14 * config/arm/arm.cc (arm_ldrd_legitimate_address): New function.
15 * config/arm/arm-protos.h (arm_ldrd_legitimate_address): New prototype.
16 * config/arm/constraints.md: Add new Uo constraint.
17 * config/arm/predicates.md (arm_ldrd_memory_operand): Add new predicate.
18 * config/arm/sync.md (arm_atomic_loaddi2_ldrd): Use
19 arm_ldrd_memory_operand and Uo.
20
21gcc/testsuite:
22 PR target/117675
23 * gcc.target/arm/pr117675.c: Add new test.
24
25(cherry picked from commit 21fbfae2e55e1a153820acc6fbd922e66f67e65b)
26
27Upstream-Status: Backport [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117675]
28---
29 gcc/config/arm/arm-protos.h | 1 +
30 gcc/config/arm/arm.cc | 24 ++++++++++++++++++++++++
31 gcc/config/arm/constraints.md | 8 +++++++-
32 gcc/config/arm/predicates.md | 4 ++++
33 gcc/config/arm/sync.md | 2 +-
34 gcc/testsuite/gcc.target/arm/pr117675.c | 17 +++++++++++++++++
35 6 files changed, 54 insertions(+), 2 deletions(-)
36 create mode 100644 gcc/testsuite/gcc.target/arm/pr117675.c
37
38--- a/gcc/config/arm/arm-protos.h
39+++ b/gcc/config/arm/arm-protos.h
40@@ -202,6 +202,7 @@ extern rtx arm_load_tp (rtx);
41 extern bool arm_coproc_builtin_available (enum unspecv);
42 extern bool arm_coproc_ldc_stc_legitimate_address (rtx);
43 extern rtx arm_stack_protect_tls_canary_mem (bool);
44+extern bool arm_ldrd_legitimate_address (rtx);
45
46
47 #if defined TREE_CODE
48--- a/gcc/config/arm/arm.cc
49+++ b/gcc/config/arm/arm.cc
50@@ -34523,6 +34523,30 @@ arm_coproc_ldc_stc_legitimate_address (r
51 return false;
52 }
53
54+/* Return true if OP is a valid memory operand for LDRD/STRD without any
55+ register overlap restrictions. Allow [base] and [base, imm] for now. */
56+bool
57+arm_ldrd_legitimate_address (rtx op)
58+{
59+ if (!MEM_P (op))
60+ return false;
61+
62+ op = XEXP (op, 0);
63+ if (REG_P (op))
64+ return true;
65+
66+ if (GET_CODE (op) != PLUS)
67+ return false;
68+ if (!REG_P (XEXP (op, 0)) || !CONST_INT_P (XEXP (op, 1)))
69+ return false;
70+
71+ HOST_WIDE_INT val = INTVAL (XEXP (op, 1));
72+
73+ if (TARGET_ARM)
74+ return IN_RANGE (val, -255, 255);
75+ return IN_RANGE (val, -1020, 1020) && (val & 3) == 0;
76+}
77+
78 /* Return the diagnostic message string if conversion from FROMTYPE to
79 TOTYPE is not allowed, NULL otherwise. */
80
81--- a/gcc/config/arm/constraints.md
82+++ b/gcc/config/arm/constraints.md
83@@ -39,7 +39,7 @@
84 ;; in all states: Pg
85
86 ;; The following memory constraints have been used:
87-;; in ARM/Thumb-2 state: Uh, Ut, Uv, Uy, Un, Um, Us, Up, Uf, Ux, Ul
88+;; in ARM/Thumb-2 state: Uh, Ut, Uv, Uy, Un, Um, Us, Uo, Up, Uf, Ux, Ul, Uz
89 ;; in ARM state: Uq
90 ;; in Thumb state: Uu, Uw
91 ;; in all states: Q
92@@ -585,6 +585,12 @@
93 (and (match_code "mem")
94 (match_test "arm_coproc_ldc_stc_legitimate_address (op)")))
95
96+(define_memory_constraint "Uo"
97+ "@internal
98+ A memory operand for Arm/Thumb-2 LDRD/STRD"
99+ (and (match_code "mem")
100+ (match_test "arm_ldrd_legitimate_address (op)")))
101+
102 ;; We used to have constraint letters for S and R in ARM state, but
103 ;; all uses of these now appear to have been removed.
104
105--- a/gcc/config/arm/predicates.md
106+++ b/gcc/config/arm/predicates.md
107@@ -849,6 +849,10 @@
108 (and (match_operand 0 "memory_operand")
109 (match_code "reg" "0")))
110
111+;; True if the operand is memory reference suitable for a ldrd/strd.
112+(define_predicate "arm_ldrd_memory_operand"
113+ (match_test "arm_ldrd_legitimate_address (op)"))
114+
115 ;; Predicates for parallel expanders based on mode.
116 (define_special_predicate "vect_par_constant_high"
117 (match_code "parallel")
118--- a/gcc/config/arm/sync.md
119+++ b/gcc/config/arm/sync.md
120@@ -161,7 +161,7 @@
121 (define_insn "arm_atomic_loaddi2_ldrd"
122 [(set (match_operand:DI 0 "register_operand" "=r")
123 (unspec_volatile:DI
124- [(match_operand:DI 1 "memory_operand" "m")]
125+ [(match_operand:DI 1 "arm_ldrd_memory_operand" "Uo")]
126 VUNSPEC_LDRD_ATOMIC))]
127 "ARM_DOUBLEWORD_ALIGN && TARGET_HAVE_LPAE"
128 "ldrd\t%0, %H0, %1"
129--- /dev/null
130+++ b/gcc/testsuite/gcc.target/arm/pr117675.c
131@@ -0,0 +1,17 @@
132+/* { dg-do compile } */
133+/* { dg-options "-O2 -marm" } */
134+/* { dg-require-effective-target arm_arch_v7ve_neon_ok } */
135+/* { dg-add-options arm_arch_v7ve_neon } */
136+/* { dg-final { check-function-bodies "**" "" "" } } */
137+
138+/*
139+** f1:
140+** add r0, r0, r1
141+** ldrd r0, r1, \[r0\]
142+** bx lr
143+*/
144+long long f1 (char *p, int i)
145+{
146+ return __atomic_load_n ((long long *)(p + i), __ATOMIC_RELAXED);
147+}
148+
diff --git a/meta/recipes-devtools/gcc/gcc/0026-gcc-Fix-c-tweak-for-Wrange-loop-construct.patch b/meta/recipes-devtools/gcc/gcc/0026-gcc-Fix-c-tweak-for-Wrange-loop-construct.patch
deleted file mode 100644
index c9bc863eea..0000000000
--- a/meta/recipes-devtools/gcc/gcc/0026-gcc-Fix-c-tweak-for-Wrange-loop-construct.patch
+++ /dev/null
@@ -1,114 +0,0 @@
1From 05106fea707f010779369c5d6e89787953d2976f Mon Sep 17 00:00:00 2001
2From: Sunil Dora <sunilkumar.dora@windriver.com>
3Date: Wed, 11 Dec 2024 10:04:56 -0800
4Subject: [PATCH] gcc: Fix c++: tweak for Wrange-loop-construct
5
6This commit updates the warning to use a check for "trivially constructible" instead of
7"trivially copyable." The original check was incorrect, as "trivially copyable" only applies
8to types that can be copied trivially, whereas "trivially constructible" is the correct check
9for types that can be trivially default-constructed.
10
11This change ensures the warning is more accurate and aligns with the proper type traits.
12
13LLVM accepted a similar fix:
14https://github.com/llvm/llvm-project/issues/47355
15
16PR c++/116731 [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116731]
17
18Upstream-Status: Backport [https://gcc.gnu.org/g:6ac4e2f4b2ca9980670e7d3815a9140730df1005]
19
20Signed-off-by: Marek Polacek <polacek@redhat.com>
21Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
22---
23 gcc/cp/parser.cc | 8 ++-
24 .../g++.dg/warn/Wrange-loop-construct3.C | 57 +++++++++++++++++++
25 2 files changed, 62 insertions(+), 3 deletions(-)
26 create mode 100644 gcc/testsuite/g++.dg/warn/Wrange-loop-construct3.C
27
28diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
29index 7e81c1010..8206489a2 100644
30--- a/gcc/cp/parser.cc
31+++ b/gcc/cp/parser.cc
32@@ -14301,11 +14301,13 @@ warn_for_range_copy (tree decl, tree expr)
33 else if (!CP_TYPE_CONST_P (type))
34 return;
35
36- /* Since small trivially copyable types are cheap to copy, we suppress the
37- warning for them. 64B is a common size of a cache line. */
38+ /* Since small trivially constructible types are cheap to construct, we
39+ suppress the warning for them. 64B is a common size of a cache line. */
40+ tree vec = make_tree_vec (1);
41+ TREE_VEC_ELT (vec, 0) = TREE_TYPE (expr);
42 if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST
43 || (tree_to_uhwi (TYPE_SIZE_UNIT (type)) <= 64
44- && trivially_copyable_p (type)))
45+ && is_trivially_xible (INIT_EXPR, type, vec)))
46 return;
47
48 /* If we can initialize a reference directly, suggest that to avoid the
49diff --git a/gcc/testsuite/g++.dg/warn/Wrange-loop-construct3.C b/gcc/testsuite/g++.dg/warn/Wrange-loop-construct3.C
50new file mode 100644
51index 000000000..3d9d0c908
52--- /dev/null
53+++ b/gcc/testsuite/g++.dg/warn/Wrange-loop-construct3.C
54@@ -0,0 +1,57 @@
55+// PR c++/116731
56+// { dg-do compile { target c++11 } }
57+// { dg-options "-Wrange-loop-construct" }
58+
59+void
60+f0 ()
61+{
62+ struct S {
63+ char a[64];
64+ S& operator=(const S&) { return *this; };
65+ };
66+
67+ S arr[8];
68+ for (const auto r : arr)
69+ (void) r;
70+}
71+
72+void
73+f1 ()
74+{
75+ struct S {
76+ char a[65];
77+ S& operator=(const S&) { return *this; };
78+ };
79+
80+ S arr[8];
81+ for (const auto r : arr) // { dg-warning "creates a copy" }
82+ (void) r;
83+}
84+
85+void
86+f2 ()
87+{
88+ struct S {
89+ char a[64];
90+ S& operator=(const S&) { return *this; };
91+ ~S() { }
92+ };
93+
94+ S arr[8];
95+ for (const auto r : arr) // { dg-warning "creates a copy" }
96+ (void) r;
97+}
98+
99+void
100+f3 ()
101+{
102+ struct S {
103+ char a[65];
104+ S& operator=(const S&) { return *this; };
105+ ~S() { }
106+ };
107+
108+ S arr[8];
109+ for (const auto r : arr) // { dg-warning "creates a copy" }
110+ (void) r;
111+}
112--
1132.43.0
114
diff --git a/meta/recipes-devtools/gcc/gcc/0027-gcc-backport-patch-to-fix-data-relocation-to-ENDBR-s.patch b/meta/recipes-devtools/gcc/gcc/0027-gcc-backport-patch-to-fix-data-relocation-to-ENDBR-s.patch
deleted file mode 100644
index 5bede60816..0000000000
--- a/meta/recipes-devtools/gcc/gcc/0027-gcc-backport-patch-to-fix-data-relocation-to-ENDBR-s.patch
+++ /dev/null
@@ -1,447 +0,0 @@
1From 4e7735a8d87559bbddfe3a985786996e22241f8d Mon Sep 17 00:00:00 2001
2From: liuhongt <hongtao.liu@intel.com>
3Date: Mon, 12 Aug 2024 14:35:31 +0800
4Subject: [PATCH] Move ix86_align_loops into a separate pass and insert the
5 pass after pass_endbr_and_patchable_area.
6
7gcc/ChangeLog:
8
9 PR target/116174
10 * config/i386/i386.cc (ix86_align_loops): Move this to ..
11 * config/i386/i386-features.cc (ix86_align_loops): .. here.
12 (class pass_align_tight_loops): New class.
13 (make_pass_align_tight_loops): New function.
14 * config/i386/i386-passes.def: Insert pass_align_tight_loops
15 after pass_insert_endbr_and_patchable_area.
16 * config/i386/i386-protos.h (make_pass_align_tight_loops): New
17 declare.
18
19gcc/testsuite/ChangeLog:
20
21 * gcc.target/i386/pr116174.c: New test.
22
23(cherry picked from commit c3c83d22d212a35cb1bfb8727477819463f0dcd8)
24
25Upstream-Status: Backport [https://gcc.gnu.org/git/?p=gcc.git;a=patch;h=4e7735a8d87559bbddfe3a985786996e22241f8d]
26
27Signed-off-by: Bin Lan <bin.lan.cn@windriver.com>
28---
29 gcc/config/i386/i386-features.cc | 191 +++++++++++++++++++++++
30 gcc/config/i386/i386-passes.def | 3 +
31 gcc/config/i386/i386-protos.h | 1 +
32 gcc/config/i386/i386.cc | 146 -----------------
33 gcc/testsuite/gcc.target/i386/pr116174.c | 12 ++
34 5 files changed, 207 insertions(+), 146 deletions(-)
35 create mode 100644 gcc/testsuite/gcc.target/i386/pr116174.c
36
37diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
38index e3e004d55267..7de19d423637 100644
39--- a/gcc/config/i386/i386-features.cc
40+++ b/gcc/config/i386/i386-features.cc
41@@ -3253,6 +3253,197 @@ make_pass_remove_partial_avx_dependency (gcc::context *ctxt)
42 return new pass_remove_partial_avx_dependency (ctxt);
43 }
44
45+/* When a hot loop can be fit into one cacheline,
46+ force align the loop without considering the max skip. */
47+static void
48+ix86_align_loops ()
49+{
50+ basic_block bb;
51+
52+ /* Don't do this when we don't know cache line size. */
53+ if (ix86_cost->prefetch_block == 0)
54+ return;
55+
56+ loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
57+ profile_count count_threshold = cfun->cfg->count_max / param_align_threshold;
58+ FOR_EACH_BB_FN (bb, cfun)
59+ {
60+ rtx_insn *label = BB_HEAD (bb);
61+ bool has_fallthru = 0;
62+ edge e;
63+ edge_iterator ei;
64+
65+ if (!LABEL_P (label))
66+ continue;
67+
68+ profile_count fallthru_count = profile_count::zero ();
69+ profile_count branch_count = profile_count::zero ();
70+
71+ FOR_EACH_EDGE (e, ei, bb->preds)
72+ {
73+ if (e->flags & EDGE_FALLTHRU)
74+ has_fallthru = 1, fallthru_count += e->count ();
75+ else
76+ branch_count += e->count ();
77+ }
78+
79+ if (!fallthru_count.initialized_p () || !branch_count.initialized_p ())
80+ continue;
81+
82+ if (bb->loop_father
83+ && bb->loop_father->latch != EXIT_BLOCK_PTR_FOR_FN (cfun)
84+ && (has_fallthru
85+ ? (!(single_succ_p (bb)
86+ && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun))
87+ && optimize_bb_for_speed_p (bb)
88+ && branch_count + fallthru_count > count_threshold
89+ && (branch_count > fallthru_count * param_align_loop_iterations))
90+ /* In case there'no fallthru for the loop.
91+ Nops inserted won't be executed. */
92+ : (branch_count > count_threshold
93+ || (bb->count > bb->prev_bb->count * 10
94+ && (bb->prev_bb->count
95+ <= ENTRY_BLOCK_PTR_FOR_FN (cfun)->count / 2)))))
96+ {
97+ rtx_insn* insn, *end_insn;
98+ HOST_WIDE_INT size = 0;
99+ bool padding_p = true;
100+ basic_block tbb = bb;
101+ unsigned cond_branch_num = 0;
102+ bool detect_tight_loop_p = false;
103+
104+ for (unsigned int i = 0; i != bb->loop_father->num_nodes;
105+ i++, tbb = tbb->next_bb)
106+ {
107+ /* Only handle continuous cfg layout. */
108+ if (bb->loop_father != tbb->loop_father)
109+ {
110+ padding_p = false;
111+ break;
112+ }
113+
114+ FOR_BB_INSNS (tbb, insn)
115+ {
116+ if (!NONDEBUG_INSN_P (insn))
117+ continue;
118+ size += ix86_min_insn_size (insn);
119+
120+ /* We don't know size of inline asm.
121+ Don't align loop for call. */
122+ if (asm_noperands (PATTERN (insn)) >= 0
123+ || CALL_P (insn))
124+ {
125+ size = -1;
126+ break;
127+ }
128+ }
129+
130+ if (size == -1 || size > ix86_cost->prefetch_block)
131+ {
132+ padding_p = false;
133+ break;
134+ }
135+
136+ FOR_EACH_EDGE (e, ei, tbb->succs)
137+ {
138+ /* It could be part of the loop. */
139+ if (e->dest == bb)
140+ {
141+ detect_tight_loop_p = true;
142+ break;
143+ }
144+ }
145+
146+ if (detect_tight_loop_p)
147+ break;
148+
149+ end_insn = BB_END (tbb);
150+ if (JUMP_P (end_insn))
151+ {
152+ /* For decoded icache:
153+ 1. Up to two branches are allowed per Way.
154+ 2. A non-conditional branch is the last micro-op in a Way.
155+ */
156+ if (onlyjump_p (end_insn)
157+ && (any_uncondjump_p (end_insn)
158+ || single_succ_p (tbb)))
159+ {
160+ padding_p = false;
161+ break;
162+ }
163+ else if (++cond_branch_num >= 2)
164+ {
165+ padding_p = false;
166+ break;
167+ }
168+ }
169+
170+ }
171+
172+ if (padding_p && detect_tight_loop_p)
173+ {
174+ emit_insn_before (gen_max_skip_align (GEN_INT (ceil_log2 (size)),
175+ GEN_INT (0)), label);
176+ /* End of function. */
177+ if (!tbb || tbb == EXIT_BLOCK_PTR_FOR_FN (cfun))
178+ break;
179+ /* Skip bb which already fits into one cacheline. */
180+ bb = tbb;
181+ }
182+ }
183+ }
184+
185+ loop_optimizer_finalize ();
186+ free_dominance_info (CDI_DOMINATORS);
187+}
188+
189+namespace {
190+
191+const pass_data pass_data_align_tight_loops =
192+{
193+ RTL_PASS, /* type */
194+ "align_tight_loops", /* name */
195+ OPTGROUP_NONE, /* optinfo_flags */
196+ TV_MACH_DEP, /* tv_id */
197+ 0, /* properties_required */
198+ 0, /* properties_provided */
199+ 0, /* properties_destroyed */
200+ 0, /* todo_flags_start */
201+ 0, /* todo_flags_finish */
202+};
203+
204+class pass_align_tight_loops : public rtl_opt_pass
205+{
206+public:
207+ pass_align_tight_loops (gcc::context *ctxt)
208+ : rtl_opt_pass (pass_data_align_tight_loops, ctxt)
209+ {}
210+
211+ /* opt_pass methods: */
212+ bool gate (function *) final override
213+ {
214+ return optimize && optimize_function_for_speed_p (cfun);
215+ }
216+
217+ unsigned int execute (function *) final override
218+ {
219+ timevar_push (TV_MACH_DEP);
220+#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
221+ ix86_align_loops ();
222+#endif
223+ timevar_pop (TV_MACH_DEP);
224+ return 0;
225+ }
226+}; // class pass_align_tight_loops
227+
228+} // anon namespace
229+
230+rtl_opt_pass *
231+make_pass_align_tight_loops (gcc::context *ctxt)
232+{
233+ return new pass_align_tight_loops (ctxt);
234+}
235+
236 /* This compares the priority of target features in function DECL1
237 and DECL2. It returns positive value if DECL1 is higher priority,
238 negative value if DECL2 is higher priority and 0 if they are the
239diff --git a/gcc/config/i386/i386-passes.def b/gcc/config/i386/i386-passes.def
240index 7d96766f7b96..e500f15c9971 100644
241--- a/gcc/config/i386/i386-passes.def
242+++ b/gcc/config/i386/i386-passes.def
243@@ -31,5 +31,8 @@ along with GCC; see the file COPYING3. If not see
244 INSERT_PASS_BEFORE (pass_cse2, 1, pass_stv, true /* timode_p */);
245
246 INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_endbr_and_patchable_area);
247+ /* pass_align_tight_loops must be after pass_insert_endbr_and_patchable_area.
248+ PR116174. */
249+ INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_align_tight_loops);
250
251 INSERT_PASS_AFTER (pass_combine, 1, pass_remove_partial_avx_dependency);
252diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
253index 46214a63974d..36c7b1aed42b 100644
254--- a/gcc/config/i386/i386-protos.h
255+++ b/gcc/config/i386/i386-protos.h
256@@ -419,6 +419,7 @@ extern rtl_opt_pass *make_pass_insert_endbr_and_patchable_area
257 (gcc::context *);
258 extern rtl_opt_pass *make_pass_remove_partial_avx_dependency
259 (gcc::context *);
260+extern rtl_opt_pass *make_pass_align_tight_loops (gcc::context *);
261
262 extern bool ix86_has_no_direct_extern_access;
263
264diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
265index 6f89891d3cb5..288c69467d62 100644
266--- a/gcc/config/i386/i386.cc
267+++ b/gcc/config/i386/i386.cc
268@@ -23444,150 +23444,6 @@ ix86_split_stlf_stall_load ()
269 }
270 }
271
272-/* When a hot loop can be fit into one cacheline,
273- force align the loop without considering the max skip. */
274-static void
275-ix86_align_loops ()
276-{
277- basic_block bb;
278-
279- /* Don't do this when we don't know cache line size. */
280- if (ix86_cost->prefetch_block == 0)
281- return;
282-
283- loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
284- profile_count count_threshold = cfun->cfg->count_max / param_align_threshold;
285- FOR_EACH_BB_FN (bb, cfun)
286- {
287- rtx_insn *label = BB_HEAD (bb);
288- bool has_fallthru = 0;
289- edge e;
290- edge_iterator ei;
291-
292- if (!LABEL_P (label))
293- continue;
294-
295- profile_count fallthru_count = profile_count::zero ();
296- profile_count branch_count = profile_count::zero ();
297-
298- FOR_EACH_EDGE (e, ei, bb->preds)
299- {
300- if (e->flags & EDGE_FALLTHRU)
301- has_fallthru = 1, fallthru_count += e->count ();
302- else
303- branch_count += e->count ();
304- }
305-
306- if (!fallthru_count.initialized_p () || !branch_count.initialized_p ())
307- continue;
308-
309- if (bb->loop_father
310- && bb->loop_father->latch != EXIT_BLOCK_PTR_FOR_FN (cfun)
311- && (has_fallthru
312- ? (!(single_succ_p (bb)
313- && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun))
314- && optimize_bb_for_speed_p (bb)
315- && branch_count + fallthru_count > count_threshold
316- && (branch_count > fallthru_count * param_align_loop_iterations))
317- /* In case there'no fallthru for the loop.
318- Nops inserted won't be executed. */
319- : (branch_count > count_threshold
320- || (bb->count > bb->prev_bb->count * 10
321- && (bb->prev_bb->count
322- <= ENTRY_BLOCK_PTR_FOR_FN (cfun)->count / 2)))))
323- {
324- rtx_insn* insn, *end_insn;
325- HOST_WIDE_INT size = 0;
326- bool padding_p = true;
327- basic_block tbb = bb;
328- unsigned cond_branch_num = 0;
329- bool detect_tight_loop_p = false;
330-
331- for (unsigned int i = 0; i != bb->loop_father->num_nodes;
332- i++, tbb = tbb->next_bb)
333- {
334- /* Only handle continuous cfg layout. */
335- if (bb->loop_father != tbb->loop_father)
336- {
337- padding_p = false;
338- break;
339- }
340-
341- FOR_BB_INSNS (tbb, insn)
342- {
343- if (!NONDEBUG_INSN_P (insn))
344- continue;
345- size += ix86_min_insn_size (insn);
346-
347- /* We don't know size of inline asm.
348- Don't align loop for call. */
349- if (asm_noperands (PATTERN (insn)) >= 0
350- || CALL_P (insn))
351- {
352- size = -1;
353- break;
354- }
355- }
356-
357- if (size == -1 || size > ix86_cost->prefetch_block)
358- {
359- padding_p = false;
360- break;
361- }
362-
363- FOR_EACH_EDGE (e, ei, tbb->succs)
364- {
365- /* It could be part of the loop. */
366- if (e->dest == bb)
367- {
368- detect_tight_loop_p = true;
369- break;
370- }
371- }
372-
373- if (detect_tight_loop_p)
374- break;
375-
376- end_insn = BB_END (tbb);
377- if (JUMP_P (end_insn))
378- {
379- /* For decoded icache:
380- 1. Up to two branches are allowed per Way.
381- 2. A non-conditional branch is the last micro-op in a Way.
382- */
383- if (onlyjump_p (end_insn)
384- && (any_uncondjump_p (end_insn)
385- || single_succ_p (tbb)))
386- {
387- padding_p = false;
388- break;
389- }
390- else if (++cond_branch_num >= 2)
391- {
392- padding_p = false;
393- break;
394- }
395- }
396-
397- }
398-
399- if (padding_p && detect_tight_loop_p)
400- {
401- emit_insn_before (gen_max_skip_align (GEN_INT (ceil_log2 (size)),
402- GEN_INT (0)), label);
403- /* End of function. */
404- if (!tbb || tbb == EXIT_BLOCK_PTR_FOR_FN (cfun))
405- break;
406- /* Skip bb which already fits into one cacheline. */
407- bb = tbb;
408- }
409- }
410- }
411-
412- loop_optimizer_finalize ();
413- free_dominance_info (CDI_DOMINATORS);
414-}
415-
416 /* Implement machine specific optimizations. We implement padding of returns
417 for K8 CPUs and pass to avoid 4 jumps in the single 16 byte window. */
418 static void
419@@ -23611,8 +23467,6 @@ ix86_reorg (void)
420 #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
421 if (TARGET_FOUR_JUMP_LIMIT)
422 ix86_avoid_jump_mispredicts ();
423-
424- ix86_align_loops ();
425 #endif
426 }
427 }
428diff --git a/gcc/testsuite/gcc.target/i386/pr116174.c b/gcc/testsuite/gcc.target/i386/pr116174.c
429new file mode 100644
430index 000000000000..8877d0b51af1
431--- /dev/null
432+++ b/gcc/testsuite/gcc.target/i386/pr116174.c
433@@ -0,0 +1,12 @@
434+/* { dg-do compile { target *-*-linux* } } */
435+/* { dg-options "-O2 -fcf-protection=branch" } */
436+
437+char *
438+foo (char *dest, const char *src)
439+{
440+ while ((*dest++ = *src++) != '\0')
441+ /* nothing */;
442+ return --dest;
443+}
444+
445+/* { dg-final { scan-assembler "\t\.cfi_startproc\n\tendbr(32|64)\n" } } */
446--
4472.43.5
diff --git a/meta/recipes-devtools/gcc/gcc/0028-fix-incorrect-preprocessor-line-numbers.patch b/meta/recipes-devtools/gcc/gcc/0028-fix-incorrect-preprocessor-line-numbers.patch
deleted file mode 100644
index 5185236a3d..0000000000
--- a/meta/recipes-devtools/gcc/gcc/0028-fix-incorrect-preprocessor-line-numbers.patch
+++ /dev/null
@@ -1,475 +0,0 @@
1From 8cbe033a8a88fe6437cc5d343ae0ddf8dd3455c8 Mon Sep 17 00:00:00 2001
2From: Jakub Jelinek <jakub@redhat.com>
3Date: Thu, 8 May 2025 11:14:24 +0200
4Subject: libcpp: Further fixes for incorrect line numbers in large files
5 [PR120061]
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10The backport of the PR108900 fix to 14 branch broke building chromium
11because static_assert (__LINE__ == expected_line_number, ""); now triggers
12as the __LINE__ values are off by one.
13This isn't the case on the trunk and 15 branch because we've switched
14to 64-bit location_t and so one actually needs far longer header files
15to trigger it.
16https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120061#c11
17https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120061#c12
18contain (large) testcases in patch form which show on the 14 branch
19that the first one used to fail before the PR108900 backport and now
20works correctly, while the second one attempts to match the chromium
21behavior and it used to pass before the PR108900 backport and now it
22FAILs.
23The two testcases show rare problematic cases, because
24do_include_common -> parse_include -> check_eol -> check_eol_1 ->
25cpp_get_token_1 -> _cpp_lex_token -> _cpp_lex_direct -> linemap_line_start
26triggers there
27 /* Allocate the new line_map. However, if the current map only has a
28 single line we can sometimes just increase its column_bits instead. */
29 if (line_delta < 0
30 || last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map)
31 || SOURCE_COLUMN (map, highest) >= (1U << (column_bits - range_bits))
32 || ( /* We can't reuse the map if the line offset is sufficiently
33 large to cause overflow when computing location_t values. */
34 (to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
35 >= (((uint64_t) 1)
36 << (CHAR_BIT * sizeof (linenum_type) - column_bits)))
37 || range_bits < map->m_range_bits)
38 map = linemap_check_ordinary
39 (const_cast <line_map *>
40 (linemap_add (set, LC_RENAME,
41 ORDINARY_MAP_IN_SYSTEM_HEADER_P (map),
42 ORDINARY_MAP_FILE_NAME (map),
43 to_line)));
44and so creates a new ordinary map on the line right after the
45(problematic) #include line.
46Now, in the spot that r14-11679-g8a884140c2bcb7 patched,
47pfile->line_table->highest_location in all 3 tests (also
48https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120061#c13
49) is before the decrement the start of the line after the #include line and so
50the decrement is really desirable in that case to put highest_location
51[jakub@tucnak gcc-15]$ git log -1 --format=%B r15-9638-gbfcb5da69a41f7a5e41faab39b763d9d7c8bd2ea | cat
52libcpp: Further fixes for incorrect line numbers in large files [PR120061]
53
54The backport of the PR108900 fix to 14 branch broke building chromium
55because static_assert (__LINE__ == expected_line_number, ""); now triggers
56as the __LINE__ values are off by one.
57This isn't the case on the trunk and 15 branch because we've switched
58to 64-bit location_t and so one actually needs far longer header files
59to trigger it.
60https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120061#c11
61https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120061#c12
62contain (large) testcases in patch form which show on the 14 branch
63that the first one used to fail before the PR108900 backport and now
64works correctly, while the second one attempts to match the chromium
65behavior and it used to pass before the PR108900 backport and now it
66FAILs.
67The two testcases show rare problematic cases, because
68do_include_common -> parse_include -> check_eol -> check_eol_1 ->
69cpp_get_token_1 -> _cpp_lex_token -> _cpp_lex_direct -> linemap_line_start
70triggers there
71 /* Allocate the new line_map. However, if the current map only has a
72 single line we can sometimes just increase its column_bits instead. */
73 if (line_delta < 0
74 || last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map)
75 || SOURCE_COLUMN (map, highest) >= (1U << (column_bits - range_bits))
76 || ( /* We can't reuse the map if the line offset is sufficiently
77 large to cause overflow when computing location_t values. */
78 (to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
79 >= (((uint64_t) 1)
80 << (CHAR_BIT * sizeof (linenum_type) - column_bits)))
81 || range_bits < map->m_range_bits)
82 map = linemap_check_ordinary
83 (const_cast <line_map *>
84 (linemap_add (set, LC_RENAME,
85 ORDINARY_MAP_IN_SYSTEM_HEADER_P (map),
86 ORDINARY_MAP_FILE_NAME (map),
87 to_line)));
88and so creates a new ordinary map on the line right after the
89(problematic) #include line.
90Now, in the spot that r14-11679-g8a884140c2bcb7 patched,
91pfile->line_table->highest_location in all 3 tests (also
92https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120061#c13
93) is before the decrement the start of the line after the #include line and so
94the decrement is really desirable in that case to put highest_location
95somewhere on the line where the #include actually is.
96But at the same time it is also undesirable, because if we do decrement it,
97then linemap_add LC_ENTER called from _cpp_do_file_change will then
98 /* Generate a start_location above the current highest_location.
99 If possible, make the low range bits be zero. */
100 location_t start_location = set->highest_location + 1;
101 unsigned range_bits = 0;
102 if (start_location < LINE_MAP_MAX_LOCATION_WITH_COLS)
103 range_bits = set->default_range_bits;
104 start_location += (1 << range_bits) - 1;
105 start_location &= ~((1 << range_bits) - 1);
106
107 linemap_assert (!LINEMAPS_ORDINARY_USED (set)
108 || (start_location
109 >= MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (set))));
110and we can end up with the new LC_ENTER ordinary map having the same
111start_location as the preceding LC_RENAME one.
112Next thing that happens is computation of included_from:
113 if (reason == LC_ENTER)
114 {
115 if (set->depth == 0)
116 map->included_from = 0;
117 else
118 /* The location of the end of the just-closed map. */
119 map->included_from
120 = (((map[0].start_location - 1 - map[-1].start_location)
121 & ~((1 << map[-1].m_column_and_range_bits) - 1))
122 + map[-1].start_location);
123The normal case (e.g. with the testcase included at the start of this comment) is
124that map[-1] starts somewhere earlier and so map->included_from computation above
125nicely computes location_t which expands to the start of the #include line.
126With r14-11679 reverted, for #c11 as well as #c12
127map[0].start_location == map[-1].start_location above, and so it is
128((location_t) -1 & ~((1 << map[-1].m_column_and_range_bits) - 1)))
129+ map[-1].start_location,
130which happens to be start of the #include line.
131For #c11 map[0].start_location is 0x500003a0 and map[-1] has
132m_column_and_range_bits 7 and map[-2] has m_column_and_range_bits 12 and
133map[0].included_from is set to 0x50000320.
134For #c12 map[0].start_location is 0x606c0402 and map[-2].start_location is
1350x606c0400 and m_column_and_range_bits is 0 for all 3 maps.
136map[0].included_from is set to 0x606c0401.
137The last important part is again in linemap_add when doing LC_LEAVE:
138 /* (MAP - 1) points to the map we are leaving. The
139 map from which (MAP - 1) got included should be the map
140 that comes right before MAP in the same file. */
141 from = linemap_included_from_linemap (set, map - 1);
142
143 /* A TO_FILE of NULL is special - we use the natural values. */
144 if (to_file == NULL)
145 {
146 to_file = ORDINARY_MAP_FILE_NAME (from);
147 to_line = SOURCE_LINE (from, from[1].start_location);
148 sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (from);
149 }
150Here it wants to compute the right to_line which ought to be the line after
151the #include directive.
152On the #c11 testcase that doesn't work correctly though, because
153map[-1].included_from is 0x50000320, from[0] for that is LC_ENTER with
154start_location 0x4080 and m_column_and_range_bits 12 but note that we've
155earlier computed map[-1].start_location + (-1 & 0xffffff80) and so only
156decreased by 7 bits, so to_line is still on the line with #include and not
157after it. In the #c12 that doesn't happen, all the ordinary maps involved
158there had 0 m_column_and_range_bits and so this computes correct line.
159
160Below is a fix for the trunk including testcases using the
161location_overflow_plugin hack to simulate the bugs without needing huge
162files (in the 14 case it is just 330KB and almost 10MB, but in the 15
163case it would need to be far bigger).
164The pre- r15-9018 trunk has
165FAIL: gcc.dg/plugin/location-overflow-test-pr116047.c -fplugin=./location_overflow_plugin.so scan-file static_assert[^\n\r]*6[^\n\r]*== 6
166and current trunk
167FAIL: gcc.dg/plugin/location-overflow-test-pr116047.c -fplugin=./location_overflow_plugin.so scan-file static_assert[^\n\r]*6[^\n\r]*== 6
168FAIL: gcc.dg/plugin/location-overflow-test-pr120061.c -fplugin=./location_overflow_plugin.so scan-file static_assert[^\n\r]*5[^\n\r]*== 5
169and with the patch everything PASSes.
170
171The patch reverts the r14-11679 change, because it is incorrect,
172we really need to decrement it even when crossing ordinary map
173boundaries, so that the location is not on the line after the #include
174line but somewhere on the #include line. It also patches two spots
175in linemap_add mentioned above to make sure we get correct locations
176both in the included_from location_t when doing LC_ENTER (second
177line-map.cc hunk) and when doing LC_LEAVE to compute the right to_line
178(first line-map.cc hunk), both in presence of an added LC_RENAME
179with the same start_location as the following LC_ENTER (i.e. the
180problematic cases).
181The LC_ENTER hunk is mostly to ensure included_form location_t is
182at the start of the #include line (column 0), without it we can
183decrease include_from not enough and end up at some random column
184in the middle of the line, because it is masking away
185map[-1].m_column_and_range_bits bits even when in the end the resulting
186include_from location_t will be found in map[-2] map with perhaps
187different m_column_and_range_bits. That alone doesn't fix the bug
188though.
189The more important is the LC_LEAVE hunk and the problem there is
190caused by linemap_line_start not actually doing
191 r = set->highest_line + (line_delta << map->m_column_and_range_bits);
192when adding a new map (the LC_RENAME one because we need to switch to
193different number of directly encoded ranges, or columns, etc.).
194So, in the original PR108900 case that
195 to_line = SOURCE_LINE (from, from[1].start_location);
196doesn't do the right thing, from there is the last < 0x50000000 map
197with m_column_and_range_bits 12, from[1] is the first one above it
198and map[-1].included_from is the correct location of column 0 on
199the #include line, but as the new LC_RENAME map has been created without
200actually increasing highest_location to be on the new line (we've just
201set to_line of the new LC_RENAME map to the correct line),
202 to_line = SOURCE_LINE (from, from[1].start_location);
203stays on the same source line. I've tried to just replace that with
204 to_line = SOURCE_LINE (from, linemap_included_from (map - 1)) + 1;
205i.e. just find out the #include line from map[-1].included_from and
206add 1 to it, unfortunately that breaks the
207c-c++-common/cpp/line-4.c
208test where we expect to stay on the same 0 line for LC_LEAVE from
209<command line> and gcc.dg/cpp/trad/Wunused.c, gcc.dg/cpp/trad/builtins.c
210and c-c++-common/analyzer/named-constants-via-macros-traditional.c tests
211all with -traditional-cpp preprocessing where to_line is also off-by-one
212from the expected one.
213So, this patch instead conditionalizes it, uses the
214 to_line = SOURCE_LINE (from, linemap_included_from (map - 1)) + 1;
215way only if from[1] is a LC_RENAME map (rather than the usual
216LC_ENTER one), that should limit it to the problematic cases of when
217parse_include peeked after EOL and had to create LC_RENAME map with
218the same start_location as the LC_ENTER after it.
219
220Some further justification for the LC_ENTER hunk, using the
221https://gcc.gnu.org/pipermail/gcc-patches/2025-May/682774.html testcase
222(old is 14 before r14-11679, vanilla current 14 and new with the 14 patch)
223I get
224$ /usr/src/gcc-14/obj/gcc/cc1.old -quiet -std=c23 pr116047.c -nostdinc
225In file included from pr116047-1.h:327677:21,
226 from pr116047.c:4:
227pr116047-2.h:1:1: error: unknown type name ‘a’
228 1 | a b c;
229 | ^
230pr116047-2.h:1:5: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘c’
231 1 | a b c;
232 | ^
233pr116047-1.h:327677:1: error: static assertion failed: ""
234327677 | #include "pr116047-2.h"
235 | ^~~~~~~~~~~~~
236$ /usr/src/gcc-14/obj/gcc/cc1.vanilla -quiet -std=c23 pr116047.c -nostdinc
237In file included from pr116047-1.h:327678,
238 from pr116047.c:4:
239pr116047-2.h:1:1: error: unknown type name ‘a’
240 1 | a b c;
241 | ^
242pr116047-2.h:1:5: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘c’
243 1 | a b c;
244 | ^
245$ /usr/src/gcc-14/obj/gcc/cc1.new -quiet -std=c23 pr116047.c -nostdinc
246In file included from pr116047-1.h:327677,
247 from pr116047.c:4:
248pr116047-2.h:1:1: error: unknown type name ‘a’
249 1 | a b c;
250 | ^
251pr116047-2.h:1:5: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘c’
252 1 | a b c;
253 | ^
254
255pr116047-1.h has on lines 327677+327678:
256 #include "pr116047-2.h"
257 static_assert (__LINE__ == 327678, "");
258so the static_assert failure is something that was dealt mainly in the
259LC_LEAVE hunk and files.cc reversion, but please have a look at the
260In file included from lines.
26114.2 emits correct line (#include "pr116047-2.h" is indeed on line
262327677) but some random column in there (which is not normally printed
263for smaller headers; 21 is the . before extension in the filename).
264Current trunk emits incorrect line (327678 instead of 327677, clearly
265it didn't decrement).
266And the patched compiler emits the right line with no column, as would
267be printed if I remove e.g. 300000 newlines from the file.
268
2692025-05-08 Jakub Jelinek <jakub@redhat.com>
270
271 PR preprocessor/108900
272 PR preprocessor/116047
273 PR preprocessor/120061
274 * files.cc (_cpp_stack_file): Revert 2025-03-28 change.
275 * line-map.cc (linemap_add): Use
276 SOURCE_LINE (from, linemap_included_from (map - 1)) + 1; instead of
277 SOURCE_LINE (from, from[1].start_location); to compute to_line
278 for LC_LEAVE if from[1].reason is LC_RENAME. For LC_ENTER
279 included_from computation, look at map[-2] or even lower if map[-1]
280 has the same start_location as map[0].
281
282 * gcc.dg/plugin/plugin.exp: Add location-overflow-test-pr116047.c
283 and location-overflow-test-pr120061.c.
284 * gcc.dg/plugin/location_overflow_plugin.c (plugin_init): Don't error
285 on unknown values, instead just break.
286 * gcc.dg/plugin/location-overflow-test-pr116047.c: New test.
287 * gcc.dg/plugin/location-overflow-test-pr116047-1.h: New test.
288 * gcc.dg/plugin/location-overflow-test-pr116047-2.h: New test.
289 * gcc.dg/plugin/location-overflow-test-pr120061.c: New test.
290 * gcc.dg/plugin/location-overflow-test-pr120061-1.h: New test.
291 * gcc.dg/plugin/location-overflow-test-pr120061-2.h: New test.
292
293Upstream-Status: Backport [https://gcc.gnu.org/cgit/gcc/commit/?id=edf745dc519ddbfef127e2789bf11bfbacd300b7]
294Signed-off-by: Yash Shinde <Yash.Shinde@windriver.com>
295---
296 .../plugin/location-overflow-test-pr116047-1.h | 6 +++
297 .../plugin/location-overflow-test-pr116047-2.h | 1 +
298 .../plugin/location-overflow-test-pr116047.c | 5 +++
299 .../plugin/location-overflow-test-pr120061-1.h | 6 +++
300 .../plugin/location-overflow-test-pr120061-2.h | 1 +
301 .../plugin/location-overflow-test-pr120061.c | 6 +++
302 .../gcc.dg/plugin/location_overflow_plugin.c | 2 +-
303 gcc/testsuite/gcc.dg/plugin/plugin.exp | 4 +-
304 libcpp/line-map.cc | 48 ++++++++++++++++++----
305 10 files changed, 69 insertions(+), 18 deletions(-)
306 create mode 100644 gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047-1.h
307 create mode 100644 gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047-2.h
308 create mode 100644 gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047.c
309 create mode 100644 gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061-1.h
310 create mode 100644 gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061-2.h
311 create mode 100644 gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061.c
312
313diff --git a/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047-1.h b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047-1.h
314new file mode 100644
315index 000000000000..3dd6434a938b
316--- /dev/null
317+++ b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047-1.h
318@@ -0,0 +1,6 @@
319+
320+
321+
322+
323+#include "location-overflow-test-pr116047-2.h"
324+static_assert (__LINE__ == 6, "");
325diff --git a/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047-2.h b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047-2.h
326new file mode 100644
327index 000000000000..048f715b4656
328--- /dev/null
329+++ b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047-2.h
330@@ -0,0 +1 @@
331+int i;
332diff --git a/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047.c b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047.c
333new file mode 100644
334index 000000000000..33f2c4ce8def
335--- /dev/null
336+++ b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr116047.c
337@@ -0,0 +1,5 @@
338+/* PR preprocessor/116047 */
339+/* { dg-do preprocess } */
340+/* { dg-options "-nostdinc -std=c23 -fplugin-arg-location_overflow_plugin-value=0x4fff8080" } */
341+#include "location-overflow-test-pr116047-1.h"
342+/* { dg-final { scan-file location-overflow-test-pr116047.i "static_assert\[^\n\r]\*6\[^\n\r]\*== 6" } } */
343diff --git a/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061-1.h b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061-1.h
344new file mode 100644
345index 000000000000..ebf7704f568e
346--- /dev/null
347+++ b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061-1.h
348@@ -0,0 +1,6 @@
349+
350+
351+
352+
353+#include "location-overflow-test-pr120061-2.h"
354+
355diff --git a/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061-2.h b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061-2.h
356new file mode 100644
357index 000000000000..048f715b4656
358--- /dev/null
359+++ b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061-2.h
360@@ -0,0 +1 @@
361+int i;
362diff --git a/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061.c b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061.c
363new file mode 100644
364index 000000000000..e8e803898da3
365--- /dev/null
366+++ b/gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr120061.c
367@@ -0,0 +1,6 @@
368+/* PR preprocessor/120061 */
369+/* { dg-do preprocess } */
370+/* { dg-options "-nostdinc -std=c23 -fplugin-arg-location_overflow_plugin-value=0x61000000" } */
371+#include "location-overflow-test-pr120061-1.h"
372+static_assert (__LINE__ == 5, "");
373+/* { dg-final { scan-file location-overflow-test-pr120061.i "static_assert\[^\n\r]\*5\[^\n\r]\*== 5" } } */
374diff --git a/gcc/testsuite/gcc.dg/plugin/location_overflow_plugin.c b/gcc/testsuite/gcc.dg/plugin/location_overflow_plugin.c
375index d0a6b0755648..6f4497a1cb16 100644
376--- a/gcc/testsuite/gcc.dg/plugin/location_overflow_plugin.c
377+++ b/gcc/testsuite/gcc.dg/plugin/location_overflow_plugin.c
378@@ -101,7 +101,7 @@ plugin_init (struct plugin_name_args *plugin_info,
379 break;
380
381 default:
382- error_at (UNKNOWN_LOCATION, "unrecognized value for plugin argument");
383+ break;
384 }
385
386 return 0;
387diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
388index 933f9a5850bc..438c6d87aad9 100644
389--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
390+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
391@@ -126,7 +126,9 @@ set plugin_test_list [list \
392 { location_overflow_plugin.c \
393 location-overflow-test-1.c \
394 location-overflow-test-2.c \
395- location-overflow-test-pr83173.c } \
396+ location-overflow-test-pr83173.c \
397+ location-overflow-test-pr116047.c \
398+ location-overflow-test-pr120061.c } \
399 { must_tail_call_plugin.c \
400 must-tail-call-1.c \
401 must-tail-call-2.c } \
402diff --git a/libcpp/line-map.cc b/libcpp/line-map.cc
403index d5200b317eee..1e659638d9f7 100644
404--- a/libcpp/line-map.cc
405+++ b/libcpp/line-map.cc
406@@ -618,8 +618,8 @@ linemap_add (line_maps *set, enum lc_reason reason,
407 #include "included", inside the same "includer" file. */
408
409 linemap_assert (!MAIN_FILE_P (map - 1));
410- /* (MAP - 1) points to the map we are leaving. The
411- map from which (MAP - 1) got included should be the map
412+ /* (MAP - 1) points to the map we are leaving. The
413+ map from which (MAP - 1) got included should be usually the map
414 that comes right before MAP in the same file. */
415 from = linemap_included_from_linemap (set, map - 1);
416
417@@ -627,7 +627,24 @@ linemap_add (line_maps *set, enum lc_reason reason,
418 if (to_file == NULL)
419 {
420 to_file = ORDINARY_MAP_FILE_NAME (from);
421- to_line = SOURCE_LINE (from, from[1].start_location);
422+ /* Compute the line on which the map resumes, for #include this
423+ should be the line after the #include line. Usually FROM is
424+ the map right before LC_ENTER map - the first map of the included
425+ file, and in that case SOURCE_LINE (from, from[1].start_location);
426+ computes the right line (and does handle even some special cases
427+ (e.g. where for returning from <command line> we still want to
428+ be at line 0 or some -traditional-cpp cases). In rare cases
429+ FROM can be followed by LC_RENAME created by linemap_line_start
430+ for line right after #include line. If that happens,
431+ start_location of the FROM[1] map will be the same as
432+ start_location of FROM[2] LC_ENTER, but FROM[1] start_location
433+ might not have advance enough for moving to a full next line.
434+ In that case compute the line of #include line and add 1 to it
435+ to advance to the next line. See PR120061. */
436+ if (from[1].reason == LC_RENAME)
437+ to_line = SOURCE_LINE (from, linemap_included_from (map - 1)) + 1;
438+ else
439+ to_line = SOURCE_LINE (from, from[1].start_location);
440 sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (from);
441 }
442 else
443@@ -657,11 +674,26 @@ linemap_add (line_maps *set, enum lc_reason reason,
444 if (set->depth == 0)
445 map->included_from = 0;
446 else
447- /* The location of the end of the just-closed map. */
448- map->included_from
449- = (((map[0].start_location - 1 - map[-1].start_location)
450- & ~((1 << map[-1].m_column_and_range_bits) - 1))
451- + map[-1].start_location);
452+ {
453+ /* Compute location from whence this line map was included.
454+ For #include this should be preferrably column 0 of the
455+ line on which #include directive appears.
456+ map[-1] is the just closed map and usually included_from
457+ falls within that map. In rare cases linemap_line_start
458+ can insert a new LC_RENAME map for the line immediately
459+ after #include line, in that case map[-1] will have the
460+ same start_location as the new one and so included_from
461+ would not be from map[-1] but likely map[-2]. If that
462+ happens, mask off map[-2] m_column_and_range_bits bits
463+ instead of map[-1]. See PR120061. */
464+ int i = -1;
465+ while (map[i].start_location == map[0].start_location)
466+ --i;
467+ map->included_from
468+ = (((map[0].start_location - 1 - map[i].start_location)
469+ & ~((1 << map[i].m_column_and_range_bits) - 1))
470+ + map[i].start_location);
471+ }
472 set->depth++;
473 if (set->trace_includes)
474 trace_include (set, map);
475--
diff --git a/meta/recipes-devtools/gcc/gcc/gcc.git-ab884fffe3fc82a710bea66ad651720d71c938b8.patch b/meta/recipes-devtools/gcc/gcc/gcc.git-ab884fffe3fc82a710bea66ad651720d71c938b8.patch
deleted file mode 100644
index e5abdcc703..0000000000
--- a/meta/recipes-devtools/gcc/gcc/gcc.git-ab884fffe3fc82a710bea66ad651720d71c938b8.patch
+++ /dev/null
@@ -1,549 +0,0 @@
1From ab884fffe3fc82a710bea66ad651720d71c938b8 Mon Sep 17 00:00:00 2001
2From: Jonathan Wakely <jwakely@redhat.com>
3Date: Tue, 30 Apr 2024 09:52:13 +0100
4Subject: [PATCH] libstdc++: Fix std::chrono::tzdb to work with vanguard format
5
6I found some issues in the std::chrono::tzdb parser by testing the
7tzdata "vanguard" format, which uses new features that aren't enabled in
8the "main" and "rearguard" data formats.
9
10Since 2024a the keyword "minimum" is no longer valid for the FROM and TO
11fields in a Rule line, which means that "m" is now a valid abbreviation
12for "maximum". Previously we expected either "mi" or "ma". For backwards
13compatibility, a FROM field beginning with "mi" is still supported and
14is treated as 1900. The "maximum" keyword is only allowed in TO now,
15because it makes no sense in FROM. To support these changes the
16minmax_year and minmax_year2 classes for parsing FROM and TO are
17replaced with a single years_from_to class that reads both fields.
18
19The vanguard format makes use of %z in Zone FORMAT fields, which caused
20an exception to be thrown from ZoneInfo::set_abbrev because no % or /
21characters were expected when a Zone doesn't use a named Rule. The
22ZoneInfo::to(sys_info&) function now uses format_abbrev_str to replace
23any %z with the current offset. Although format_abbrev_str also checks
24for %s and STD/DST formats, those only make sense when a named Rule is
25in effect, so won't occur when ZoneInfo::to(sys_info&) is used.
26
27Since making this change on trunk, the tzdata-2024b release started
28using %z in the main format, not just vanguard. This makes a backport to
29release branches necessary (see PR 116657).
30
31This change also implements a feature that has always been missing from
32time_zone::_M_get_sys_info: finding the Rule that is active before the
33specified time point, so that we can correctly handle %s in the FORMAT
34for the first new sys_info that gets created. This requires implementing
35a poorly documented feature of zic, to get the LETTERS field from a
36later transition, as described at
37https://mm.icann.org/pipermail/tz/2024-April/058891.html
38In order for this to work we need to be able to distinguish an empty
39letters field (as used by CE%sT where the variable part is either empty
40or "S") from "the letters field is not known for this transition". The
41tzdata file uses "-" for an empty letters field, which libstdc++ was
42previously replacing with "" when the Rule was parsed. Instead, we now
43preserve the "-" in the Rule object, so that "" can be used for the case
44where we don't know the letters (and so need to decide it).
45
46(cherry picked from commit 0ca8d56f2085715f27ee536c6c344bc47af49cdd)
47
48Upstream-Status: Backport [https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=5ceea2ac106d6dd1aa8175670b15a801316cf1c9]
49
50Signed-off-by: Markus Volk <f_l_k@t-online.de>
51---
52 libstdc++-v3/src/c++20/tzdb.cc | 265 +++++++++++-------
53 .../std/time/time_zone/sys_info_abbrev.cc | 106 +++++++
54 libstdc++-v3/testsuite/std/time/tzdb/1.cc | 6 +-
55 3 files changed, 274 insertions(+), 103 deletions(-)
56 create mode 100644 libstdc++-v3/testsuite/std/time/time_zone/sys_info_abbrev.cc
57
58diff --git a/libstdc++-v3/src/c++20/tzdb.cc b/libstdc++-v3/src/c++20/tzdb.cc
59index c7c7cc9deee6..7e8cce7ce8cf 100644
60--- a/libstdc++-v3/src/c++20/tzdb.cc
61+++ b/libstdc++-v3/src/c++20/tzdb.cc
62@@ -342,51 +342,103 @@ namespace std::chrono
63 friend istream& operator>>(istream&, on_day&);
64 };
65
66- // Wrapper for chrono::year that reads a year, or one of the keywords
67- // "minimum" or "maximum", or an unambiguous prefix of a keyword.
68- struct minmax_year
69+ // Wrapper for two chrono::year values, which reads the FROM and TO
70+ // fields of a Rule line. The FROM field is a year and TO is a year or
71+ // one of the keywords "maximum" or "only" (or an abbreviation of those).
72+ // For backwards compatibility, the keyword "minimum" is recognized
73+ // for FROM and interpreted as 1900.
74+ struct years_from_to
75 {
76- year& y;
77+ year& from;
78+ year& to;
79
80- friend istream& operator>>(istream& in, minmax_year&& y)
81+ friend istream& operator>>(istream& in, years_from_to&& yy)
82 {
83- if (ws(in).peek() == 'm') // keywords "minimum" or "maximum"
84+ string s;
85+ auto c = ws(in).peek();
86+ if (c == 'm') [[unlikely]] // keyword "minimum"
87 {
88- string s;
89- in >> s; // extract the rest of the word, but only look at s[1]
90- if (s[1] == 'a')
91- y.y = year::max();
92- else if (s[1] == 'i')
93- y.y = year::min();
94- else
95- in.setstate(ios::failbit);
96+ in >> s; // extract the rest of the word
97+ yy.from = year(1900);
98+ }
99+ else if (int num = 0; in >> num) [[likely]]
100+ yy.from = year{num};
101+
102+ c = ws(in).peek();
103+ if (c == 'm') // keyword "maximum"
104+ {
105+ in >> s; // extract the rest of the word
106+ yy.to = year::max();
107+ }
108+ else if (c == 'o') // keyword "only"
109+ {
110+ in >> s; // extract the rest of the word
111+ yy.to = yy.from;
112 }
113 else if (int num = 0; in >> num)
114- y.y = year{num};
115+ yy.to = year{num};
116+
117 return in;
118 }
119 };
120
121- // As above for minmax_year, but also supports the keyword "only",
122- // meaning that the TO year is the same as the FROM year.
123- struct minmax_year2
124+ bool
125+ select_std_or_dst_abbrev(string& abbrev, minutes save)
126 {
127- minmax_year to;
128- year from;
129+ if (size_t pos = abbrev.find('/'); pos != string::npos)
130+ {
131+ // Select one of "STD/DST" for standard or daylight.
132+ if (save == 0min)
133+ abbrev.erase(pos);
134+ else
135+ abbrev.erase(0, pos + 1);
136+ return true;
137+ }
138+ return false;
139+ }
140
141- friend istream& operator>>(istream& in, minmax_year2&& y)
142- {
143- if (ws(in).peek() == 'o') // keyword "only"
144- {
145- string s;
146- in >> s; // extract the whole keyword
147- y.to.y = y.from;
148- }
149- else
150- in >> std::move(y.to);
151- return in;
152- }
153- };
154+ // Set the sys_info::abbrev string by expanding any placeholders.
155+ void
156+ format_abbrev_str(sys_info& info, string_view letters = {})
157+ {
158+ if (size_t pos = info.abbrev.find('%'); pos != string::npos)
159+ {
160+ if (info.abbrev[pos + 1] == 's')
161+ {
162+ // Expand "%s" to the variable part, given by Rule::letters.
163+ if (letters == "-")
164+ info.abbrev.erase(pos, 2);
165+ else
166+ info.abbrev.replace(pos, 2, letters);
167+ }
168+ else if (info.abbrev[pos + 1] == 'z')
169+ {
170+ // Expand "%z" to the UT offset as +/-hh, +/-hhmm, or +/-hhmmss.
171+ hh_mm_ss<seconds> t(info.offset);
172+ string z(1, "+-"[t.is_negative()]);
173+ long val = t.hours().count();
174+ int digits = 2;
175+ if (int m = t.minutes().count())
176+ {
177+ digits = 4;
178+ val *= 100;
179+ val += m;
180+ if (int s = t.seconds().count())
181+ {
182+ digits = 6;
183+ val *= 100;
184+ val += s;
185+ }
186+ }
187+ auto sval = std::to_string(val);
188+ z += string(digits - sval.size(), '0');
189+ z += sval;
190+ info.abbrev.replace(pos, 2, z);
191+ }
192+ }
193+ else
194+ select_std_or_dst_abbrev(info.abbrev, info.save);
195+ }
196
197 // A time zone information record.
198 // Zone NAME STDOFF RULES FORMAT [UNTIL]
199@@ -462,6 +514,7 @@ namespace std::chrono
200 info.offset = offset();
201 info.save = minutes(m_save);
202 info.abbrev = format();
203+ format_abbrev_str(info); // expand %z
204 return true;
205 }
206
207@@ -469,12 +522,9 @@ namespace std::chrono
208 friend class time_zone;
209
210 void
211- set_abbrev(const string& abbrev)
212+ set_abbrev(string abbrev)
213 {
214- // In practice, the FORMAT field never needs expanding here.
215- if (abbrev.find_first_of("/%") != abbrev.npos)
216- __throw_runtime_error("std::chrono::time_zone: invalid data");
217- m_buf = abbrev;
218+ m_buf = std::move(abbrev);
219 m_pos = 0;
220 m_expanded = true;
221 }
222@@ -544,9 +594,7 @@ namespace std::chrono
223
224 // Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
225
226- in >> quoted(rule.name)
227- >> minmax_year{rule.from}
228- >> minmax_year2{rule.to, rule.from};
229+ in >> quoted(rule.name) >> years_from_to{rule.from, rule.to};
230
231 if (char type; in >> type && type != '-')
232 in.setstate(ios::failbit);
233@@ -557,7 +605,7 @@ namespace std::chrono
234 if (save_time.indicator != at_time::Wall)
235 {
236 // We don't actually store the save_time.indicator, because we
237- // assume that it's always deducable from the actual offset value.
238+ // assume that it's always deducible from the offset value.
239 auto expected = save_time.time == 0s
240 ? at_time::Standard
241 : at_time::Daylight;
242@@ -567,8 +615,6 @@ namespace std::chrono
243 rule.save = save_time.time;
244
245 in >> rule.letters;
246- if (rule.letters == "-")
247- rule.letters.clear();
248 return in;
249 }
250
251@@ -719,58 +765,6 @@ namespace std::chrono
252 #endif // TZDB_DISABLED
253 };
254
255-#ifndef TZDB_DISABLED
256- namespace
257- {
258- bool
259- select_std_or_dst_abbrev(string& abbrev, minutes save)
260- {
261- if (size_t pos = abbrev.find('/'); pos != string::npos)
262- {
263- // Select one of "STD/DST" for standard or daylight.
264- if (save == 0min)
265- abbrev.erase(pos);
266- else
267- abbrev.erase(0, pos + 1);
268- return true;
269- }
270- return false;
271- }
272-
273- // Set the sys_info::abbrev string by expanding any placeholders.
274- void
275- format_abbrev_str(sys_info& info, string_view letters = {})
276- {
277- if (size_t pos = info.abbrev.find("%s"); pos != string::npos)
278- {
279- // Expand "%s" to the variable part, given by Rule::letters.
280- info.abbrev.replace(pos, 2, letters);
281- }
282- else if (size_t pos = info.abbrev.find("%z"); pos != string::npos)
283- {
284- // Expand "%z" to the UT offset as +/-hh, +/-hhmm, or +/-hhmmss.
285- hh_mm_ss<seconds> t(info.offset);
286- string z(1, "+-"[t.is_negative()]);
287- long val = t.hours().count();
288- if (minutes m = t.minutes(); m != m.zero())
289- {
290- val *= 100;
291- val += m.count();
292- if (seconds s = t.seconds(); s != s.zero())
293- {
294- val *= 100;
295- val += s.count();
296- }
297- }
298- z += std::to_string(val);
299- info.abbrev.replace(pos, 2, z);
300- }
301- else
302- select_std_or_dst_abbrev(info.abbrev, info.save);
303- }
304- }
305-#endif // TZDB_DISABLED
306-
307 // Implementation of std::chrono::time_zone::get_info(const sys_time<D>&)
308 sys_info
309 time_zone::_M_get_sys_info(sys_seconds tp) const
310@@ -839,12 +833,72 @@ namespace std::chrono
311 info.abbrev = ri.format();
312
313 string_view letters;
314- if (i != infos.begin())
315+ if (i != infos.begin() && i[-1].expanded())
316+ letters = i[-1].next_letters();
317+
318+ if (letters.empty())
319 {
320- if (i[-1].expanded())
321- letters = i[-1].next_letters();
322- // XXX else need to find Rule active before this time and use it
323- // to know the initial offset, save, and letters.
324+ sys_seconds t = info.begin - seconds(1);
325+ const year_month_day date(chrono::floor<days>(t));
326+
327+ // Try to find a Rule active before this time, to get initial
328+ // SAVE and LETTERS values. There may not be a Rule for the period
329+ // before the first DST transition, so find the earliest DST->STD
330+ // transition and use the LETTERS from that.
331+ const Rule* active_rule = nullptr;
332+ sys_seconds active_rule_start = sys_seconds::min();
333+ const Rule* first_std = nullptr;
334+ for (const auto& rule : rules)
335+ {
336+ if (rule.save == minutes(0))
337+ {
338+ if (!first_std)
339+ first_std = &rule;
340+ else if (rule.from < first_std->from)
341+ first_std = &rule;
342+ else if (rule.from == first_std->from)
343+ {
344+ if (rule.start_time(rule.from, {})
345+ < first_std->start_time(first_std->from, {}))
346+ first_std = &rule;
347+ }
348+ }
349+
350+ year y = date.year();
351+
352+ if (y > rule.to) // rule no longer applies at time t
353+ continue;
354+ if (y < rule.from) // rule doesn't apply yet at time t
355+ continue;
356+
357+ sys_seconds rule_start;
358+
359+ seconds offset{}; // appropriate for at_time::Universal
360+ if (rule.when.indicator == at_time::Wall)
361+ offset = info.offset;
362+ else if (rule.when.indicator == at_time::Standard)
363+ offset = ri.offset();
364+
365+ // Time the rule takes effect this year:
366+ rule_start = rule.start_time(y, offset);
367+
368+ if (rule_start >= t && rule.from < y)
369+ {
370+ // Try this rule in the previous year.
371+ rule_start = rule.start_time(--y, offset);
372+ }
373+
374+ if (active_rule_start < rule_start && rule_start < t)
375+ {
376+ active_rule_start = rule_start;
377+ active_rule = &rule;
378+ }
379+ }
380+
381+ if (active_rule)
382+ letters = active_rule->letters;
383+ else if (first_std)
384+ letters = first_std->letters;
385 }
386
387 const Rule* curr_rule = nullptr;
388@@ -2069,9 +2123,11 @@ namespace std::chrono
389 istringstream in2(std::move(rules));
390 in2 >> rules_time;
391 inf.m_save = duration_cast<minutes>(rules_time.time);
392+ // If the FORMAT is "STD/DST" then we can choose the right one
393+ // now, so that we store a shorter string.
394 select_std_or_dst_abbrev(fmt, inf.m_save);
395 }
396- inf.set_abbrev(fmt);
397+ inf.set_abbrev(std::move(fmt));
398 }
399
400 // YEAR [MONTH [DAY [TIME]]]
401@@ -2082,7 +2138,12 @@ namespace std::chrono
402 abbrev_month m{January};
403 int d = 1;
404 at_time t{};
405+ // XXX DAY should support ON format, e.g. lastSun or Sun>=8
406 in >> m >> d >> t;
407+ // XXX UNTIL field should be interpreted
408+ // "using the rules in effect just before the transition"
409+ // so might need to store as year_month_day and hh_mm_ss and only
410+ // convert to a sys_time once we know the offset in effect.
411 inf.m_until = sys_days(year(y)/m.m/day(d)) + seconds(t.time);
412 }
413 else
414diff --git a/libstdc++-v3/testsuite/std/time/time_zone/sys_info_abbrev.cc b/libstdc++-v3/testsuite/std/time/time_zone/sys_info_abbrev.cc
415new file mode 100644
416index 000000000000..f1a8fff02f58
417--- /dev/null
418+++ b/libstdc++-v3/testsuite/std/time/time_zone/sys_info_abbrev.cc
419@@ -0,0 +1,106 @@
420+// { dg-do run { target c++20 } }
421+// { dg-require-effective-target tzdb }
422+// { dg-require-effective-target cxx11_abi }
423+// { dg-xfail-run-if "no weak override on AIX" { powerpc-ibm-aix* } }
424+
425+#include <chrono>
426+#include <fstream>
427+#include <testsuite_hooks.h>
428+
429+static bool override_used = false;
430+
431+namespace __gnu_cxx
432+{
433+ const char* zoneinfo_dir_override() {
434+ override_used = true;
435+ return "./";
436+ }
437+}
438+
439+using namespace std::chrono;
440+
441+void
442+test_format()
443+{
444+ std::ofstream("tzdata.zi") << R"(# version test_1
445+Zone Africa/Bissau -1:2:20 - LMT 1912 Ja 1 1u
446+ -1 - %z 1975
447+ 0 - GMT
448+Zon Some/Zone 1:2:3 - %z 1900
449+ 1:23:45 - %z 1950
450+Zo Another/Zone 1:2:3 - AZ0 1901
451+ 1 Roolz A%sZ 2000
452+ 1 Roolz SAZ/DAZ 2005
453+ 1 Roolz %z
454+Rule Roolz 1950 max - April 1 2 1 D
455+Rul Roolz 1950 max - Oct 1 1 0 S
456+Z Strange/Zone 1 - X%sX 1980
457+ 1 - FOO/BAR 1990
458+ 2:00 - %zzz 1995
459+ 0:9 - %zzz 1996
460+ 0:8:7 - %zzz 1997
461+ 0:6:5.5 - %zzz 1998
462+)";
463+
464+ const auto& db = reload_tzdb();
465+ VERIFY( override_used ); // If this fails then XFAIL for the target.
466+ VERIFY( db.version == "test_1" );
467+
468+ // Test formatting %z as
469+ auto tz = locate_zone("Africa/Bissau");
470+ auto inf = tz->get_info(sys_days(1974y/1/1));
471+ VERIFY( inf.abbrev == "-01" );
472+
473+ tz = locate_zone("Some/Zone");
474+ inf = tz->get_info(sys_days(1899y/1/1));
475+ VERIFY( inf.abbrev == "+010203" );
476+ inf = tz->get_info(sys_days(1955y/1/1));
477+ VERIFY( inf.abbrev == "+012345" );
478+
479+ tz = locate_zone("Another/Zone");
480+ // Test formatting %s as the LETTER/S field from the active Rule.
481+ inf = tz->get_info(sys_days(1910y/January/1));
482+ VERIFY( inf.abbrev == "ASZ" );
483+ inf = tz->get_info(sys_days(1950y/January/1));
484+ VERIFY( inf.abbrev == "ASZ" );
485+ inf = tz->get_info(sys_days(1950y/June/1));
486+ VERIFY( inf.abbrev == "ADZ" );
487+ inf = tz->get_info(sys_days(1999y/January/1));
488+ VERIFY( inf.abbrev == "ASZ" );
489+ inf = tz->get_info(sys_days(1999y/July/1));
490+ VERIFY( inf.abbrev == "ADZ" );
491+ // Test formatting STD/DST according to the active Rule.
492+ inf = tz->get_info(sys_days(2000y/January/2));
493+ VERIFY( inf.abbrev == "SAZ" );
494+ inf = tz->get_info(sys_days(2001y/January/1));
495+ VERIFY( inf.abbrev == "SAZ" );
496+ inf = tz->get_info(sys_days(2001y/July/1));
497+ VERIFY( inf.abbrev == "DAZ" );
498+ // Test formatting %z as the offset determined by the active Rule.
499+ inf = tz->get_info(sys_days(2005y/January/2));
500+ VERIFY( inf.abbrev == "+01" );
501+ inf = tz->get_info(sys_days(2006y/January/1));
502+ VERIFY( inf.abbrev == "+01" );
503+ inf = tz->get_info(sys_days(2006y/July/1));
504+ VERIFY( inf.abbrev == "+02" );
505+
506+ // Test formatting %z, %s and S/D for a Zone with no associated Rules.
507+ tz = locate_zone("Strange/Zone");
508+ inf = tz->get_info(sys_days(1979y/January/1));
509+ VERIFY( inf.abbrev == "XX" ); // No Rule means nothing to use for %s.
510+ inf = tz->get_info(sys_days(1981y/July/1));
511+ VERIFY( inf.abbrev == "FOO" ); // Always standard time means first string.
512+ inf = tz->get_info(sys_days(1994y/July/1));
513+ VERIFY( inf.abbrev == "+02zz" );
514+ inf = tz->get_info(sys_days(1995y/July/1));
515+ VERIFY( inf.abbrev == "+0009zz" );
516+ inf = tz->get_info(sys_days(1996y/July/1));
517+ VERIFY( inf.abbrev == "+000807zz" );
518+ inf = tz->get_info(sys_days(1997y/July/1));
519+ VERIFY( inf.abbrev == "+000606zz" );
520+}
521+
522+int main()
523+{
524+ test_format();
525+}
526diff --git a/libstdc++-v3/testsuite/std/time/tzdb/1.cc b/libstdc++-v3/testsuite/std/time/tzdb/1.cc
527index 796f3a8b4256..7a31c1c20ba7 100644
528--- a/libstdc++-v3/testsuite/std/time/tzdb/1.cc
529+++ b/libstdc++-v3/testsuite/std/time/tzdb/1.cc
530@@ -39,11 +39,15 @@ test_locate()
531 const tzdb& db = get_tzdb();
532 const time_zone* tz = db.locate_zone("GMT");
533 VERIFY( tz != nullptr );
534- VERIFY( tz->name() == "Etc/GMT" );
535 VERIFY( tz == std::chrono::locate_zone("GMT") );
536 VERIFY( tz == db.locate_zone("Etc/GMT") );
537 VERIFY( tz == db.locate_zone("Etc/GMT+0") );
538
539+ // Since 2022f GMT is now a Zone and Etc/GMT a link instead of vice versa,
540+ // but only when using the vanguard format. As of 2024a, the main and
541+ // rearguard formats still have Etc/GMT as a Zone and GMT as a link.
542+ VERIFY( tz->name() == "GMT" || tz->name() == "Etc/GMT" );
543+
544 VERIFY( db.locate_zone(db.current_zone()->name()) == db.current_zone() );
545 }
546
547--
5482.43.5
549
diff --git a/meta/recipes-devtools/gcc/gcc_14.2.bb b/meta/recipes-devtools/gcc/gcc_14.3.bb
index 255fe552bd..255fe552bd 100644
--- a/meta/recipes-devtools/gcc/gcc_14.2.bb
+++ b/meta/recipes-devtools/gcc/gcc_14.3.bb
diff --git a/meta/recipes-devtools/gcc/libgcc-initial_14.2.bb b/meta/recipes-devtools/gcc/libgcc-initial_14.3.bb
index a259082b47..a259082b47 100644
--- a/meta/recipes-devtools/gcc/libgcc-initial_14.2.bb
+++ b/meta/recipes-devtools/gcc/libgcc-initial_14.3.bb
diff --git a/meta/recipes-devtools/gcc/libgcc_14.2.bb b/meta/recipes-devtools/gcc/libgcc_14.3.bb
index fdcd6cc0da..fdcd6cc0da 100644
--- a/meta/recipes-devtools/gcc/libgcc_14.2.bb
+++ b/meta/recipes-devtools/gcc/libgcc_14.3.bb
diff --git a/meta/recipes-devtools/gcc/libgfortran_14.2.bb b/meta/recipes-devtools/gcc/libgfortran_14.3.bb
index 71dd8b4bdc..71dd8b4bdc 100644
--- a/meta/recipes-devtools/gcc/libgfortran_14.2.bb
+++ b/meta/recipes-devtools/gcc/libgfortran_14.3.bb