diff --git a/.devtoolset-11-gcc.metadata b/.devtoolset-11-gcc.metadata index e1aafa1..ea49c74 100644 --- a/.devtoolset-11-gcc.metadata +++ b/.devtoolset-11-gcc.metadata @@ -1,5 +1,5 @@ 7f4348418dc3efefd357b32a2b5c8010211ab284 SOURCES/doxygen-1.8.0.src.tar.gz -8bb88a8a2cc72b6e4563e0e5e19f53ff09d72ee1 SOURCES/gcc-11.2.1-20210728.tar.xz +54f8e112180f2cad6cf9459aab4681c7f157aca9 SOURCES/gcc-11.2.1-20220127.tar.xz db38c7b67f8eea9f2e5b8a48d219165b2fdab11f SOURCES/gmp-6.1.0.tar.bz2 bbffc5a2b05e4f0c97e882f96c448504491dc4ed SOURCES/isl-0.18.tar.bz2 b8be66396c726fdc36ebb0f692ed8a8cca3bcc66 SOURCES/mpc-1.0.3.tar.gz diff --git a/.gitignore b/.gitignore index e8281b4..c2e41e2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ SOURCES/doxygen-1.8.0.src.tar.gz -SOURCES/gcc-11.2.1-20210728.tar.xz +SOURCES/gcc-11.2.1-20220127.tar.xz SOURCES/gmp-6.1.0.tar.bz2 SOURCES/isl-0.18.tar.bz2 SOURCES/mpc-1.0.3.tar.gz diff --git a/SOURCES/0001-basic_string-reserve-n-semantics-are-not-available-i.patch b/SOURCES/0001-basic_string-reserve-n-semantics-are-not-available-i.patch new file mode 100644 index 0000000..7031726 --- /dev/null +++ b/SOURCES/0001-basic_string-reserve-n-semantics-are-not-available-i.patch @@ -0,0 +1,85 @@ +From 8a7f364afd86a4c4c2c747ae9cb4216fe992acc8 Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Wed, 25 Aug 2021 12:36:42 -0400 +Subject: [PATCH 01/17] basic_string::reserve(n) semantics are not available in + DTS + +Various tests were added upstream 2020-08-06 as part of: + "libstdc++: Implement P0966 std::string::reserve should not shrink" + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=140cf935cd118f7208b7c3826a8b9d50936242f0 + +std::string and std::wstring are instantiated in the system libstdc++.so +via explicit instantiation definitions, so the new basic_string::reserve(n) +semantics are not available in DTS. + +Update/disable the pertinent parts of the tests to reflect the behavior +when run against the system libstdc++.so. +--- + .../testsuite/21_strings/basic_string/capacity/char/1.cc | 6 ------ + .../21_strings/basic_string/capacity/char/18654.cc | 2 +- + .../testsuite/21_strings/basic_string/capacity/wchar_t/1.cc | 6 ------ + .../21_strings/basic_string/capacity/wchar_t/18654.cc | 2 +- + 4 files changed, 2 insertions(+), 14 deletions(-) + +diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc +index eea69771f..64187718d 100644 +--- a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc ++++ b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc +@@ -41,12 +41,6 @@ void test01() + sz01 = str01.capacity(); + VERIFY( sz01 < sz02 ); + +- // P0966: reserve should not shrink +- str01.reserve(100); +- sz01 = str01.capacity(); +- str01.reserve(sz01 - 1); +- VERIFY( str01.capacity() == sz01 ); +- + sz01 = str01.size() + 5; + str01.resize(sz01); + sz02 = str01.size(); +diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/18654.cc b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/18654.cc +index 02ce78ea6..3a7352123 100644 +--- a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/18654.cc ++++ b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/18654.cc +@@ -51,7 +51,7 @@ void test01() + VERIFY( cap >= 3 * i ); + + str.reserve(2 * i); +- VERIFY( str.capacity() == cap ); ++ VERIFY( str.capacity() == 2 * i ); + + #if __cplusplus <= 201703L + str.reserve(); +diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc +index f01a27e8c..70915a94d 100644 +--- a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc ++++ b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc +@@ -41,12 +41,6 @@ void test01() + sz01 = str01.capacity(); + VERIFY( sz01 < sz02 ); + +- // P0966: reserve should not shrink +- str01.reserve(100); +- sz01 = str01.capacity(); +- str01.reserve(sz01 - 1); +- VERIFY( str01.capacity() == sz01 ); +- + sz01 = str01.size() + 5; + str01.resize(sz01); + sz02 = str01.size(); +diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/18654.cc b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/18654.cc +index 267fd198b..c9711a294 100644 +--- a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/18654.cc ++++ b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/18654.cc +@@ -51,7 +51,7 @@ void test01() + VERIFY( cap >= 3 * i ); + + str.reserve(2 * i); +- VERIFY( str.capacity() == cap ); ++ VERIFY( str.capacity() == 2 * i ); + + #if __cplusplus <= 201703L + str.reserve(); +-- +2.31.1 diff --git a/SOURCES/0004-operator-istream-char-N-eofbit-fixes-are-not-availab.patch b/SOURCES/0004-operator-istream-char-N-eofbit-fixes-are-not-availab.patch new file mode 100644 index 0000000..264745b --- /dev/null +++ b/SOURCES/0004-operator-istream-char-N-eofbit-fixes-are-not-availab.patch @@ -0,0 +1,46 @@ +From d7fae9f17479c44dae68483d457fc3fbb58c4b83 Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Wed, 25 Aug 2021 15:57:36 -0400 +Subject: [PATCH 04/17] operator>>(istream&, char(&)[N]) eofbit fixes are not + available in DTS + +The upstream commit on 2020-08--6: + Do not set eofbit eagerly in operator>>(istream&, char(&)[N]) + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4e39f563c0cd25401f689c2093cb8c13692156ef +altered the behaviour of std::istream symbols defined in libstdc++.so, +but with DTS you get the old definitions from the system libstdc++.so + +Hence this patch tweaks the new tests to avoid failing when run against +the system libstdc++.so +--- + .../21_strings/basic_string/inserters_extractors/char/13.cc | 1 - + .../21_strings/basic_string/inserters_extractors/wchar_t/13.cc | 1 - + 2 files changed, 2 deletions(-) + +diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/char/13.cc b/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/char/13.cc +index a25d8a93d..7d85e6ead 100644 +--- a/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/char/13.cc ++++ b/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/char/13.cc +@@ -29,7 +29,6 @@ test01() + std::string buf; + in.width(4); + in >> buf; +- VERIFY( !in.eof() ); // should stop after reading 4 chars + VERIFY( buf == str ); + } + +diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/wchar_t/13.cc b/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/wchar_t/13.cc +index f15294a44..fa5fe3d4a 100644 +--- a/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/wchar_t/13.cc ++++ b/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/wchar_t/13.cc +@@ -29,7 +29,6 @@ test01() + std::wstring buf; + in.width(4); + in >> buf; +- VERIFY( !in.eof() ); // should stop after reading 4 chars + VERIFY( buf == str ); + } + +-- +2.31.1 + diff --git a/SOURCES/0005-Disable-tests-for-PR-libstdc-79820-and-PR-libstdc-81.patch b/SOURCES/0005-Disable-tests-for-PR-libstdc-79820-and-PR-libstdc-81.patch new file mode 100644 index 0000000..0641e85 --- /dev/null +++ b/SOURCES/0005-Disable-tests-for-PR-libstdc-79820-and-PR-libstdc-81.patch @@ -0,0 +1,53 @@ +From 3ede89bd19328c26bcd881b873cf4a766ae0da3a Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Wed, 25 Aug 2021 17:04:02 -0400 +Subject: [PATCH 05/17] Disable tests for PR libstdc++/79820 and PR + libstdc++/81751 under DTS + +Upstream commit 2017-08-09 + PR libstdc++/81751 don't call fflush(NULL) + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=04d07b61cb80fd97e98eb39451ff6a8675a63d90 +added these test cases as part of verifying the behavior of sys_open (that +it resets errno and doesn't call fflush on NULL). + +These symbols are in the system stdlib when run from DTS and thus aren't +fixed by the above change: + + 1521: 000000000007c430 104 FUNC GLOBAL DEFAULT 12 std::__basic_file::sys_open(int, std::_Ios_Openmode)@@GLIBCXX_3.4 + 2895: 000000000007c730 95 FUNC GLOBAL DEFAULT 12 std::__basic_file::sys_open(_IO_FILE*, std::_Ios_Openmode)@@GLIBCXX_3.4 + +This patch disables the non-fixed assertions. +--- + libstdc++-v3/testsuite/ext/stdio_filebuf/char/79820.cc | 2 -- + libstdc++-v3/testsuite/ext/stdio_filebuf/char/81751.cc | 1 - + 2 files changed, 3 deletions(-) + +diff --git a/libstdc++-v3/testsuite/ext/stdio_filebuf/char/79820.cc b/libstdc++-v3/testsuite/ext/stdio_filebuf/char/79820.cc +index 278b99169..e2a8e3b3d 100644 +--- a/libstdc++-v3/testsuite/ext/stdio_filebuf/char/79820.cc ++++ b/libstdc++-v3/testsuite/ext/stdio_filebuf/char/79820.cc +@@ -26,9 +26,7 @@ void + test01() + { + FILE* f = std::fopen("79820.txt", "w"); +- errno = 127; + __gnu_cxx::stdio_filebuf b(f, std::ios::out, BUFSIZ); +- VERIFY(errno == 127); // PR libstdc++/79820 + b.close(); + std::fclose(f); + } +diff --git a/libstdc++-v3/testsuite/ext/stdio_filebuf/char/81751.cc b/libstdc++-v3/testsuite/ext/stdio_filebuf/char/81751.cc +index 21aa06f78..6a231d7cf 100644 +--- a/libstdc++-v3/testsuite/ext/stdio_filebuf/char/81751.cc ++++ b/libstdc++-v3/testsuite/ext/stdio_filebuf/char/81751.cc +@@ -31,7 +31,6 @@ test01() + FILE* in1 = std::fopen("81751.txt", "r"); + __gnu_cxx::stdio_filebuf buf1(in1, std::ios::in, BUFSIZ); + int c = buf1.sgetc(); +- VERIFY( c == std::char_traits::eof() ); // PR libstdc++/81751 + + std::fflush(out); + FILE* in2 = std::fopen("81751.txt", "r"); +-- +2.31.1 + diff --git a/SOURCES/0006-Don-t-assume-has_facet-codecvt_c16-when-run-against-.patch b/SOURCES/0006-Don-t-assume-has_facet-codecvt_c16-when-run-against-.patch new file mode 100644 index 0000000..dcabb08 --- /dev/null +++ b/SOURCES/0006-Don-t-assume-has_facet-codecvt_c16-when-run-against-.patch @@ -0,0 +1,118 @@ +From 59388ee3dac5c737086ed1f83f552a44481a2213 Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Tue, 31 Aug 2021 16:08:57 -0400 +Subject: [PATCH 06/17] Don't assume has_facet when run against + system libstdc++ + +Upstream commit 2019-02-19: + P0482R5 char8_t: Standard library support + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=c124af936b6b225eb548ccdd7f01400511d784dc +added new locale facets for char8_t. + +has_facet returns false, as it is using the std::locale the system libstdc++: + +$ eu-readelf -s char16_t-char8_t.exe |c++filt |grep UNDEF|grep locale + 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::locale::classic()@GLIBCXX_3.4 (2) + 8: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::locale::locale(std::locale const&)@GLIBCXX_3.4 (2) + 13: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::locale::id::_M_id() const@GLIBCXX_3.4 (2) + 22: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::locale::~locale()@GLIBCXX_3.4 (2) + 64: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::locale::classic()@@GLIBCXX_3.4 + 76: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::locale::locale(std::locale const&)@@GLIBCXX_3.4 + 89: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::locale::id::_M_id() const@@GLIBCXX_3.4 + 108: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::locale::~locale()@@GLIBCXX_3.4 + +Hence this patch tweaks tests so that they bail out if run against an older std::locale. +--- + libstdc++-v3/testsuite/22_locale/codecvt/char16_t-char8_t.cc | 3 ++- + libstdc++-v3/testsuite/22_locale/codecvt/char16_t.cc | 3 ++- + libstdc++-v3/testsuite/22_locale/codecvt/char32_t-char8_t.cc | 3 ++- + libstdc++-v3/testsuite/22_locale/codecvt/char32_t.cc | 3 ++- + libstdc++-v3/testsuite/22_locale/codecvt/utf8-char8_t.cc | 2 ++ + libstdc++-v3/testsuite/22_locale/codecvt/utf8.cc | 2 ++ + 6 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/char16_t-char8_t.cc b/libstdc++-v3/testsuite/22_locale/codecvt/char16_t-char8_t.cc +index 71a23bef4..d4aa519a2 100644 +--- a/libstdc++-v3/testsuite/22_locale/codecvt/char16_t-char8_t.cc ++++ b/libstdc++-v3/testsuite/22_locale/codecvt/char16_t-char8_t.cc +@@ -31,7 +31,8 @@ test01() + using namespace std; + typedef codecvt codecvt_c16; + locale loc_c = locale::classic(); +- VERIFY(has_facet(loc_c)); ++ if (!has_facet(loc_c)) ++ return; + const codecvt_c16* const cvt = &use_facet(loc_c); + + VERIFY(!cvt->always_noconv()); +diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/char16_t.cc b/libstdc++-v3/testsuite/22_locale/codecvt/char16_t.cc +index 7b5ce126d..05c77b2b1 100644 +--- a/libstdc++-v3/testsuite/22_locale/codecvt/char16_t.cc ++++ b/libstdc++-v3/testsuite/22_locale/codecvt/char16_t.cc +@@ -29,7 +29,8 @@ test01() + using namespace std; + typedef codecvt codecvt_c16; + locale loc_c = locale::classic(); +- VERIFY(has_facet(loc_c)); ++ if (!has_facet(loc_c)) ++ return; + const codecvt_c16* const cvt = &use_facet(loc_c); + + VERIFY(!cvt->always_noconv()); +diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/char32_t-char8_t.cc b/libstdc++-v3/testsuite/22_locale/codecvt/char32_t-char8_t.cc +index f30ae22e9..281969e9b 100644 +--- a/libstdc++-v3/testsuite/22_locale/codecvt/char32_t-char8_t.cc ++++ b/libstdc++-v3/testsuite/22_locale/codecvt/char32_t-char8_t.cc +@@ -33,7 +33,8 @@ test01() + using namespace std; + typedef codecvt codecvt_c32; + locale loc_c = locale::classic(); +- VERIFY(has_facet(loc_c)); ++ if (!has_facet(loc_c)) ++ return; + const codecvt_c32* const cvt = &use_facet(loc_c); + + VERIFY(!cvt->always_noconv()); +diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/char32_t.cc b/libstdc++-v3/testsuite/22_locale/codecvt/char32_t.cc +index 558ba9145..82980b702 100644 +--- a/libstdc++-v3/testsuite/22_locale/codecvt/char32_t.cc ++++ b/libstdc++-v3/testsuite/22_locale/codecvt/char32_t.cc +@@ -31,7 +31,8 @@ test01() + using namespace std; + typedef codecvt codecvt_c32; + locale loc_c = locale::classic(); +- VERIFY(has_facet(loc_c)); ++ if (!has_facet(loc_c)) ++ return; + const codecvt_c32* const cvt = &use_facet(loc_c); + + VERIFY(!cvt->always_noconv()); +diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/utf8-char8_t.cc b/libstdc++-v3/testsuite/22_locale/codecvt/utf8-char8_t.cc +index 5eab05ba2..d6f663ce6 100644 +--- a/libstdc++-v3/testsuite/22_locale/codecvt/utf8-char8_t.cc ++++ b/libstdc++-v3/testsuite/22_locale/codecvt/utf8-char8_t.cc +@@ -34,6 +34,8 @@ void test(const C* from) + std::mbstate_t state{}; + char8_t buf[16] = { }; + using test_type = std::codecvt; ++ if (!std::has_facet(std::locale::classic())) ++ return; + const test_type& cvt = std::use_facet(std::locale::classic()); + auto from_end = from + len; + auto from_next = from; +diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/utf8.cc b/libstdc++-v3/testsuite/22_locale/codecvt/utf8.cc +index b1b3cff31..167bc0ca3 100644 +--- a/libstdc++-v3/testsuite/22_locale/codecvt/utf8.cc ++++ b/libstdc++-v3/testsuite/22_locale/codecvt/utf8.cc +@@ -32,6 +32,8 @@ void test(const C* from) + std::mbstate_t state{}; + char buf[16] = { }; + using test_type = std::codecvt; ++ if (!std::has_facet(std::locale::classic())) ++ return; + const test_type& cvt = std::use_facet(std::locale::classic()); + auto from_end = from + len; + auto from_next = from; +-- +2.31.1 + diff --git a/SOURCES/0008-testsuite-build-plugins-with-std-c-11.patch b/SOURCES/0008-testsuite-build-plugins-with-std-c-11.patch new file mode 100644 index 0000000..f97bad3 --- /dev/null +++ b/SOURCES/0008-testsuite-build-plugins-with-std-c-11.patch @@ -0,0 +1,42 @@ +From 16694079a3f415f5e5683b0afe6978810ac259b1 Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Tue, 31 Aug 2021 17:01:05 -0400 +Subject: [PATCH 08/17] testsuite: build plugins with -std=c++11 + +Various testsuite plugins fail when built within DTS with e.g.: + cc1: error: cannot load plugin ./diagnostic_plugin_test_paths.so: /builddir/build/BUILD/gcc-11.1.1-20210623/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/src/.libs/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by ./diagnostic_plugin_test_paths.so) + +These turn out to C++14's sized deletion +(see https://en.cppreference.com/w/cpp/memory/new/operator_delete): + + 14: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF _ZdlPvm@CXXABI_1.3.9 (4) + 48: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF _ZdlPvm@CXXABI_1.3.9 + 14: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF operator delete(void*, unsigned long)@CXXABI_1.3.9 (4) + 48: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF operator delete(void*, unsigned long)@CXXABI_1.3.9 + +Looks like plugin.exp is building the test plugins against the +freshly-built libstdc++, and then trying to dynamically load them +against the system libstdc++. + +This patch forces the use of -std=c++11 when building these test plugins, +to sidestep the problem. +--- + gcc/testsuite/lib/plugin-support.exp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gcc/testsuite/lib/plugin-support.exp b/gcc/testsuite/lib/plugin-support.exp +index 6d651901e..9943dbb37 100644 +--- a/gcc/testsuite/lib/plugin-support.exp ++++ b/gcc/testsuite/lib/plugin-support.exp +@@ -103,7 +103,7 @@ proc plugin-test-execute { plugin_src plugin_tests } { + } + set optstr [concat $optstr "-DIN_GCC -fPIC -shared -fno-rtti -undefined dynamic_lookup"] + } else { +- set plug_cflags $PLUGINCFLAGS ++ set plug_cflags "$PLUGINCFLAGS -std=c++11" + set optstr "$includes $extra_flags -DIN_GCC -fPIC -shared -fno-rtti" + } + +-- +2.31.1 + diff --git a/SOURCES/0009-Fix-22_locale-locale-cons-unicode.cc-when-run-under-.patch b/SOURCES/0009-Fix-22_locale-locale-cons-unicode.cc-when-run-under-.patch new file mode 100644 index 0000000..a540702 --- /dev/null +++ b/SOURCES/0009-Fix-22_locale-locale-cons-unicode.cc-when-run-under-.patch @@ -0,0 +1,36 @@ +From 87e2a4f28b444f376ebe15f38e2743eb952ff355 Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Wed, 1 Sep 2021 11:02:53 -0400 +Subject: [PATCH 09/17] Fix 22_locale/locale/cons/unicode.cc when run under DTS + +Various has_facet calls return false in DTS, as DTS is using the +std::locale from the system libstdc++. + +Hence this patch tweaks tests to remove the VERIFY from the result of +the call, so that they do not fail if run against an older +std::locale. + +These VERIFY tests were added upstream 2015-01-16 in + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=bb93f35da1612940266f5d159b6cc5a3e54fca14 +--- + libstdc++-v3/testsuite/22_locale/locale/cons/unicode.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/unicode.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/unicode.cc +index 15c621099..328145094 100644 +--- a/libstdc++-v3/testsuite/22_locale/locale/cons/unicode.cc ++++ b/libstdc++-v3/testsuite/22_locale/locale/cons/unicode.cc +@@ -70,8 +70,8 @@ void test01() + VERIFY( has_facet(loc13) ); + #endif + #ifdef _GLIBCXX_USE_C99_STDINT_TR1 +- VERIFY( has_facet(loc13) ); +- VERIFY( has_facet(loc13) ); ++ (void)( has_facet(loc13) ); ++ (void)( has_facet(loc13) ); + #ifdef _GLIBCXX_USE_CHAR8_T + VERIFY( has_facet(loc13) ); + VERIFY( has_facet(loc13) ); +-- +2.31.1 + diff --git a/SOURCES/0010-Don-t-verify-exception-handling-in-basic_filebuf-clo.patch b/SOURCES/0010-Don-t-verify-exception-handling-in-basic_filebuf-clo.patch new file mode 100644 index 0000000..9e16d2e --- /dev/null +++ b/SOURCES/0010-Don-t-verify-exception-handling-in-basic_filebuf-clo.patch @@ -0,0 +1,30 @@ +From d1555ffdd9b4fa6f3ceaa166bbfee0b3b9973ecf Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Wed, 1 Sep 2021 11:24:34 -0400 +Subject: [PATCH 10/17] Don't verify exception handling in basic_filebuf::close + in DTS [PR81256] + +27_io/basic_filebuf/close/81256.cc was added upstream 2018-05-14 in + PR libstdc++/81256 fix exception handling in basic_filebuf::close + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=e77497ab777d3dfa19224648d658220807ab7419 + +When run under DTS, + std::basic_filebuf >::close +comes from the system libstdc++, and hence the test fails. +--- + libstdc++-v3/testsuite/27_io/basic_filebuf/close/81256.cc | 1 - + 1 file changed, 1 deletion(-) + +--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/81256.cc ++++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/81256.cc +@@ -80,7 +80,6 @@ test01() + caught = true; + } + VERIFY( conv.exceptions_thrown == 1 ); +- VERIFY( caught ); + } + VERIFY( conv.exceptions_thrown == 1 ); + } +-- +2.31.1 + diff --git a/SOURCES/0011-Add-dts.exp-and-use-it-to-fix-22_locale-messages-136.patch b/SOURCES/0011-Add-dts.exp-and-use-it-to-fix-22_locale-messages-136.patch new file mode 100644 index 0000000..7d28f1e --- /dev/null +++ b/SOURCES/0011-Add-dts.exp-and-use-it-to-fix-22_locale-messages-136.patch @@ -0,0 +1,117 @@ +From b6989e3a4acda2d75612f3f3847dbea4245ff536 Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Wed, 1 Sep 2021 15:39:45 -0400 +Subject: [PATCH 11/17] Add dts.exp and use it to fix + 22_locale/messages/13631.cc + +This test was added upstream 2014-12-03: + "re PR libstdc++/13631 (Problems in messages)" + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=d31008d7a0d53b431f176aad8dda5498de823122 + +as part of a fix that is present in the system libstdc++.so in +GCC 5 onwards. + +When run in DTS against such a system library, this test will fail. +This patch introduces a dts.exp which detects the version of the +underlying system libstdc++.so and exposes it to tests via +-D__CXXSTDLIB_SO_VERSION__=, so that we can ifdef specific tests +away, conditionally on the base GCC. +--- + .../testsuite/22_locale/messages/13631.cc | 7 +++++ + libstdc++-v3/testsuite/lib/dts.exp | 31 +++++++++++++++++++ + libstdc++-v3/testsuite/lib/libstdc++.exp | 6 ++++ + 3 files changed, 44 insertions(+) + create mode 100644 libstdc++-v3/testsuite/lib/dts.exp + +diff --git a/libstdc++-v3/testsuite/22_locale/messages/13631.cc b/libstdc++-v3/testsuite/22_locale/messages/13631.cc +index b8ae3d4f1..5b20df382 100644 +--- a/libstdc++-v3/testsuite/22_locale/messages/13631.cc ++++ b/libstdc++-v3/testsuite/22_locale/messages/13631.cc +@@ -50,7 +50,10 @@ void test01() + msgs_facet.close(fake_msgs); + msgs_facet.close(msgs); + ++ // Fixed upstream in GCC 5 ++#if __CXXSTDLIB_SO_VERSION__ >= 501000 + VERIFY( translation1 == translation2 ); ++#endif + } + + void test02() +@@ -72,8 +75,12 @@ void test02() + std::wstring translation1 = msgs_facet.get(msgs, 0, 0, msgid); + + // Without a real translation this test doesn't mean anything: ++ ++ // Fixed upstream in GCC 5 ++#if __CXXSTDLIB_SO_VERSION__ >= 501000 + VERIFY( !translation1.empty() ); + VERIFY( translation1 != msgid ); ++#endif + + // Opening another catalog was enough to show the problem, even a fake + // catalog. +diff --git a/libstdc++-v3/testsuite/lib/dts.exp b/libstdc++-v3/testsuite/lib/dts.exp +new file mode 100644 +index 000000000..76ece66d3 +--- /dev/null ++++ b/libstdc++-v3/testsuite/lib/dts.exp +@@ -0,0 +1,31 @@ ++# For DTS testing, generate a number expressing the ++# system version of libstdc++.so ++# ++# Generate a version number equivalent to ++# #define GCC_VERSION (__GNUC__ * 10000 \ ++# + __GNUC_MINOR__ * 100 \ ++# + __GNUC_PATCHLEVEL__) ++# ++# For example, given an underlying version of gcc 4.8.5 ++# this function will return 408050. ++ ++proc get_dts_base_version { } { ++ ++ # Invoke gcc in the PATH to get at the underlying GCC version ++ # in dotted form (e.g. "4.8.5"). ++ set dotted_version [exec gcc -dumpversion] ++ verbose "dotted_version: '$dotted_version'" 2 ++ ++ # Extract major, minor, patchlevel ++ regexp {([0-9]+)\.([0-9]+)\.([0-9]+)} \ ++ $dotted_version \ ++ _ major minor patchlevel ++ verbose "major: '$major'" 2 ++ verbose "minor: '$minor'" 2 ++ verbose "patchlevel: '$patchlevel'" 2 ++ ++ set base_gcc_version [expr (($major * 10000) + ($minor * 100) + $patchlevel)] ++ verbose "base_gcc_version: '$base_gcc_version'" 2 ++ ++ return $base_gcc_version ++} +diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp +index 7f9580db8..5e4b32f76 100644 +--- a/libstdc++-v3/testsuite/lib/libstdc++.exp ++++ b/libstdc++-v3/testsuite/lib/libstdc++.exp +@@ -58,6 +58,7 @@ load_gcc_lib timeout.exp + load_gcc_lib timeout-dg.exp + load_gcc_lib wrapper.exp + load_gcc_lib target-utils.exp ++load_lib dts.exp + + # Useful for debugging. Pass the name of a variable and the verbosity + # threshold (number of -v's on the command line). +@@ -323,6 +324,11 @@ proc libstdc++_init { testfile } { + set ccflags "$cxxflags -DLOCALEDIR=\".\"" + set cxxflags "$cxxflags -DLOCALEDIR=\".\"" + ++ # For DTS testing, expose the system version of libstdc++.so as ++ # a preprocessor define. ++ set base_gcc_version [get_dts_base_version] ++ set cxxflags "$cxxflags -D__CXXSTDLIB_SO_VERSION__=$base_gcc_version" ++ + # If a PCH file is available, use it. We must delay performing + # this check until $cxx and such have been initialized because we + # perform a test compilation. (Ideally, gcc --print-file-name would +-- +2.31.1 + diff --git a/SOURCES/0012-dts.exp-use-usr-bin-gcc.patch b/SOURCES/0012-dts.exp-use-usr-bin-gcc.patch new file mode 100644 index 0000000..129ef2d --- /dev/null +++ b/SOURCES/0012-dts.exp-use-usr-bin-gcc.patch @@ -0,0 +1,28 @@ +From c3910bb945aba02e0c06dec041da9f1f148b0df1 Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Thu, 2 Sep 2021 11:40:42 -0400 +Subject: [PATCH 12/17] dts.exp: use /usr/bin/gcc + +--- + libstdc++-v3/testsuite/lib/dts.exp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libstdc++-v3/testsuite/lib/dts.exp b/libstdc++-v3/testsuite/lib/dts.exp +index 76ece66d3..dc5cf3e95 100644 +--- a/libstdc++-v3/testsuite/lib/dts.exp ++++ b/libstdc++-v3/testsuite/lib/dts.exp +@@ -11,9 +11,9 @@ + + proc get_dts_base_version { } { + +- # Invoke gcc in the PATH to get at the underlying GCC version ++ # Invoke /usr/bin/gcc to get at the underlying GCC version + # in dotted form (e.g. "4.8.5"). +- set dotted_version [exec gcc -dumpversion] ++ set dotted_version [exec /usr/bin/gcc -dumpversion] + verbose "dotted_version: '$dotted_version'" 2 + + # Extract major, minor, patchlevel +-- +2.31.1 + diff --git a/SOURCES/0013-Rename-__CXXSTDLIB_SO_VERSION__-to-__LIBSTDCXX_SO_VE.patch b/SOURCES/0013-Rename-__CXXSTDLIB_SO_VERSION__-to-__LIBSTDCXX_SO_VE.patch new file mode 100644 index 0000000..52f160d --- /dev/null +++ b/SOURCES/0013-Rename-__CXXSTDLIB_SO_VERSION__-to-__LIBSTDCXX_SO_VE.patch @@ -0,0 +1,86 @@ +From c922a56d4461c9e4ca2af07ecccb3626b99a35ae Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Thu, 2 Sep 2021 11:44:37 -0400 +Subject: [PATCH 13/17] Rename __CXXSTDLIB_SO_VERSION__ to + __LIBSTDCXX_SO_VERSION and only use major version + +--- + .../testsuite/22_locale/messages/13631.cc | 4 ++-- + libstdc++-v3/testsuite/lib/dts.exp | 18 +++++------------- + libstdc++-v3/testsuite/lib/libstdc++.exp | 4 ++-- + 3 files changed, 9 insertions(+), 17 deletions(-) + +diff --git a/libstdc++-v3/testsuite/22_locale/messages/13631.cc b/libstdc++-v3/testsuite/22_locale/messages/13631.cc +index 5b20df382..f4c5eb7a2 100644 +--- a/libstdc++-v3/testsuite/22_locale/messages/13631.cc ++++ b/libstdc++-v3/testsuite/22_locale/messages/13631.cc +@@ -51,7 +51,7 @@ void test01() + msgs_facet.close(msgs); + + // Fixed upstream in GCC 5 +-#if __CXXSTDLIB_SO_VERSION__ >= 501000 ++#if __LIBSTDCXX_SO_VERSION >= 5 + VERIFY( translation1 == translation2 ); + #endif + } +@@ -77,7 +77,7 @@ void test02() + // Without a real translation this test doesn't mean anything: + + // Fixed upstream in GCC 5 +-#if __CXXSTDLIB_SO_VERSION__ >= 501000 ++#if __LIBSTDCXX_SO_VERSION >= 5 + VERIFY( !translation1.empty() ); + VERIFY( translation1 != msgid ); + #endif +diff --git a/libstdc++-v3/testsuite/lib/dts.exp b/libstdc++-v3/testsuite/lib/dts.exp +index dc5cf3e95..60f94bd6d 100644 +--- a/libstdc++-v3/testsuite/lib/dts.exp ++++ b/libstdc++-v3/testsuite/lib/dts.exp +@@ -1,15 +1,10 @@ +-# For DTS testing, generate a number expressing the +-# system version of libstdc++.so +-# +-# Generate a version number equivalent to +-# #define GCC_VERSION (__GNUC__ * 10000 \ +-# + __GNUC_MINOR__ * 100 \ +-# + __GNUC_PATCHLEVEL__) ++# For DTS testing, get the major version of the ++# system libstdc++.so + # + # For example, given an underlying version of gcc 4.8.5 +-# this function will return 408050. ++# this function will return 4 + +-proc get_dts_base_version { } { ++proc get_dts_base_major_version { } { + + # Invoke /usr/bin/gcc to get at the underlying GCC version + # in dotted form (e.g. "4.8.5"). +@@ -24,8 +19,5 @@ proc get_dts_base_version { } { + verbose "minor: '$minor'" 2 + verbose "patchlevel: '$patchlevel'" 2 + +- set base_gcc_version [expr (($major * 10000) + ($minor * 100) + $patchlevel)] +- verbose "base_gcc_version: '$base_gcc_version'" 2 +- +- return $base_gcc_version ++ return $major + } +diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp +index 5e4b32f76..297485b19 100644 +--- a/libstdc++-v3/testsuite/lib/libstdc++.exp ++++ b/libstdc++-v3/testsuite/lib/libstdc++.exp +@@ -326,8 +326,8 @@ proc libstdc++_init { testfile } { + + # For DTS testing, expose the system version of libstdc++.so as + # a preprocessor define. +- set base_gcc_version [get_dts_base_version] +- set cxxflags "$cxxflags -D__CXXSTDLIB_SO_VERSION__=$base_gcc_version" ++ set base_gcc_version [get_dts_base_major_version] ++ set cxxflags "$cxxflags -D__LIBSTDCXX_SO_VERSION=$base_gcc_version" + + # If a PCH file is available, use it. We must delay performing + # this check until $cxx and such have been initialized because we +-- +2.31.1 + diff --git a/SOURCES/0014-Conditionalize-tests-for-PR-libstdc-98466-on-__LIBST.patch b/SOURCES/0014-Conditionalize-tests-for-PR-libstdc-98466-on-__LIBST.patch new file mode 100644 index 0000000..0da5b14 --- /dev/null +++ b/SOURCES/0014-Conditionalize-tests-for-PR-libstdc-98466-on-__LIBST.patch @@ -0,0 +1,84 @@ +From fa770c25013df537c41d0929c4202b0a774a6a75 Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Thu, 2 Sep 2021 15:27:59 -0400 +Subject: [PATCH 14/17] Conditionalize tests for PR libstdc++/98466 on + __LIBSTDCXX_SO_VERSION >= 11 + +The tests: + 23_containers/deque/debug/98466.cc + 23_containers/unordered_map/debug/98466.cc +were added upstream 2021-01-01 as part of: + libstdc++: Implement N3644 for _GLIBCXX_DEBUG iterators + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=05a30af3f237984b4dcf1dbbc17fdac583c46506 +but fail when run in DTS against a system libstdc++.so +from an older GCC. + +In particular, they use the older implementation of _M_can_compare from +the dynamic library: + +$ eu-readelf -s 98466.exe | grep can_compare | c++filt + 11: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF __gnu_debug::_Safe_iterator_base::_M_can_compare(__gnu_debug::_Safe_iterator_base const&) const@GLIBCXX_3.4 (4) + 157: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF __gnu_debug::_Safe_iterator_base::_M_can_compare(__gnu_debug::_Safe_iterator_base const&) const@@GLIBCXX_3.4 +--- + .../testsuite/23_containers/deque/debug/98466.cc | 6 ++++++ + .../23_containers/unordered_map/debug/98466.cc | 12 ++++++++++++ + 2 files changed, 18 insertions(+) + +diff --git a/libstdc++-v3/testsuite/23_containers/deque/debug/98466.cc b/libstdc++-v3/testsuite/23_containers/deque/debug/98466.cc +index c2d793374..e92d719bf 100644 +--- a/libstdc++-v3/testsuite/23_containers/deque/debug/98466.cc ++++ b/libstdc++-v3/testsuite/23_containers/deque/debug/98466.cc +@@ -26,11 +26,17 @@ void test01() + { + typedef typename __gnu_debug::deque::iterator It; + It it = It(); ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( it == it ); ++#endif + + typedef typename __gnu_debug::deque::const_iterator Cit; + Cit cit = Cit(); ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( cit == cit ); ++#endif + } + + int main() +diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/98466.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/98466.cc +index cc22b9ff8..3a1b6cd32 100644 +--- a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/98466.cc ++++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/98466.cc +@@ -25,16 +25,28 @@ + void test01() + { + __gnu_debug::unordered_map::iterator it{}; ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( it == it ); ++#endif + + __gnu_debug::unordered_map::const_iterator cit{}; ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( cit == cit ); ++#endif + + __gnu_debug::unordered_map::local_iterator lit{}; ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( lit == lit ); ++#endif + + __gnu_debug::unordered_map::const_local_iterator clit{}; ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( clit == clit ); ++#endif + } + + int main() +-- +2.31.1 + diff --git a/SOURCES/0015-Conditionalize-test-for-PR-libstdc-87135-on-__LIBSTD.patch b/SOURCES/0015-Conditionalize-test-for-PR-libstdc-87135-on-__LIBSTD.patch new file mode 100644 index 0000000..087b20e --- /dev/null +++ b/SOURCES/0015-Conditionalize-test-for-PR-libstdc-87135-on-__LIBSTD.patch @@ -0,0 +1,41 @@ +From 992665eab6c48d6a4819f42509346d24b277485d Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Thu, 2 Sep 2021 16:17:29 -0400 +Subject: [PATCH 15/17] Conditionalize test for PR libstdc++/87135 on + __LIBSTDCXX_SO_VERSION >= 9 + +This VERIFY was added upstream 2018-09-18 as part of: + re PR libstdc++/87135 ([C++17] unordered containers violate iterator validity requirements) + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=a521e62615e439aea7502a52fd0f8a21eaa6304f + +but fails when run in DTS against a system libstdc++.so from an older GCC. + +In particular, rehash from the header is using + std::__detail::_Prime_rehash_policy::_M_next_bkt +from the system .so: + + 12: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::__detail::_Prime_rehash_policy::_M_next_bkt(unsigned long) const@GLIBCXX_3.4.18 (5) + 225: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::__detail::_Prime_rehash_policy::_M_next_bkt(unsigned long) const@@GLIBCXX_3.4.18 +--- + .../23_containers/unordered_map/modifiers/reserve.cc | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/reserve.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/reserve.cc +index 58c8924b9..4c79ec2e6 100644 +--- a/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/reserve.cc ++++ b/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/reserve.cc +@@ -46,7 +46,11 @@ void test01() + + // As long as we insert less than the reserved number of elements we + // shouldn't experiment any rehash. ++ ++ // Fixed upstream in GCC 9 ++#if __LIBSTDCXX_SO_VERSION >= 9 + VERIFY( m.bucket_count() == bkts ); ++#endif + + VERIFY( m.load_factor() <= m.max_load_factor() ); + } +-- +2.31.1 + diff --git a/SOURCES/0016-Conditionalize-test-for-hashtable-bucket-sizes-on-__.patch b/SOURCES/0016-Conditionalize-test-for-hashtable-bucket-sizes-on-__.patch new file mode 100644 index 0000000..213a6f5 --- /dev/null +++ b/SOURCES/0016-Conditionalize-test-for-hashtable-bucket-sizes-on-__.patch @@ -0,0 +1,102 @@ +From db8f53df0be1daeda3159c1413549ff40696c710 Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Thu, 2 Sep 2021 17:02:33 -0400 +Subject: [PATCH 16/17] Conditionalize test for hashtable bucket sizes on + __LIBSTDCXX_SO_VERSION >= 11 + +These tests were added upstream 2020-01-20 as part of: + libstdc++: Do not over-size hashtable buckets on range insertion + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=6dcf042368012e2d7ce1626ee5d378bf3ad0ccfc + +but fail when run in DTS against a system libstdc++.so from an older GCC. + +In particular, _M_insert_unique_node from the header is using the older +implementation of + std::__detail::_Prime_rehash_policy::_M_need_rehash +from the dynamic library. + + 23: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::__detail::_Prime_rehash_policy::_M_need_rehash(unsigned long, unsigned long, unsigned long) const@GLIBCXX_3.4.18 (5) + 412: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF std::__detail::_Prime_rehash_policy::_M_need_rehash(unsigned long, unsigned long, unsigned long) const@@GLIBCXX_3.4.18 +--- + .../23_containers/unordered_set/cons/bucket_hint.cc | 10 ++++++++++ + .../23_containers/unordered_set/modifiers/insert.cc | 9 +++++++++ + 2 files changed, 19 insertions(+) + +diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/bucket_hint.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/bucket_hint.cc +index a3b014a3a..af231e54e 100644 +--- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/bucket_hint.cc ++++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/bucket_hint.cc +@@ -29,7 +29,11 @@ void test01() + a.reserve(2); + + std::unordered_set b({ 0, 1, 0, 1, 0, 1, 0, 1 }, a.bucket_count()); ++ ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( b.bucket_count() == a.bucket_count() ); ++#endif + } + + void test02() +@@ -40,7 +44,10 @@ void test02() + std::vector v { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }; + + std::unordered_set b(v.begin(), v.end(), a.bucket_count()); ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( b.bucket_count() == a.bucket_count() ); ++#endif + } + + void test03() +@@ -51,7 +58,10 @@ void test03() + std::forward_list fl { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }; + + std::unordered_set b(fl.begin(), fl.end(), a.bucket_count()); ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( b.bucket_count() == a.bucket_count() ); ++#endif + } + + int main() +diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/insert.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/insert.cc +index 015c2f872..aae8298ae 100644 +--- a/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/insert.cc ++++ b/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/insert.cc +@@ -30,7 +30,10 @@ void test01() + + auto bkt_count = a.bucket_count(); + a.insert({ 0, 1, 0, 1, 0, 1, 0, 1 }); ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( a.bucket_count() == bkt_count ); ++#endif + } + + void test02() +@@ -42,7 +45,10 @@ void test02() + + auto bkt_count = a.bucket_count(); + a.insert(v.begin(), v.end()); ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( a.bucket_count() == bkt_count ); ++#endif + } + + void test03() +@@ -54,7 +60,10 @@ void test03() + + auto bkt_count = a.bucket_count(); + a.insert(fl.begin(), fl.end()); ++ // Fixed upstream in GCC 11 ++#if __LIBSTDCXX_SO_VERSION >= 11 + VERIFY( a.bucket_count() == bkt_count ); ++#endif + } + + int main() +-- +2.31.1 + diff --git a/SOURCES/0017-Conditionalize-test-for-PR-libstdc-71181-on-__LIBSTD.patch b/SOURCES/0017-Conditionalize-test-for-PR-libstdc-71181-on-__LIBSTD.patch new file mode 100644 index 0000000..d18de1d --- /dev/null +++ b/SOURCES/0017-Conditionalize-test-for-PR-libstdc-71181-on-__LIBSTD.patch @@ -0,0 +1,33 @@ +From 102adc148612b50a4e3f12a88871ddc47bfb469e Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Thu, 2 Sep 2021 17:17:50 -0400 +Subject: [PATCH 17/17] Conditionalize test for PR libstdc++/71181 on + __LIBSTDCXX_SO_VERSION >= 7 + +This test was added upstream 2016-06-20 as part of: + re PR libstdc++/71181 (Reserving in unordered_map doesn't reserve enough) + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=29dbb034cb3199167a9d0aaed040733c72326eed + +but fails when run in DTS against a system libstdc++.so from an older GCC. +--- + .../testsuite/23_containers/unordered_set/hash_policy/71181.cc | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/71181.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/71181.cc +index 324d735b8..b2dcd0137 100644 +--- a/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/71181.cc ++++ b/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/71181.cc +@@ -39,7 +39,10 @@ template + + us.insert(nb_insert); + ++ // Fixed upstream in GCC 7 ++#if __LIBSTDCXX_SO_VERSION >= 7 + VERIFY( us.bucket_count() == bkts ); ++#endif + } + } + +-- +2.31.1 + diff --git a/SOURCES/gcc11-Wbidi-chars.patch b/SOURCES/gcc11-Wbidi-chars.patch new file mode 100644 index 0000000..c2b4211 --- /dev/null +++ b/SOURCES/gcc11-Wbidi-chars.patch @@ -0,0 +1,1721 @@ +commit 51c500269bf53749b107807d84271385fad35628 +Author: Marek Polacek +Date: Wed Oct 6 14:33:59 2021 -0400 + + libcpp: Implement -Wbidi-chars for CVE-2021-42574 [PR103026] + + From a link below: + "An issue was discovered in the Bidirectional Algorithm in the Unicode + Specification through 14.0. It permits the visual reordering of + characters via control sequences, which can be used to craft source code + that renders different logic than the logical ordering of tokens + ingested by compilers and interpreters. Adversaries can leverage this to + encode source code for compilers accepting Unicode such that targeted + vulnerabilities are introduced invisibly to human reviewers." + + More info: + https://nvd.nist.gov/vuln/detail/CVE-2021-42574 + https://trojansource.codes/ + + This is not a compiler bug. However, to mitigate the problem, this patch + implements -Wbidi-chars=[none|unpaired|any] to warn about possibly + misleading Unicode bidirectional control characters the preprocessor may + encounter. + + The default is =unpaired, which warns about improperly terminated + bidirectional control characters; e.g. a LRE without its corresponding PDF. + The level =any warns about any use of bidirectional control characters. + + This patch handles both UCNs and UTF-8 characters. UCNs designating + bidi characters in identifiers are accepted since r204886. Then r217144 + enabled -fextended-identifiers by default. Extended characters in C/C++ + identifiers have been accepted since r275979. However, this patch still + warns about mixing UTF-8 and UCN bidi characters; there seems to be no + good reason to allow mixing them. + + We warn in different contexts: comments (both C and C++-style), string + literals, character constants, and identifiers. Expectedly, UCNs are ignored + in comments and raw string literals. The bidirectional control characters + can nest so this patch handles that as well. + + I have not included nor tested this at all with Fortran (which also has + string literals and line comments). + + Dave M. posted patches improving diagnostic involving Unicode characters. + This patch does not make use of this new infrastructure yet. + + PR preprocessor/103026 + + gcc/c-family/ChangeLog: + + * c.opt (Wbidi-chars, Wbidi-chars=): New option. + + gcc/ChangeLog: + + * doc/invoke.texi: Document -Wbidi-chars. + + libcpp/ChangeLog: + + * include/cpplib.h (enum cpp_bidirectional_level): New. + (struct cpp_options): Add cpp_warn_bidirectional. + (enum cpp_warning_reason): Add CPP_W_BIDIRECTIONAL. + * internal.h (struct cpp_reader): Add warn_bidi_p member + function. + * init.c (cpp_create_reader): Set cpp_warn_bidirectional. + * lex.c (bidi): New namespace. + (get_bidi_utf8): New function. + (get_bidi_ucn): Likewise. + (maybe_warn_bidi_on_close): Likewise. + (maybe_warn_bidi_on_char): Likewise. + (_cpp_skip_block_comment): Implement warning about bidirectional + control characters. + (skip_line_comment): Likewise. + (forms_identifier_p): Likewise. + (lex_identifier): Likewise. + (lex_string): Likewise. + (lex_raw_string): Likewise. + + gcc/testsuite/ChangeLog: + + * c-c++-common/Wbidi-chars-1.c: New test. + * c-c++-common/Wbidi-chars-2.c: New test. + * c-c++-common/Wbidi-chars-3.c: New test. + * c-c++-common/Wbidi-chars-4.c: New test. + * c-c++-common/Wbidi-chars-5.c: New test. + * c-c++-common/Wbidi-chars-6.c: New test. + * c-c++-common/Wbidi-chars-7.c: New test. + * c-c++-common/Wbidi-chars-8.c: New test. + * c-c++-common/Wbidi-chars-9.c: New test. + * c-c++-common/Wbidi-chars-10.c: New test. + * c-c++-common/Wbidi-chars-11.c: New test. + * c-c++-common/Wbidi-chars-12.c: New test. + * c-c++-common/Wbidi-chars-13.c: New test. + * c-c++-common/Wbidi-chars-14.c: New test. + * c-c++-common/Wbidi-chars-15.c: New test. + * c-c++-common/Wbidi-chars-16.c: New test. + * c-c++-common/Wbidi-chars-17.c: New test. + +diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt +index 8a4cd634f77..3976fc368db 100644 +--- a/gcc/c-family/c.opt ++++ b/gcc/c-family/c.opt +@@ -374,6 +374,30 @@ Wbad-function-cast + C ObjC Var(warn_bad_function_cast) Warning + Warn about casting functions to incompatible types. + ++Wbidi-chars ++C ObjC C++ ObjC++ Warning Alias(Wbidi-chars=,any,none) ++; ++ ++Wbidi-chars= ++C ObjC C++ ObjC++ RejectNegative Joined Warning CPP(cpp_warn_bidirectional) CppReason(CPP_W_BIDIRECTIONAL) Var(warn_bidirectional) Init(bidirectional_unpaired) Enum(cpp_bidirectional_level) ++-Wbidi-chars=[none|unpaired|any] Warn about UTF-8 bidirectional control characters. ++ ++; Required for these enum values. ++SourceInclude ++cpplib.h ++ ++Enum ++Name(cpp_bidirectional_level) Type(int) UnknownError(argument %qs to %<-Wbidi-chars%> not recognized) ++ ++EnumValue ++Enum(cpp_bidirectional_level) String(none) Value(bidirectional_none) ++ ++EnumValue ++Enum(cpp_bidirectional_level) String(unpaired) Value(bidirectional_unpaired) ++ ++EnumValue ++Enum(cpp_bidirectional_level) String(any) Value(bidirectional_any) ++ + Wbool-compare + 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 6070288856c..a22758d18ee 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -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 + -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= ++@opindex Wbidi-chars ++@opindex Wno-bidi-chars ++Warn about possibly misleading UTF-8 bidirectional control characters in ++comments, string literals, character constants, and identifiers. Such ++characters can change left-to-right writing direction into right-to-left ++(and vice versa), which can cause confusion between the logical order and ++visual order. This may be dangerous; for instance, it may seem that a piece ++of code is not commented out, whereas it in fact is. ++ ++There are three levels of warning supported by GCC@. The default is ++@option{-Wbidi-chars=unpaired}, which warns about improperly terminated ++bidi contexts. @option{-Wbidi-chars=none} turns the warning off. ++@option{-Wbidi-chars=any} warns about any use of bidirectional control ++characters. ++ + @item -Wbool-compare + @opindex Wno-bool-compare + @opindex Wbool-compare +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-1.c b/gcc/testsuite/c-c++-common/Wbidi-chars-1.c +new file mode 100644 +index 00000000000..34f5ac19271 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-1.c +@@ -0,0 +1,12 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++ ++int main() { ++ int isAdmin = 0; ++ /*‮ } ⁦if (isAdmin)⁩ ⁦ begin admins only */ ++/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ ++ __builtin_printf("You are an admin.\n"); ++ /* end admins only ‮ { ⁦*/ ++/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ ++ return 0; ++} +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-10.c b/gcc/testsuite/c-c++-common/Wbidi-chars-10.c +new file mode 100644 +index 00000000000..3f851b69e65 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-10.c +@@ -0,0 +1,27 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++/* { dg-options "-Wbidi-chars=unpaired" } */ ++/* More nesting testing. */ ++ ++/* RLE‫ LRI⁦ PDF‬ PDI⁩*/ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int LRE_\u202a_PDF_\u202c; ++int LRE_\u202a_PDF_\u202c_LRE_\u202a_PDF_\u202c; ++int LRE_\u202a_LRI_\u2066_PDF_\u202c_PDI_\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int RLE_\u202b_RLI_\u2067_PDF_\u202c_PDI_\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int RLE_\u202b_RLI_\u2067_PDI_\u2069_PDF_\u202c; ++int FSI_\u2068_LRO_\u202d_PDI_\u2069_PDF_\u202c; ++int FSI_\u2068; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int FSI_\u2068_PDI_\u2069; ++int FSI_\u2068_FSI_\u2068_PDI_\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069; ++int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDF_\u202c; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_FSI_\u2068_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069; ++/* { 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..270ce2368a9 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-11.c +@@ -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_‬"; ++/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */ +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-12.c b/gcc/testsuite/c-c++-common/Wbidi-chars-12.c +new file mode 100644 +index 00000000000..b07eec1da91 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-12.c +@@ -0,0 +1,19 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile { target { c || c++11 } } } */ ++/* { dg-options "-Wbidi-chars=any" } */ ++/* Test raw strings. */ ++ ++const char *s1 = R"(a b c LRE‪ 1 2 3 PDF‬ x y z)"; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++const char *s2 = R"(a b c RLE‫ 1 2 3 PDF‬ x y z)"; ++/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ ++const char *s3 = R"(a b c LRO‭ 1 2 3 PDF‬ x y z)"; ++/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ ++const char *s4 = R"(a b c RLO‮ 1 2 3 PDF‬ x y z)"; ++/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ ++const char *s7 = R"(a b c FSI⁨ 1 2 3 PDI⁩ x y) z"; ++/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ ++const char *s8 = R"(a b c PDI⁩ x y )z"; ++/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ ++const char *s9 = R"(a b c PDF‬ x y z)"; ++/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-13.c b/gcc/testsuite/c-c++-common/Wbidi-chars-13.c +new file mode 100644 +index 00000000000..b2dd9fde752 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-13.c +@@ -0,0 +1,17 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile { target { c || c++11 } } } */ ++/* { dg-options "-Wbidi-chars=unpaired" } */ ++/* Test raw strings. */ ++ ++const char *s1 = R"(a b c LRE‪ 1 2 3)"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++const char *s2 = R"(a b c RLE‫ 1 2 3)"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++const char *s3 = R"(a b c LRO‭ 1 2 3)"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++const char *s4 = R"(a b c FSI⁨ 1 2 3)"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++const char *s5 = R"(a b c LRI⁦ 1 2 3)"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++const char *s6 = R"(a b c RLI⁧ 1 2 3)"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-14.c b/gcc/testsuite/c-c++-common/Wbidi-chars-14.c +new file mode 100644 +index 00000000000..ba5f75d9553 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-14.c +@@ -0,0 +1,38 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++/* { dg-options "-Wbidi-chars=unpaired" } */ ++/* Test PDI handling, which also pops any subsequent LREs, RLEs, LROs, ++ or RLOs. */ ++ ++/* LRI_⁦_LRI_⁦_RLE_‫_RLE_‫_RLE_‫_PDI_⁩*/ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++// LRI_⁦_RLE_‫_RLE_‫_RLE_‫_PDI_⁩ ++// LRI_⁦_RLO_‮_RLE_‫_RLE_‫_PDI_⁩ ++// LRI_⁦_RLO_‮_RLE_‫_PDI_⁩ ++// FSI_⁨_RLO_‮_PDI_⁩ ++// FSI_⁨_FSI_⁨_RLO_‮_PDI_⁩ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ ++int LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069_PDI_\u2069; ++int LRI_\u2066_LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069_PDI_\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int PDI_\u2069; ++int LRI_\u2066_PDI_\u2069; ++int RLI_\u2067_PDI_\u2069; ++int LRE_\u202a_LRI_\u2066_PDI_\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int LRI_\u2066_LRE_\u202a_PDF_\u202c_PDI_\u2069; ++int LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069; ++int RLI_\u2067_LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int FSI_\u2068_LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int RLO_\u202e_PDI_\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int RLI_\u2067_PDI_\u2069_RLI_\u2067; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int FSI_\u2068_PDF_\u202c_PDI_\u2069; ++int FSI_\u2068_FSI_\u2068_PDF_\u202c_PDI_\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-15.c b/gcc/testsuite/c-c++-common/Wbidi-chars-15.c +new file mode 100644 +index 00000000000..a0ce8ff5e2c +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-15.c +@@ -0,0 +1,59 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++/* { dg-options "-Wbidi-chars=unpaired" } */ ++/* Test unpaired bidi control chars in multiline comments. */ ++ ++/* ++ * LRE‪ end ++ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++/* ++ * RLE‫ end ++ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++/* ++ * LRO‭ end ++ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++/* ++ * RLO‮ end ++ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++/* ++ * LRI⁦ end ++ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++/* ++ * RLI⁧ end ++ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++/* ++ * FSI⁨ end ++ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++/* LRE‪ ++ PDF‬ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++/* FSI⁨ ++ PDI⁩ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++ ++/* LRE<‪> ++ * ++ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-3 } */ ++ ++/* ++ * LRE<‪> ++ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++ ++/* ++ * ++ * LRE<‪> */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ ++/* RLI<⁧> */ /* PDI<⁩> */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* LRE<‪> */ /* PDF<‬> */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-16.c b/gcc/testsuite/c-c++-common/Wbidi-chars-16.c +new file mode 100644 +index 00000000000..baa0159861c +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-16.c +@@ -0,0 +1,26 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++/* { dg-options "-Wbidi-chars=any" } */ ++/* Test LTR/RTL chars. */ ++ ++/* LTR<‎> */ ++/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */ ++// LTR<‎> ++/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */ ++/* RTL<‏> */ ++/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */ ++// RTL<‏> ++/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */ ++ ++const char *s1 = "LTR<‎>"; ++/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */ ++const char *s2 = "LTR\u200e"; ++/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */ ++const char *s3 = "LTR\u200E"; ++/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */ ++const char *s4 = "RTL<‏>"; ++/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */ ++const char *s5 = "RTL\u200f"; ++/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */ ++const char *s6 = "RTL\u200F"; ++/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */ +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-17.c b/gcc/testsuite/c-c++-common/Wbidi-chars-17.c +new file mode 100644 +index 00000000000..07cb4321f96 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-17.c +@@ -0,0 +1,30 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++/* { dg-options "-Wbidi-chars=unpaired" } */ ++/* Test LTR/RTL chars. */ ++ ++/* LTR<‎> */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++// LTR<‎> ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++/* RTL<‏> */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++// RTL<‏> ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int ltr_\u200e; ++/* { dg-error "universal character " "" { target *-*-* } .-1 } */ ++int rtl_\u200f; ++/* { dg-error "universal character " "" { target *-*-* } .-1 } */ ++ ++const char *s1 = "LTR<‎>"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++const char *s2 = "LTR\u200e"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++const char *s3 = "LTR\u200E"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++const char *s4 = "RTL<‏>"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++const char *s5 = "RTL\u200f"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++const char *s6 = "RTL\u200F"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-2.c b/gcc/testsuite/c-c++-common/Wbidi-chars-2.c +new file mode 100644 +index 00000000000..2340374f276 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-2.c +@@ -0,0 +1,9 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++ ++int main() { ++ /* Say hello; newline⁧/*/ return 0 ; ++/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ ++ __builtin_printf("Hello world.\n"); ++ return 0; ++} +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-3.c b/gcc/testsuite/c-c++-common/Wbidi-chars-3.c +new file mode 100644 +index 00000000000..9dc7edb6e64 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-3.c +@@ -0,0 +1,11 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++ ++int main() { ++ const char* access_level = "user"; ++ if (__builtin_strcmp(access_level, "user‮ ⁦// Check if admin⁩ ⁦")) { ++/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ ++ __builtin_printf("You are an admin.\n"); ++ } ++ return 0; ++} +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..639e5c62e88 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-4.c +@@ -0,0 +1,188 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++/* { dg-options "-Wbidi-chars=any -Wno-multichar -Wno-overflow" } */ ++/* Test all bidi chars in various contexts (identifiers, comments, ++ string literals, character constants), both UCN and UTF-8. The bidi ++ chars here are properly terminated, except for the character constants. */ ++ ++/* a b c LRE‪ 1 2 3 PDF‬ x y z */ ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++/* a b c RLE‫ 1 2 3 PDF‬ x y z */ ++/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ ++/* a b c LRO‭ 1 2 3 PDF‬ x y z */ ++/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ ++/* a b c RLO‮ 1 2 3 PDF‬ x y z */ ++/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ ++/* a b c LRI⁦ 1 2 3 PDI⁩ x y z */ ++/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ ++/* a b c RLI⁧ 1 2 3 PDI⁩ x y */ ++/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ ++/* a b c FSI⁨ 1 2 3 PDI⁩ x y z */ ++/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ ++ ++/* Same but C++ comments instead. */ ++// a b c LRE‪ 1 2 3 PDF‬ x y z ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++// a b c RLE‫ 1 2 3 PDF‬ x y z ++/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ ++// a b c LRO‭ 1 2 3 PDF‬ x y z ++/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ ++// a b c RLO‮ 1 2 3 PDF‬ x y z ++/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ ++// a b c LRI⁦ 1 2 3 PDI⁩ x y z ++/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ ++// a b c RLI⁧ 1 2 3 PDI⁩ x y ++/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ ++// a b c FSI⁨ 1 2 3 PDI⁩ x y z ++/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ ++ ++/* Here we're closing an unopened context, warn when =any. */ ++/* a b c PDI⁩ x y z */ ++/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ ++/* a b c PDF‬ x y z */ ++/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ ++// a b c PDI⁩ x y z ++/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ ++// a b c PDF‬ x y z ++/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ ++ ++/* Multiline comments. */ ++/* a b c PDI⁩ x y z ++ */ ++/* { dg-warning "U\\+2069" "" { target *-*-* } .-2 } */ ++/* a b c PDF‬ x y z ++ */ ++/* { dg-warning "U\\+202C" "" { target *-*-* } .-2 } */ ++/* first ++ a b c PDI⁩ x y z ++ */ ++/* { dg-warning "U\\+2069" "" { target *-*-* } .-2 } */ ++/* first ++ a b c PDF‬ x y z ++ */ ++/* { dg-warning "U\\+202C" "" { target *-*-* } .-2 } */ ++/* first ++ a b c PDI⁩ x y z */ ++/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ ++/* first ++ a b c PDF‬ x y z */ ++/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ ++ ++void ++g1 () ++{ ++ const char *s1 = "a b c LRE‪ 1 2 3 PDF‬ x y z"; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++ const char *s2 = "a b c RLE‫ 1 2 3 PDF‬ x y z"; ++/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ ++ const char *s3 = "a b c LRO‭ 1 2 3 PDF‬ x y z"; ++/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ ++ const char *s4 = "a b c RLO‮ 1 2 3 PDF‬ x y z"; ++/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ ++ const char *s5 = "a b c LRI⁦ 1 2 3 PDI⁩ x y z"; ++/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ ++ const char *s6 = "a b c RLI⁧ 1 2 3 PDI⁩ x y z"; ++/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ ++ const char *s7 = "a b c FSI⁨ 1 2 3 PDI⁩ x y z"; ++/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ ++ const char *s8 = "a b c PDI⁩ x y z"; ++/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ ++ const char *s9 = "a b c PDF‬ x y z"; ++/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ ++ ++ const char *s10 = "a b c LRE\u202a 1 2 3 PDF\u202c x y z"; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++ const char *s11 = "a b c LRE\u202A 1 2 3 PDF\u202c x y z"; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++ const char *s12 = "a b c RLE\u202b 1 2 3 PDF\u202c x y z"; ++/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ ++ const char *s13 = "a b c RLE\u202B 1 2 3 PDF\u202c x y z"; ++/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ ++ const char *s14 = "a b c LRO\u202d 1 2 3 PDF\u202c x y z"; ++/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ ++ const char *s15 = "a b c LRO\u202D 1 2 3 PDF\u202c x y z"; ++/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ ++ const char *s16 = "a b c RLO\u202e 1 2 3 PDF\u202c x y z"; ++/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ ++ const char *s17 = "a b c RLO\u202E 1 2 3 PDF\u202c x y z"; ++/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ ++ const char *s18 = "a b c LRI\u2066 1 2 3 PDI\u2069 x y z"; ++/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ ++ const char *s19 = "a b c RLI\u2067 1 2 3 PDI\u2069 x y z"; ++/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ ++ const char *s20 = "a b c FSI\u2068 1 2 3 PDI\u2069 x y z"; ++/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ ++} ++ ++void ++g2 () ++{ ++ const char c1 = '\u202a'; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++ const char c2 = '\u202A'; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++ const char c3 = '\u202b'; ++/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ ++ const char c4 = '\u202B'; ++/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ ++ const char c5 = '\u202d'; ++/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ ++ const char c6 = '\u202D'; ++/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ ++ const char c7 = '\u202e'; ++/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ ++ const char c8 = '\u202E'; ++/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ ++ const char c9 = '\u2066'; ++/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ ++ const char c10 = '\u2067'; ++/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ ++ const char c11 = '\u2068'; ++/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ ++} ++ ++int a‪b‬c; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++int a‫b‬c; ++/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ ++int a‭b‬c; ++/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ ++int a‮b‬c; ++/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ ++int a⁦b⁩c; ++/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ ++int a⁧b⁩c; ++/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ ++int a⁨b⁩c; ++/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ ++int A‬X; ++/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ ++int A\u202cY; ++/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ ++int A\u202CY2; ++/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ ++ ++int d\u202ae\u202cf; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++int d\u202Ae\u202cf2; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++int d\u202be\u202cf; ++/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ ++int d\u202Be\u202cf2; ++/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ ++int d\u202de\u202cf; ++/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ ++int d\u202De\u202cf2; ++/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ ++int d\u202ee\u202cf; ++/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ ++int d\u202Ee\u202cf2; ++/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ ++int d\u2066e\u2069f; ++/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ ++int d\u2067e\u2069f; ++/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ ++int d\u2068e\u2069f; ++/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ ++int X\u2069; ++/* { 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..68cb053144b +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-5.c +@@ -0,0 +1,188 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++/* { dg-options "-Wbidi-chars=unpaired -Wno-multichar -Wno-overflow" } */ ++/* Test all bidi chars in various contexts (identifiers, comments, ++ string literals, character constants), both UCN and UTF-8. The bidi ++ chars here are properly terminated, except for the character constants. */ ++ ++/* a b c LRE‪ 1 2 3 PDF‬ x y z */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c RLE‫ 1 2 3 PDF‬ x y z */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c LRO‭ 1 2 3 PDF‬ x y z */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c RLO‮ 1 2 3 PDF‬ x y z */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c LRI⁦ 1 2 3 PDI⁩ x y z */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c RLI⁧ 1 2 3 PDI⁩ x y */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c FSI⁨ 1 2 3 PDI⁩ x y z */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ ++/* Same but C++ comments instead. */ ++// a b c LRE‪ 1 2 3 PDF‬ x y z ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++// a b c RLE‫ 1 2 3 PDF‬ x y z ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++// a b c LRO‭ 1 2 3 PDF‬ x y z ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++// a b c RLO‮ 1 2 3 PDF‬ x y z ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++// a b c LRI⁦ 1 2 3 PDI⁩ x y z ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++// a b c RLI⁧ 1 2 3 PDI⁩ x y ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++// a b c FSI⁨ 1 2 3 PDI⁩ x y z ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ ++/* Here we're closing an unopened context, warn when =any. */ ++/* a b c PDI⁩ x y z */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c PDF‬ x y z */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++// a b c PDI⁩ x y z ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++// a b c PDF‬ x y z ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ ++/* Multiline comments. */ ++/* a b c PDI⁩ x y z ++ */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */ ++/* a b c PDF‬ x y z ++ */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */ ++/* first ++ a b c PDI⁩ x y z ++ */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */ ++/* first ++ a b c PDF‬ x y z ++ */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */ ++/* first ++ a b c PDI⁩ x y z */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++/* first ++ a b c PDF‬ x y z */ ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ ++void ++g1 () ++{ ++ const char *s1 = "a b c LRE‪ 1 2 3 PDF‬ x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s2 = "a b c RLE‫ 1 2 3 PDF‬ x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s3 = "a b c LRO‭ 1 2 3 PDF‬ x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s4 = "a b c RLO‮ 1 2 3 PDF‬ x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s5 = "a b c LRI⁦ 1 2 3 PDI⁩ x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s6 = "a b c RLI⁧ 1 2 3 PDI⁩ x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s7 = "a b c FSI⁨ 1 2 3 PDI⁩ x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s8 = "a b c PDI⁩ x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s9 = "a b c PDF‬ x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ ++ const char *s10 = "a b c LRE\u202a 1 2 3 PDF\u202c x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s11 = "a b c LRE\u202A 1 2 3 PDF\u202c x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s12 = "a b c RLE\u202b 1 2 3 PDF\u202c x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s13 = "a b c RLE\u202B 1 2 3 PDF\u202c x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s14 = "a b c LRO\u202d 1 2 3 PDF\u202c x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s15 = "a b c LRO\u202D 1 2 3 PDF\u202c x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s16 = "a b c RLO\u202e 1 2 3 PDF\u202c x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s17 = "a b c RLO\u202E 1 2 3 PDF\u202c x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s18 = "a b c LRI\u2066 1 2 3 PDI\u2069 x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s19 = "a b c RLI\u2067 1 2 3 PDI\u2069 x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s20 = "a b c FSI\u2068 1 2 3 PDI\u2069 x y z"; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++} ++ ++void ++g2 () ++{ ++ const char c1 = '\u202a'; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char c2 = '\u202A'; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char c3 = '\u202b'; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char c4 = '\u202B'; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char c5 = '\u202d'; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char c6 = '\u202D'; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char c7 = '\u202e'; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char c8 = '\u202E'; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char c9 = '\u2066'; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char c10 = '\u2067'; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char c11 = '\u2068'; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++} ++ ++int a‪b‬c; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int a‫b‬c; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int a‭b‬c; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int a‮b‬c; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int a⁦b⁩c; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int a⁧b⁩c; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int a⁨b⁩c; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int A‬X; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int A\u202cY; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int A\u202CY2; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++ ++int d\u202ae\u202cf; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int d\u202Ae\u202cf2; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int d\u202be\u202cf; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int d\u202Be\u202cf2; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int d\u202de\u202cf; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int d\u202De\u202cf2; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int d\u202ee\u202cf; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int d\u202Ee\u202cf2; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int d\u2066e\u2069f; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int d\u2067e\u2069f; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int d\u2068e\u2069f; ++/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ ++int X\u2069; ++/* { 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..0ce6fff2dee +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-6.c +@@ -0,0 +1,155 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++/* { dg-options "-Wbidi-chars=unpaired" } */ ++/* Test nesting of bidi chars in various contexts. */ ++ ++/* Terminated by the wrong char: */ ++/* a b c LRE‪ 1 2 3 PDI⁩ x y z */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c RLE‫ 1 2 3 PDI⁩ x y z*/ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c LRO‭ 1 2 3 PDI⁩ x y z */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c RLO‮ 1 2 3 PDI⁩ x y z */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c LRI⁦ 1 2 3 PDF‬ x y z */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c RLI⁧ 1 2 3 PDF‬ x y z */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* a b c FSI⁨ 1 2 3 PDF‬ x y z*/ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ ++/* LRE‪ PDF‬ */ ++/* LRE‪ LRE‪ PDF‬ PDF‬ */ ++/* PDF‬ LRE‪ PDF‬ */ ++/* LRE‪ PDF‬ LRE‪ PDF‬ */ ++/* LRE‪ LRE‪ PDF‬ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* PDF‬ LRE‪ */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ ++// a b c LRE‪ 1 2 3 PDI⁩ x y z ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++// a b c RLE‫ 1 2 3 PDI⁩ x y z*/ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++// a b c LRO‭ 1 2 3 PDI⁩ x y z ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++// a b c RLO‮ 1 2 3 PDI⁩ x y z ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++// a b c LRI⁦ 1 2 3 PDF‬ x y z ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++// a b c RLI⁧ 1 2 3 PDF‬ x y z ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++// a b c FSI⁨ 1 2 3 PDF‬ x y z ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ ++// LRE‪ PDF‬ ++// LRE‪ LRE‪ PDF‬ PDF‬ ++// PDF‬ LRE‪ PDF‬ ++// LRE‪ PDF‬ LRE‪ PDF‬ ++// LRE‪ LRE‪ PDF‬ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++// PDF‬ LRE‪ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ ++void ++g1 () ++{ ++ const char *s1 = "a b c LRE‪ 1 2 3 PDI⁩ x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s2 = "a b c LRE\u202a 1 2 3 PDI\u2069 x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s3 = "a b c RLE‫ 1 2 3 PDI⁩ x y "; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s4 = "a b c RLE\u202b 1 2 3 PDI\u2069 x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s5 = "a b c LRO‭ 1 2 3 PDI⁩ x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s6 = "a b c LRO\u202d 1 2 3 PDI\u2069 x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s7 = "a b c RLO‮ 1 2 3 PDI⁩ x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s8 = "a b c RLO\u202e 1 2 3 PDI\u2069 x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s9 = "a b c LRI⁦ 1 2 3 PDF‬ x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s10 = "a b c LRI\u2066 1 2 3 PDF\u202c x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s11 = "a b c RLI⁧ 1 2 3 PDF‬ x y z\ ++ "; ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++ const char *s12 = "a b c RLI\u2067 1 2 3 PDF\u202c x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s13 = "a b c FSI⁨ 1 2 3 PDF‬ x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s14 = "a b c FSI\u2068 1 2 3 PDF\u202c x y z"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s15 = "PDF‬ LRE‪"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s16 = "PDF\u202c LRE\u202a"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s17 = "LRE‪ PDF‬"; ++ const char *s18 = "LRE\u202a PDF\u202c"; ++ const char *s19 = "LRE‪ LRE‪ PDF‬ PDF‬"; ++ const char *s20 = "LRE\u202a LRE\u202a PDF\u202c PDF\u202c"; ++ const char *s21 = "PDF‬ LRE‪ PDF‬"; ++ const char *s22 = "PDF\u202c LRE\u202a PDF\u202c"; ++ const char *s23 = "LRE‪ LRE‪ PDF‬"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s24 = "LRE\u202a LRE\u202a PDF\u202c"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s25 = "PDF‬ LRE‪"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s26 = "PDF\u202c LRE\u202a"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s27 = "PDF‬ LRE\u202a"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ const char *s28 = "PDF\u202c LRE‪"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++} ++ ++int aLRE‪bPDI⁩; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int A\u202aB\u2069C; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int aRLE‫bPDI⁩; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int a\u202bB\u2069c; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int aLRO‭bPDI⁩; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int a\u202db\u2069c2; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int aRLO‮bPDI⁩; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int a\u202eb\u2069; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int aLRI⁦bPDF‬; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int a\u2066b\u202c; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int aRLI⁧bPDF‬c ++; ++/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ ++int a\u2067b\u202c; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int aFSI⁨bPDF‬; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int a\u2068b\u202c; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int aFSI⁨bPD\u202C; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int aFSI\u2068bPDF‬_; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++int aLRE‪bPDF‬b; ++int A\u202aB\u202c; ++int a_LRE‪_LRE‪_b_PDF‬_PDF‬; ++int A\u202aA\u202aB\u202cB\u202c; ++int aPDF‬bLREadPDF‬; ++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 +new file mode 100644 +index 00000000000..d012d420ec0 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-7.c +@@ -0,0 +1,9 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++/* { dg-options "-Wbidi-chars=any" } */ ++/* Test we ignore UCNs in comments. */ ++ ++// a b c \u202a 1 2 3 ++// a b c \u202A 1 2 3 ++/* a b c \u202a 1 2 3 */ ++/* a b c \u202A 1 2 3 */ +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-8.c b/gcc/testsuite/c-c++-common/Wbidi-chars-8.c +new file mode 100644 +index 00000000000..4f54c5092ec +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-8.c +@@ -0,0 +1,13 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++/* { dg-options "-Wbidi-chars=any" } */ ++/* Test \u vs \U. */ ++ ++int a_\u202A; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++int a_\u202a_2; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++int a_\U0000202A_3; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ ++int a_\U0000202a_4; ++/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ +diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-9.c b/gcc/testsuite/c-c++-common/Wbidi-chars-9.c +new file mode 100644 +index 00000000000..e2af1b1ca97 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/Wbidi-chars-9.c +@@ -0,0 +1,29 @@ ++/* PR preprocessor/103026 */ ++/* { dg-do compile } */ ++/* { dg-options "-Wbidi-chars=unpaired" } */ ++/* Test that we properly separate bidi contexts (comment/identifier/character ++ constant/string literal). */ ++ ++/* LRE ->‪<- */ int pdf_\u202c_1; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* RLE ->‫<- */ int pdf_\u202c_2; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* LRO ->‭<- */ int pdf_\u202c_3; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* RLO ->‮<- */ int pdf_\u202c_4; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* LRI ->⁦<-*/ int pdi_\u2069_1; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* RLI ->⁧<- */ int pdi_\u2069_12; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* FSI ->⁨<- */ int pdi_\u2069_3; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++ ++const char *s1 = "LRE\u202a"; /* PDF ->‬<- */ ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++/* LRE ->‪<- */ const char *s2 = "PDF\u202c"; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++const char *s3 = "LRE\u202a"; int pdf_\u202c_5; ++/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ ++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 176f8c5bbce..112b9c24751 100644 +--- a/libcpp/include/cpplib.h ++++ b/libcpp/include/cpplib.h +@@ -319,6 +319,17 @@ enum cpp_main_search + CMS_system, /* Search the system INCLUDE path. */ + }; + ++/* The possible bidirectional control characters checking levels, from least ++ restrictive to most. */ ++enum cpp_bidirectional_level { ++ /* No checking. */ ++ bidirectional_none, ++ /* Only detect unpaired uses of bidirectional control characters. */ ++ bidirectional_unpaired, ++ /* Detect any use of bidirectional control characters. */ ++ bidirectional_any ++}; ++ + /* This structure is nested inside struct cpp_reader, and + carries all the options visible to the command line. */ + 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; + ++ /* Nonzero if bidirectional control characters checking is on. See enum ++ cpp_bidirectional_level. */ ++ unsigned char cpp_warn_bidirectional; ++ + /* Dependency generation. */ + struct + { +@@ -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 + }; + + /* Callback for header lookup for HEADER, which is the name of a +diff --git a/libcpp/init.c b/libcpp/init.c +index 5a424e23553..f9a8f5f088f 100644 +--- a/libcpp/init.c ++++ b/libcpp/init.c +@@ -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; ++ CPP_OPTION (pfile, cpp_warn_bidirectional) = bidirectional_unpaired; + + /* 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 8577cab6c83..0ce0246c5a2 100644 +--- a/libcpp/internal.h ++++ b/libcpp/internal.h +@@ -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. */ ++ bool warn_bidi_p () const ++ { ++ return CPP_OPTION (this, cpp_warn_bidirectional) != bidirectional_none; ++ } + }; + + /* Character classes. Based on the more primitive macros in safe-ctype.h. +diff --git a/libcpp/lex.c b/libcpp/lex.c +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) + } + } + ++namespace bidi { ++ 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. */ ++ 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 ++ represents a PDI context. The next bit is 1 if this context was open ++ by a bidi character written as a UCN, and 0 when it was UTF-8. */ ++ semi_embedded_vec vec; ++ ++ /* Close the whole comment/identifier/string literal/character constant ++ context. */ ++ void on_close () ++ { ++ vec.truncate (0); ++ } ++ ++ /* Pop the last element in the vector. */ ++ void pop () ++ { ++ unsigned int len = vec.count (); ++ gcc_checking_assert (len > 0); ++ vec.truncate (len - 1); ++ } ++ ++ /* Return the context of the Ith element. */ ++ kind ctx_at (unsigned int i) ++ { ++ return (vec[i] & 1) ? kind::PDF : kind::PDI; ++ } ++ ++ /* Return which context is currently opened. */ ++ kind current_ctx () ++ { ++ unsigned int len = vec.count (); ++ if (len == 0) ++ return kind::NONE; ++ return ctx_at (len - 1); ++ } ++ ++ /* Return true if the current context comes from a UCN origin, that is, ++ the bidi char which started this bidi context was written as a UCN. */ ++ bool current_ctx_ucn_p () ++ { ++ unsigned int len = vec.count (); ++ gcc_checking_assert (len > 0); ++ return (vec[len - 1] >> 1) & 1; ++ } ++ ++ /* We've read a bidi char, update the current vector as necessary. */ ++ void on_char (kind k, bool ucn_p) ++ { ++ switch (k) ++ { ++ case kind::LRE: ++ case kind::RLE: ++ case kind::LRO: ++ case kind::RLO: ++ vec.push (ucn_p ? 3u : 1u); ++ break; ++ 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 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 kind::PDI: ++ for (int i = vec.count () - 1; i >= 0; --i) ++ if (ctx_at (i) == kind::PDI) ++ { ++ vec.truncate (i); ++ break; ++ } ++ break; ++ case kind::LTR: ++ case kind::RTL: ++ /* These aren't popped by a PDF/PDI. */ ++ break; ++ [[likely]] case kind::NONE: ++ break; ++ default: ++ abort (); ++ } ++ } ++ ++ /* Return a descriptive string for K. */ ++ const char *to_str (kind k) ++ { ++ switch (k) ++ { ++ case kind::LRE: ++ return "U+202A (LEFT-TO-RIGHT EMBEDDING)"; ++ case kind::RLE: ++ return "U+202B (RIGHT-TO-LEFT EMBEDDING)"; ++ case kind::LRO: ++ return "U+202D (LEFT-TO-RIGHT OVERRIDE)"; ++ case kind::RLO: ++ return "U+202E (RIGHT-TO-LEFT OVERRIDE)"; ++ case kind::LRI: ++ return "U+2066 (LEFT-TO-RIGHT ISOLATE)"; ++ case kind::RLI: ++ return "U+2067 (RIGHT-TO-LEFT ISOLATE)"; ++ case kind::FSI: ++ return "U+2068 (FIRST STRONG ISOLATE)"; ++ case kind::PDF: ++ return "U+202C (POP DIRECTIONAL FORMATTING)"; ++ case kind::PDI: ++ return "U+2069 (POP DIRECTIONAL ISOLATE)"; ++ case kind::LTR: ++ return "U+200E (LEFT-TO-RIGHT MARK)"; ++ case kind::RTL: ++ return "U+200F (RIGHT-TO-LEFT MARK)"; ++ default: ++ abort (); ++ } ++ } ++} ++ ++/* Parse a sequence of 3 bytes starting with P and return its bidi code. */ ++ ++static bidi::kind ++get_bidi_utf8 (const unsigned char *const p) ++{ ++ gcc_checking_assert (p[0] == bidi::utf8_start); ++ ++ if (p[1] == 0x80) ++ switch (p[2]) ++ { ++ case 0xaa: ++ return bidi::kind::LRE; ++ case 0xab: ++ return bidi::kind::RLE; ++ case 0xac: ++ return bidi::kind::PDF; ++ case 0xad: ++ return bidi::kind::LRO; ++ case 0xae: ++ return bidi::kind::RLO; ++ case 0x8e: ++ return bidi::kind::LTR; ++ case 0x8f: ++ return bidi::kind::RTL; ++ default: ++ break; ++ } ++ else if (p[1] == 0x81) ++ switch (p[2]) ++ { ++ case 0xa6: ++ return bidi::kind::LRI; ++ case 0xa7: ++ return bidi::kind::RLI; ++ case 0xa8: ++ return bidi::kind::FSI; ++ case 0xa9: ++ return bidi::kind::PDI; ++ default: ++ break; ++ } ++ ++ return bidi::kind::NONE; ++} ++ ++/* Parse a UCN where P points just past \u or \U and return its bidi code. */ ++ ++static bidi::kind ++get_bidi_ucn (const unsigned char *p, bool is_U) ++{ ++ /* 6.4.3 Universal Character Names ++ \u hex-quad ++ \U hex-quad hex-quad ++ where \unnnn means \U0000nnnn. */ ++ ++ if (is_U) ++ { ++ if (p[0] != '0' || p[1] != '0' || p[2] != '0' || p[3] != '0') ++ 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::kind::NONE; ++ else if (p[2] == '2') ++ switch (p[3]) ++ { ++ case 'a': ++ case 'A': ++ return bidi::kind::LRE; ++ case 'b': ++ case 'B': ++ return bidi::kind::RLE; ++ case 'c': ++ case 'C': ++ return bidi::kind::PDF; ++ case 'd': ++ case 'D': ++ return bidi::kind::LRO; ++ case 'e': ++ case 'E': ++ return bidi::kind::RLO; ++ default: ++ break; ++ } ++ else if (p[2] == '6') ++ switch (p[3]) ++ { ++ case '6': ++ return bidi::kind::LRI; ++ case '7': ++ return bidi::kind::RLI; ++ case '8': ++ return bidi::kind::FSI; ++ case '9': ++ return bidi::kind::PDI; ++ default: ++ break; ++ } ++ else if (p[2] == '0') ++ switch (p[3]) ++ { ++ case 'e': ++ case 'E': ++ return bidi::kind::LTR; ++ case 'f': ++ case 'F': ++ return bidi::kind::RTL; ++ default: ++ break; ++ } ++ ++ return bidi::kind::NONE; ++} ++ ++/* We're closing a bidi context, that is, we've encountered a newline, ++ are closing a C-style comment, or are at the end of a string literal, ++ character constant, or identifier. Warn if this context was not ++ properly terminated by a PDI or PDF. P points to the last character ++ in this context. */ ++ ++static void ++maybe_warn_bidi_on_close (cpp_reader *pfile, const uchar *p) ++{ ++ if (CPP_OPTION (pfile, cpp_warn_bidirectional) == bidirectional_unpaired ++ && bidi::vec.count () > 0) ++ { ++ 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, ++ "unpaired UTF-8 bidirectional control character " ++ "detected"); ++ } ++ /* We're done with this context. */ ++ bidi::on_close (); ++} ++ ++/* We're at the beginning or in the middle of an identifier/comment/string ++ literal/character constant. Warn if we've encountered a bidi character. ++ KIND says which bidi character it was; P points to it in the character ++ stream. UCN_P is true iff this bidi character was written as a UCN. */ ++ ++static void ++maybe_warn_bidi_on_char (cpp_reader *pfile, const uchar *p, bidi::kind kind, ++ bool ucn_p) ++{ ++ if (__builtin_expect (kind == bidi::kind::NONE, 1)) ++ return; ++ ++ const auto warn_bidi = CPP_OPTION (pfile, cpp_warn_bidirectional); ++ ++ if (warn_bidi != bidirectional_none) ++ { ++ 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 ++ an opened context because we've already warned about the ++ opening character. Except warn when we have a UCN x UTF-8 ++ mismatch. */ ++ if (kind == bidi::current_ctx ()) ++ { ++ if (warn_bidi == bidirectional_unpaired ++ && bidi::current_ctx_ucn_p () != ucn_p) ++ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0, ++ "UTF-8 vs UCN mismatch when closing " ++ "a context by \"%s\"", bidi::to_str (kind)); ++ } ++ else if (warn_bidi == bidirectional_any) ++ { ++ 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)); ++ else ++ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0, ++ "found problematic Unicode character \"%s\"", ++ bidi::to_str (kind)); ++ } ++ } ++ /* We're done with this context. */ ++ bidi::on_char (kind, ucn_p); ++} ++ + /* Skip a C-style block comment. We find the end of the comment by + seeing if an asterisk is before every '/' we encounter. Returns + nonzero if comment terminated by EOF, zero otherwise. +@@ -1175,6 +1493,7 @@ _cpp_skip_block_comment (cpp_reader *pfile) + cpp_buffer *buffer = pfile->buffer; + const uchar *cur = buffer->cur; + uchar c; ++ const bool warn_bidi_p = pfile->warn_bidi_p (); + + cur++; + if (*cur == '/') +@@ -1189,7 +1508,11 @@ _cpp_skip_block_comment (cpp_reader *pfile) + if (c == '/') + { + if (cur[-2] == '*') +- break; ++ { ++ if (warn_bidi_p) ++ maybe_warn_bidi_on_close (pfile, cur); ++ break; ++ } + + /* Warn about potential nested comments, but not if the '/' + comes immediately before the true comment delimiter. +@@ -1208,6 +1531,8 @@ _cpp_skip_block_comment (cpp_reader *pfile) + { + unsigned int cols; + buffer->cur = cur - 1; ++ if (warn_bidi_p) ++ maybe_warn_bidi_on_close (pfile, cur); + _cpp_process_line_notes (pfile, true); + if (buffer->next_line >= buffer->rlimit) + return true; +@@ -1218,6 +1543,13 @@ _cpp_skip_block_comment (cpp_reader *pfile) + + cur = buffer->cur; + } ++ /* If this is a beginning of a UTF-8 encoding, it might be ++ a bidirectional control character. */ ++ else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p) ++ { ++ bidi::kind kind = get_bidi_utf8 (cur - 1); ++ maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/false); ++ } + } + + buffer->cur = cur; +@@ -1233,9 +1565,31 @@ skip_line_comment (cpp_reader *pfile) + { + cpp_buffer *buffer = pfile->buffer; + location_t orig_line = pfile->line_table->highest_line; ++ const bool warn_bidi_p = pfile->warn_bidi_p (); + +- while (*buffer->cur != '\n') +- buffer->cur++; ++ if (!warn_bidi_p) ++ while (*buffer->cur != '\n') ++ buffer->cur++; ++ else ++ { ++ while (*buffer->cur != '\n' ++ && *buffer->cur != bidi::utf8_start) ++ buffer->cur++; ++ if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0)) ++ { ++ while (*buffer->cur != '\n') ++ { ++ if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0)) ++ { ++ bidi::kind kind = get_bidi_utf8 (buffer->cur); ++ maybe_warn_bidi_on_char (pfile, buffer->cur, kind, ++ /*ucn_p=*/false); ++ } ++ buffer->cur++; ++ } ++ maybe_warn_bidi_on_close (pfile, buffer->cur); ++ } ++ } + + _cpp_process_line_notes (pfile, true); + return orig_line != pfile->line_table->highest_line; +@@ -1346,11 +1700,13 @@ static const cppchar_t utf8_signifier = 0xC0; + + /* Returns TRUE if the sequence starting at buffer->cur is valid in + an identifier. FIRST is TRUE if this starts an identifier. */ ++ + static bool + forms_identifier_p (cpp_reader *pfile, int first, + struct normalize_state *state) + { + cpp_buffer *buffer = pfile->buffer; ++ const bool warn_bidi_p = pfile->warn_bidi_p (); + + if (*buffer->cur == '$') + { +@@ -1373,6 +1729,13 @@ forms_identifier_p (cpp_reader *pfile, int first, + cppchar_t s; + 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); ++ const bool warn_bidi_p = pfile->warn_bidi_p (); + + cur = pfile->buffer->cur; + if (! 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)); ++ if (warn_bidi_p) ++ maybe_warn_bidi_on_close (pfile, pfile->buffer->cur); + result = _cpp_interpret_identifier (pfile, base, + pfile->buffer->cur - base); + *spelling = cpp_lookup (pfile, base, pfile->buffer->cur - base); +@@ -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 (); + + /* '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, pos - 1, get_bidi_utf8 (pos - 1), ++ /*ucn_p=*/false); + } + ++ if (warn_bidi_p) ++ 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 +@@ -2090,15 +2471,27 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) + else + terminator = '>', type = CPP_HEADER_NAME; + ++ const bool warn_bidi_p = pfile->warn_bidi_p (); + for (;;) + { + cppchar_t c = *cur++; + + /* In #include-style directives, terminators are not escapable. */ + if (c == '\\' && !pfile->state.angled_headers && *cur != '\n') +- cur++; ++ { ++ if ((cur[0] == 'u' || cur[0] == 'U') && warn_bidi_p) ++ { ++ bidi::kind kind = get_bidi_ucn (cur + 1, cur[0] == 'U'); ++ maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/true); ++ } ++ cur++; ++ } + else if (c == terminator) +- break; ++ { ++ if (warn_bidi_p) ++ maybe_warn_bidi_on_close (pfile, cur - 1); ++ break; ++ } + else if (c == '\n') + { + cur--; +@@ -2115,6 +2508,11 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) + } + else if (c == '\0') + saw_NUL = true; ++ else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p) ++ { ++ bidi::kind kind = get_bidi_utf8 (cur - 1); ++ maybe_warn_bidi_on_char (pfile, cur - 1, kind, /*ucn_p=*/false); ++ } + } + + if (saw_NUL && !pfile->state.skipping) diff --git a/SOURCES/gcc11-add-Wbidirectional.patch b/SOURCES/gcc11-add-Wbidirectional.patch deleted file mode 100644 index 3792984..0000000 --- a/SOURCES/gcc11-add-Wbidirectional.patch +++ /dev/null @@ -1,1443 +0,0 @@ -From a241a9b727f03afe62a161a2662a0f1192fd523a Mon Sep 17 00:00:00 2001 -From: Marek Polacek -Date: Wed, 6 Oct 2021 14:33:59 -0400 -Subject: [PATCH] cpp: Implement -Wbidirectional=[none|unpaired|any] - -This patch implements -Wbidirectional=[none|unpaired|any] to warn about -possibly dangerous bidirectional characters. - -gcc/c-family/ChangeLog: - - * c.opt (Wbidirectional, Wbidirectional=): New option. - -gcc/ChangeLog: - - * doc/invoke.texi: Document -Wbidirectional. - -libcpp/ChangeLog: - - * include/cpplib.h (enum cpp_bidirectional_level): New. - (struct cpp_options): Add cpp_warn_bidirectional. - (enum cpp_warning_reason): Add CPP_W_BIDIRECTIONAL. - * init.c (cpp_create_reader): Set cpp_warn_bidirectional. - * lex.c (bidi): New namespace. - (get_bidi_utf8): New function. - (get_bidi_ucn): Likewise. - (maybe_warn_bidi_on_close): Likewise. - (maybe_warn_bidi_on_char): Likewise. - (_cpp_skip_block_comment): Implement warning about bidirectional - characters. - (skip_line_comment): Likewise. - (forms_identifier_p): Likewise. - (lex_identifier): Likewise. - (lex_string): Likewise. - (lex_raw_string): Likewise. - -gcc/testsuite/ChangeLog: - - * c-c++-common/Wbidirectional-1.c: New test. - * c-c++-common/Wbidirectional-2.c: New test. - * c-c++-common/Wbidirectional-3.c: New test. - * c-c++-common/Wbidirectional-4.c: New test. - * c-c++-common/Wbidirectional-5.c: New test. - * c-c++-common/Wbidirectional-6.c: New test. - * c-c++-common/Wbidirectional-7.c: New test. - * c-c++-common/Wbidirectional-8.c: New test. - * c-c++-common/Wbidirectional-9.c: New test. - * c-c++-common/Wbidirectional-10.c: New test. - * c-c++-common/Wbidirectional-11.c: New test. - * c-c++-common/Wbidirectional-12.c: New test. - * c-c++-common/Wbidirectional-13.c: New test. ---- - gcc/c-family/c.opt | 24 ++ - gcc/doc/invoke.texi | 19 +- - gcc/testsuite/c-c++-common/Wbidirectional-1.c | 11 + - .../c-c++-common/Wbidirectional-10.c | 27 ++ - .../c-c++-common/Wbidirectional-11.c | 12 + - .../c-c++-common/Wbidirectional-12.c | 18 + - .../c-c++-common/Wbidirectional-13.c | 16 + - gcc/testsuite/c-c++-common/Wbidirectional-2.c | 8 + - gcc/testsuite/c-c++-common/Wbidirectional-3.c | 10 + - gcc/testsuite/c-c++-common/Wbidirectional-4.c | 165 ++++++++ - gcc/testsuite/c-c++-common/Wbidirectional-5.c | 165 ++++++++ - gcc/testsuite/c-c++-common/Wbidirectional-6.c | 154 +++++++ - gcc/testsuite/c-c++-common/Wbidirectional-7.c | 8 + - gcc/testsuite/c-c++-common/Wbidirectional-8.c | 12 + - gcc/testsuite/c-c++-common/Wbidirectional-9.c | 28 ++ - libcpp/include/cpplib.h | 18 +- - libcpp/init.c | 1 + - libcpp/lex.c | 391 +++++++++++++++++- - 18 files changed, 1072 insertions(+), 15 deletions(-) - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-1.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-10.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-11.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-12.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-13.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-2.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-3.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-4.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-5.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-6.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-7.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-8.c - create mode 100644 gcc/testsuite/c-c++-common/Wbidirectional-9.c - -diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt -index 06457ac739e..09391824676 100644 ---- a/gcc/c-family/c.opt -+++ b/gcc/c-family/c.opt -@@ -374,6 +374,30 @@ Wbad-function-cast - C ObjC Var(warn_bad_function_cast) Warning - Warn about casting functions to incompatible types. - -+Wbidirectional -+C ObjC C++ ObjC++ Warning Alias(Wbidirectional=,any,none) -+; -+ -+Wbidirectional= -+C ObjC C++ ObjC++ RejectNegative Joined Warning CPP(cpp_warn_bidirectional) CppReason(CPP_W_BIDIRECTIONAL) Var(warn_bidirectional) Init(bidirectional_unpaired) Enum(cpp_bidirectional_level) -+-Wbidirectional=[none|unpaired|any] Warn about UTF-8 bidirectional characters. -+ -+; Required for these enum values. -+SourceInclude -+cpplib.h -+ -+Enum -+Name(cpp_bidirectional_level) Type(int) UnknownError(argument %qs to %<-Wbidirectional%> not recognized) -+ -+EnumValue -+Enum(cpp_bidirectional_level) String(none) Value(bidirectional_none) -+ -+EnumValue -+Enum(cpp_bidirectional_level) String(unpaired) Value(bidirectional_unpaired) -+ -+EnumValue -+Enum(cpp_bidirectional_level) String(any) Value(bidirectional_any) -+ - Wbool-compare - 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 b64ec18ae46..e32858ce767 100644 ---- a/gcc/doc/invoke.texi -+++ b/gcc/doc/invoke.texi -@@ -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 -+-Wbidirectional=@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 - -Wc11-c2x-compat @gol -@@ -7557,6 +7559,21 @@ Attributes considered include @code{allo - This is the default. You can disable these warnings with either - @option{-Wno-attribute-alias} or @option{-Wattribute-alias=0}. - -+@item -Wbidirectional=@r{[}none@r{|}unpaired@r{|}any@r{]} -+@opindex Wbidirectional= -+@opindex Wbidirectional -+@opindex Wno-bidirectional -+Warn about UTF-8 bidirectional characters. Such characters can change -+left-to-right writing direction into right-to-left (and vice versa), -+which can cause confusion between the logical order and visual order. -+This may be dangerous; for instance, it may seem that a piece of code -+is not commented out, whereas it in fact is. -+ -+There are three levels of warning supported by GCC@. The default is -+@option{-Wbidirectional=unpaired}, which warns about improperly terminated -+bidi contexts. @option{-Wbidirectional=none} turns the warning off. -+@option{-Wbidirectional=any} warns about any use of bidirectional characters. -+ - @item -Wbool-compare - @opindex Wno-bool-compare - @opindex Wbool-compare -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-1.c b/gcc/testsuite/c-c++-common/Wbidirectional-1.c -new file mode 100644 -index 00000000000..750de81fdd8 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-1.c -@@ -0,0 +1,11 @@ -+/* { dg-do compile } */ -+ -+int main() { -+ int isAdmin = 0; -+ /*‮ } ⁦if (isAdmin)⁩ ⁦ begin admins only */ -+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ -+ __builtin_printf("You are an admin.\n"); -+ /* end admins only ‮ { ⁦*/ -+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ -+ return 0; -+} -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-10.c b/gcc/testsuite/c-c++-common/Wbidirectional-10.c -new file mode 100644 -index 00000000000..cd4abeeefbd ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-10.c -@@ -0,0 +1,27 @@ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidirectional=unpaired" } */ -+/* More nesting testing. */ -+ -+/* RLE‫ LRI⁦ PDF‬ PDI⁩*/ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int LRE_\u202a_PDF_\u202c; -+int LRE_\u202a_PDF_\u202c_LRE_\u202a_PDF_\u202c; -+int LRE_\u202a_LRI_\u2066_PDF_\u202c_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLE_\u202b_RLI_\u2067_PDF_\u202c_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLE_\u202b_RLI_\u2067_PDI_\u2069_PDF_\u202c; -+int FSI_\u2068_LRO_\u202d_PDI_\u2069_PDF_\u202c; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int FSI_\u2068; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int FSI_\u2068_PDI_\u2069; -+int FSI_\u2068_FSI_\u2068_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069; -+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDF_\u202c; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_FSI_\u2068_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-11.c b/gcc/testsuite/c-c++-common/Wbidirectional-11.c -new file mode 100644 -index 00000000000..43d699acc64 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-11.c -@@ -0,0 +1,12 @@ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidirectional=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_‬"; -+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-12.c b/gcc/testsuite/c-c++-common/Wbidirectional-12.c -new file mode 100644 -index 00000000000..20d1566401a ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-12.c -@@ -0,0 +1,18 @@ -+/* { dg-do compile { target { c || c++11 } } } */ -+/* { dg-options "-Wbidirectional=any" } */ -+/* Test raw strings. */ -+ -+const char *s1 = R"(a b c LRE‪ 1 2 3 PDF‬ x y z)"; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+const char *s2 = R"(a b c RLE‫ 1 2 3 PDF‬ x y z)"; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+const char *s3 = R"(a b c LRO‭ 1 2 3 PDF‬ x y z)"; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+const char *s4 = R"(a b c RLO‮ 1 2 3 PDF‬ x y z)"; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+const char *s7 = R"(a b c FSI⁨ 1 2 3 PDI⁩ x y) z"; -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+const char *s8 = R"(a b c PDI⁩ x y )z"; -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ -+const char *s9 = R"(a b c PDF‬ x y z)"; -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-13.c b/gcc/testsuite/c-c++-common/Wbidirectional-13.c -new file mode 100644 -index 00000000000..08010e3b37b ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-13.c -@@ -0,0 +1,16 @@ -+/* { dg-do compile { target { c || c++11 } } } */ -+/* { dg-options "-Wbidirectional=unpaired" } */ -+/* Test raw strings. */ -+ -+const char *s1 = R"(a b c LRE‪ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s2 = R"(a b c RLE‫ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s3 = R"(a b c LRO‭ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s4 = R"(a b c FSI⁨ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s5 = R"(a b c LRI⁦ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s6 = R"(a b c RLI⁧ 1 2 3)"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-2.c b/gcc/testsuite/c-c++-common/Wbidirectional-2.c -new file mode 100644 -index 00000000000..4e04202e058 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-2.c -@@ -0,0 +1,8 @@ -+/* { dg-do compile } */ -+ -+int main() { -+ /* Say hello; newline⁧/*/ return 0 ; -+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ -+ __builtin_printf("Hello world.\n"); -+ return 0; -+} -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-3.c b/gcc/testsuite/c-c++-common/Wbidirectional-3.c -new file mode 100644 -index 00000000000..921300e94e0 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-3.c -@@ -0,0 +1,10 @@ -+/* { dg-do compile } */ -+ -+int main() { -+ const char* access_level = "user"; -+ if (__builtin_strcmp(access_level, "user‮ ⁦// Check if admin⁩ ⁦")) { -+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */ -+ __builtin_printf("You are an admin.\n"); -+ } -+ return 0; -+} -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-4.c b/gcc/testsuite/c-c++-common/Wbidirectional-4.c -new file mode 100644 -index 00000000000..e6638aecc6a ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-4.c -@@ -0,0 +1,165 @@ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidirectional=any -Wno-multichar -Wno-overflow" } */ -+/* Test all bidi chars in various contexts (identifiers, comments, -+ string literals, character constants), both UCN and UTF-8. The bidi -+ chars here are properly terminated, except for the character constants. */ -+ -+/* a b c LRE‪ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+/* a b c RLE‫ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+/* a b c LRO‭ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+/* a b c RLO‮ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+/* a b c LRI⁦ 1 2 3 PDI⁩ x y z */ -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+/* a b c RLI⁧ 1 2 3 PDI⁩ x y */ -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+/* a b c FSI⁨ 1 2 3 PDI⁩ x y z */ -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+ -+/* Same but C++ comments instead. */ -+// a b c LRE‪ 1 2 3 PDF‬ x y z -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+// a b c RLE‫ 1 2 3 PDF‬ x y z -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+// a b c LRO‭ 1 2 3 PDF‬ x y z -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+// a b c RLO‮ 1 2 3 PDF‬ x y z -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+// a b c LRI⁦ 1 2 3 PDI⁩ x y z -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+// a b c RLI⁧ 1 2 3 PDI⁩ x y -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+// a b c FSI⁨ 1 2 3 PDI⁩ x y z -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+ -+/* Here we're closing an unopened context, warn when =any. */ -+/* a b c PDI⁩ x y z */ -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ -+/* a b c PDF‬ x y z */ -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+// a b c PDI⁩ x y z -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ -+// a b c PDF‬ x y z -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+ -+void -+g1 () -+{ -+ const char *s1 = "a b c LRE‪ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+ const char *s2 = "a b c RLE‫ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+ const char *s3 = "a b c LRO‭ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+ const char *s4 = "a b c RLO‮ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+ const char *s5 = "a b c LRI⁦ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+ const char *s6 = "a b c RLI⁧ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+ const char *s7 = "a b c FSI⁨ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+ const char *s8 = "a b c PDI⁩ x y z"; -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ -+ const char *s9 = "a b c PDF‬ x y z"; -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+ -+ const char *s10 = "a b c LRE\u202a 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+ const char *s11 = "a b c LRE\u202A 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+ const char *s12 = "a b c RLE\u202b 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+ const char *s13 = "a b c RLE\u202B 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+ const char *s14 = "a b c LRO\u202d 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+ const char *s15 = "a b c LRO\u202D 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+ const char *s16 = "a b c RLO\u202e 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+ const char *s17 = "a b c RLO\u202E 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+ const char *s18 = "a b c LRI\u2066 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+ const char *s19 = "a b c RLI\u2067 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+ const char *s20 = "a b c FSI\u2068 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+} -+ -+void -+g2 () -+{ -+ const char c1 = '\u202a'; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+ const char c2 = '\u202A'; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+ const char c3 = '\u202b'; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+ const char c4 = '\u202B'; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+ const char c5 = '\u202d'; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+ const char c6 = '\u202D'; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+ const char c7 = '\u202e'; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+ const char c8 = '\u202E'; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+ const char c9 = '\u2066'; -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+ const char c10 = '\u2067'; -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+ const char c11 = '\u2068'; -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+} -+ -+int a‪b‬c; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+int a‫b‬c; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+int a‭b‬c; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+int a‮b‬c; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+int a⁦b⁩c; -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+int a⁧b⁩c; -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+int a⁨b⁩c; -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+int A‬X; -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+int A\u202cY; -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+int A\u202CY2; -+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */ -+ -+int d\u202ae\u202cf; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+int d\u202Ae\u202cf2; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+int d\u202be\u202cf; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+int d\u202Be\u202cf2; -+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */ -+int d\u202de\u202cf; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+int d\u202De\u202cf2; -+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ -+int d\u202ee\u202cf; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+int d\u202Ee\u202cf2; -+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */ -+int d\u2066e\u2069f; -+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */ -+int d\u2067e\u2069f; -+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */ -+int d\u2068e\u2069f; -+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */ -+int X\u2069; -+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-5.c b/gcc/testsuite/c-c++-common/Wbidirectional-5.c -new file mode 100644 -index 00000000000..45d3402c941 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-5.c -@@ -0,0 +1,165 @@ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidirectional=unpaired -Wno-multichar -Wno-overflow" } */ -+/* Test all bidi chars in various contexts (identifiers, comments, -+ string literals, character constants), both UCN and UTF-8. The bidi -+ chars here are properly terminated, except for the character constants. */ -+ -+/* a b c LRE‪ 1 2 3 PDF‬ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLE‫ 1 2 3 PDF‬ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c LRO‭ 1 2 3 PDF‬ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLO‮ 1 2 3 PDF‬ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c LRI⁦ 1 2 3 PDI⁩ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLI⁧ 1 2 3 PDI⁩ x y */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c FSI⁨ 1 2 3 PDI⁩ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ -+/* Same but C++ comments instead. */ -+// a b c LRE‪ 1 2 3 PDF‬ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLE‫ 1 2 3 PDF‬ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c LRO‭ 1 2 3 PDF‬ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLO‮ 1 2 3 PDF‬ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c LRI⁦ 1 2 3 PDI⁩ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLI⁧ 1 2 3 PDI⁩ x y -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c FSI⁨ 1 2 3 PDI⁩ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ -+/* Here we're closing an unopened context, warn when =any. */ -+/* a b c PDI⁩ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c PDF‬ x y z */ -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c PDI⁩ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+// a b c PDF‬ x y z -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ -+void -+g1 () -+{ -+ const char *s1 = "a b c LRE‪ 1 2 3 PDF‬ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s2 = "a b c RLE‫ 1 2 3 PDF‬ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s3 = "a b c LRO‭ 1 2 3 PDF‬ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s4 = "a b c RLO‮ 1 2 3 PDF‬ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s5 = "a b c LRI⁦ 1 2 3 PDI⁩ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s6 = "a b c RLI⁧ 1 2 3 PDI⁩ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s7 = "a b c FSI⁨ 1 2 3 PDI⁩ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s8 = "a b c PDI⁩ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s9 = "a b c PDF‬ x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ -+ const char *s10 = "a b c LRE\u202a 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s11 = "a b c LRE\u202A 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s12 = "a b c RLE\u202b 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s13 = "a b c RLE\u202B 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s14 = "a b c LRO\u202d 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s15 = "a b c LRO\u202D 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s16 = "a b c RLO\u202e 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s17 = "a b c RLO\u202E 1 2 3 PDF\u202c x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s18 = "a b c LRI\u2066 1 2 3 PDI\u2069 x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s19 = "a b c RLI\u2067 1 2 3 PDI\u2069 x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s20 = "a b c FSI\u2068 1 2 3 PDI\u2069 x y z"; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+} -+ -+void -+g2 () -+{ -+ const char c1 = '\u202a'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c2 = '\u202A'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c3 = '\u202b'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c4 = '\u202B'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c5 = '\u202d'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c6 = '\u202D'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c7 = '\u202e'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c8 = '\u202E'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c9 = '\u2066'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c10 = '\u2067'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char c11 = '\u2068'; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+} -+ -+int a‪b‬c; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int a‫b‬c; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int a‭b‬c; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int a‮b‬c; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int a⁦b⁩c; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int a⁧b⁩c; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int a⁨b⁩c; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int A‬X; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int A\u202cY; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int A\u202CY2; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+ -+int d\u202ae\u202cf; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202Ae\u202cf2; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202be\u202cf; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202Be\u202cf2; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202de\u202cf; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202De\u202cf2; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202ee\u202cf; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u202Ee\u202cf2; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u2066e\u2069f; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u2067e\u2069f; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int d\u2068e\u2069f; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -+int X\u2069; -+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-6.c b/gcc/testsuite/c-c++-common/Wbidirectional-6.c -new file mode 100644 -index 00000000000..1be017f828d ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-6.c -@@ -0,0 +1,154 @@ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidirectional=unpaired" } */ -+/* Test nesting of bidi chars in various contexts. */ -+ -+/* Terminated by the wrong char: */ -+/* a b c LRE‪ 1 2 3 PDI⁩ x y z */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLE‫ 1 2 3 PDI⁩ x y z*/ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c LRO‭ 1 2 3 PDI⁩ x y z */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLO‮ 1 2 3 PDI⁩ x y z */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c LRI⁦ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c RLI⁧ 1 2 3 PDF‬ x y z */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* a b c FSI⁨ 1 2 3 PDF‬ x y z*/ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+/* LRE‪ PDF‬ */ -+/* LRE‪ LRE‪ PDF‬ PDF‬ */ -+/* PDF‬ LRE‪ PDF‬ */ -+/* LRE‪ PDF‬ LRE‪ PDF‬ */ -+/* LRE‪ LRE‪ PDF‬ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* PDF‬ LRE‪ */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+// a b c LRE‪ 1 2 3 PDI⁩ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLE‫ 1 2 3 PDI⁩ x y z*/ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c LRO‭ 1 2 3 PDI⁩ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLO‮ 1 2 3 PDI⁩ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c LRI⁦ 1 2 3 PDF‬ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c RLI⁧ 1 2 3 PDF‬ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// a b c FSI⁨ 1 2 3 PDF‬ x y z -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+// LRE‪ PDF‬ -+// LRE‪ LRE‪ PDF‬ PDF‬ -+// PDF‬ LRE‪ PDF‬ -+// LRE‪ PDF‬ LRE‪ PDF‬ -+// LRE‪ LRE‪ PDF‬ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+// PDF‬ LRE‪ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+void -+g1 () -+{ -+ const char *s1 = "a b c LRE‪ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s2 = "a b c LRE\u202a 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s3 = "a b c RLE‫ 1 2 3 PDI⁩ x y "; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s4 = "a b c RLE\u202b 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s5 = "a b c LRO‭ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s6 = "a b c LRO\u202d 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s7 = "a b c RLO‮ 1 2 3 PDI⁩ x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s8 = "a b c RLO\u202e 1 2 3 PDI\u2069 x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s9 = "a b c LRI⁦ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s10 = "a b c LRI\u2066 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s11 = "a b c RLI⁧ 1 2 3 PDF‬ x y z\ -+ "; -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+ const char *s12 = "a b c RLI\u2067 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s13 = "a b c FSI⁨ 1 2 3 PDF‬ x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s14 = "a b c FSI\u2068 1 2 3 PDF\u202c x y z"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s15 = "PDF‬ LRE‪"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s16 = "PDF\u202c LRE\u202a"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s17 = "LRE‪ PDF‬"; -+ const char *s18 = "LRE\u202a PDF\u202c"; -+ const char *s19 = "LRE‪ LRE‪ PDF‬ PDF‬"; -+ const char *s20 = "LRE\u202a LRE\u202a PDF\u202c PDF\u202c"; -+ const char *s21 = "PDF‬ LRE‪ PDF‬"; -+ const char *s22 = "PDF\u202c LRE\u202a PDF\u202c"; -+ const char *s23 = "LRE‪ LRE‪ PDF‬"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s24 = "LRE\u202a LRE\u202a PDF\u202c"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s25 = "PDF‬ LRE‪"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s26 = "PDF\u202c LRE\u202a"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s27 = "PDF‬ LRE\u202a"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ const char *s28 = "PDF\u202c LRE‪"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+} -+ -+int aLRE‪bPDI⁩; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int A\u202aB\u2069C; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int aRLE‫bPDI⁩; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int a\u202bB\u2069c; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int aLRO‭bPDI⁩; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int a\u202db\u2069c2; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int aRLO‮bPDI⁩; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int a\u202eb\u2069; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int aLRI⁦bPDF‬; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int a\u2066b\u202c; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int aRLI⁧bPDF‬c -+; -+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */ -+int a\u2067b\u202c; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int aFSI⁨bPDF‬; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int a\u2068b\u202c; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int aFSI⁨bPD\u202C; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int aFSI\u2068bPDF‬_; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+int aLRE‪bPDF‬b; -+int A\u202aB\u202c; -+int a_LRE‪_LRE‪_b_PDF‬_PDF‬; -+int A\u202aA\u202aB\u202cB\u202c; -+int aPDF‬bLREadPDF‬; -+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/Wbidirectional-7.c b/gcc/testsuite/c-c++-common/Wbidirectional-7.c -new file mode 100644 -index 00000000000..f0f7b3ca14a ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-7.c -@@ -0,0 +1,8 @@ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidirectional=any" } */ -+/* Test we ignore UCNs in comments. */ -+ -+// a b c \u202a 1 2 3 -+// a b c \u202A 1 2 3 -+/* a b c \u202a 1 2 3 */ -+/* a b c \u202A 1 2 3 */ -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-8.c b/gcc/testsuite/c-c++-common/Wbidirectional-8.c -new file mode 100644 -index 00000000000..c7d02193131 ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-8.c -@@ -0,0 +1,12 @@ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidirectional=any" } */ -+/* Test \u vs \U. */ -+ -+int a_\u202A; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+int a_\u202a_2; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+int a_\U0000202A_3; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -+int a_\U0000202a_4; -+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */ -diff --git a/gcc/testsuite/c-c++-common/Wbidirectional-9.c b/gcc/testsuite/c-c++-common/Wbidirectional-9.c -new file mode 100644 -index 00000000000..d029209babb ---- /dev/null -+++ b/gcc/testsuite/c-c++-common/Wbidirectional-9.c -@@ -0,0 +1,28 @@ -+/* { dg-do compile } */ -+/* { dg-options "-Wbidirectional=unpaired" } */ -+/* Test that we properly separate bidi contexts (comment/identifier/character -+ constant/string literal). */ -+ -+/* LRE ->‪<- */ int pdf_\u202c_1; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* RLE ->‫<- */ int pdf_\u202c_2; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* LRO ->‭<- */ int pdf_\u202c_3; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* RLO ->‮<- */ int pdf_\u202c_4; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* LRI ->⁦<-*/ int pdi_\u2069_1; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* RLI ->⁧<- */ int pdi_\u2069_12; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* FSI ->⁨<- */ int pdi_\u2069_3; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+ -+const char *s1 = "LRE\u202a"; /* PDF ->‬<- */ -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+/* LRE ->‪<- */ const char *s2 = "PDF\u202c"; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+const char *s3 = "LRE\u202a"; int pdf_\u202c_5; -+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ -+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 6e2fcb6b1f2..e48d13c4ee1 100644 ---- a/libcpp/include/cpplib.h -+++ b/libcpp/include/cpplib.h -@@ -318,6 +318,17 @@ enum cpp_main_search - CMS_system, /* Search the system INCLUDE path. */ - }; - -+/* The possible bidirectional characters checking levels, from least -+ restrictive to most. */ -+enum cpp_bidirectional_level { -+ /* No checking. */ -+ bidirectional_none, -+ /* Only detect unpaired uses of bidirectional characters. */ -+ bidirectional_unpaired, -+ /* Detect any use of bidirectional characters. */ -+ bidirectional_any -+}; -+ - /* This structure is nested inside struct cpp_reader, and - carries all the options visible to the command line. */ - struct cpp_options -@@ -538,6 +549,10 @@ struct cpp_options - /* True if warn about differences between C++98 and C++11. */ - bool cpp_warn_cxx11_compat; - -+ /* Nonzero of bidirectional characters checking is on. See enum -+ cpp_bidirectional_level. */ -+ unsigned char cpp_warn_bidirectional; -+ - /* Dependency generation. */ - struct - { -@@ -642,7 +657,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 - }; - - /* Callback for header lookup for HEADER, which is the name of a -diff --git a/libcpp/init.c b/libcpp/init.c -index 5a424e23553..f9a8f5f088f 100644 ---- a/libcpp/init.c -+++ b/libcpp/init.c -@@ -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; -+ CPP_OPTION (pfile, cpp_warn_bidirectional) = bidirectional_unpaired; - - /* Default CPP arithmetic to something sensible for the host for the - benefit of dumb users like fix-header. */ -diff --git a/libcpp/lex.c b/libcpp/lex.c -index 8e3ef096bbe..d9c39a4105f 100644 ---- a/libcpp/lex.c -+++ b/libcpp/lex.c -@@ -1164,6 +1164,284 @@ _cpp_process_line_notes (cpp_reader *pfile, int in_comment) - } - } - -+namespace bidi { -+ enum class kind { -+ NONE, LRE, RLE, LRO, RLO, LRI, RLI, FSI, PDF, PDI -+ }; -+ -+ /* All the UTF-8 encodings of bidi characters start with E2. */ -+ 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 -+ represents a PDI context. The next bit is 1 if this context was open -+ by a bidi character written as a UCN, and 0 when it was UTF-8. */ -+ semi_embedded_vec vec; -+ -+ /* Close the whole comment/identifier/string literal/character constant -+ context. */ -+ void on_close () -+ { -+ vec.truncate (0); -+ } -+ -+ /* Pop the last element in the vector. */ -+ void pop () -+ { -+ unsigned int len = vec.count (); -+ gcc_checking_assert (len > 0); -+ vec.truncate (len - 1); -+ } -+ -+ /* Return which context is currently opened. */ -+ kind current_ctx () -+ { -+ unsigned int len = vec.count (); -+ if (len == 0) -+ return kind::NONE; -+ return (vec[len - 1] & 1) ? kind::PDF : kind::PDI; -+ } -+ -+ /* Return true if the current context comes from a UCN origin, that is, -+ the bidi char which started this bidi context was written as a UCN. */ -+ bool current_ctx_ucn_p () -+ { -+ unsigned int len = vec.count (); -+ gcc_checking_assert (len > 0); -+ return (vec[len - 1] >> 1) & 1; -+ } -+ -+ /* We've read a bidi char, update the current vector as necessary. */ -+ void on_char (kind k, bool ucn_p) -+ { -+ switch (k) -+ { -+ case kind::LRE: -+ case kind::RLE: -+ case kind::LRO: -+ case kind::RLO: -+ vec.push (ucn_p ? 3u : 1u); -+ break; -+ case kind::LRI: -+ case kind::RLI: -+ case kind::FSI: -+ vec.push (ucn_p ? 2u : 0u); -+ break; -+ case kind::PDF: -+ if (current_ctx () == kind::PDF) -+ pop (); -+ break; -+ case kind::PDI: -+ if (current_ctx () == kind::PDI) -+ pop (); -+ break; -+ [[likely]] case kind::NONE: -+ break; -+ default: -+ abort (); -+ } -+ } -+ -+ /* Return a descriptive string for K. */ -+ const char *to_str (kind k) -+ { -+ switch (k) -+ { -+ case kind::LRE: -+ return "U+202A (LEFT-TO-RIGHT EMBEDDING)"; -+ case kind::RLE: -+ return "U+202B (RIGHT-TO-LEFT EMBEDDING)"; -+ case kind::LRO: -+ return "U+202D (LEFT-TO-RIGHT OVERRIDE)"; -+ case kind::RLO: -+ return "U+202E (RIGHT-TO-LEFT OVERRIDE)"; -+ case kind::LRI: -+ return "U+2066 (LEFT-TO-RIGHT ISOLATE)"; -+ case kind::RLI: -+ return "U+2067 (RIGHT-TO-LEFT ISOLATE)"; -+ case kind::FSI: -+ return "U+2068 (FIRST STRONG ISOLATE)"; -+ case kind::PDF: -+ return "U+202C (POP DIRECTIONAL FORMATTING)"; -+ case kind::PDI: -+ return "U+2069 (POP DIRECTIONAL ISOLATE)"; -+ default: -+ abort (); -+ } -+ } -+} -+ -+/* Parse a sequence of 3 bytes starting with P and return its bidi code. */ -+ -+static bidi::kind -+get_bidi_utf8 (const unsigned char *const p) -+{ -+ gcc_checking_assert (p[0] == bidi::utf8_start); -+ -+ if (p[1] == 0x80) -+ switch (p[2]) -+ { -+ case 0xaa: -+ return bidi::kind::LRE; -+ case 0xab: -+ return bidi::kind::RLE; -+ case 0xac: -+ return bidi::kind::PDF; -+ case 0xad: -+ return bidi::kind::LRO; -+ case 0xae: -+ return bidi::kind::RLO; -+ default: -+ break; -+ } -+ else if (p[1] == 0x81) -+ switch (p[2]) -+ { -+ case 0xa6: -+ return bidi::kind::LRI; -+ case 0xa7: -+ return bidi::kind::RLI; -+ case 0xa8: -+ return bidi::kind::FSI; -+ case 0xa9: -+ return bidi::kind::PDI; -+ default: -+ break; -+ } -+ -+ return bidi::kind::NONE; -+} -+ -+/* Parse a UCN where P points just past \u or \U and return its bidi code. */ -+ -+static bidi::kind -+get_bidi_ucn (const unsigned char *p, bool is_U) -+{ -+ /* 6.4.3 Universal Character Names -+ \u hex-quad -+ \U hex-quad hex-quad -+ where \unnnn means \U0000nnnn. */ -+ -+ if (is_U) -+ { -+ if (p[0] != '0' || p[1] != '0' || p[2] != '0' || p[3] != '0') -+ 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::kind::NONE; -+ else if (p[2] == '2') -+ switch (p[3]) -+ { -+ case 'a': -+ case 'A': -+ return bidi::kind::LRE; -+ case 'b': -+ case 'B': -+ return bidi::kind::RLE; -+ case 'c': -+ case 'C': -+ return bidi::kind::PDF; -+ case 'd': -+ case 'D': -+ return bidi::kind::LRO; -+ case 'e': -+ case 'E': -+ return bidi::kind::RLO; -+ default: -+ break; -+ } -+ else if (p[2] == '6') -+ switch (p[3]) -+ { -+ case '6': -+ return bidi::kind::LRI; -+ case '7': -+ return bidi::kind::RLI; -+ case '8': -+ return bidi::kind::FSI; -+ case '9': -+ return bidi::kind::PDI; -+ default: -+ break; -+ } -+ -+ return bidi::kind::NONE; -+} -+ -+/* We're closing a bidi context, that is, we've encountered a newline, -+ are closing a C-style comment, or are at the end of a string literal, -+ character constant, or identifier. Warn if this context was not -+ properly terminated by a PDI or PDF. P points to the last character -+ in this context. */ -+ -+static void -+maybe_warn_bidi_on_close (cpp_reader *pfile, const uchar *p) -+{ -+ if (CPP_OPTION (pfile, cpp_warn_bidirectional) == bidirectional_unpaired -+ && bidi::vec.count () > 0) -+ { -+ 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, -+ "unpaired UTF-8 bidirectional character " -+ "detected"); -+ } -+ /* We're done with this context. */ -+ bidi::on_close (); -+} -+ -+/* We're at the beginning or in the middle of an identifier/comment/string -+ literal/character constant. Warn if we've encountered a bidi character. -+ KIND says which bidi character it was; P points to it in the character -+ stream. UCN_P is true iff this bidi character was written as a UCN. */ -+ -+static void -+maybe_warn_bidi_on_char (cpp_reader *pfile, const uchar *p, bidi::kind kind, -+ bool ucn_p) -+{ -+ if (__builtin_expect (kind == bidi::kind::NONE, 1)) -+ return; -+ -+ const auto warn_bidi = CPP_OPTION (pfile, cpp_warn_bidirectional); -+ -+ if (warn_bidi != bidirectional_none) -+ { -+ 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 -+ an opened context because we've already warned about the -+ opening character. Except warn when we have a UCN x UTF-8 -+ mismatch. */ -+ if (kind == bidi::current_ctx ()) -+ { -+ if (warn_bidi == bidirectional_unpaired -+ && bidi::current_ctx_ucn_p () != ucn_p) -+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0, -+ "UTF-8 vs UCN mismatch when closing " -+ "a context by \"%s\"", bidi::to_str (kind)); -+ } -+ else if (warn_bidi == bidirectional_any) -+ { -+ 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)); -+ else -+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0, -+ "found problematic Unicode character \"%s\"", -+ bidi::to_str (kind)); -+ } -+ } -+ /* We're done with this context. */ -+ bidi::on_char (kind, ucn_p); -+} -+ - /* Skip a C-style block comment. We find the end of the comment by - seeing if an asterisk is before every '/' we encounter. Returns - nonzero if comment terminated by EOF, zero otherwise. -@@ -1175,7 +1453,8 @@ _cpp_skip_block_comment (cpp_reader *pfile) - cpp_buffer *buffer = pfile->buffer; - const uchar *cur = buffer->cur; - uchar c; -- -+ const bool warn_bidi_p = (CPP_OPTION (pfile, cpp_warn_bidirectional) -+ != bidirectional_none); - cur++; - if (*cur == '/') - cur++; -@@ -1189,7 +1468,11 @@ _cpp_skip_block_comment (cpp_reader *pfile) - if (c == '/') - { - if (cur[-2] == '*') -- break; -+ { -+ if (warn_bidi_p) -+ maybe_warn_bidi_on_close (pfile, cur); -+ break; -+ } - - /* Warn about potential nested comments, but not if the '/' - comes immediately before the true comment delimiter. -@@ -1208,6 +1491,8 @@ _cpp_skip_block_comment (cpp_reader *pfile) - { - unsigned int cols; - buffer->cur = cur - 1; -+ if (warn_bidi_p) -+ maybe_warn_bidi_on_close (pfile, cur); - _cpp_process_line_notes (pfile, true); - if (buffer->next_line >= buffer->rlimit) - return true; -@@ -1218,6 +1503,13 @@ _cpp_skip_block_comment (cpp_reader *pfile) - - cur = buffer->cur; - } -+ /* If this is a beginning of a UTF-8 encoding, it might be -+ a bidirectional character. */ -+ else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p) -+ { -+ bidi::kind kind = get_bidi_utf8 (cur - 1); -+ maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/false); -+ } - } - - buffer->cur = cur; -@@ -1233,9 +1525,32 @@ skip_line_comment (cpp_reader *pfile) - { - cpp_buffer *buffer = pfile->buffer; - location_t orig_line = pfile->line_table->highest_line; -+ const bool warn_bidi_p = (CPP_OPTION (pfile, cpp_warn_bidirectional) -+ != bidirectional_none); - -- while (*buffer->cur != '\n') -- buffer->cur++; -+ if (!warn_bidi_p) -+ while (*buffer->cur != '\n') -+ buffer->cur++; -+ else -+ { -+ while (*buffer->cur != '\n' -+ && *buffer->cur != bidi::utf8_start) -+ buffer->cur++; -+ if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0)) -+ { -+ while (*buffer->cur != '\n') -+ { -+ if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0)) -+ { -+ bidi::kind kind = get_bidi_utf8 (buffer->cur); -+ maybe_warn_bidi_on_char (pfile, buffer->cur, kind, -+ /*ucn_p=*/false); -+ } -+ buffer->cur++; -+ } -+ maybe_warn_bidi_on_close (pfile, buffer->cur); -+ } -+ } - - _cpp_process_line_notes (pfile, true); - return orig_line != pfile->line_table->highest_line; -@@ -1320,11 +1635,14 @@ static const cppchar_t utf8_signifier = 0xC0; - - /* Returns TRUE if the sequence starting at buffer->cur is valid in - an identifier. FIRST is TRUE if this starts an identifier. */ -+ - static bool - forms_identifier_p (cpp_reader *pfile, int first, - struct normalize_state *state) - { - cpp_buffer *buffer = pfile->buffer; -+ const bool warn_bidi_p = (CPP_OPTION (pfile, cpp_warn_bidirectional) -+ != bidirectional_none); - - if (*buffer->cur == '$') - { -@@ -1347,6 +1665,13 @@ forms_identifier_p (cpp_reader *pfile, int first, - cppchar_t s; - 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; -@@ -1355,6 +1680,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; -@@ -1463,6 +1795,8 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn, - const uchar *cur; - unsigned int len; - unsigned int hash = HT_HASHSTEP (0, *base); -+ const bool warn_bidi_p = (CPP_OPTION (pfile, cpp_warn_bidirectional) -+ != bidirectional_none); - - cur = pfile->buffer->cur; - if (! starts_ucn) -@@ -1479,13 +1813,17 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn, - { - /* Slower version for identifiers containing UCNs - or extended chars (including $). */ -- do { -- while (ISIDNUM (*pfile->buffer->cur)) -- { -- NORMALIZE_STATE_UPDATE_IDNUM (nst, *pfile->buffer->cur); -- pfile->buffer->cur++; -- } -- } while (forms_identifier_p (pfile, false, nst)); -+ do -+ { -+ while (ISIDNUM (*pfile->buffer->cur)) -+ { -+ NORMALIZE_STATE_UPDATE_IDNUM (nst, *pfile->buffer->cur); -+ pfile->buffer->cur++; -+ } -+ } -+ while (forms_identifier_p (pfile, false, nst)); -+ if (warn_bidi_p) -+ maybe_warn_bidi_on_close (pfile, pfile->buffer->cur); - result = _cpp_interpret_identifier (pfile, base, - pfile->buffer->cur - base); - *spelling = cpp_lookup (pfile, base, pfile->buffer->cur - base); -@@ -1732,6 +2070,8 @@ static void - lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base) - { - const uchar *pos = base; -+ const bool warn_bidi_p = (CPP_OPTION (pfile, cpp_warn_bidirectional) -+ != bidirectional_none); - - /* 'tis a pity this information isn't passed down from the lexer's - initial categorization of the token. */ -@@ -1968,8 +2308,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, pos - 1, get_bidi_utf8 (pos - 1), -+ /*ucn_p=*/false); - } - -+ if (warn_bidi_p) -+ 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 -@@ -2064,15 +2411,28 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) - else - terminator = '>', type = CPP_HEADER_NAME; - -+ const bool warn_bidi_p = (CPP_OPTION (pfile, cpp_warn_bidirectional) -+ != bidirectional_none); - for (;;) - { - cppchar_t c = *cur++; - - /* In #include-style directives, terminators are not escapable. */ - if (c == '\\' && !pfile->state.angled_headers && *cur != '\n') -- cur++; -+ { -+ if ((cur[0] == 'u' || cur[0] == 'U') && warn_bidi_p) -+ { -+ bidi::kind kind = get_bidi_ucn (cur + 1, cur[0] == 'U'); -+ maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/true); -+ } -+ cur++; -+ } - else if (c == terminator) -- break; -+ { -+ if (warn_bidi_p) -+ maybe_warn_bidi_on_close (pfile, cur - 1); -+ break; -+ } - else if (c == '\n') - { - cur--; -@@ -2089,6 +2449,11 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) - } - else if (c == '\0') - saw_NUL = true; -+ else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p) -+ { -+ bidi::kind kind = get_bidi_utf8 (cur - 1); -+ maybe_warn_bidi_on_char (pfile, cur - 1, kind, /*ucn_p=*/false); -+ } - } - - if (saw_NUL && !pfile->state.skipping) - -base-commit: b0b1d8d5d90d7c499e2733e8d01ba8b73217f332 --- -2.31.1 - diff --git a/SOURCES/gcc11-dg-ice-fixes.patch b/SOURCES/gcc11-dg-ice-fixes.patch new file mode 100644 index 0000000..33d0bc4 --- /dev/null +++ b/SOURCES/gcc11-dg-ice-fixes.patch @@ -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 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 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 +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" } diff --git a/SOURCES/gcc11-libgcc-link.patch b/SOURCES/gcc11-libgcc-link.patch new file mode 100644 index 0000000..8551934 --- /dev/null +++ b/SOURCES/gcc11-libgcc-link.patch @@ -0,0 +1,57 @@ +libgcc: Honor LDFLAGS_FOR_TARGET when linking libgcc_s + +When building gcc with some specific LDFLAGS_FOR_TARGET, e.g. +LDFLAGS_FOR_TARGET=-Wl,-z,relro,-z,now +those flags propagate info linking of target shared libraries, +e.g. lib{ubsan,tsan,stdc++,quadmath,objc,lsan,itm,gphobos,gdruntime,gomp,go,gfortran,atomic,asan}.so.* +but there is one important exception, libgcc_s.so.* linking ignores it. + +The following patch fixes that. + +Bootstrapped/regtested on x86_64-linux with LDFLAGS_FOR_TARGET=-Wl,-z,relro,-z,now +and verified that libgcc_s.so.* is BIND_NOW when it previously wasn't, and +without any LDFLAGS_FOR_TARGET on x86_64-linux and i686-linux. +There on x86_64-linux I've verified that the libgcc_s.so.1 linking command +line for -m64 is identical except for whitespace to one without the patch, +and for -m32 multilib $(LDFLAGS) actually do supply there an extra -m32 +that also repeats later in the @multilib_flags@, which should be harmless. + +2021-08-04 Jakub Jelinek + + * config/t-slibgcc (SHLIB_LINK): Add $(LDFLAGS). + * config/t-slibgcc-darwin (SHLIB_LINK): Likewise. + * config/t-slibgcc-vms (SHLIB_LINK): Likewise. + +--- libgcc/config/t-slibgcc ++++ libgcc/config/t-slibgcc +@@ -32,7 +32,7 @@ SHLIB_INSTALL_SOLINK = $(LN_S) $(SHLIB_SONAME) \ + $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK) + + SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \ +- $(SHLIB_LDFLAGS) \ ++ $(SHLIB_LDFLAGS) $(LDFLAGS) \ + -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \ + $(SHLIB_OBJS) $(SHLIB_LC) && \ + rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \ +--- libgcc/config/t-slibgcc-darwin ++++ libgcc/config/t-slibgcc-darwin +@@ -15,7 +15,7 @@ SHLIB_LC = -lc + # Note that this version is used for the loader, not the linker; the linker + # uses the stub versions named by the versioned members of $(INSTALL_FILES). + +-SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -dynamiclib -nodefaultlibs \ ++SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) $(LDFLAGS) -dynamiclib -nodefaultlibs \ + -install_name @shlib_slibdir@/$(SHLIB_INSTALL_NAME) \ + -single_module -o $(SHLIB_DIR)/$(SHLIB_SONAME) \ + -Wl,-exported_symbols_list,$(SHLIB_MAP) \ +--- libgcc/config/t-slibgcc-vms ++++ libgcc/config/t-slibgcc-vms +@@ -22,7 +22,7 @@ SHLIB_LINK = \ + objdump --syms $(SHLIB_OBJS) | \ + $(SHLIB_SYMVEC) >> SYMVEC_$$$$.opt ; \ + echo "case_sensitive=NO" >> SYMVEC_$$$$.opt; \ +- $(CC) $(LIBGCC2_CFLAGS) -nodefaultlibs \ ++ $(CC) $(LIBGCC2_CFLAGS) $(LDFLAGS) -nodefaultlibs \ + -shared --for-linker=/noinform -o $(SHLIB_NAME) $(SHLIB_OBJS) \ + --for-linker=SYMVEC_$$$$.opt \ + --for-linker=gsmatch=equal,$(shlib_version) diff --git a/SOURCES/gcc11-libstdc++-compat.patch b/SOURCES/gcc11-libstdc++-compat.patch index 6dec130..c9e0a9b 100644 --- a/SOURCES/gcc11-libstdc++-compat.patch +++ b/SOURCES/gcc11-libstdc++-compat.patch @@ -165,9 +165,9 @@ __at_thread_exit(__at_thread_exit_elt*); --- libstdc++-v3/src/c++11/system_error.cc.libstdc++-compat~ 2021-05-12 09:34:49.000000000 -0400 +++ libstdc++-v3/src/c++11/system_error.cc 2021-05-17 12:05:15.766954365 -0400 -@@ -346,7 +346,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION +@@ -372,7 +372,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const error_category& - _V2::generic_category() noexcept { return generic_category_instance; } + _V2::generic_category() noexcept { return generic_category_instance.obj; } +#ifndef _GLIBCXX_NONSHARED_CXX11 system_error::~system_error() noexcept = default; @@ -175,7 +175,7 @@ error_condition error_category::default_error_condition(int __i) const noexcept -@@ -361,9 +363,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION +@@ -387,9 +389,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION error_category::equivalent(const error_code& __code, int __i) const noexcept { return *this == __code.category() && __code.value() == __i; } @@ -13452,8 +13452,8 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF --#line 12133 "configure" -+#line 12135 "configure" +-#line 12179 "configure" ++#line 12181 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -13461,8 +13461,8 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF --#line 12239 "configure" -+#line 12241 "configure" +-#line 12285 "configure" ++#line 12287 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -13470,8 +13470,8 @@ # Fake what AC_TRY_COMPILE does. cat > conftest.$ac_ext << EOF --#line 15921 "configure" -+#line 15923 "configure" +-#line 15967 "configure" ++#line 15969 "configure" int main() { typedef bool atomic_type; @@ -13479,8 +13479,8 @@ rm -f conftest* cat > conftest.$ac_ext << EOF --#line 15956 "configure" -+#line 15958 "configure" +-#line 16002 "configure" ++#line 16004 "configure" int main() { typedef short atomic_type; @@ -13488,8 +13488,8 @@ rm -f conftest* cat > conftest.$ac_ext << EOF --#line 15991 "configure" -+#line 15993 "configure" +-#line 16037 "configure" ++#line 16039 "configure" int main() { // NB: _Atomic_word not necessarily int. @@ -13497,8 +13497,8 @@ rm -f conftest* cat > conftest.$ac_ext << EOF --#line 16027 "configure" -+#line 16029 "configure" +-#line 16073 "configure" ++#line 16075 "configure" int main() { typedef long long atomic_type; @@ -13506,8 +13506,8 @@ # unnecessary for this test. cat > conftest.$ac_ext << EOF --#line 16180 "configure" -+#line 16182 "configure" +-#line 16226 "configure" ++#line 16228 "configure" int main() { _Decimal32 d1; @@ -13515,8 +13515,8 @@ # unnecessary for this test. cat > conftest.$ac_ext << EOF --#line 16222 "configure" -+#line 16224 "configure" +-#line 16268 "configure" ++#line 16270 "configure" template struct same { typedef T2 type; }; @@ -13524,8 +13524,8 @@ rm -f conftest* cat > conftest.$ac_ext << EOF --#line 16256 "configure" -+#line 16258 "configure" +-#line 16302 "configure" ++#line 16304 "configure" template struct same { typedef T2 type; }; diff --git a/SOURCES/gcc11-mtune-alderlake.patch b/SOURCES/gcc11-mtune-alderlake.patch new file mode 100644 index 0000000..c9142a9 --- /dev/null +++ b/SOURCES/gcc11-mtune-alderlake.patch @@ -0,0 +1,457 @@ +From 54ccc52ba3f842cd94718967465a6015a752ca47 Mon Sep 17 00:00:00 2001 +From: "Cui,Lili" +Date: Thu, 4 Nov 2021 10:38:56 +0800 +Subject: [PATCH] x86: Update -mtune=alderlake +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Update mtune for alderlake, Alder Lake Intel Hybrid Technology will not support +Intel® AVX-512. ISA features such as Intel® AVX, AVX-VNNI, Intel® AVX2, and +UMONITOR/UMWAIT/TPAUSE are supported. + +gcc/ChangeLog + + * config/i386/i386-options.c (m_CORE_AVX2): Remove Alderlake + from m_CORE_AVX2. + (processor_cost_table): Use alderlake_cost for Alderlake. + * config/i386/i386.c (ix86_sched_init_global): Handle Alderlake. + * config/i386/x86-tune-costs.h (struct processor_costs): Add alderlake + cost. + * config/i386/x86-tune-sched.c (ix86_issue_rate): Change Alderlake + issue rate to 4. + (ix86_adjust_cost): Handle Alderlake. + * config/i386/x86-tune.def (X86_TUNE_SCHEDULE): Enable for Alderlake. + (X86_TUNE_PARTIAL_REG_DEPENDENCY): Likewise. + (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY): Likewise. + (X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY): Likewise. + (X86_TUNE_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY): Likewise. + (X86_TUNE_MEMORY_MISMATCH_STALL): Likewise. + (X86_TUNE_USE_LEAVE): Likewise. + (X86_TUNE_PUSH_MEMORY): Likewise. + (X86_TUNE_USE_INCDEC): Likewise. + (X86_TUNE_INTEGER_DFMODE_MOVES): Likewise. + (X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES): Likewise. + (X86_TUNE_USE_SAHF): Likewise. + (X86_TUNE_USE_BT): Likewise. + (X86_TUNE_AVOID_FALSE_DEP_FOR_BMI): Likewise. + (X86_TUNE_ONE_IF_CONV_INSN): Likewise. + (X86_TUNE_AVOID_MFENCE): Likewise. + (X86_TUNE_USE_SIMODE_FIOP): Likewise. + (X86_TUNE_EXT_80387_CONSTANTS): Likewise. + (X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL): Likewise. + (X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL): Likewise. + (X86_TUNE_SSE_TYPELESS_STORES): Likewise. + (X86_TUNE_SSE_LOAD0_BY_PXOR): Likewise. + (X86_TUNE_AVOID_4BYTE_PREFIXES): Likewise. + (X86_TUNE_USE_GATHER): Disable for Alderlake. +--- + gcc/config/i386/i386-options.c | 4 +- + gcc/config/i386/i386.c | 1 + + gcc/config/i386/x86-tune-costs.h | 120 +++++++++++++++++++++++++++++++ + gcc/config/i386/x86-tune-sched.c | 2 + + gcc/config/i386/x86-tune.def | 58 +++++++-------- + 5 files changed, 155 insertions(+), 30 deletions(-) + +diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c +index e7a3bd4aaea..a8cc0664f11 100644 +--- a/gcc/config/i386/i386-options.c ++++ b/gcc/config/i386/i386-options.c +@@ -131,7 +131,7 @@ along with GCC; see the file COPYING3. If not see + | m_ICELAKE_CLIENT | m_ICELAKE_SERVER | m_CASCADELAKE \ + | m_TIGERLAKE | m_COOPERLAKE | m_SAPPHIRERAPIDS \ + | m_ROCKETLAKE) +-#define m_CORE_AVX2 (m_HASWELL | m_SKYLAKE | m_ALDERLAKE | m_CORE_AVX512) ++#define m_CORE_AVX2 (m_HASWELL | m_SKYLAKE | m_CORE_AVX512) + #define m_CORE_ALL (m_CORE2 | m_NEHALEM | m_SANDYBRIDGE | m_CORE_AVX2) + #define m_GOLDMONT (HOST_WIDE_INT_1U<integer move cost is 2. */ ++ 6, /* cost for loading QImode using movzbl */ ++ {6, 6, 6}, /* cost of loading integer registers ++ in QImode, HImode and SImode. ++ Relative to reg-reg move (2). */ ++ {6, 6, 6}, /* cost of storing integer registers */ ++ 4, /* cost of reg,reg fld/fst */ ++ {6, 6, 12}, /* cost of loading fp registers ++ in SFmode, DFmode and XFmode */ ++ {6, 6, 12}, /* cost of storing fp registers ++ in SFmode, DFmode and XFmode */ ++ 2, /* cost of moving MMX register */ ++ {6, 6}, /* cost of loading MMX registers ++ in SImode and DImode */ ++ {6, 6}, /* cost of storing MMX registers ++ in SImode and DImode */ ++ 2, 3, 4, /* cost of moving XMM,YMM,ZMM register */ ++ {6, 6, 6, 10, 15}, /* cost of loading SSE registers ++ in 32,64,128,256 and 512-bit */ ++ {6, 6, 6, 10, 15}, /* cost of storing SSE registers ++ in 32,64,128,256 and 512-bit */ ++ 6, 6, /* SSE->integer and integer->SSE moves */ ++ 6, 6, /* mask->integer and integer->mask moves */ ++ {6, 6, 6}, /* cost of loading mask register ++ in QImode, HImode, SImode. */ ++ {6, 6, 6}, /* cost if storing mask register ++ in QImode, HImode, SImode. */ ++ 2, /* cost of moving mask register. */ ++ /* End of register allocator costs. */ ++ }, ++ ++ COSTS_N_INSNS (1), /* cost of an add instruction */ ++ COSTS_N_INSNS (1) + 1, /* cost of a lea instruction */ ++ COSTS_N_INSNS (1), /* variable shift costs */ ++ COSTS_N_INSNS (1), /* constant shift costs */ ++ {COSTS_N_INSNS (3), /* cost of starting multiply for QI */ ++ COSTS_N_INSNS (4), /* HI */ ++ COSTS_N_INSNS (3), /* SI */ ++ COSTS_N_INSNS (4), /* DI */ ++ COSTS_N_INSNS (4)}, /* other */ ++ 0, /* cost of multiply per each bit set */ ++ {COSTS_N_INSNS (16), /* cost of a divide/mod for QI */ ++ COSTS_N_INSNS (22), /* HI */ ++ COSTS_N_INSNS (30), /* SI */ ++ COSTS_N_INSNS (74), /* DI */ ++ COSTS_N_INSNS (74)}, /* other */ ++ COSTS_N_INSNS (1), /* cost of movsx */ ++ COSTS_N_INSNS (1), /* cost of movzx */ ++ 8, /* "large" insn */ ++ 17, /* MOVE_RATIO */ ++ 17, /* CLEAR_RATIO */ ++ {6, 6, 6}, /* cost of loading integer registers ++ in QImode, HImode and SImode. ++ Relative to reg-reg move (2). */ ++ {6, 6, 6}, /* cost of storing integer registers */ ++ {6, 6, 6, 10, 15}, /* cost of loading SSE register ++ in 32bit, 64bit, 128bit, 256bit and 512bit */ ++ {6, 6, 6, 10, 15}, /* cost of storing SSE register ++ in 32bit, 64bit, 128bit, 256bit and 512bit */ ++ {6, 6, 6, 10, 15}, /* cost of unaligned loads. */ ++ {6, 6, 6, 10, 15}, /* cost of unaligned storess. */ ++ 2, 3, 4, /* cost of moving XMM,YMM,ZMM register */ ++ 6, /* cost of moving SSE register to integer. */ ++ 18, 6, /* Gather load static, per_elt. */ ++ 18, 6, /* Gather store static, per_elt. */ ++ 32, /* size of l1 cache. */ ++ 512, /* size of l2 cache. */ ++ 64, /* size of prefetch block */ ++ 6, /* number of parallel prefetches */ ++ 3, /* Branch cost */ ++ COSTS_N_INSNS (3), /* cost of FADD and FSUB insns. */ ++ COSTS_N_INSNS (5), /* cost of FMUL instruction. */ ++ COSTS_N_INSNS (17), /* cost of FDIV instruction. */ ++ COSTS_N_INSNS (1), /* cost of FABS instruction. */ ++ COSTS_N_INSNS (1), /* cost of FCHS instruction. */ ++ COSTS_N_INSNS (14), /* cost of FSQRT instruction. */ ++ ++ COSTS_N_INSNS (1), /* cost of cheap SSE instruction. */ ++ COSTS_N_INSNS (3), /* cost of ADDSS/SD SUBSS/SD insns. */ ++ COSTS_N_INSNS (4), /* cost of MULSS instruction. */ ++ COSTS_N_INSNS (5), /* cost of MULSD instruction. */ ++ COSTS_N_INSNS (5), /* cost of FMA SS instruction. */ ++ COSTS_N_INSNS (5), /* cost of FMA SD instruction. */ ++ COSTS_N_INSNS (13), /* cost of DIVSS instruction. */ ++ COSTS_N_INSNS (17), /* cost of DIVSD instruction. */ ++ COSTS_N_INSNS (14), /* cost of SQRTSS instruction. */ ++ COSTS_N_INSNS (18), /* cost of SQRTSD instruction. */ ++ 1, 4, 3, 3, /* reassoc int, fp, vec_int, vec_fp. */ ++ alderlake_memcpy, ++ alderlake_memset, ++ COSTS_N_INSNS (4), /* cond_taken_branch_cost. */ ++ COSTS_N_INSNS (2), /* cond_not_taken_branch_cost. */ ++ "16:11:8", /* Loop alignment. */ ++ "16:11:8", /* Jump alignment. */ ++ "0:0:8", /* Label alignment. */ ++ "16", /* Func alignment. */ ++}; ++ + /* BTVER1 has optimized REP instruction for medium sized blocks, but for + very small blocks it is better to use loop. For large blocks, libcall can + do nontemporary accesses and beat inline considerably. */ +diff --git a/gcc/config/i386/x86-tune-sched.c b/gcc/config/i386/x86-tune-sched.c +index 56ada99a450..0c149a09531 100644 +--- a/gcc/config/i386/x86-tune-sched.c ++++ b/gcc/config/i386/x86-tune-sched.c +@@ -72,6 +72,7 @@ ix86_issue_rate (void) + case PROCESSOR_SANDYBRIDGE: + case PROCESSOR_HASWELL: + case PROCESSOR_TREMONT: ++ case PROCESSOR_ALDERLAKE: + case PROCESSOR_GENERIC: + return 4; + +@@ -431,6 +432,7 @@ ix86_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost, + case PROCESSOR_SANDYBRIDGE: + case PROCESSOR_HASWELL: + case PROCESSOR_TREMONT: ++ case PROCESSOR_ALDERLAKE: + case PROCESSOR_GENERIC: + /* Stack engine allows to execute push&pop instructions in parall. */ + if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP) +diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def +index 58e8ead56b4..4ae0b569841 100644 +--- a/gcc/config/i386/x86-tune.def ++++ b/gcc/config/i386/x86-tune.def +@@ -42,7 +42,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + DEF_TUNE (X86_TUNE_SCHEDULE, "schedule", + m_PENT | m_LAKEMONT | m_PPRO | m_CORE_ALL | m_BONNELL | m_SILVERMONT + | m_INTEL | m_KNL | m_KNM | m_K6_GEODE | m_AMD_MULTIPLE | m_GOLDMONT +- | m_GOLDMONT_PLUS | m_TREMONT | m_GENERIC) ++ | m_GOLDMONT_PLUS | m_TREMONT | m_ALDERLAKE |m_GENERIC) + + /* X86_TUNE_PARTIAL_REG_DEPENDENCY: Enable more register renaming + on modern chips. Preffer stores affecting whole integer register +@@ -51,7 +51,7 @@ DEF_TUNE (X86_TUNE_SCHEDULE, "schedule", + DEF_TUNE (X86_TUNE_PARTIAL_REG_DEPENDENCY, "partial_reg_dependency", + m_P4_NOCONA | m_CORE2 | m_NEHALEM | m_SANDYBRIDGE | m_CORE_AVX2 + | m_BONNELL | m_SILVERMONT | m_GOLDMONT | m_GOLDMONT_PLUS | m_INTEL +- | m_KNL | m_KNM | m_AMD_MULTIPLE | m_TREMONT ++ | m_KNL | m_KNM | m_AMD_MULTIPLE | m_TREMONT | m_ALDERLAKE + | m_GENERIC) + + /* X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY: This knob promotes all store +@@ -62,7 +62,7 @@ DEF_TUNE (X86_TUNE_PARTIAL_REG_DEPENDENCY, "partial_reg_dependency", + that can be partly masked by careful scheduling of moves. */ + DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY, "sse_partial_reg_dependency", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_AMDFAM10 +- | m_BDVER | m_ZNVER | m_TREMONT | m_GENERIC) ++ | m_BDVER | m_ZNVER | m_TREMONT | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY: This knob avoids + partial write to the destination in scalar SSE conversion from FP +@@ -70,14 +70,14 @@ DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY, "sse_partial_reg_dependency", + DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY, + "sse_partial_reg_fp_converts_dependency", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_AMDFAM10 +- | m_BDVER | m_ZNVER | m_GENERIC) ++ | m_BDVER | m_ZNVER | m_ALDERLAKE| m_GENERIC) + + /* X86_TUNE_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY: This knob avoids partial + write to the destination in scalar SSE conversion from integer to FP. */ + DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY, + "sse_partial_reg_converts_dependency", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_AMDFAM10 +- | m_BDVER | m_ZNVER | m_GENERIC) ++ | m_BDVER | m_ZNVER | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_SSE_SPLIT_REGS: Set for machines where the type and dependencies + are resolved on SSE register parts instead of whole registers, so we may +@@ -103,14 +103,14 @@ DEF_TUNE (X86_TUNE_MOVX, "movx", + m_PPRO | m_P4_NOCONA | m_CORE2 | m_NEHALEM | m_SANDYBRIDGE + | m_BONNELL | m_SILVERMONT | m_GOLDMONT | m_KNL | m_KNM | m_INTEL + | m_GOLDMONT_PLUS | m_GEODE | m_AMD_MULTIPLE +- | m_CORE_AVX2 | m_TREMONT | m_GENERIC) ++ | m_CORE_AVX2 | m_TREMONT | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_MEMORY_MISMATCH_STALL: Avoid partial stores that are followed by + full sized loads. */ + DEF_TUNE (X86_TUNE_MEMORY_MISMATCH_STALL, "memory_mismatch_stall", + m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_SILVERMONT | m_INTEL + | m_KNL | m_KNM | m_GOLDMONT | m_GOLDMONT_PLUS | m_AMD_MULTIPLE +- | m_TREMONT | m_GENERIC) ++ | m_TREMONT | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_FUSE_CMP_AND_BRANCH_32: Fuse compare with a subsequent + conditional jump instruction for 32 bit TARGET. */ +@@ -166,14 +166,14 @@ DEF_TUNE (X86_TUNE_EPILOGUE_USING_MOVE, "epilogue_using_move", + /* X86_TUNE_USE_LEAVE: Use "leave" instruction in epilogues where it fits. */ + DEF_TUNE (X86_TUNE_USE_LEAVE, "use_leave", + m_386 | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE | m_TREMONT +- | m_GENERIC) ++ | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_PUSH_MEMORY: Enable generation of "push mem" instructions. + Some chips, like 486 and Pentium works faster with separate load + and push instructions. */ + DEF_TUNE (X86_TUNE_PUSH_MEMORY, "push_memory", + m_386 | m_P4_NOCONA | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE +- | m_TREMONT | m_GENERIC) ++ | m_TREMONT | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_SINGLE_PUSH: Enable if single push insn is preferred + over esp subtraction. */ +@@ -243,14 +243,14 @@ DEF_TUNE (X86_TUNE_READ_MODIFY, "read_modify", ~(m_PENT | m_LAKEMONT | m_PPRO)) + DEF_TUNE (X86_TUNE_USE_INCDEC, "use_incdec", + ~(m_P4_NOCONA | m_CORE2 | m_NEHALEM | m_SANDYBRIDGE + | m_BONNELL | m_SILVERMONT | m_INTEL | m_KNL | m_KNM | m_GOLDMONT +- | m_GOLDMONT_PLUS | m_TREMONT | m_GENERIC)) ++ | m_GOLDMONT_PLUS | m_TREMONT | m_ALDERLAKE | m_GENERIC)) + + /* X86_TUNE_INTEGER_DFMODE_MOVES: Enable if integer moves are preferred + for DFmode copies */ + DEF_TUNE (X86_TUNE_INTEGER_DFMODE_MOVES, "integer_dfmode_moves", + ~(m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_SILVERMONT + | m_KNL | m_KNM | m_INTEL | m_GEODE | m_AMD_MULTIPLE | m_GOLDMONT +- | m_GOLDMONT_PLUS | m_TREMONT | m_GENERIC)) ++ | m_GOLDMONT_PLUS | m_TREMONT | m_ALDERLAKE | m_GENERIC)) + + /* X86_TUNE_OPT_AGU: Optimize for Address Generation Unit. This flag + will impact LEA instruction selection. */ +@@ -298,14 +298,14 @@ DEF_TUNE (X86_TUNE_PREFER_KNOWN_REP_MOVSB_STOSB, + DEF_TUNE (X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES, + "misaligned_move_string_pro_epilogues", + m_386 | m_486 | m_CORE_ALL | m_AMD_MULTIPLE | m_TREMONT +- | m_GENERIC) ++ | m_ALDERLAKE |m_GENERIC) + + /* X86_TUNE_USE_SAHF: Controls use of SAHF. */ + DEF_TUNE (X86_TUNE_USE_SAHF, "use_sahf", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_SILVERMONT + | m_KNL | m_KNM | m_INTEL | m_K6_GEODE | m_K8 | m_AMDFAM10 | m_BDVER + | m_BTVER | m_ZNVER | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT +- | m_GENERIC) ++ | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_USE_CLTD: Controls use of CLTD and CTQO instructions. */ + DEF_TUNE (X86_TUNE_USE_CLTD, "use_cltd", +@@ -316,12 +316,12 @@ DEF_TUNE (X86_TUNE_USE_CLTD, "use_cltd", + DEF_TUNE (X86_TUNE_USE_BT, "use_bt", + m_CORE_ALL | m_BONNELL | m_SILVERMONT | m_KNL | m_KNM | m_INTEL + | m_LAKEMONT | m_AMD_MULTIPLE | m_GOLDMONT | m_GOLDMONT_PLUS +- | m_TREMONT | m_GENERIC) ++ | m_TREMONT | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_AVOID_FALSE_DEP_FOR_BMI: Avoid false dependency + for bit-manipulation instructions. */ + DEF_TUNE (X86_TUNE_AVOID_FALSE_DEP_FOR_BMI, "avoid_false_dep_for_bmi", +- m_SANDYBRIDGE | m_CORE_AVX2 | m_TREMONT | m_GENERIC) ++ m_SANDYBRIDGE | m_CORE_AVX2 | m_TREMONT | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_ADJUST_UNROLL: This enables adjusting the unroll factor based + on hardware capabilities. Bdver3 hardware has a loop buffer which makes +@@ -333,11 +333,11 @@ DEF_TUNE (X86_TUNE_ADJUST_UNROLL, "adjust_unroll_factor", m_BDVER3 | m_BDVER4) + if-converted sequence to one. */ + DEF_TUNE (X86_TUNE_ONE_IF_CONV_INSN, "one_if_conv_insn", + m_SILVERMONT | m_KNL | m_KNM | m_INTEL | m_CORE_ALL | m_GOLDMONT +- | m_GOLDMONT_PLUS | m_TREMONT | m_GENERIC) ++ | m_GOLDMONT_PLUS | m_TREMONT | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_AVOID_MFENCE: Use lock prefixed instructions instead of mfence. */ + DEF_TUNE (X86_TUNE_AVOID_MFENCE, "avoid_mfence", +- m_CORE_ALL | m_BDVER | m_ZNVER | m_TREMONT | m_GENERIC) ++ m_CORE_ALL | m_BDVER | m_ZNVER | m_TREMONT | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_EXPAND_ABS: This enables a new abs pattern by + generating instructions for abs (x) = (((signed) x >> (W-1) ^ x) - +@@ -361,7 +361,8 @@ DEF_TUNE (X86_TUNE_USE_HIMODE_FIOP, "use_himode_fiop", + DEF_TUNE (X86_TUNE_USE_SIMODE_FIOP, "use_simode_fiop", + ~(m_PENT | m_LAKEMONT | m_PPRO | m_CORE_ALL | m_BONNELL + | m_SILVERMONT | m_KNL | m_KNM | m_INTEL | m_AMD_MULTIPLE +- | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_GENERIC)) ++ | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_ALDERLAKE ++ | m_GENERIC)) + + /* X86_TUNE_USE_FFREEP: Use freep instruction instead of fstp. */ + DEF_TUNE (X86_TUNE_USE_FFREEP, "use_ffreep", m_AMD_MULTIPLE) +@@ -370,7 +371,7 @@ DEF_TUNE (X86_TUNE_USE_FFREEP, "use_ffreep", m_AMD_MULTIPLE) + DEF_TUNE (X86_TUNE_EXT_80387_CONSTANTS, "ext_80387_constants", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_SILVERMONT + | m_KNL | m_KNM | m_INTEL | m_K6_GEODE | m_ATHLON_K8 | m_GOLDMONT +- | m_GOLDMONT_PLUS | m_TREMONT | m_GENERIC) ++ | m_GOLDMONT_PLUS | m_TREMONT | m_ALDERLAKE | m_GENERIC) + + /*****************************************************************************/ + /* SSE instruction selection tuning */ +@@ -385,15 +386,15 @@ DEF_TUNE (X86_TUNE_GENERAL_REGS_SSE_SPILL, "general_regs_sse_spill", + of a sequence loading registers by parts. */ + DEF_TUNE (X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL, "sse_unaligned_load_optimal", + m_NEHALEM | m_SANDYBRIDGE | m_CORE_AVX2 | m_SILVERMONT | m_KNL | m_KNM +- | m_INTEL | m_GOLDMONT | m_GOLDMONT_PLUS +- | m_TREMONT | m_AMDFAM10 | m_BDVER | m_BTVER | m_ZNVER | m_GENERIC) ++ | m_INTEL | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_ALDERLAKE ++ | m_AMDFAM10 | m_BDVER | m_BTVER | m_ZNVER | m_GENERIC) + + /* X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL: Use movups for misaligned stores + instead of a sequence loading registers by parts. */ + DEF_TUNE (X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL, "sse_unaligned_store_optimal", + m_NEHALEM | m_SANDYBRIDGE | m_CORE_AVX2 | m_SILVERMONT | m_KNL | m_KNM + | m_INTEL | m_GOLDMONT | m_GOLDMONT_PLUS +- | m_TREMONT | m_BDVER | m_ZNVER | m_GENERIC) ++ | m_TREMONT | m_ALDERLAKE | m_BDVER | m_ZNVER | m_GENERIC) + + /* X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL: Use packed single + precision 128bit instructions instead of double where possible. */ +@@ -402,13 +403,13 @@ DEF_TUNE (X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL, "sse_packed_single_insn_optim + + /* X86_TUNE_SSE_TYPELESS_STORES: Always movaps/movups for 128bit stores. */ + DEF_TUNE (X86_TUNE_SSE_TYPELESS_STORES, "sse_typeless_stores", +- m_AMD_MULTIPLE | m_CORE_ALL | m_TREMONT | m_GENERIC) ++ m_AMD_MULTIPLE | m_CORE_ALL | m_TREMONT | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_SSE_LOAD0_BY_PXOR: Always use pxor to load0 as opposed to + xorps/xorpd and other variants. */ + DEF_TUNE (X86_TUNE_SSE_LOAD0_BY_PXOR, "sse_load0_by_pxor", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BDVER | m_BTVER | m_ZNVER +- | m_TREMONT | m_GENERIC) ++ | m_TREMONT | m_ALDERLAKE | m_GENERIC) + + /* X86_TUNE_INTER_UNIT_MOVES_TO_VEC: Enable moves in from integer + to SSE registers. If disabled, the moves will be done by storing +@@ -454,11 +455,12 @@ DEF_TUNE (X86_TUNE_SLOW_PSHUFB, "slow_pshufb", + + /* X86_TUNE_AVOID_4BYTE_PREFIXES: Avoid instructions requiring 4+ bytes of prefixes. */ + DEF_TUNE (X86_TUNE_AVOID_4BYTE_PREFIXES, "avoid_4byte_prefixes", +- m_SILVERMONT | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_INTEL) ++ m_SILVERMONT | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_ALDERLAKE ++ | m_INTEL) + + /* X86_TUNE_USE_GATHER: Use gather instructions. */ + DEF_TUNE (X86_TUNE_USE_GATHER, "use_gather", +- ~(m_ZNVER1 | m_ZNVER2 | m_GENERIC)) ++ ~(m_ZNVER1 | m_ZNVER2 | m_GENERIC | m_ALDERLAKE)) + + /* X86_TUNE_AVOID_128FMA_CHAINS: Avoid creating loops with tight 128bit or + smaller FMA chain. */ +-- +2.17.1 + diff --git a/SOURCES/gcc11-pr101786.patch b/SOURCES/gcc11-pr101786.patch new file mode 100644 index 0000000..427c10a --- /dev/null +++ b/SOURCES/gcc11-pr101786.patch @@ -0,0 +1,66 @@ +c++: Optimize constinit thread_local vars [PR101786] + +The paper that introduced constinit mentioned in rationale that constinit +can be used on externs as well and that it can be used to avoid the +thread_local initialization wrappers, because the standard requires that +if constinit is present on any declaration, it is also present on the +initialization declaration, even if it is in some other TU etc. + +There is a small problem though, we use the tls wrappers not just if +the thread_local variable needs dynamic initialization, but also when +it has static initialization, but non-trivial destructor, as the +"dynamic initialization" in that case needs to register the destructor. + +So, the following patch optimizes constinit thread_local vars only +if we can prove they will not have non-trivial destructors. That includes +the case where we have incomplete type where we don't know and need to +conservatively assume the type will have non-trivial destructor at the +initializing declaration side. + +2021-08-11 Jakub Jelinek + + PR c++/101786 + * decl2.c (var_defined_without_dynamic_init): Return true for + DECL_DECLARED_CONSTINIT_P with complete type and trivial destructor. + + * g++.dg/cpp2a/constinit16.C: New test. + +--- gcc/cp/decl2.c ++++ gcc/cp/decl2.c +@@ -3447,6 +3447,12 @@ set_guard (tree guard) + static bool + var_defined_without_dynamic_init (tree var) + { ++ /* constinit vars are guaranteed to not have dynamic initializer, ++ but still registering the destructor counts as dynamic initialization. */ ++ if (DECL_DECLARED_CONSTINIT_P (var) ++ && COMPLETE_TYPE_P (TREE_TYPE (var)) ++ && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var))) ++ return true; + /* If it's defined in another TU, we can't tell. */ + if (DECL_EXTERNAL (var)) + return false; +--- gcc/testsuite/g++.dg/cpp2a/constinit16.C ++++ gcc/testsuite/g++.dg/cpp2a/constinit16.C +@@ -0,0 +1,21 @@ ++// PR c++/101786 ++// { dg-do compile { target c++20 } } ++// { dg-add-options tls } ++// { dg-require-alias "" } ++// { dg-require-effective-target tls_runtime } ++// { dg-final { scan-assembler-not "_ZTH17mythreadlocalvar1" } } ++// { dg-final { scan-assembler "_ZTH17mythreadlocalvar2" } } ++// { dg-final { scan-assembler-not "_ZTH17mythreadlocalvar3" } } ++// { dg-final { scan-assembler "_ZTH17mythreadlocalvar4" } } ++ ++extern thread_local constinit int mythreadlocalvar1; ++struct S; ++extern thread_local constinit S mythreadlocalvar2; ++struct T { int t; }; ++extern thread_local constinit T mythreadlocalvar3; ++struct U { int u; ~U (); }; ++extern thread_local constinit U mythreadlocalvar4; ++int foo () { return mythreadlocalvar1; } ++S *bar () { return &mythreadlocalvar2; } ++T *baz () { return &mythreadlocalvar3; } ++U *qux () { return &mythreadlocalvar4; } diff --git a/SOURCES/gcc11-stringify-__VA_OPT__-2.patch b/SOURCES/gcc11-stringify-__VA_OPT__-2.patch new file mode 100644 index 0000000..5874bc1 --- /dev/null +++ b/SOURCES/gcc11-stringify-__VA_OPT__-2.patch @@ -0,0 +1,197 @@ +libcpp: Fix up #__VA_OPT__ handling [PR103415] + +stringify_arg uses pfile->u_buff to create the string literal. +Unfortunately, paste_tokens -> _cpp_lex_direct -> lex_number -> _cpp_unaligned_alloc +can in some cases use pfile->u_buff too, which results in losing everything +prepared for the string literal until the token pasting. + +The following patch fixes that by not calling paste_token during the +construction of the string literal, but doing that before. All the tokens +we are processing have been pushed into a token buffer using +tokens_buff_add_token so it is fine if we paste some of them in that buffer +(successful pasting creates a new token in that buffer), move following +tokens if any to make it contiguous, pop (throw away) the extra tokens at +the end and then do stringify_arg. + +Also, paste_tokens now copies over PREV_WHITE and PREV_FALLTHROUGH flags +from the original lhs token to the replacement token. Copying that way +the PREV_WHITE flag is needed for the #__VA_OPT__ handling and copying +over PREV_FALLTHROUGH fixes the new Wimplicit-fallthrough-38.c test. + +2021-12-01 Jakub Jelinek + + PR preprocessor/103415 +libcpp/ + * macro.c (stringify_arg): Remove va_opt argument and va_opt handling. + (paste_tokens): On successful paste or in PREV_WHITE and + PREV_FALLTHROUGH flags from the *plhs token to the new token. + (replace_args): Adjust stringify_arg callers. For #__VA_OPT__, + perform token pasting in a separate loop before stringify_arg call. +gcc/testsuite/ + * c-c++-common/cpp/va-opt-8.c: New test. + * c-c++-common/Wimplicit-fallthrough-38.c: New test. + +--- libcpp/macro.c.jj ++++ libcpp/macro.c +@@ -295,7 +295,7 @@ static cpp_context *next_context (cpp_re + static const cpp_token *padding_token (cpp_reader *, const cpp_token *); + static const cpp_token *new_string_token (cpp_reader *, uchar *, unsigned int); + static const cpp_token *stringify_arg (cpp_reader *, const cpp_token **, +- unsigned int, bool); ++ unsigned int); + static void paste_all_tokens (cpp_reader *, const cpp_token *); + static bool paste_tokens (cpp_reader *, location_t, + const cpp_token **, const cpp_token *); +@@ -826,8 +826,7 @@ cpp_quote_string (uchar *dest, const uch + /* Convert a token sequence FIRST to FIRST+COUNT-1 to a single string token + according to the rules of the ISO C #-operator. */ + static const cpp_token * +-stringify_arg (cpp_reader *pfile, const cpp_token **first, unsigned int count, +- bool va_opt) ++stringify_arg (cpp_reader *pfile, const cpp_token **first, unsigned int count) + { + unsigned char *dest; + unsigned int i, escape_it, backslash_count = 0; +@@ -844,24 +843,6 @@ stringify_arg (cpp_reader *pfile, const + { + const cpp_token *token = first[i]; + +- if (va_opt && (token->flags & PASTE_LEFT)) +- { +- location_t virt_loc = pfile->invocation_location; +- const cpp_token *rhs; +- do +- { +- if (i == count) +- abort (); +- rhs = first[++i]; +- if (!paste_tokens (pfile, virt_loc, &token, rhs)) +- { +- --i; +- break; +- } +- } +- while (rhs->flags & PASTE_LEFT); +- } +- + if (token->type == CPP_PADDING) + { + if (source == NULL +@@ -995,6 +976,7 @@ paste_tokens (cpp_reader *pfile, locatio + return false; + } + ++ lhs->flags |= (*plhs)->flags & (PREV_WHITE | PREV_FALLTHROUGH); + *plhs = lhs; + _cpp_pop_buffer (pfile); + return true; +@@ -1937,8 +1919,7 @@ replace_args (cpp_reader *pfile, cpp_has + if (src->flags & STRINGIFY_ARG) + { + if (!arg->stringified) +- arg->stringified = stringify_arg (pfile, arg->first, arg->count, +- false); ++ arg->stringified = stringify_arg (pfile, arg->first, arg->count); + } + else if ((src->flags & PASTE_LEFT) + || (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT))) +@@ -2065,11 +2046,46 @@ replace_args (cpp_reader *pfile, cpp_has + { + unsigned int count + = start ? paste_flag - start : tokens_buff_count (buff); +- const cpp_token *t +- = stringify_arg (pfile, +- start ? start + 1 +- : (const cpp_token **) (buff->base), +- count, true); ++ const cpp_token **first ++ = start ? start + 1 ++ : (const cpp_token **) (buff->base); ++ unsigned int i, j; ++ ++ /* Paste any tokens that need to be pasted before calling ++ stringify_arg, because stringify_arg uses pfile->u_buff ++ which paste_tokens can use as well. */ ++ for (i = 0, j = 0; i < count; i++, j++) ++ { ++ const cpp_token *token = first[i]; ++ ++ if (token->flags & PASTE_LEFT) ++ { ++ location_t virt_loc = pfile->invocation_location; ++ const cpp_token *rhs; ++ do ++ { ++ if (i == count) ++ abort (); ++ rhs = first[++i]; ++ if (!paste_tokens (pfile, virt_loc, &token, rhs)) ++ { ++ --i; ++ break; ++ } ++ } ++ while (rhs->flags & PASTE_LEFT); ++ } ++ ++ first[j] = token; ++ } ++ if (j != i) ++ { ++ while (i-- != j) ++ tokens_buff_remove_last_token (buff); ++ count = j; ++ } ++ ++ const cpp_token *t = stringify_arg (pfile, first, count); + while (count--) + tokens_buff_remove_last_token (buff); + if (src->flags & PASTE_LEFT) +--- gcc/testsuite/c-c++-common/cpp/va-opt-8.c.jj ++++ gcc/testsuite/c-c++-common/cpp/va-opt-8.c +@@ -0,0 +1,18 @@ ++/* PR preprocessor/103415 */ ++/* { dg-do run } */ ++/* { dg-options "-std=gnu99" { target c } } */ ++/* { dg-options "-std=c++20" { target c++ } } */ ++ ++#define n(x, ...) = #__VA_OPT__(x##3) ++#define o(x, ...) #__VA_OPT__(x##__VA_ARGS__##9) ++const char *c n(1 2, 4); ++const char *d = o(5 6, 7 8); ++ ++int ++main () ++{ ++ if (__builtin_strcmp (c, "1 23") ++ || __builtin_strcmp (d, "5 67 89")) ++ __builtin_abort (); ++ return 0; ++} +--- gcc/testsuite/c-c++-common/Wimplicit-fallthrough-38.c.jj ++++ gcc/testsuite/c-c++-common/Wimplicit-fallthrough-38.c +@@ -0,0 +1,24 @@ ++/* { dg-do compile } */ ++/* { dg-options "-Wimplicit-fallthrough=3" } */ ++ ++#define FOO \ ++int \ ++foo (int a) \ ++{ \ ++ switch (a) \ ++ { \ ++ case 1: \ ++ ++a; \ ++ /* FALLTHRU */ \ ++ case 2: \ ++ ++a; \ ++ /* FALLTHRU */ \ ++ ca##se 3: \ ++ ++a; \ ++ default: \ ++ break; \ ++ } \ ++ return a; \ ++} ++ ++FOO diff --git a/SOURCES/gcc11-stringify-__VA_OPT__.patch b/SOURCES/gcc11-stringify-__VA_OPT__.patch new file mode 100644 index 0000000..101b026 --- /dev/null +++ b/SOURCES/gcc11-stringify-__VA_OPT__.patch @@ -0,0 +1,307 @@ +c++: Add C++20 #__VA_OPT__ support + +The following patch implements C++20 # __VA_OPT__ (...) support. +Testcases cover what I came up with myself and what LLVM has for #__VA_OPT__ +in its testsuite and the string literals are identical between the two +compilers on the va-opt-5.c testcase. + +2021-08-17 Jakub Jelinek + +libcpp/ + * macro.c (vaopt_state): Add m_stringify member. + (vaopt_state::vaopt_state): Initialize it. + (vaopt_state::update): Overwrite it. + (vaopt_state::stringify): New method. + (stringify_arg): Replace arg argument with first, count arguments + and add va_opt argument. Use first instead of arg->first and + count instead of arg->count, for va_opt add paste_tokens handling. + (paste_tokens): Fix up len calculation. Don't spell rhs twice, + instead use %.*s to supply lhs and rhs spelling lengths. Don't call + _cpp_backup_tokens here. + (paste_all_tokens): Call it here instead. + (replace_args): Adjust stringify_arg caller. For vaopt_state::END + if stringify is true handle __VA_OPT__ stringification. + (create_iso_definition): Handle # __VA_OPT__ similarly to # macro_arg. +gcc/testsuite/ + * c-c++-common/cpp/va-opt-5.c: New test. + * c-c++-common/cpp/va-opt-6.c: New test. + +--- libcpp/macro.c ++++ libcpp/macro.c +@@ -118,6 +118,7 @@ class vaopt_state { + m_arg (arg), + m_variadic (is_variadic), + m_last_was_paste (false), ++ m_stringify (false), + m_state (0), + m_paste_location (0), + m_location (0), +@@ -145,6 +146,7 @@ class vaopt_state { + } + ++m_state; + m_location = token->src_loc; ++ m_stringify = (token->flags & STRINGIFY_ARG) != 0; + return BEGIN; + } + else if (m_state == 1) +@@ -234,6 +236,12 @@ class vaopt_state { + return m_state == 0; + } + ++ /* Return true for # __VA_OPT__. */ ++ bool stringify () const ++ { ++ return m_stringify; ++ } ++ + private: + + /* The cpp_reader. */ +@@ -247,6 +255,8 @@ class vaopt_state { + /* If true, the previous token was ##. This is used to detect when + a paste occurs at the end of the sequence. */ + bool m_last_was_paste; ++ /* True for #__VA_OPT__. */ ++ bool m_stringify; + + /* The state variable: + 0 means not parsing +@@ -284,7 +294,8 @@ static _cpp_buff *collect_args (cpp_read + static cpp_context *next_context (cpp_reader *); + static const cpp_token *padding_token (cpp_reader *, const cpp_token *); + static const cpp_token *new_string_token (cpp_reader *, uchar *, unsigned int); +-static const cpp_token *stringify_arg (cpp_reader *, macro_arg *); ++static const cpp_token *stringify_arg (cpp_reader *, const cpp_token **, ++ unsigned int, bool); + static void paste_all_tokens (cpp_reader *, const cpp_token *); + static bool paste_tokens (cpp_reader *, location_t, + const cpp_token **, const cpp_token *); +@@ -812,10 +823,11 @@ cpp_quote_string (uchar *dest, const uch + return dest; + } + +-/* Convert a token sequence ARG to a single string token according to +- the rules of the ISO C #-operator. */ ++/* Convert a token sequence FIRST to FIRST+COUNT-1 to a single string token ++ according to the rules of the ISO C #-operator. */ + static const cpp_token * +-stringify_arg (cpp_reader *pfile, macro_arg *arg) ++stringify_arg (cpp_reader *pfile, const cpp_token **first, unsigned int count, ++ bool va_opt) + { + unsigned char *dest; + unsigned int i, escape_it, backslash_count = 0; +@@ -828,9 +840,27 @@ stringify_arg (cpp_reader *pfile, macro_ + *dest++ = '"'; + + /* Loop, reading in the argument's tokens. */ +- for (i = 0; i < arg->count; i++) ++ for (i = 0; i < count; i++) + { +- const cpp_token *token = arg->first[i]; ++ const cpp_token *token = first[i]; ++ ++ if (va_opt && (token->flags & PASTE_LEFT)) ++ { ++ location_t virt_loc = pfile->invocation_location; ++ const cpp_token *rhs; ++ do ++ { ++ if (i == count) ++ abort (); ++ rhs = first[++i]; ++ if (!paste_tokens (pfile, virt_loc, &token, rhs)) ++ { ++ --i; ++ break; ++ } ++ } ++ while (rhs->flags & PASTE_LEFT); ++ } + + if (token->type == CPP_PADDING) + { +@@ -917,7 +947,7 @@ paste_tokens (cpp_reader *pfile, locatio + cpp_token *lhs; + unsigned int len; + +- len = cpp_token_len (*plhs) + cpp_token_len (rhs) + 1; ++ len = cpp_token_len (*plhs) + cpp_token_len (rhs) + 2; + buf = (unsigned char *) alloca (len); + end = lhsend = cpp_spell_token (pfile, *plhs, buf, true); + +@@ -943,8 +973,10 @@ paste_tokens (cpp_reader *pfile, locatio + location_t saved_loc = lhs->src_loc; + + _cpp_pop_buffer (pfile); +- _cpp_backup_tokens (pfile, 1); +- *lhsend = '\0'; ++ ++ unsigned char *rhsstart = lhsend; ++ if ((*plhs)->type == CPP_DIV && rhs->type != CPP_EQ) ++ rhsstart++; + + /* We have to remove the PASTE_LEFT flag from the old lhs, but + we want to keep the new location. */ +@@ -956,8 +988,10 @@ paste_tokens (cpp_reader *pfile, locatio + /* Mandatory error for all apart from assembler. */ + if (CPP_OPTION (pfile, lang) != CLK_ASM) + cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0, +- "pasting \"%s\" and \"%s\" does not give a valid preprocessing token", +- buf, cpp_token_as_text (pfile, rhs)); ++ "pasting \"%.*s\" and \"%.*s\" does not give " ++ "a valid preprocessing token", ++ (int) (lhsend - buf), buf, ++ (int) (end - rhsstart), rhsstart); + return false; + } + +@@ -1033,7 +1067,10 @@ paste_all_tokens (cpp_reader *pfile, con + abort (); + } + if (!paste_tokens (pfile, virt_loc, &lhs, rhs)) +- break; ++ { ++ _cpp_backup_tokens (pfile, 1); ++ break; ++ } + } + while (rhs->flags & PASTE_LEFT); + +@@ -1900,7 +1937,8 @@ replace_args (cpp_reader *pfile, cpp_has + if (src->flags & STRINGIFY_ARG) + { + if (!arg->stringified) +- arg->stringified = stringify_arg (pfile, arg); ++ arg->stringified = stringify_arg (pfile, arg->first, arg->count, ++ false); + } + else if ((src->flags & PASTE_LEFT) + || (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT))) +@@ -2023,6 +2061,24 @@ replace_args (cpp_reader *pfile, cpp_has + paste_flag = tokens_buff_last_token_ptr (buff); + } + ++ if (vaopt_tracker.stringify ()) ++ { ++ unsigned int count ++ = start ? paste_flag - start : tokens_buff_count (buff); ++ const cpp_token *t ++ = stringify_arg (pfile, ++ start ? start + 1 ++ : (const cpp_token **) (buff->base), ++ count, true); ++ while (count--) ++ tokens_buff_remove_last_token (buff); ++ if (src->flags & PASTE_LEFT) ++ copy_paste_flag (pfile, &t, src); ++ tokens_buff_add_token (buff, virt_locs, ++ t, t->src_loc, t->src_loc, ++ NULL, 0); ++ continue; ++ } + if (start && paste_flag == start && (*start)->flags & PASTE_LEFT) + /* If __VA_OPT__ expands to nothing (either because __VA_ARGS__ + is empty or because it is __VA_OPT__() ), drop PASTE_LEFT +@@ -3584,7 +3640,10 @@ create_iso_definition (cpp_reader *pfile + function-like macros when lexing the subsequent token. */ + if (macro->count > 1 && token[-1].type == CPP_HASH && macro->fun_like) + { +- if (token->type == CPP_MACRO_ARG) ++ if (token->type == CPP_MACRO_ARG ++ || (macro->variadic ++ && token->type == CPP_NAME ++ && token->val.node.node == pfile->spec_nodes.n__VA_OPT__)) + { + if (token->flags & PREV_WHITE) + token->flags |= SP_PREV_WHITE; +--- gcc/testsuite/c-c++-common/cpp/va-opt-5.c ++++ gcc/testsuite/c-c++-common/cpp/va-opt-5.c +@@ -0,0 +1,67 @@ ++/* { dg-do run } */ ++/* { dg-options "-std=gnu99" { target c } } */ ++/* { dg-options "-std=c++20" { target c++ } } */ ++ ++#define lparen ( ++#define a0 fooa0 ++#define a1 fooa1 a0 ++#define a2 fooa2 a1 ++#define a3 fooa3 a2 ++#define a() b lparen ) ++#define b() c lparen ) ++#define c() d lparen ) ++#define g h ++#define i(j) j ++#define f(...) #__VA_OPT__(g i(0)) ++#define k(x,...) # __VA_OPT__(x) #x #__VA_OPT__(__VA_ARGS__) ++#define l(x,...) #__VA_OPT__(a1 x) ++#define m(x,...) "a()" #__VA_OPT__(a3 __VA_ARGS__ x ## __VA_ARGS__ ## x ## c a3) "a()" ++#define n(x,...) = #__VA_OPT__(a3 __VA_ARGS__ x ## __VA_ARGS__ ## x ## c a3) #x #__VA_OPT__(a0 __VA_ARGS__ x ## __VA_ARGS__ ## x ## c a0) ; ++#define o(x, ...) #__VA_OPT__(x##x x##x) ++#define p(x, ...) #__VA_OPT__(_Pragma ("foobar")) ++#define q(...) #__VA_OPT__(/* foo */x/* bar */) ++const char *v1 = f(); ++const char *v2 = f(123); ++const char *v3 = k(1); ++const char *v4 = k(1, 2, 3 ); ++const char *v5 = l(a()); ++const char *v6 = l(a1 a(), 1); ++const char *v7 = m(); ++const char *v8 = m(,); ++const char *v9 = m(,a3); ++const char *v10 = m(a3,a(),a0); ++const char *v11 n() ++const char *v12 n(,) ++const char *v13 n(,a0) ++const char *v14 n(a0, a(),a0) ++const char *v15 = o(, 0); ++const char *v16 = p(0); ++const char *v17 = p(0, 1); ++const char *v18 = q(); ++const char *v19 = q(1); ++ ++int ++main () ++{ ++ if (__builtin_strcmp (v1, "") ++ || __builtin_strcmp (v2, "g i(0)") ++ || __builtin_strcmp (v3, "1") ++ || __builtin_strcmp (v4, "112, 3") ++ || __builtin_strcmp (v5, "") ++ || __builtin_strcmp (v6, "a1 fooa1 fooa0 b ( )") ++ || __builtin_strcmp (v7, "a()a()") ++ || __builtin_strcmp (v8, "a()a()") ++ || __builtin_strcmp (v9, "a()a3 fooa3 fooa2 fooa1 fooa0 a3c a3a()") ++ || __builtin_strcmp (v10, "a()a3 b ( ),fooa0 a3a(),a0a3c a3a()") ++ || __builtin_strcmp (v11, "") ++ || __builtin_strcmp (v12, "") ++ || __builtin_strcmp (v13, "a3 fooa0 a0c a3a0 fooa0 a0c a0") ++ || __builtin_strcmp (v14, "a3 b ( ),fooa0 a0a(),a0a0c a3a0a0 b ( ),fooa0 a0a(),a0a0c a0") ++ || __builtin_strcmp (v15, "") ++ || __builtin_strcmp (v16, "") ++ || __builtin_strcmp (v17, "_Pragma (\"foobar\")") ++ || __builtin_strcmp (v18, "") ++ || __builtin_strcmp (v19, "x")) ++ __builtin_abort (); ++ return 0; ++} +--- gcc/testsuite/c-c++-common/cpp/va-opt-6.c ++++ gcc/testsuite/c-c++-common/cpp/va-opt-6.c +@@ -0,0 +1,17 @@ ++/* { dg-do preprocess } */ ++/* { dg-options "-std=gnu99" { target c } } */ ++/* { dg-options "-std=c++20" { target c++ } } */ ++ ++#define a "" ++#define b(...) a ## #__VA_OPT__(1) /* { dg-error "pasting \"a\" and \"\"\"\" does not give a valid preprocessing token" } */ ++#define c(...) a ## #__VA_OPT__(1) /* { dg-error "pasting \"a\" and \"\"1\"\" does not give a valid preprocessing token" } */ ++#define d(...) #__VA_OPT__(1) ## ! ++#define e(...) #__VA_OPT__(1) ## ! ++#define f(...) #__VA_OPT__(. ## !) ++#define g(...) #__VA_OPT__(. ## !) ++b() ++c(1) ++d( ) /* { dg-error "pasting \"\"\"\" and \"!\" does not give a valid preprocessing token" } */ ++e( 1 ) /* { dg-error "pasting \"\"1\"\" and \"!\" does not give a valid preprocessing token" } */ ++f() ++g(0) /* { dg-error "pasting \".\" and \"!\" does not give a valid preprocessing token" } */ diff --git a/SOURCES/gcc11-tremont1.patch b/SOURCES/gcc11-tremont1.patch new file mode 100644 index 0000000..6442f0b --- /dev/null +++ b/SOURCES/gcc11-tremont1.patch @@ -0,0 +1,294 @@ +From cbd145b132c79c36e990a0eaf10c86159009f18d Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Wed, 15 Sep 2021 14:15:10 +0800 +Subject: [PATCH 1/3] x86: Update -mtune=tremont + +Initial -mtune=tremont update + +1. Use Haswell scheduling model. +2. Assume that stack engine allows to execute push&pop instructions in +parall. +3. Prepare for scheduling pass as -mtune=generic. +4. Use the same issue rate as -mtune=generic. +5. Enable partial_reg_dependency. +6. Disable accumulate_outgoing_args +7. Enable use_leave +8. Enable push_memory +9. Disable four_jump_limit +10. Disable opt_agu +11. Disable avoid_lea_for_addr +12. Disable avoid_mem_opnd_for_cmove +13. Enable misaligned_move_string_pro_epilogues +14. Enable use_cltd +16. Enable avoid_false_dep_for_bmi +17. Enable avoid_mfence +18. Disable expand_abs +19. Enable sse_typeless_stores +20. Enable sse_load0_by_pxor +21. Disable split_mem_opnd_for_fp_converts +22. Disable slow_pshufb +23. Enable partial_reg_dependency + +This is the first patch to tune for Tremont. With all patches applied, +performance impacts on SPEC CPU 2017 are: + +500.perlbench_r 1.81% +502.gcc_r 0.57% +505.mcf_r 1.16% +520.omnetpp_r 0.00% +523.xalancbmk_r 0.00% +525.x264_r 4.55% +531.deepsjeng_r 0.00% +541.leela_r 0.39% +548.exchange2_r 1.13% +557.xz_r 0.00% +geomean for intrate 0.95% +503.bwaves_r 0.00% +507.cactuBSSN_r 6.94% +508.namd_r 12.37% +510.parest_r 1.01% +511.povray_r 3.70% +519.lbm_r 36.61% +521.wrf_r 8.79% +526.blender_r 2.91% +527.cam4_r 6.23% +538.imagick_r 0.28% +544.nab_r 21.99% +549.fotonik3d_r 3.63% +554.roms_r -1.20% +geomean for fprate 7.50% + +gcc/ChangeLog + + * common/config/i386/i386-common.c: Use Haswell scheduling model + for Tremont. + * config/i386/i386.c (ix86_sched_init_global): Prepare for Tremont + scheduling pass. + * config/i386/x86-tune-sched.c (ix86_issue_rate): Change Tremont + issue rate to 4. + (ix86_adjust_cost): Handle Tremont. + * config/i386/x86-tune.def (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY): + Enable for Tremont. + (X86_TUNE_USE_LEAVE): Likewise. + (X86_TUNE_PUSH_MEMORY): Likewise. + (X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES): Likewise. + (X86_TUNE_USE_CLTD): Likewise. + (X86_TUNE_AVOID_FALSE_DEP_FOR_BMI): Likewise. + (X86_TUNE_AVOID_MFENCE): Likewise. + (X86_TUNE_SSE_TYPELESS_STORES): Likewise. + (X86_TUNE_SSE_LOAD0_BY_PXOR): Likewise. + (X86_TUNE_ACCUMULATE_OUTGOING_ARGS): Disable for Tremont. + (X86_TUNE_FOUR_JUMP_LIMIT): Likewise. + (X86_TUNE_OPT_AGU): Likewise. + (X86_TUNE_AVOID_LEA_FOR_ADDR): Likewise. + (X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE): Likewise. + (X86_TUNE_EXPAND_ABS): Likewise. + (X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS): Likewise. + (X86_TUNE_SLOW_PSHUFB): Likewise. +--- + gcc/common/config/i386/i386-common.c | 2 +- + gcc/config/i386/i386.c | 1 + + gcc/config/i386/x86-tune-sched.c | 2 ++ + gcc/config/i386/x86-tune.def | 37 ++++++++++++++-------------- + 4 files changed, 23 insertions(+), 19 deletions(-) + +diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c +index 38dbb9d9263..ef382ec9a22 100644 +--- a/gcc/common/config/i386/i386-common.c ++++ b/gcc/common/config/i386/i386-common.c +@@ -1916,7 +1916,7 @@ const pta processor_alias_table[] = + M_CPU_TYPE (INTEL_GOLDMONT), P_PROC_SSE4_2}, + {"goldmont-plus", PROCESSOR_GOLDMONT_PLUS, CPU_GLM, PTA_GOLDMONT_PLUS, + M_CPU_TYPE (INTEL_GOLDMONT_PLUS), P_PROC_SSE4_2}, +- {"tremont", PROCESSOR_TREMONT, CPU_GLM, PTA_TREMONT, ++ {"tremont", PROCESSOR_TREMONT, CPU_HASWELL, PTA_TREMONT, + M_CPU_TYPE (INTEL_TREMONT), P_PROC_SSE4_2}, + {"knl", PROCESSOR_KNL, CPU_SLM, PTA_KNL, + M_CPU_TYPE (INTEL_KNL), P_PROC_AVX512F}, +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c +index 42c47d2b12b..fc2a27b5cbf 100644 +--- a/gcc/config/i386/i386.c ++++ b/gcc/config/i386/i386.c +@@ -16732,6 +16732,7 @@ ix86_sched_init_global (FILE *, int, int) + case PROCESSOR_NEHALEM: + case PROCESSOR_SANDYBRIDGE: + case PROCESSOR_HASWELL: ++ case PROCESSOR_TREMONT: + case PROCESSOR_GENERIC: + /* Do not perform multipass scheduling for pre-reload schedule + to save compile time. */ +diff --git a/gcc/config/i386/x86-tune-sched.c b/gcc/config/i386/x86-tune-sched.c +index 2bcc64b865a..278035eec0b 100644 +--- a/gcc/config/i386/x86-tune-sched.c ++++ b/gcc/config/i386/x86-tune-sched.c +@@ -71,6 +71,7 @@ ix86_issue_rate (void) + case PROCESSOR_NEHALEM: + case PROCESSOR_SANDYBRIDGE: + case PROCESSOR_HASWELL: ++ case PROCESSOR_TREMONT: + case PROCESSOR_GENERIC: + return 4; + +@@ -430,6 +431,7 @@ ix86_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost, + case PROCESSOR_NEHALEM: + case PROCESSOR_SANDYBRIDGE: + case PROCESSOR_HASWELL: ++ case PROCESSOR_TREMONT: + case PROCESSOR_GENERIC: + /* Stack engine allows to execute push&pop instructions in parall. */ + if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP) +diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def +index eb057a67750..6bd7087a03f 100644 +--- a/gcc/config/i386/x86-tune.def ++++ b/gcc/config/i386/x86-tune.def +@@ -62,7 +62,7 @@ DEF_TUNE (X86_TUNE_PARTIAL_REG_DEPENDENCY, "partial_reg_dependency", + that can be partly masked by careful scheduling of moves. */ + DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY, "sse_partial_reg_dependency", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_AMDFAM10 +- | m_BDVER | m_ZNVER | m_GENERIC) ++ | m_BDVER | m_ZNVER | m_TREMONT | m_GENERIC) + + /* X86_TUNE_SSE_SPLIT_REGS: Set for machines where the type and dependencies + are resolved on SSE register parts instead of whole registers, so we may +@@ -136,7 +136,7 @@ DEF_TUNE (X86_TUNE_FUSE_ALU_AND_BRANCH, "fuse_alu_and_branch", + + DEF_TUNE (X86_TUNE_ACCUMULATE_OUTGOING_ARGS, "accumulate_outgoing_args", + m_PPRO | m_P4_NOCONA | m_BONNELL | m_SILVERMONT | m_KNL | m_KNM | m_INTEL +- | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_ATHLON_K8) ++ | m_GOLDMONT | m_GOLDMONT_PLUS | m_ATHLON_K8) + + /* X86_TUNE_PROLOGUE_USING_MOVE: Do not use push/pop in prologues that are + considered on critical path. */ +@@ -150,14 +150,15 @@ DEF_TUNE (X86_TUNE_EPILOGUE_USING_MOVE, "epilogue_using_move", + + /* X86_TUNE_USE_LEAVE: Use "leave" instruction in epilogues where it fits. */ + DEF_TUNE (X86_TUNE_USE_LEAVE, "use_leave", +- m_386 | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE | m_GENERIC) ++ m_386 | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE | m_TREMONT ++ | m_GENERIC) + + /* X86_TUNE_PUSH_MEMORY: Enable generation of "push mem" instructions. + Some chips, like 486 and Pentium works faster with separate load + and push instructions. */ + DEF_TUNE (X86_TUNE_PUSH_MEMORY, "push_memory", + m_386 | m_P4_NOCONA | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE +- | m_GENERIC) ++ | m_TREMONT | m_GENERIC) + + /* X86_TUNE_SINGLE_PUSH: Enable if single push insn is preferred + over esp subtraction. */ +@@ -198,8 +199,7 @@ DEF_TUNE (X86_TUNE_PAD_RETURNS, "pad_returns", + than 4 branch instructions in the 16 byte window. */ + DEF_TUNE (X86_TUNE_FOUR_JUMP_LIMIT, "four_jump_limit", + m_PPRO | m_P4_NOCONA | m_BONNELL | m_SILVERMONT | m_KNL | m_KNM +- | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_INTEL | m_ATHLON_K8 +- | m_AMDFAM10) ++ | m_GOLDMONT | m_GOLDMONT_PLUS | m_INTEL | m_ATHLON_K8 | m_AMDFAM10) + + /*****************************************************************************/ + /* Integer instruction selection tuning */ +@@ -240,11 +240,11 @@ DEF_TUNE (X86_TUNE_INTEGER_DFMODE_MOVES, "integer_dfmode_moves", + /* X86_TUNE_OPT_AGU: Optimize for Address Generation Unit. This flag + will impact LEA instruction selection. */ + DEF_TUNE (X86_TUNE_OPT_AGU, "opt_agu", m_BONNELL | m_SILVERMONT | m_KNL +- | m_KNM | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_INTEL) ++ | m_KNM | m_GOLDMONT | m_GOLDMONT_PLUS | m_INTEL) + + /* X86_TUNE_AVOID_LEA_FOR_ADDR: Avoid lea for address computation. */ + DEF_TUNE (X86_TUNE_AVOID_LEA_FOR_ADDR, "avoid_lea_for_addr", +- m_BONNELL | m_SILVERMONT | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT ++ m_BONNELL | m_SILVERMONT | m_GOLDMONT | m_GOLDMONT_PLUS + | m_KNL | m_KNM) + + /* X86_TUNE_SLOW_IMUL_IMM32_MEM: Imul of 32-bit constant and memory is +@@ -263,7 +263,7 @@ DEF_TUNE (X86_TUNE_SLOW_IMUL_IMM8, "slow_imul_imm8", + a conditional move. */ + DEF_TUNE (X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE, "avoid_mem_opnd_for_cmove", + m_BONNELL | m_SILVERMONT | m_GOLDMONT | m_GOLDMONT_PLUS | m_KNL +- | m_KNM | m_TREMONT | m_INTEL) ++ | m_KNM | m_INTEL) + + /* X86_TUNE_SINGLE_STRINGOP: Enable use of single string operations, such + as MOVS and STOS (without a REP prefix) to move/set sequences of bytes. */ +@@ -282,7 +282,8 @@ DEF_TUNE (X86_TUNE_PREFER_KNOWN_REP_MOVSB_STOSB, + FIXME: This may actualy be a win on more targets than listed here. */ + DEF_TUNE (X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES, + "misaligned_move_string_pro_epilogues", +- m_386 | m_486 | m_CORE_ALL | m_AMD_MULTIPLE | m_GENERIC) ++ m_386 | m_486 | m_CORE_ALL | m_AMD_MULTIPLE | m_TREMONT ++ | m_GENERIC) + + /* X86_TUNE_USE_SAHF: Controls use of SAHF. */ + DEF_TUNE (X86_TUNE_USE_SAHF, "use_sahf", +@@ -294,7 +295,7 @@ DEF_TUNE (X86_TUNE_USE_SAHF, "use_sahf", + /* X86_TUNE_USE_CLTD: Controls use of CLTD and CTQO instructions. */ + DEF_TUNE (X86_TUNE_USE_CLTD, "use_cltd", + ~(m_PENT | m_LAKEMONT | m_BONNELL | m_SILVERMONT | m_KNL | m_KNM | m_INTEL +- | m_K6 | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT)) ++ | m_K6 | m_GOLDMONT | m_GOLDMONT_PLUS)) + + /* X86_TUNE_USE_BT: Enable use of BT (bit test) instructions. */ + DEF_TUNE (X86_TUNE_USE_BT, "use_bt", +@@ -305,7 +306,7 @@ DEF_TUNE (X86_TUNE_USE_BT, "use_bt", + /* X86_TUNE_AVOID_FALSE_DEP_FOR_BMI: Avoid false dependency + for bit-manipulation instructions. */ + DEF_TUNE (X86_TUNE_AVOID_FALSE_DEP_FOR_BMI, "avoid_false_dep_for_bmi", +- m_SANDYBRIDGE | m_CORE_AVX2 | m_GENERIC) ++ m_SANDYBRIDGE | m_CORE_AVX2 | m_TREMONT | m_GENERIC) + + /* X86_TUNE_ADJUST_UNROLL: This enables adjusting the unroll factor based + on hardware capabilities. Bdver3 hardware has a loop buffer which makes +@@ -321,14 +322,14 @@ DEF_TUNE (X86_TUNE_ONE_IF_CONV_INSN, "one_if_conv_insn", + + /* X86_TUNE_AVOID_MFENCE: Use lock prefixed instructions instead of mfence. */ + DEF_TUNE (X86_TUNE_AVOID_MFENCE, "avoid_mfence", +- m_CORE_ALL | m_BDVER | m_ZNVER | m_GENERIC) ++ m_CORE_ALL | m_BDVER | m_ZNVER | m_TREMONT | m_GENERIC) + + /* X86_TUNE_EXPAND_ABS: This enables a new abs pattern by + generating instructions for abs (x) = (((signed) x >> (W-1) ^ x) - + (signed) x >> (W-1)) instead of cmove or SSE max/abs instructions. */ + DEF_TUNE (X86_TUNE_EXPAND_ABS, "expand_abs", + m_CORE_ALL | m_SILVERMONT | m_KNL | m_KNM | m_GOLDMONT +- | m_GOLDMONT_PLUS | m_TREMONT ) ++ | m_GOLDMONT_PLUS) + + /*****************************************************************************/ + /* 387 instruction selection tuning */ +@@ -386,13 +387,13 @@ DEF_TUNE (X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL, "sse_packed_single_insn_optim + + /* X86_TUNE_SSE_TYPELESS_STORES: Always movaps/movups for 128bit stores. */ + DEF_TUNE (X86_TUNE_SSE_TYPELESS_STORES, "sse_typeless_stores", +- m_AMD_MULTIPLE | m_CORE_ALL | m_GENERIC) ++ m_AMD_MULTIPLE | m_CORE_ALL | m_TREMONT | m_GENERIC) + + /* X86_TUNE_SSE_LOAD0_BY_PXOR: Always use pxor to load0 as opposed to + xorps/xorpd and other variants. */ + DEF_TUNE (X86_TUNE_SSE_LOAD0_BY_PXOR, "sse_load0_by_pxor", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BDVER | m_BTVER | m_ZNVER +- | m_GENERIC) ++ | m_TREMONT | m_GENERIC) + + /* X86_TUNE_INTER_UNIT_MOVES_TO_VEC: Enable moves in from integer + to SSE registers. If disabled, the moves will be done by storing +@@ -419,7 +420,7 @@ DEF_TUNE (X86_TUNE_INTER_UNIT_CONVERSIONS, "inter_unit_conversions", + fp converts to destination register. */ + DEF_TUNE (X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS, "split_mem_opnd_for_fp_converts", + m_SILVERMONT | m_KNL | m_KNM | m_GOLDMONT | m_GOLDMONT_PLUS +- | m_TREMONT | m_INTEL) ++ | m_INTEL) + + /* X86_TUNE_USE_VECTOR_FP_CONVERTS: Prefer vector packed SSE conversion + from FP to FP. This form of instructions avoids partial write to the +@@ -434,7 +435,7 @@ DEF_TUNE (X86_TUNE_USE_VECTOR_CONVERTS, "use_vector_converts", m_AMDFAM10) + /* X86_TUNE_SLOW_SHUFB: Indicates tunings with slow pshufb instruction. */ + DEF_TUNE (X86_TUNE_SLOW_PSHUFB, "slow_pshufb", + m_BONNELL | m_SILVERMONT | m_KNL | m_KNM | m_GOLDMONT +- | m_GOLDMONT_PLUS | m_TREMONT | m_INTEL) ++ | m_GOLDMONT_PLUS | m_INTEL) + + /* X86_TUNE_AVOID_4BYTE_PREFIXES: Avoid instructions requiring 4+ bytes of prefixes. */ + DEF_TUNE (X86_TUNE_AVOID_4BYTE_PREFIXES, "avoid_4byte_prefixes", +-- +2.18.2 + diff --git a/SOURCES/gcc11-tremont2.patch b/SOURCES/gcc11-tremont2.patch new file mode 100644 index 0000000..b452b2a --- /dev/null +++ b/SOURCES/gcc11-tremont2.patch @@ -0,0 +1,196 @@ +From 80c2ed8228817fb6438120997227811a746272ba Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Wed, 15 Sep 2021 14:17:08 +0800 +Subject: [PATCH 2/3] x86: Update memcpy/memset inline strategies for + -mtune=tremont + +Simply memcpy and memset inline strategies to avoid branches for +-mtune=tremont: + +1. Create Tremont cost model from generic cost model. +2. With MOVE_RATIO and CLEAR_RATIO == 17, GCC will use integer/vector + load and store for up to 16 * 16 (256) bytes when the data size is + fixed and known. +3. Inline only if data size is known to be <= 256. + a. Use "rep movsb/stosb" with simple code sequence if the data size + is a constant. + b. Use loop if data size is not a constant. +4. Use memcpy/memset libray function if data size is unknown or > 256. + + * config/i386/i386-options.c (processor_cost_table): Use + tremont_cost for Tremont. + * config/i386/x86-tune-costs.h (tremont_memcpy): New. + (tremont_memset): Likewise. + (tremont_cost): Likewise. + * config/i386/x86-tune.def (X86_TUNE_PREFER_KNOWN_REP_MOVSB_STOSB): + Enable for Tremont. +--- + gcc/config/i386/i386-options.c | 2 +- + gcc/config/i386/x86-tune-costs.h | 124 +++++++++++++++++++++++++++++++ + gcc/config/i386/x86-tune.def | 2 +- + 3 files changed, 126 insertions(+), 2 deletions(-) + +diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c +index 19632b5fd6b..4b77d62926f 100644 +--- a/gcc/config/i386/i386-options.c ++++ b/gcc/config/i386/i386-options.c +@@ -719,7 +719,7 @@ static const struct processor_costs *processor_cost_table[] = + &slm_cost, + &slm_cost, + &slm_cost, +- &slm_cost, ++ &tremont_cost, + &slm_cost, + &slm_cost, + &skylake_cost, +diff --git a/gcc/config/i386/x86-tune-costs.h b/gcc/config/i386/x86-tune-costs.h +index ffe810f2bcb..93644be9cb3 100644 +--- a/gcc/config/i386/x86-tune-costs.h ++++ b/gcc/config/i386/x86-tune-costs.h +@@ -2734,6 +2734,130 @@ struct processor_costs slm_cost = { + "16", /* Func alignment. */ + }; + ++static stringop_algs tremont_memcpy[2] = { ++ {libcall, ++ {{256, rep_prefix_1_byte, true}, ++ {256, loop, false}, ++ {-1, libcall, false}}}, ++ {libcall, ++ {{256, rep_prefix_1_byte, true}, ++ {256, loop, false}, ++ {-1, libcall, false}}}}; ++static stringop_algs tremont_memset[2] = { ++ {libcall, ++ {{256, rep_prefix_1_byte, true}, ++ {256, loop, false}, ++ {-1, libcall, false}}}, ++ {libcall, ++ {{256, rep_prefix_1_byte, true}, ++ {256, loop, false}, ++ {-1, libcall, false}}}}; ++static const ++struct processor_costs tremont_cost = { ++ { ++ /* Start of register allocator costs. integer->integer move cost is 2. */ ++ 6, /* cost for loading QImode using movzbl */ ++ {6, 6, 6}, /* cost of loading integer registers ++ in QImode, HImode and SImode. ++ Relative to reg-reg move (2). */ ++ {6, 6, 6}, /* cost of storing integer registers */ ++ 4, /* cost of reg,reg fld/fst */ ++ {6, 6, 12}, /* cost of loading fp registers ++ in SFmode, DFmode and XFmode */ ++ {6, 6, 12}, /* cost of storing fp registers ++ in SFmode, DFmode and XFmode */ ++ 2, /* cost of moving MMX register */ ++ {6, 6}, /* cost of loading MMX registers ++ in SImode and DImode */ ++ {6, 6}, /* cost of storing MMX registers ++ in SImode and DImode */ ++ 2, 3, 4, /* cost of moving XMM,YMM,ZMM register */ ++ {6, 6, 6, 10, 15}, /* cost of loading SSE registers ++ in 32,64,128,256 and 512-bit */ ++ {6, 6, 6, 10, 15}, /* cost of storing SSE registers ++ in 32,64,128,256 and 512-bit */ ++ 6, 6, /* SSE->integer and integer->SSE moves */ ++ 6, 6, /* mask->integer and integer->mask moves */ ++ {6, 6, 6}, /* cost of loading mask register ++ in QImode, HImode, SImode. */ ++ {6, 6, 6}, /* cost if storing mask register ++ in QImode, HImode, SImode. */ ++ 2, /* cost of moving mask register. */ ++ /* End of register allocator costs. */ ++ }, ++ ++ COSTS_N_INSNS (1), /* cost of an add instruction */ ++ /* Setting cost to 2 makes our current implementation of synth_mult result in ++ use of unnecessary temporary registers causing regression on several ++ SPECfp benchmarks. */ ++ COSTS_N_INSNS (1) + 1, /* cost of a lea instruction */ ++ COSTS_N_INSNS (1), /* variable shift costs */ ++ COSTS_N_INSNS (1), /* constant shift costs */ ++ {COSTS_N_INSNS (3), /* cost of starting multiply for QI */ ++ COSTS_N_INSNS (4), /* HI */ ++ COSTS_N_INSNS (3), /* SI */ ++ COSTS_N_INSNS (4), /* DI */ ++ COSTS_N_INSNS (4)}, /* other */ ++ 0, /* cost of multiply per each bit set */ ++ {COSTS_N_INSNS (16), /* cost of a divide/mod for QI */ ++ COSTS_N_INSNS (22), /* HI */ ++ COSTS_N_INSNS (30), /* SI */ ++ COSTS_N_INSNS (74), /* DI */ ++ COSTS_N_INSNS (74)}, /* other */ ++ COSTS_N_INSNS (1), /* cost of movsx */ ++ COSTS_N_INSNS (1), /* cost of movzx */ ++ 8, /* "large" insn */ ++ 17, /* MOVE_RATIO */ ++ 17, /* CLEAR_RATIO */ ++ {6, 6, 6}, /* cost of loading integer registers ++ in QImode, HImode and SImode. ++ Relative to reg-reg move (2). */ ++ {6, 6, 6}, /* cost of storing integer registers */ ++ {6, 6, 6, 10, 15}, /* cost of loading SSE register ++ in 32bit, 64bit, 128bit, 256bit and 512bit */ ++ {6, 6, 6, 10, 15}, /* cost of storing SSE register ++ in 32bit, 64bit, 128bit, 256bit and 512bit */ ++ {6, 6, 6, 10, 15}, /* cost of unaligned loads. */ ++ {6, 6, 6, 10, 15}, /* cost of unaligned storess. */ ++ 2, 3, 4, /* cost of moving XMM,YMM,ZMM register */ ++ 6, /* cost of moving SSE register to integer. */ ++ 18, 6, /* Gather load static, per_elt. */ ++ 18, 6, /* Gather store static, per_elt. */ ++ 32, /* size of l1 cache. */ ++ 512, /* size of l2 cache. */ ++ 64, /* size of prefetch block */ ++ 6, /* number of parallel prefetches */ ++ /* Benchmarks shows large regressions on K8 sixtrack benchmark when this ++ value is increased to perhaps more appropriate value of 5. */ ++ 3, /* Branch cost */ ++ COSTS_N_INSNS (3), /* cost of FADD and FSUB insns. */ ++ COSTS_N_INSNS (5), /* cost of FMUL instruction. */ ++ COSTS_N_INSNS (17), /* cost of FDIV instruction. */ ++ COSTS_N_INSNS (1), /* cost of FABS instruction. */ ++ COSTS_N_INSNS (1), /* cost of FCHS instruction. */ ++ COSTS_N_INSNS (14), /* cost of FSQRT instruction. */ ++ ++ COSTS_N_INSNS (1), /* cost of cheap SSE instruction. */ ++ COSTS_N_INSNS (3), /* cost of ADDSS/SD SUBSS/SD insns. */ ++ COSTS_N_INSNS (4), /* cost of MULSS instruction. */ ++ COSTS_N_INSNS (5), /* cost of MULSD instruction. */ ++ COSTS_N_INSNS (5), /* cost of FMA SS instruction. */ ++ COSTS_N_INSNS (5), /* cost of FMA SD instruction. */ ++ COSTS_N_INSNS (13), /* cost of DIVSS instruction. */ ++ COSTS_N_INSNS (17), /* cost of DIVSD instruction. */ ++ COSTS_N_INSNS (14), /* cost of SQRTSS instruction. */ ++ COSTS_N_INSNS (18), /* cost of SQRTSD instruction. */ ++ 1, 4, 3, 3, /* reassoc int, fp, vec_int, vec_fp. */ ++ tremont_memcpy, ++ tremont_memset, ++ COSTS_N_INSNS (4), /* cond_taken_branch_cost. */ ++ COSTS_N_INSNS (2), /* cond_not_taken_branch_cost. */ ++ "16:11:8", /* Loop alignment. */ ++ "16:11:8", /* Jump alignment. */ ++ "0:0:8", /* Label alignment. */ ++ "16", /* Func alignment. */ ++}; ++ + static stringop_algs intel_memcpy[2] = { + {libcall, {{11, loop, false}, {-1, rep_prefix_4_byte, false}}}, + {libcall, {{32, loop, false}, {64, rep_prefix_4_byte, false}, +diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def +index 6bd7087a03f..636e0c788bf 100644 +--- a/gcc/config/i386/x86-tune.def ++++ b/gcc/config/i386/x86-tune.def +@@ -273,7 +273,7 @@ DEF_TUNE (X86_TUNE_SINGLE_STRINGOP, "single_stringop", m_386 | m_P4_NOCONA) + move/set sequences of bytes with known size. */ + DEF_TUNE (X86_TUNE_PREFER_KNOWN_REP_MOVSB_STOSB, + "prefer_known_rep_movsb_stosb", +- m_SKYLAKE | m_ALDERLAKE | m_CORE_AVX512) ++ m_SKYLAKE | m_ALDERLAKE | m_TREMONT | m_CORE_AVX512) + + /* X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES: Enable generation of + compact prologues and epilogues by issuing a misaligned moves. This +-- +2.18.2 + diff --git a/SOURCES/gcc11-tremont3.patch b/SOURCES/gcc11-tremont3.patch new file mode 100644 index 0000000..6105e52 --- /dev/null +++ b/SOURCES/gcc11-tremont3.patch @@ -0,0 +1,185 @@ +From c4c7244349999f91ef2a7cd2108eee0372490be9 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Wed, 15 Sep 2021 14:18:21 +0800 +Subject: [PATCH 3/3] x86: Add TARGET_SSE_PARTIAL_REG_[FP_]CONVERTS_DEPENDENCY + +1. Replace TARGET_SSE_PARTIAL_REG_DEPENDENCY with +TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY in SSE FP to FP splitters. +2. Replace TARGET_SSE_PARTIAL_REG_DEPENDENCY with +TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY in SSE INT to FP splitters. + +gcc/ + + * config/i386/i386.h (TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY): + New. + (TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY): Likewise. + * config/i386/i386.md (SSE FP to FP splitters): Replace + TARGET_SSE_PARTIAL_REG_DEPENDENCY with + TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY. + (SSE INT to FP splitter): Replace TARGET_SSE_PARTIAL_REG_DEPENDENCY + with TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY. + * config/i386/x86-tune.def + (X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY): New. + (X86_TUNE_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY): Likewise. + +gcc/testsuite/ + + * gcc.target/i386/sse-covert-1.c: Likewise. + * gcc.target/i386/sse-fp-covert-1.c: Likewise. + * gcc.target/i386/sse-int-covert-1.c: Likewise. +--- + gcc/config/i386/i386.h | 4 ++++ + gcc/config/i386/i386.md | 9 ++++++--- + gcc/config/i386/x86-tune.def | 15 +++++++++++++++ + gcc/testsuite/gcc.target/i386/sse-covert-1.c | 19 +++++++++++++++++++ + .../gcc.target/i386/sse-fp-covert-1.c | 15 +++++++++++++++ + .../gcc.target/i386/sse-int-covert-1.c | 14 ++++++++++++++ + 6 files changed, 73 insertions(+), 3 deletions(-) + create mode 100644 gcc/testsuite/gcc.target/i386/sse-covert-1.c + create mode 100644 gcc/testsuite/gcc.target/i386/sse-fp-covert-1.c + create mode 100644 gcc/testsuite/gcc.target/i386/sse-int-covert-1.c + +diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h +index 73e118900f7..5b992195df7 100644 +--- a/gcc/config/i386/i386.h ++++ b/gcc/config/i386/i386.h +@@ -553,6 +553,10 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST]; + ix86_tune_features[X86_TUNE_PARTIAL_REG_DEPENDENCY] + #define TARGET_SSE_PARTIAL_REG_DEPENDENCY \ + ix86_tune_features[X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY] ++#define TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY \ ++ ix86_tune_features[X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY] ++#define TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY \ ++ ix86_tune_features[X86_TUNE_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY] + #define TARGET_SSE_UNALIGNED_LOAD_OPTIMAL \ + ix86_tune_features[X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL] + #define TARGET_SSE_UNALIGNED_STORE_OPTIMAL \ +diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md +index 97325e38676..053bec1c1e1 100644 +--- a/gcc/config/i386/i386.md ++++ b/gcc/config/i386/i386.md +@@ -4378,7 +4378,8 @@ + (float_extend:DF + (match_operand:SF 1 "nonimmediate_operand")))] + "!TARGET_AVX +- && TARGET_SSE_PARTIAL_REG_DEPENDENCY && epilogue_completed ++ && TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY ++ && epilogue_completed + && optimize_function_for_speed_p (cfun) + && (!REG_P (operands[1]) + || (!TARGET_AVX && REGNO (operands[0]) != REGNO (operands[1]))) +@@ -4540,7 +4541,8 @@ + (float_truncate:SF + (match_operand:DF 1 "nonimmediate_operand")))] + "!TARGET_AVX +- && TARGET_SSE_PARTIAL_REG_DEPENDENCY && epilogue_completed ++ && TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY ++ && epilogue_completed + && optimize_function_for_speed_p (cfun) + && (!REG_P (operands[1]) + || (!TARGET_AVX && REGNO (operands[0]) != REGNO (operands[1]))) +@@ -5053,7 +5055,8 @@ + [(set (match_operand:MODEF 0 "sse_reg_operand") + (float:MODEF (match_operand:SWI48 1 "nonimmediate_operand")))] + "!TARGET_AVX +- && TARGET_SSE_PARTIAL_REG_DEPENDENCY && epilogue_completed ++ && TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY ++ && epilogue_completed + && optimize_function_for_speed_p (cfun) + && (!EXT_REX_SSE_REG_P (operands[0]) + || TARGET_AVX512VL)" +diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def +index 636e0c788bf..b5166fb1316 100644 +--- a/gcc/config/i386/x86-tune.def ++++ b/gcc/config/i386/x86-tune.def +@@ -64,6 +64,21 @@ DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY, "sse_partial_reg_dependency", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_AMDFAM10 + | m_BDVER | m_ZNVER | m_TREMONT | m_GENERIC) + ++/* X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY: This knob avoids ++ partial write to the destination in scalar SSE conversion from FP ++ to FP. */ ++DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY, ++ "sse_partial_reg_fp_converts_dependency", ++ m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_AMDFAM10 ++ | m_BDVER | m_ZNVER | m_GENERIC) ++ ++/* X86_TUNE_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY: This knob avoids partial ++ write to the destination in scalar SSE conversion from integer to FP. */ ++DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY, ++ "sse_partial_reg_converts_dependency", ++ m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BONNELL | m_AMDFAM10 ++ | m_BDVER | m_ZNVER | m_GENERIC) ++ + /* X86_TUNE_SSE_SPLIT_REGS: Set for machines where the type and dependencies + are resolved on SSE register parts instead of whole registers, so we may + maintain just lower part of scalar values in proper format leaving the +diff --git a/gcc/testsuite/gcc.target/i386/sse-covert-1.c b/gcc/testsuite/gcc.target/i386/sse-covert-1.c +new file mode 100644 +index 00000000000..c30af694505 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/i386/sse-covert-1.c +@@ -0,0 +1,19 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -march=x86-64 -mfpmath=sse -mtune-ctrl=^sse_partial_reg_fp_converts_dependency,^sse_partial_reg_converts_dependency" } */ ++ ++extern float f; ++extern double d; ++extern int i; ++ ++void ++foo (void) ++{ ++ d = f; ++ f = i; ++} ++ ++/* { dg-final { scan-assembler "cvtss2sd" } } */ ++/* { dg-final { scan-assembler "cvtsi2ssl" } } */ ++/* { dg-final { scan-assembler-not "cvtps2pd" } } */ ++/* { dg-final { scan-assembler-not "cvtdq2ps" } } */ ++/* { dg-final { scan-assembler-not "pxor" } } */ +diff --git a/gcc/testsuite/gcc.target/i386/sse-fp-covert-1.c b/gcc/testsuite/gcc.target/i386/sse-fp-covert-1.c +new file mode 100644 +index 00000000000..b6567e60e3e +--- /dev/null ++++ b/gcc/testsuite/gcc.target/i386/sse-fp-covert-1.c +@@ -0,0 +1,15 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -march=x86-64 -mfpmath=sse -mtune-ctrl=^sse_partial_reg_fp_converts_dependency" } */ ++ ++extern float f; ++extern double d; ++ ++void ++foo (void) ++{ ++ d = f; ++} ++ ++/* { dg-final { scan-assembler "cvtss2sd" } } */ ++/* { dg-final { scan-assembler-not "cvtps2pd" } } */ ++/* { dg-final { scan-assembler-not "pxor" } } */ +diff --git a/gcc/testsuite/gcc.target/i386/sse-int-covert-1.c b/gcc/testsuite/gcc.target/i386/sse-int-covert-1.c +new file mode 100644 +index 00000000000..107f7241def +--- /dev/null ++++ b/gcc/testsuite/gcc.target/i386/sse-int-covert-1.c +@@ -0,0 +1,14 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -march=x86-64 -mfpmath=sse -mtune-ctrl=^sse_partial_reg_converts_dependency" } */ ++ ++extern float f; ++extern int i; ++ ++void ++foo (void) ++{ ++ f = i; ++} ++ ++/* { dg-final { scan-assembler "cvtsi2ssl" } } */ ++/* { dg-final { scan-assembler-not "pxor" } } */ +-- +2.18.2 + diff --git a/SPECS/gcc.spec b/SPECS/gcc.spec index 79a5f1b..aa189be 100644 --- a/SPECS/gcc.spec +++ b/SPECS/gcc.spec @@ -2,13 +2,13 @@ %{?scl:%global __strip %%{_scl_root}/usr/bin/strip} %{?scl:%global __objdump %%{_scl_root}/usr/bin/objdump} %{?scl:%scl_package gcc} -%global DATE 20210728 -%global gitrev 134ab8155c937122663513b76afa8e64ad61fe99 +%global DATE 20220127 +%global gitrev 2fa6e5c54e782377faa4c9c1f0e0b16db27f266c %global gcc_version 11.2.1 %global gcc_major 11 # Note, gcc_release must be integer, if you want to add suffixes to # %%{release}, append them after %%{gcc_release} on Release: line. -%global gcc_release 1 +%global gcc_release 9 %global nvptx_tools_gitrev 5f6f343a302d620b0868edab376c00b15741e39e %global newlib_cygwin_gitrev 50e2a63b04bdd018484605fbb954fd1bd5147fa0 %global mpc_version 1.0.3 @@ -18,6 +18,7 @@ %global doxygen_version 1.8.0 %global _unpackaged_files_terminate_build 0 %if 0%{?fedora} > 27 || 0%{?rhel} > 7 +# Until annobin is fixed (#1519165). %undefine _annotated_build %endif # Strip will fail on nvptx-none *.a archives and the brp-* scripts will @@ -133,7 +134,7 @@ Summary: GCC version 11 Name: %{?scl_prefix}gcc Version: %{gcc_version} -Release: %{gcc_release}.2%{?dist} +Release: %{gcc_release}%{?dist} # libgcc, libgfortran, libgomp, libstdc++ and crtstuff have # GCC Runtime Exception. License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ with exceptions and LGPLv2+ and BSD @@ -193,7 +194,7 @@ BuildRequires: texinfo, texinfo-tex, /usr/bin/pod2man #BuildRequires: gmp-devel >= 4.1.2-8, mpfr-devel >= 3.1.0, libmpc-devel >= 0.8.1 #BuildRequires: python3-devel, /usr/bin/python BuildRequires: gcc, gcc-c++, make -%if 0%{?rhel} <= 7 +%if 0%{?rhel} == 7 BuildRequires: python3 %endif # For VTA guality testing @@ -333,7 +334,11 @@ Patch9: gcc11-foffload-default.patch Patch10: gcc11-Wno-format-security.patch Patch11: gcc11-rh1574936.patch Patch12: gcc11-d-shared-libphobos.patch -Patch13: gcc11-add-Wbidirectional.patch +Patch14: gcc11-libgcc-link.patch +Patch15: gcc11-pr101786.patch +Patch16: gcc11-stringify-__VA_OPT__.patch +Patch17: gcc11-stringify-__VA_OPT__-2.patch +Patch18: gcc11-Wbidi-chars.patch Patch100: gcc11-fortran-fdec-duplicates.patch Patch101: gcc11-fortran-flogical-as-integer.patch @@ -346,6 +351,11 @@ Patch107: gcc11-fortran-fdec-promotion.patch Patch108: gcc11-fortran-fdec-sequence.patch Patch109: gcc11-fortran-fdec-add-missing-indexes.patch +Patch200: gcc11-tremont1.patch +Patch201: gcc11-tremont2.patch +Patch202: gcc11-tremont3.patch +Patch203: gcc11-mtune-alderlake.patch + Patch1000: gcc11-libstdc++-compat.patch Patch1001: gcc11-alt-compat-test.patch Patch1002: gcc11-libgfortran-compat.patch @@ -354,6 +364,22 @@ Patch2001: doxygen-1.7.1-config.patch Patch2002: doxygen-1.7.5-timestamp.patch Patch2003: doxygen-1.8.0-rh856725.patch +Patch3000: 0001-basic_string-reserve-n-semantics-are-not-available-i.patch +Patch3001: 0004-operator-istream-char-N-eofbit-fixes-are-not-availab.patch +Patch3002: 0005-Disable-tests-for-PR-libstdc-79820-and-PR-libstdc-81.patch +Patch3003: 0006-Don-t-assume-has_facet-codecvt_c16-when-run-against-.patch +Patch3004: 0008-testsuite-build-plugins-with-std-c-11.patch +Patch3005: 0009-Fix-22_locale-locale-cons-unicode.cc-when-run-under-.patch +Patch3006: 0010-Don-t-verify-exception-handling-in-basic_filebuf-clo.patch +Patch3007: 0011-Add-dts.exp-and-use-it-to-fix-22_locale-messages-136.patch +Patch3008: 0012-dts.exp-use-usr-bin-gcc.patch +Patch3009: 0013-Rename-__CXXSTDLIB_SO_VERSION__-to-__LIBSTDCXX_SO_VE.patch +Patch3010: 0014-Conditionalize-tests-for-PR-libstdc-98466-on-__LIBST.patch +Patch3011: 0015-Conditionalize-test-for-PR-libstdc-87135-on-__LIBSTD.patch +Patch3012: 0016-Conditionalize-test-for-hashtable-bucket-sizes-on-__.patch +Patch3013: 0017-Conditionalize-test-for-PR-libstdc-71181-on-__LIBSTD.patch +Patch3014: gcc11-dg-ice-fixes.patch + %if 0%{?rhel} > 7 %global nonsharedver 80 %else @@ -682,7 +708,11 @@ to NVidia PTX capable devices if available. %patch11 -p0 -b .rh1574936~ %endif %patch12 -p0 -b .d-shared-libphobos~ -%patch13 -p1 -b .bidi~ +%patch14 -p0 -b .libgcc-link~ +%patch15 -p0 -b .pr101786~ +%patch16 -p0 -b .stringify-__VA_OPT__~ +%patch17 -p0 -b .stringify-__VA_OPT__-2~ +%patch18 -p1 -b .bidi~ %patch100 -p1 -b .fortran-fdec-duplicates~ %patch101 -p1 -b .fortran-flogical-as-integer~ @@ -695,6 +725,11 @@ to NVidia PTX capable devices if available. %patch108 -p1 -b .fortran-fdec-sequence~ %patch109 -p1 -b .fortran-fdec-add-missing-indexes~ +%patch200 -p1 -b .tremont1~ +%patch201 -p1 -b .tremont2~ +%patch202 -p1 -b .tremont3~ +%patch203 -p1 -b .alderlake~ + %patch1000 -p0 -b .libstdc++-compat~ %ifarch %{ix86} x86_64 %if 0%{?rhel} < 7 @@ -715,6 +750,22 @@ cd .. %endif %endif +# Apply DTS-specific testsuite patches. +%patch3000 -p1 -b .dts-test-0~ +%patch3001 -p1 -b .dts-test-1~ +%patch3002 -p1 -b .dts-test-2~ +%patch3003 -p1 -b .dts-test-3~ +%patch3004 -p1 -b .dts-test-4~ +%patch3005 -p1 -b .dts-test-5~ +%patch3006 -p1 -b .dts-test-6~ +%patch3007 -p1 -b .dts-test-7~ +%patch3008 -p1 -b .dts-test-8~ +%patch3009 -p1 -b .dts-test-9~ +%patch3010 -p1 -b .dts-test-10~ +%patch3011 -p1 -b .dts-test-11~ +%patch3012 -p1 -b .dts-test-12~ +%patch3013 -p1 -b .dts-test-13~ +%patch3014 -p1 -b .dts-test-14~ find gcc/testsuite -name \*.pr96939~ | xargs rm -f @@ -1052,7 +1103,7 @@ CONFIGURE_OPTS="\ %ifnarch sparc sparcv9 ppc --build=%{gcc_target_platform} \ %endif -%if 0%{?fedora} >= 35 +%if 0%{?fedora} >= 35 || 0%{?rhel} >= 9 %ifarch x86_64 %{ix86} ppc64le s390x --with-build-config=bootstrap-lto --enable-link-serialization=1 \ %endif @@ -1068,9 +1119,9 @@ CC="$CC" CXX="$CXX" CFLAGS="$OPT_FLAGS" \ $CONFIGURE_OPTS %ifarch sparc sparcv9 sparc64 -make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" bootstrap +make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" LDFLAGS_FOR_TARGET=-Wl,-z,relro,-z,now bootstrap %else -make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" profiledbootstrap +make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" LDFLAGS_FOR_TARGET=-Wl,-z,relro,-z,now profiledbootstrap %endif %if 0%{?rhel} <= 8 @@ -1784,6 +1835,7 @@ ln -sf lib64/libasan_preinit.o libasan_preinit.o %endif %if %{build_libubsan} ln -sf ../lib32/libubsan.a 32/libubsan.a +# BZ #2027391 mv -f lib64/libubsan.a libubsan.a %endif %else @@ -2296,6 +2348,7 @@ fi %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/hresetintrin.h %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/keylockerintrin.h %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avxvnniintrin.h +%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mwaitintrin.h %endif %ifarch ia64 %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ia64intrin.h @@ -2841,8 +2894,89 @@ fi %endif %changelog -* Fri Oct 29 2021 Marek Polacek 11.2.1-1.2 -- add -Wbidirectional patch +* Fri Jan 28 2022 Marek Polacek 11.2.1-9 +- update from releases/gcc-11-branch (#2047298) + - PRs fortran/104127, fortran/104212, fortran/104227, target/101529 +- fix up va-opt-6.c testcase + +* Fri Jan 28 2022 Marek Polacek 11.2.1-8 +- update from releases/gcc-11-branch (#2047298) + - PRs ada/103538, analyzer/101962, bootstrap/103688, c++/85846, c++/95009, + c++/98394, c++/99911, c++/100493, c++/101715, c++/102229, c++/102933, + c++/103012, c++/103198, c++/103480, c++/103703, c++/103714, + c++/103758, c++/103783, c++/103831, c++/103912, c++/104055, c/97548, + c/101289, c/101537, c/103587, c/103881, d/103604, debug/103838, + debug/103874, fortran/67804, fortran/83079, fortran/101329, + fortran/101762, fortran/102332, fortran/102717, fortran/102787, + fortran/103411, fortran/103412, fortran/103418, fortran/103473, + fortran/103505, fortran/103588, fortran/103591, fortran/103606, + fortran/103607, fortran/103609, fortran/103610, fortran/103692, + fortran/103717, fortran/103718, fortran/103719, fortran/103776, + fortran/103777, fortran/103778, fortran/103782, fortran/103789, + ipa/101354, jit/103562, libfortran/103634, libstdc++/100017, + libstdc++/102994, libstdc++/103453, libstdc++/103501, + libstdc++/103549, libstdc++/103877, libstdc++/103919, + middle-end/101751, middle-end/102860, middle-end/103813, objc/103639, + preprocessor/89971, preprocessor/102432, rtl-optimization/102478, + rtl-optimization/103837, rtl-optimization/103860, + rtl-optimization/103908, sanitizer/102911, target/102347, + target/103465, target/103661, target/104172, target/104188, + tree-optimization/101615, tree-optimization/103523, + tree-optimization/103603, tree-optimization/103995 + +* Tue Jan 4 2022 Marek Polacek 11.2.1-7.2 +- fix dg-ice tests (#1986854) + +* Thu Dec 9 2021 Marek Polacek 11.2.1-7.1 +- update Intel Tremont tuning patches (#2014276) +- backport Intel Alderlake tuning (#2023553) + +* Tue Dec 7 2021 Marek Polacek 11.2.1-7 +- update from releases/gcc-11-branch (#1996860) + - PRs ada/100486, c++/70796, c++/92746, c++/93286, c++/94490, c++/102642, + c++/102786, debug/101378, debug/103046, debug/103315, fortran/87711, + fortran/87851, fortran/97896, fortran/99061, fortran/99348, + fortran/102521, fortran/102685, fortran/102715, fortran/102745, + fortran/102816, fortran/102817, fortran/102917, fortran/103137, + fortran/103138, fortran/103392, gcov-profile/100520, ipa/102714, + ipa/102762, ipa/103052, ipa/103246, ipa/103267, libstdc++/96416, + libstdc++/98421, libstdc++/100117, libstdc++/100153, libstdc++/100748, + libstdc++/101571, libstdc++/101608, libstdc++/102894, + libstdc++/103022, libstdc++/103086, libstdc++/103133, + libstdc++/103240, libstdc++/103381, middle-end/64888, + middle-end/101480, middle-end/102431, middle-end/102518, + middle-end/103059, middle-end/103181, middle-end/103248, + middle-end/103384, preprocessor/103130, rtl-optimization/102356, + rtl-optimization/102842, target/101985, target/102976, target/102991, + target/103205, target/103274, target/103275, testsuite/102690, + tree-optimization/100393, tree-optimization/102139, + tree-optimization/102505, tree-optimization/102572, + tree-optimization/102788, tree-optimization/102789, + tree-optimization/102798, tree-optimization/102970, + tree-optimization/103192, tree-optimization/103204, + tree-optimization/103237, tree-optimization/103255, + tree-optimization/103435 +- fix up #__VA_OPT__ handling (PR preprocessor/103415) + +* Mon Nov 29 2021 Marek Polacek 11.2.1-6.3 +- fix libubsan.a symlink (#2027391) + +* Wed Nov 17 2021 Marek Polacek 11.2.1-6.2 +- backport Intel Tremont tuning (#2014276) + +* Wed Nov 17 2021 Marek Polacek 11.2.1-6.1 +- add -Wbidi-chars patch +- use devtoolset-11-gdb + +* Tue Oct 26 2021 Marek Polacek 11.2.1-6 +- update from releases/gcc-11-branch (#1996860) + - PRs target/100208, target/100316, target/102761 +- build target shared libraries with -Wl,-z,relro,-z,now +- add mwaitintrin.h on x86 (#2013860) +- improve generated code with extern thread_local constinit vars + with trivial dtors +- add support for C++20 #__VA_OPT__ +- apply DTS-specific testsuite patches (#1986854) * Mon Aug 16 2021 Marek Polacek 11.2.1-1.1 - add .hidden for _ZNSt10filesystem9_Dir_base7advanceEbRSt10error_code