commit 98b9ac3f4c4aae26d230ba4ce841cecfb99e3999
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Apr 27 12:36:33 2021

    Bump BASE-VER
    
    2021-05-27  Jakub Jelinek  <jakub@redhat.com>
    
            * BASE-VER: Set to 11.1.1.

diff --git a/gcc/BASE-VER b/gcc/BASE-VER
index 68d8f15e23c..668182d21a4 100644
--- a/gcc/BASE-VER
+++ b/gcc/BASE-VER
@@ -1 +1 @@
-11.1.0
+11.1.1

commit 12333b7e7636d7337054b85d37cb2def3b2e4ca4
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Wed Apr 21 12:31:45 2021

    cprop: Fix -fcompare-debug bug in constprop_register [PR100148]
    
    The following testcase shows different behavior between -g and -g0
    in constprop_register, if a flags register setter is separated
    from a conditional jump using those flags with -g by a DEBUG_INSN.
    As it uses just NEXT_INSN, for -g it will look at the DEBUG_INSN which is
    not a conditional jump, while otherwise it would look at the conditional
    jump and call cprop_jump.
    
    2021-04-21  Jakub Jelinek  <jakub@redhat.com>
    
            PR rtl-optimization/100148
            * cprop.c (constprop_register): Use next_nondebug_insn instead of
            NEXT_INSN.
    
            * g++.dg/opt/pr100148.C: New test.
    
    (cherry picked from commit 022f6ee3ad67ee30f62c8c2aeeb4156494f3284e)

diff --git a/gcc/cprop.c b/gcc/cprop.c
index 73034ce72d0..6f34f6b2418 100644
--- a/gcc/cprop.c
+++ b/gcc/cprop.c
@@ -1007,16 +1007,18 @@ static int
 constprop_register (rtx from, rtx src, rtx_insn *insn)
 {
   rtx sset;
+  rtx_insn *next_insn;
 
   /* Check for reg or cc0 setting instructions followed by
      conditional branch instructions first.  */
   if ((sset = single_set (insn)) != NULL
-      && NEXT_INSN (insn)
-      && any_condjump_p (NEXT_INSN (insn)) && onlyjump_p (NEXT_INSN (insn)))
+      && (next_insn = next_nondebug_insn (insn)) != NULL
+      && any_condjump_p (next_insn)
+      && onlyjump_p (next_insn))
     {
       rtx dest = SET_DEST (sset);
       if ((REG_P (dest) || CC0_P (dest))
-	  && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn),
+	  && cprop_jump (BLOCK_FOR_INSN (insn), insn, next_insn,
 			 from, src))
 	return 1;
     }
diff --git a/gcc/testsuite/g++.dg/opt/pr100148.C b/gcc/testsuite/g++.dg/opt/pr100148.C
new file mode 100644
index 00000000000..d038879b6b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr100148.C
@@ -0,0 +1,27 @@
+// PR rtl-optimization/100148
+// { dg-do compile }
+// { dg-options "-O2 -fno-dce -fno-tree-dce -fno-tree-dominator-opts -fno-tree-sink -fcompare-debug" }
+
+int i;
+enum E { } e, ee;
+
+bool
+baz (int)
+{
+  return ee;
+}
+
+bool bar ();
+bool a, b;
+
+void
+foo ()
+{
+  switch (ee)
+    {
+    case 0:
+      e = E (a ? : i);
+    case 1:
+      !(b || baz (0) && bar ());
+    }
+}

commit c7421c7dd2ce1e27cf704fa444984a2628a1587f
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Wed Apr 21 15:17:10 2021

    testsuite: Add -fchecking to dg-ice tests
    
    In --enable-checking=release builds (which is the default on release
    branches), I'm getting various extra FAILs that don't appear in
    --enable-checking=yes builds.
    
    XPASS: g++.dg/cpp0x/constexpr-52830.C  -std=c++14 (internal compiler error)
    FAIL: g++.dg/cpp0x/constexpr-52830.C  -std=c++14 (test for excess errors)
    XPASS: g++.dg/cpp0x/constexpr-52830.C  -std=c++17 (internal compiler error)
    FAIL: g++.dg/cpp0x/constexpr-52830.C  -std=c++17 (test for excess errors)
    XPASS: g++.dg/cpp0x/constexpr-52830.C  -std=c++2a (internal compiler error)
    FAIL: g++.dg/cpp0x/constexpr-52830.C  -std=c++2a (test for excess errors)
    FAIL: g++.dg/cpp0x/vt-88982.C  -std=c++14 (test for excess errors)
    FAIL: g++.dg/cpp0x/vt-88982.C  -std=c++17 (test for excess errors)
    FAIL: g++.dg/cpp0x/vt-88982.C  -std=c++2a (test for excess errors)
    FAIL: g++.dg/cpp1y/auto-fn61.C  -std=c++14 (test for excess errors)
    FAIL: g++.dg/cpp1y/auto-fn61.C  -std=c++17 (test for excess errors)
    FAIL: g++.dg/cpp1y/auto-fn61.C  -std=c++2a (test for excess errors)
    FAIL: g++.dg/cpp1z/constexpr-lambda26.C  -std=c++17 (test for excess errors)
    FAIL: g++.dg/cpp1z/constexpr-lambda26.C  -std=c++2a (test for excess errors)
    FAIL: g++.dg/cpp2a/nontype-class39.C  -std=c++2a (test for excess errors)
    FAIL: c-c++-common/goacc/kernels-decompose-ice-1.c  -std=c++14 (test for excess errors)
    FAIL: c-c++-common/goacc/kernels-decompose-ice-1.c  -std=c++17 (test for excess errors)
    FAIL: c-c++-common/goacc/kernels-decompose-ice-1.c  -std=c++2a (test for excess errors)
    FAIL: c-c++-common/goacc/kernels-decompose-ice-1.c  -std=c++98 (test for excess errors)
    FAIL: c-c++-common/goacc/kernels-decompose-ice-2.c  -std=c++14 (test for excess errors)
    FAIL: c-c++-common/goacc/kernels-decompose-ice-2.c  -std=c++17 (test for excess errors)
    FAIL: c-c++-common/goacc/kernels-decompose-ice-2.c  -std=c++2a (test for excess errors)
    FAIL: c-c++-common/goacc/kernels-decompose-ice-2.c  -std=c++98 (test for excess errors)
    
    These are tests that have dg-ice and most of those ICEs are checking ICEs
    which go away in release checking when -fno-checking is the default.
    
    The following patch adds -fchecking option to those.
    
    2021-04-21  Jakub Jelinek  <jakub@redhat.com>
    
            * g++.dg/cpp1z/constexpr-lambda26.C: Add dg-additional-options
            -fchecking.
            * g++.dg/cpp1y/auto-fn61.C: Likewise.
            * g++.dg/cpp2a/nontype-class39.C: Likewise.
            * g++.dg/cpp0x/constexpr-52830.C: Likewise.
            * g++.dg/cpp0x/vt-88982.C: Likewise.
            * c-c++-common/goacc/kernels-decompose-ice-1.c: Add -fchecking to
            dg-additional-options.
            * c-c++-common/goacc/kernels-decompose-ice-2.c: Likewise.
    
    (cherry picked from commit ca4bf1dd4398dc65d8fff8b9f5c67733729cee95)

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 d770b91dd09..8c3884bdc00 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 "--param=openacc-kernels=decompose" } */
+/* { dg-additional-options "-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 ae059eb354b..8bf60a9a509 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 "--param=openacc-kernels=decompose" } */
+/* { dg-additional-options "-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 2c9d2f9b329..eae0d8c377b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
@@ -1,5 +1,6 @@
 // PR c++/52830
 // { dg-do compile { target c++11 } }
+// { dg-additional-options "-fchecking" }
 // { dg-ice "comptypes" }
 
 template<bool b> struct eif { typedef void type; };
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-88982.C b/gcc/testsuite/g++.dg/cpp0x/vt-88982.C
index cb9530dcee1..7a868233d73 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-88982.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-88982.C
@@ -1,5 +1,6 @@
 // PR c++/88982
 // { dg-do compile { target c++11 } }
+// { dg-additional-options "-fchecking" }
 // { dg-ice "tsubst_pack_expansion" }
 
 template<typename...Ts> struct A {
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn61.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn61.C
index c24c3b85d78..bed5ea0cfc0 100644
--- a/gcc/testsuite/g++.dg/cpp1y/auto-fn61.C
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn61.C
@@ -1,5 +1,6 @@
 // PR c++/88003
 // { dg-do compile { target c++14 } }
+// { dg-additional-options "-fchecking" }
 // { 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 d6c8bae525f..0cdb400d21c 100644
--- a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda26.C
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda26.C
@@ -1,5 +1,6 @@
 // PR c++/87765
 // { dg-do compile { target c++17 } }
+// { dg-additional-options "-fchecking" }
 // { dg-ice "cxx_eval_constant_expression" }
 
 template <int N>
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C
index f5f79a71ec2..512afad8e4f 100644
--- a/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C
@@ -1,5 +1,6 @@
 // PR c++/89565
 // { dg-do compile { target c++20 } }
+// { dg-additional-options "-fchecking" }
 // { dg-ice "resolve_args" }
 
 template <auto>

commit b363daf1321bec59b96908ddfb674312732173ad
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Mon Apr 26 09:59:15 2021

    vmsdbgout: Remove useless register keywords
    
    register keyword was removed in C++17, and in vmsdbgout.c it served no
    useful purpose.
    
    2021-04-26  Jakub Jelinek  <jakub@redhat.com>
    
            PR debug/100255
            * vmsdbgout.c (ASM_OUTPUT_DEBUG_STRING, vmsdbgout_begin_block,
            vmsdbgout_end_block, lookup_filename, vmsdbgout_source_line): Remove
            register keywords.
    
    (cherry picked from commit 297bfacdb448c0d29b8dfac2818350b90902bc75)

diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c
index a7640004b87..c226bc69c85 100644
--- a/gcc/vmsdbgout.c
+++ b/gcc/vmsdbgout.c
@@ -365,13 +365,13 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 #define ASM_OUTPUT_DEBUG_STRING(FILE,P)		\
   do						\
     {						\
-      register int slen = strlen (P);		\
-      register const char *p = (P);		\
-      register int i;				\
+      int slen = strlen (P);			\
+      const char *p = (P);			\
+      int i;					\
       fprintf (FILE, "\t.ascii \"");		\
       for (i = 0; i < slen; i++)		\
 	{					\
-	  register int c = p[i];		\
+	  int c = p[i];				\
 	  if (c == '\"' || c == '\\')		\
 	    putc ('\\', FILE);			\
 	  if (c >= ' ' && c < 0177)		\
@@ -1229,7 +1229,7 @@ vmsdbgout_end_epilogue (unsigned int line, const char *file)
    a lexical block.  */
 
 static void
-vmsdbgout_begin_block (register unsigned line, register unsigned blocknum)
+vmsdbgout_begin_block (unsigned line, unsigned blocknum)
 {
   if (write_symbols == VMS_AND_DWARF2_DEBUG)
     (*dwarf2_debug_hooks.begin_block) (line, blocknum);
@@ -1242,7 +1242,7 @@ vmsdbgout_begin_block (register unsigned line, register unsigned blocknum)
    lexical block.  */
 
 static void
-vmsdbgout_end_block (register unsigned line, register unsigned blocknum)
+vmsdbgout_end_block (unsigned line, unsigned blocknum)
 {
   if (write_symbols == VMS_AND_DWARF2_DEBUG)
     (*dwarf2_debug_hooks.end_block) (line, blocknum);
@@ -1315,8 +1315,8 @@ static unsigned int
 lookup_filename (const char *file_name)
 {
   static unsigned int last_file_lookup_index = 0;
-  register char *fn;
-  register unsigned i;
+  char *fn;
+  unsigned i;
   const char *fnam;
   long long cdt = 0;
   long ebk = 0;
@@ -1405,8 +1405,8 @@ vmsdbgout_write_source_line (unsigned line, const char *filename,
 }
 
 static void
-vmsdbgout_source_line (register unsigned line, unsigned int column,
-		       register const char *filename,
+vmsdbgout_source_line (unsigned line, unsigned int column,
+		       const char *filename,
                        int discriminator, bool is_stmt)
 {
   if (write_symbols == VMS_AND_DWARF2_DEBUG)

commit 7f8eea0b16494554d623113c8138879b3f31d67a
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Apr 27 15:26:24 2021

    cfgcleanup: Fix -fcompare-debug issue in outgoing_edges_match [PR100254]
    
    The following testcase fails with -fcompare-debug.  The problem is that
    outgoing_edges_match behaves differently between -g0 and -g, if
    some load/store with REG_EH_REGION is followed by DEBUG_INSNs, the
    REG_EH_REGION check is not done, while when there are no DEBUG_INSNs, it is
    done.
    
    We already compute last1 and last2 as BB_END (bb{1,2}) with skipped debug
    insns and notes, so this patch just uses those.
    
    2021-04-27  Jakub Jelinek  <jakub@redhat.com>
    
            PR rtl-optimization/100254
            * cfgcleanup.c (outgoing_edges_match): Check REG_EH_REGION on
            last1 and last2 insns rather than BB_END (bb1) and BB_END (bb2) insns.
    
            * g++.dg/opt/pr100254.C: New test.
    
    (cherry picked from commit e600df51a15b2ec7a72731921a2464ffe59cf5ab)

diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 8650fb7f264..260a896ac48 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -1885,8 +1885,8 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
 
   /* Ensure the same EH region.  */
   {
-    rtx n1 = find_reg_note (BB_END (bb1), REG_EH_REGION, 0);
-    rtx n2 = find_reg_note (BB_END (bb2), REG_EH_REGION, 0);
+    rtx n1 = find_reg_note (last1, REG_EH_REGION, 0);
+    rtx n2 = find_reg_note (last2, REG_EH_REGION, 0);
 
     if (!n1 && n2)
       return false;
diff --git a/gcc/testsuite/g++.dg/opt/pr100254.C b/gcc/testsuite/g++.dg/opt/pr100254.C
new file mode 100644
index 00000000000..dbdac1638c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr100254.C
@@ -0,0 +1,101 @@
+// PR rtl-optimization/100254
+// { dg-do compile }
+// { dg-options "-O2 -fno-guess-branch-probability -fipa-pta -fnon-call-exceptions -fcompare-debug" }
+// { dg-additional-options "-mtune=goldmont" { target i?86-*-* x86_64-*-* } }
+
+struct _Rb_tree_node_base {
+  typedef _Rb_tree_node_base *_Base_ptr;
+  typedef _Rb_tree_node_base *_Const_Base_ptr;
+  _Base_ptr _M_left;
+};
+template <typename _Key_compare> struct _Rb_tree_key_compare {
+  _Key_compare _M_key_compare;
+};
+struct _Rb_tree_header {
+  _Rb_tree_node_base _M_header;
+};
+struct _Rb_tree_iterator {
+  _Rb_tree_iterator(_Rb_tree_node_base::_Base_ptr);
+  friend bool operator==(_Rb_tree_iterator, _Rb_tree_iterator);
+};
+template <typename _Tp> struct _Rb_tree_const_iterator {
+  typedef _Rb_tree_const_iterator _Self;
+  _Rb_tree_const_iterator(_Rb_tree_node_base::_Const_Base_ptr) {}
+  _Tp operator*();
+  template <typename _Up>
+  friend bool operator!=(_Rb_tree_const_iterator<_Up>, _Rb_tree_const_iterator<_Up>);
+};
+template <typename _Key, typename _Val, typename _Compare> struct _Rb_tree {
+  template <typename _Key_compare>
+  struct _Rb_tree_impl : _Rb_tree_key_compare<_Key_compare>, _Rb_tree_header {};
+  _Rb_tree_impl<_Compare> _M_impl;
+  _Key _S_key();
+  typedef _Rb_tree_const_iterator<_Val> const_iterator;
+  const_iterator begin() { return _M_impl._M_header._M_left; }
+  _Rb_tree_iterator find(const _Key &);
+};
+template <typename _Key, typename _Val, typename _Compare>
+_Rb_tree_iterator _Rb_tree<_Key, _Val, _Compare>::find(const _Key &__k) {
+  _Rb_tree_iterator __j = 0;
+  return __j == 0 || _M_impl._M_key_compare(__k, _S_key()) ? 0 : __j;
+}
+template <typename _Key, typename _Compare = _Key> struct set {
+  typedef _Key key_type;
+  typedef _Rb_tree<key_type, _Key, _Compare> _Rep_type;
+  _Rep_type _M_t;
+  typedef typename _Rep_type::const_iterator iterator;
+  iterator begin() { return _M_t.begin(); }
+  iterator end();
+  void find(key_type __x) { _M_t.find(__x); }
+};
+struct WindowDesc {
+  WindowDesc(short);
+} _station_view_desc(0);
+struct Window {
+  void IsWidgetLowered();
+  virtual void OnClick(int, int, int);
+};
+int AllocateWindowDescFront_window_number;
+template <typename Wcls> void AllocateWindowDescFront(WindowDesc *desc, bool) {
+  Wcls(desc, AllocateWindowDescFront_window_number);
+}
+class CargoDataEntry;
+struct CargoSorter {
+  bool operator()(const CargoDataEntry *, const CargoDataEntry *) const;
+};
+struct CargoDataEntry {
+  ~CargoDataEntry();
+  char Retrieve_cargo;
+  void Retrieve() {
+    CargoDataEntry t(Retrieve_cargo);
+    children->find(&t);
+  }
+  CargoDataEntry(char);
+  set<CargoDataEntry *, CargoSorter> *children;
+};
+CargoDataEntry::CargoDataEntry(char) : children() {}
+CargoDataEntry::~CargoDataEntry() {
+  if (children)
+    for (set<CargoDataEntry *>::iterator i = children->begin();
+         i != children->end();)
+      delete *i;
+}
+bool CargoSorter::operator()(const CargoDataEntry *,
+                             const CargoDataEntry *) const { return false; }
+struct StationViewWindow : Window {
+  StationViewWindow(WindowDesc *, int);
+  CargoDataEntry HandleCargoWaitingClick_filter;
+  void OnClick(int, int widget, int) {
+    switch (widget) {
+    case 0:
+      HandleCargoWaitingClick_filter.Retrieve();
+      HandleCargoWaitingClick_filter.Retrieve();
+    case 1:
+      IsWidgetLowered();
+    }
+  }
+};
+void ShowStationViewWindow_station() {
+  AllocateWindowDescFront<StationViewWindow>(&_station_view_desc,
+                                             ShowStationViewWindow_station);
+}

commit 80dc24f813a9d8951d75eea7324f6d713b872bca
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Apr 27 15:42:47 2021

    veclower: Fix up vec_shl matching of VEC_PERM_EXPR [PR100239]
    
    The following testcase ICEs at -O0, because lower_vec_perm sees the
      _1 = { 0, 0, 0, 0, 0, 0, 0, 0 };
      _2 = VEC_COND_EXPR <_1, { -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 0, 0, 0, 0, 0, 0, 0 }>;
      _3 = { 6, 0, 0, 0, 0, 0, 0, 0 };
      _4 = VEC_PERM_EXPR <{ 0, 0, 0, 0, 0, 0, 0, 0 }, _2, _3>;
    and as the ISA is SSE2, there is no support for the particular permutation
    nor for variable mask permutation.  But, the code to match vec_shl matches
    it, because the permutation has the first operand a zero vector and the
    mask picks all elements randomly from that vector.
    So, in the end that isn't a vec_shl, but the permutation could be in theory
    optimized into the first argument.  As we keep it as is, it will fail
    during expansion though, because that for vec_shl correctly requires that
    it actually is a shift:
          unsigned firstidx = 0;
          for (unsigned int i = 0; i < nelt; i++)
            {
              if (known_eq (sel[i], nelt))
                {
                  if (i == 0 || firstidx)
                    return NULL_RTX;
                  firstidx = i;
                }
              else if (firstidx
                       ? maybe_ne (sel[i], nelt + i - firstidx)
                       : maybe_ge (sel[i], nelt))
                return NULL_RTX;
            }
    
          if (firstidx == 0)
            return NULL_RTX;
          first = firstidx;
    The if (firstidx == 0) return NULL; is what is missing a counterpart
    on the lower_vec_perm side.
    As with optimize != 0 we fold it in other spots, I think it is not needed
    to optimize this cornercase in lower_vec_perm (which would mean we'd need
    to recurse on the newly created _4 = { 0, 0, 0, 0, 0, 0, 0, 0 };
    whether it is supported or not).
    
    2021-04-27  Jakub Jelinek  <jakub@redhat.com>
    
            PR tree-optimization/100239
            * tree-vect-generic.c (lower_vec_perm): Don't accept constant
            permutations with all indices from the first zero element as vec_shl.
    
            * gcc.dg/pr100239.c: New test.
    
    (cherry picked from commit 83d26d0e1b3625ab6c2d83610a13976b52f63e0a)

diff --git a/gcc/testsuite/gcc.dg/pr100239.c b/gcc/testsuite/gcc.dg/pr100239.c
new file mode 100644
index 00000000000..1ade810c52b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr100239.c
@@ -0,0 +1,12 @@
+/* PR tree-optimization/100239 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+typedef short __attribute__((__vector_size__ (8 * sizeof (short)))) V;
+V v, w;
+
+void
+foo (void)
+{
+  w = __builtin_shuffle (v != v, 0 < (V) {}, (V) {192} >> 5);
+}
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index c8d8493e6ea..3348545d18b 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -1515,7 +1515,7 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
 					      elements + i - first)
 		     : maybe_ge (poly_uint64 (indices[i]), elements))
 	      break;
-	  if (i == elements)
+	  if (first && i == elements)
 	    {
 	      gimple_assign_set_rhs3 (stmt, mask);
 	      update_stmt (stmt);

commit 3fe1c1fd0eb5e4bbc1af313b3e9dd4605ec5a134
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Apr 27 15:46:16 2021

    aarch64: Fix UB in the compiler [PR100200]
    
    The following patch fixes UBs in the compiler when negativing
    a CONST_INT containing HOST_WIDE_INT_MIN.  I've changed the spots where
    there wasn't an obvious earlier condition check or predicate that
    would fail for such CONST_INTs.
    
    2021-04-27  Jakub Jelinek  <jakub@redhat.com>
    
            PR target/100200
            * config/aarch64/predicates.md (aarch64_sub_immediate,
            aarch64_plus_immediate): Use -UINTVAL instead of -INTVAL.
            * config/aarch64/aarch64.md (casesi, rotl<mode>3): Likewise.
            * config/aarch64/aarch64.c (aarch64_print_operand,
            aarch64_split_atomic_op, aarch64_expand_subvti): Likewise.
    
    (cherry picked from commit 618ae596ebcd1de03857d20485d1324931852569)

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 12625a4bee3..7985940ba42 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -10778,7 +10778,7 @@ aarch64_print_operand (FILE *f, rtx x, int code)
 	}
 
       if (GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_INT)
-	asm_fprintf (f, "%wd", -INTVAL (elt));
+	asm_fprintf (f, "%wd", -UINTVAL (elt));
       else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_FLOAT
 	       && aarch64_print_vector_float_operand (f, x, true))
 	;
@@ -21598,7 +21598,7 @@ aarch64_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
     case MINUS:
       if (CONST_INT_P (value))
 	{
-	  value = GEN_INT (-INTVAL (value));
+	  value = GEN_INT (-UINTVAL (value));
 	  code = PLUS;
 	}
       /* Fall through.  */
@@ -23514,7 +23514,7 @@ aarch64_expand_subvti (rtx op0, rtx low_dest, rtx low_in1,
     {
       if (aarch64_plus_immediate (low_in2, DImode))
 	emit_insn (gen_subdi3_compare1_imm (low_dest, low_in1, low_in2,
-					    GEN_INT (-INTVAL (low_in2))));
+					    GEN_INT (-UINTVAL (low_in2))));
       else
 	{
 	  low_in2 = force_reg (DImode, low_in2);
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index abfd8452674..aef6da9732d 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -747,7 +747,8 @@
 	   constant can be represented in SImode, this is important
 	   for the corner case where operand[1] is INT_MIN.  */
 
-	operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
+	operands[1]
+	  = GEN_INT (trunc_int_for_mode (-UINTVAL (operands[1]), SImode));
 
 	if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
 	      (operands[1], SImode))
@@ -5008,7 +5009,7 @@
     /* (SZ - cnt) % SZ == -cnt % SZ */
     if (CONST_INT_P (operands[2]))
       {
-        operands[2] = GEN_INT ((-INTVAL (operands[2]))
+        operands[2] = GEN_INT ((-UINTVAL (operands[2]))
 			       & (GET_MODE_BITSIZE (<MODE>mode) - 1));
         if (operands[2] == const0_rtx)
           {
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index c55842b9c74..49f02ae0381 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -121,12 +121,12 @@
 
 (define_predicate "aarch64_sub_immediate"
   (and (match_code "const_int")
-       (match_test "aarch64_uimm12_shift (-INTVAL (op))")))
+       (match_test "aarch64_uimm12_shift (-UINTVAL (op))")))
 
 (define_predicate "aarch64_plus_immediate"
   (and (match_code "const_int")
        (ior (match_test "aarch64_uimm12_shift (INTVAL (op))")
-	    (match_test "aarch64_uimm12_shift (-INTVAL (op))"))))
+	    (match_test "aarch64_uimm12_shift (-UINTVAL (op))"))))
 
 (define_predicate "aarch64_plus_operand"
   (ior (match_operand 0 "register_operand")

commit 9e80a135fffa5c1b36b6007e7e57d303535fbe84
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Tue Apr 27 16:52:57 2021

    [PATCH] Backport fix for PR target/98952
    
    The test in the PowerPC 32-bit trampoline support is backwards.  It aborts
    if the trampoline size is greater than the expected size.  It should abort
    when the trampoline size is less than the expected size.  I fixed the test
    so the operands are reversed.  I then folded the load immediate into the
    compare instruction.
    
    I verified this by creating a 32-bit trampoline program and manually
    changing the size of the trampoline to be 48 instead of 40.  The program
    aborted with the larger size.  I updated this code and ran the test again
    and it passed.
    
    I added a test case that runs on PowerPC 32-bit Linux systems and it calls
    the __trampoline_setup function with a larger buffer size than the
    compiler uses.  The test is not run on 64-bit systems, since the function
    __trampoline_setup is not called.  I also limited the test to just Linux
    systems, in case trampolines are handled differently in other systems.
    
    libgcc/
    2021-04-27  Michael Meissner  <meissner@linux.ibm.com>
    
            PR target/98952
            * config/rs6000/tramp.S (__trampoline_setup, elfv1 #ifdef): Fix
            trampoline size comparison in 32-bit by reversing test and
            combining load immediate with compare.  Fix backported from trunk
            change on 4/23, 886b6c1e8af502b69e3f318b9830b73b88215878.
            (__trampoline_setup, elfv2 #ifdef): Fix trampoline size comparison
            in 32-bit by reversing test and combining load immediate with
            compare.
    
    gcc/testsuite/
    2021-04-27  Michael Meissner  <meissner@linux.ibm.com>
    
            PR target/98952
            * gcc.target/powerpc/pr98952.c: New test.  Test backported from
            trunk change on 4/23, 886b6c1e8af502b69e3f318b9830b73b88215878.

diff --git a/gcc/testsuite/gcc.target/powerpc/pr98952.c b/gcc/testsuite/gcc.target/powerpc/pr98952.c
new file mode 100644
index 00000000000..c487fbc403e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr98952.c
@@ -0,0 +1,28 @@
+/* { dg-do run { target { powerpc*-*-linux* && ilp32 } } } */
+/* { dg-options "-O2" } */
+
+/* PR 96983 reported that the test in libgcc's tramp.S was backwards and it
+   would abort if the trampoline size passed to the function was greater than
+   the size the runtime was expecting (40).  It should abort if the size is less
+   than 40, not greater than 40.  This test creates a call to __trampoline_setup
+   with a much larger buffer to make sure the function does not abort.
+
+   We do not run this test on 64-bit since __trampoline_setup is not present in
+   64-bit systems.
+
+   We only run the test under Linux in case the other systems have some
+   different variant for __trampoline_setup.  */
+
+#ifndef SIZE
+#define SIZE 100
+#endif
+
+extern void __trampoline_setup (int *, unsigned, void *, void *);
+
+int main (void)
+{
+  int tramp[SIZE / sizeof (int)];
+
+  __trampoline_setup (tramp, SIZE, 0, 0);
+  return 0;
+}
diff --git a/libgcc/config/rs6000/tramp.S b/libgcc/config/rs6000/tramp.S
index 4236a82b402..68baf16de9f 100644
--- a/libgcc/config/rs6000/tramp.S
+++ b/libgcc/config/rs6000/tramp.S
@@ -64,8 +64,7 @@ FUNC_START(__trampoline_setup)
         mflr	r11
         addi	r7,r11,trampoline_initial-4-.LCF0 /* trampoline address -4 */
 
-	li	r8,trampoline_size	/* verify that the trampoline is big enough */
-	cmpw	cr1,r8,r4
+	cmpwi	cr1,r4,trampoline_size	/* verify that the trampoline is big enough */
 	srwi	r4,r4,2		/* # words to move */
 	addi	r9,r3,-4	/* adjust pointer for lwzu */
 	mtctr	r4
@@ -156,8 +155,7 @@ FUNC_START(__trampoline_setup)
 	ld 7,.LC0@toc@l(7)	/* trampoline address -8 */
 #endif
 
-	li	r8,trampoline_size	/* verify that the trampoline is big enough */
-	cmpw	cr1,r8,r4
+	cmpwi	cr1,r4,trampoline_size	/* verify that the trampoline is big enough */
 	srwi	r4,r4,3		/* # doublewords to move */
 	addi	r9,r3,-8	/* adjust pointer for stdu */
 	mtctr	r4

commit e89e883a450126d021874536ae102f60a1cacb78
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Apr 27 17:50:53 2021

    aarch64: Fix up last commit [PR100200]
    
    Pedantically signed vs. unsigned mismatches in va_arg are only well defined
    if the value can be represented in both signed and unsigned integer types.
    
    2021-04-27  Jakub Jelinek  <jakub@redhat.com>
    
            PR target/100200
            * config/aarch64/aarch64.c (aarch64_print_operand): Cast -UINTVAL
            back to HOST_WIDE_INT.
    
    (cherry picked from commit 1c0c371d0ea297af2e3180c64cd18f2bfce919b1)

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 7985940ba42..e979a51f3af 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -10778,7 +10778,7 @@ aarch64_print_operand (FILE *f, rtx x, int code)
 	}
 
       if (GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_INT)
-	asm_fprintf (f, "%wd", -UINTVAL (elt));
+	asm_fprintf (f, "%wd", (HOST_WIDE_INT) -UINTVAL (elt));
       else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_FLOAT
 	       && aarch64_print_vector_float_operand (f, x, true))
 	;

commit bb3316a6f10b95c8adef092678da2e161a8fd494
Author: Tobias Burnus <tobias@codesourcery.com>
Date:   Wed Apr 21 20:07:19 2021

    libgomp/testsuite: Fix checks for dg-excess-errors
    
    For the tests modified below, the effective target line has to be effective
    when compiling for an offload target, except that variable-not-offloaded.c
    would compile with unified-share memory and pr86416-*.c if long double/float128
    is supported.
    The previous check used a run-time device ability check. This new variant
    now enables those dg- lines when _compiling_ for nvptx or gcn.
    
    libgomp/ChangeLog:
    
            * testsuite/lib/libgomp.exp (offload_target_to_openacc_device_type):
            New, based on check_effective_target_offload_target_nvptx.
            (check_effective_target_offload_target_nvptx): Call it.
            (check_effective_target_offload_target_amdgcn): New.
            * testsuite/libgomp.c-c++-common/function-not-offloaded.c:
            Require target offload_target_nvptx || offload_target_amdgcn.
            * testsuite/libgomp.c-c++-common/variable-not-offloaded.c: Likewise.
            * testsuite/libgomp.c/pr86416-1.c: Likewise.
            * testsuite/libgomp.c/pr86416-2.c: Likewise.
    
    (cherry picked from commit 95dfc3ac7baca19157bb976ee4c8c69753e1e178)

diff --git a/libgomp/testsuite/lib/libgomp.exp b/libgomp/testsuite/lib/libgomp.exp
index 14dcfdfd00a..46cce9b8445 100644
--- a/libgomp/testsuite/lib/libgomp.exp
+++ b/libgomp/testsuite/lib/libgomp.exp
@@ -340,8 +340,10 @@ proc offload_target_to_openacc_device_type { offload_target } {
     }
 }
 
-# Return 1 if compiling for offload target nvptx.
-proc check_effective_target_offload_target_nvptx { } {
+# Return 1 if compiling for the specified offload target
+# Takes -foffload=... into account by checking OFFLOAD_TARGET_NAMES=
+# in the -v compiler output.
+proc libgomp_check_effective_target_offload_target { target_name } {
     # Consider all actual options, including the flags passed to
     # 'gcc-dg-runtest', or 'gfortran-dg-runtest' (see the 'libgomp.*/*.exp'
     # files; in particular, '-foffload', 'libgomp.oacc-*/*.exp'), which don't
@@ -354,13 +356,23 @@ proc check_effective_target_offload_target_nvptx { } {
     set gcc_output [libgomp_target_compile "" "" "none" $options]
     if [regexp "(?n)^OFFLOAD_TARGET_NAMES=(.*)" $gcc_output dummy offload_targets] {
 	verbose "compiling for offload targets: $offload_targets"
-	return [string match "*:nvptx*:*" ":$offload_targets:"]
+	return [string match "*:$target_name*:*" ":$offload_targets:"]
     }
 
-    verbose "not compiling for any offload targets"
+    verbose "not compiling for $target_name offload target"
     return 0
 }
 
+# Return 1 if compiling for offload target nvptx.
+proc check_effective_target_offload_target_nvptx { } {
+    return [libgomp_check_effective_target_offload_target "nvptx"]
+}
+
+# Return 1 if compiling for offload target amdgcn
+proc check_effective_target_offload_target_amdgcn { } {
+    return [libgomp_check_effective_target_offload_target "amdgcn"]
+}
+
 # Return 1 if offload device is available.
 proc check_effective_target_offload_device { } {
     return [check_runtime_nocache offload_device_available_ {
diff --git a/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c b/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c
index 9e59ef8864e..bc1ae68941a 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c
@@ -1,5 +1,5 @@
 /* { dg-do link } */
-/* { dg-excess-errors "unresolved symbol foo, lto1, mkoffload and lto-wrapper fatal errors" { target offload_device_nonshared_as } } */
+/* { dg-excess-errors "unresolved symbol foo, lto1, mkoffload and lto-wrapper fatal errors" { target { offload_target_nvptx || offload_target_amdgcn } } } */
 /* { dg-additional-sources "function-not-offloaded-aux.c" } */
 
 #pragma omp declare target
diff --git a/libgomp/testsuite/libgomp.c-c++-common/variable-not-offloaded.c b/libgomp/testsuite/libgomp.c-c++-common/variable-not-offloaded.c
index bc4b916e9a4..fe2a8b26242 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/variable-not-offloaded.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/variable-not-offloaded.c
@@ -1,7 +1,7 @@
 /* { dg-do link } */
-/* { dg-excess-errors "lto1, mkoffload and lto-wrapper fatal errors" { target offload_device_nonshared_as } } */
+/* { dg-excess-errors "lto1, mkoffload and lto-wrapper fatal errors" { target { offload_target_nvptx || offload_target_amdgcn } } } */
 
-int var; /* { dg-error "variable 'var' has been referenced in offloaded code but hasn't been marked to be included in the offloaded code" "" { target offload_device_nonshared_as } } */
+int var; /* { dg-error "variable 'var' has been referenced in offloaded code but hasn't been marked to be included in the offloaded code" "" { target { offload_target_nvptx || offload_target_amdgcn } } } */
 
 #pragma omp declare target
 void  __attribute__((noinline, noclone))
diff --git a/libgomp/testsuite/libgomp.c/pr86416-1.c b/libgomp/testsuite/libgomp.c/pr86416-1.c
index ad9370f78f3..6d3869264fd 100644
--- a/libgomp/testsuite/libgomp.c/pr86416-1.c
+++ b/libgomp/testsuite/libgomp.c/pr86416-1.c
@@ -2,8 +2,8 @@
 /* { dg-require-effective-target large_long_double } */
 
 /* PR middle-end/86416  */
-/* { dg-error "bit-precision floating-point numbers unsupported .mode '.F'." "" { target offload_device } 0 }  */
-/* { dg-excess-errors "Follow-up errors from mkoffload and lto-wrapper" { target offload_device } }  */
+/* { dg-error "bit-precision floating-point numbers unsupported .mode '.F'." "" { target { offload_target_nvptx || offload_target_amdgcn } } 0 }  */
+/* { dg-excess-errors "Follow-up errors from mkoffload and lto-wrapper" { target { offload_target_nvptx || offload_target_amdgcn } } }  */
 
 #include <stdlib.h>  /* For abort. */
 
diff --git a/libgomp/testsuite/libgomp.c/pr86416-2.c b/libgomp/testsuite/libgomp.c/pr86416-2.c
index ec45e400f95..cffeb3f7107 100644
--- a/libgomp/testsuite/libgomp.c/pr86416-2.c
+++ b/libgomp/testsuite/libgomp.c/pr86416-2.c
@@ -2,8 +2,8 @@
 /* { dg-add-options __float128 } */
 
 /* PR middle-end/86416  */
-/* { dg-error "bit-precision floating-point numbers unsupported .mode '.F'." "" { target offload_device } 0 }  */
-/* { dg-excess-errors "Follow-up errors from mkoffload and lto-wrapper" { target offload_device } }  */
+/* { dg-error "bit-precision floating-point numbers unsupported .mode '.F'." "" { target { offload_target_nvptx || offload_target_amdgcn } } 0 }  */
+/* { dg-excess-errors "Follow-up errors from mkoffload and lto-wrapper" { target { offload_target_nvptx || offload_target_amdgcn } } }  */
 
 #include <stdlib.h>  /* For abort. */
 

commit af53e450e5c61e36bd01aa2db1251483a60be007
Author: Marek Polacek <polacek@redhat.com>
Date:   Tue Apr 20 18:16:04 2021

    c++: Don't allow defining types in enum-base [PR96380]
    
    In r11-2064 I made cp_parser_enum_specifier commit to tentative parse
    when seeing a '{'.  That still looks like the correct thing to do, but
    it caused an ICE-on-invalid as well as accepts-invalid.
    
    When we have something sneaky like this, which is broken in multiple
    ways:
    
      template <class>
      enum struct c : union enum struct c { e = b, f = a };
    
    we parse the "enum struct c" part (that's OK) and then we see that
    we have an enum-base, so we consume ':' and then parse the type-specifier
    that follows the :.  "union enum" is clearly invalid, but we're still
    parsing tentatively and we parse everything up to the ;, and then
    throw away the underlying type.  We parsed everything because we were
    tricked into parsing an enum-specifier in an enum-base of another
    enum-specifier!  Not good.
    
    Since the grammar for enum-base doesn't allow a defining-type-specifier,
    only a type-specifier, we should set type_definition_forbidden_message
    which fixes all the problems in this PR.
    
    gcc/cp/ChangeLog:
    
            PR c++/96380
            * parser.c (cp_parser_enum_specifier): Don't allow defining
            types in enum-base.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/96380
            * g++.dg/cpp0x/enum_base4.C: New test.
            * g++.dg/cpp0x/enum_base5.C: New test.
    
    (cherry picked from commit 001c63d15e31bc0a1545426d889a0b9f671b4961)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 99eccf0c5e4..fba516efa23 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19942,6 +19942,10 @@ cp_parser_enum_specifier (cp_parser* parser)
       /* Consume the `:'.  */
       cp_lexer_consume_token (parser->lexer);
 
+      auto tdf
+	= make_temp_override (parser->type_definition_forbidden_message,
+			      G_("types may not be defined in enum-base"));
+
       /* Parse the type-specifier-seq.  */
       cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
 				    /*is_declaration=*/false,
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum_base4.C b/gcc/testsuite/g++.dg/cpp0x/enum_base4.C
new file mode 100644
index 00000000000..b3015256386
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum_base4.C
@@ -0,0 +1,8 @@
+// PR c++/96380
+// { dg-do compile { target c++11 } }
+
+extern const int a, b;
+enum struct c;
+template <class>
+enum struct c : union enum struct c { e = b, f = a };  // { dg-error "types may not be defined|expected|elaborated-type-specifier" }
+enum class c {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum_base5.C b/gcc/testsuite/g++.dg/cpp0x/enum_base5.C
new file mode 100644
index 00000000000..c01e857e612
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum_base5.C
@@ -0,0 +1,7 @@
+// PR c++/96380
+// { dg-do compile { target c++11 } }
+
+extern const int a, b;
+enum struct c;
+template <class>
+enum struct c : union enum struct c { e = b, f = a }; // { dg-error "types may not be defined|expected|elaborated-type-specifier" }

commit fb7c736c2f17ad054ee7815b688fa91135690f6d
Author: Marek Polacek <polacek@redhat.com>
Date:   Wed Apr 21 02:24:09 2021

    c++: Prevent bogus -Wtype-limits warning with NTTP [PR100161]
    
    Recently, we made sure that we never call value_dependent_expression_p
    on an expression that isn't potential_constant_expression.  That caused
    this bogus warning with a non-type template parameter, something that
    users don't want to see.
    
    The problem is that in tsubst_copy_and_build/LE_EXPR 't' is "i < n",
    which, due to 'i', is not p_c_e, therefore we call t_d_e_p.  But the
    type of 'n' isn't dependent, so we think the whole 't' expression is
    not dependent.  It seems we need to test both op0 and op1 separately
    to suppress this warning.
    
    gcc/cp/ChangeLog:
    
            PR c++/100161
            * pt.c (tsubst_copy_and_build) <case PLUS_EXPR>: Test op0 and
            op1 separately for value- or type-dependence.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/100161
            * g++.dg/warn/Wtype-limits6.C: New test.
    
    (cherry picked from commit 244dfb95119106e9267f37583caac565c39eb0ec)

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 19fdafa4c43..ada2b63efb9 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19900,15 +19900,21 @@ tsubst_copy_and_build (tree t,
     case MEMBER_REF:
     case DOTSTAR_EXPR:
       {
-	/* If T was type-dependent, suppress warnings that depend on the range
-	   of the types involved.  */
-	++processing_template_decl;
-	const bool was_dep = (potential_constant_expression (t)
-			      ? value_dependent_expression_p (t)
-			      : type_dependent_expression_p (t));
-	--processing_template_decl;
-	tree op0 = RECUR (TREE_OPERAND (t, 0));
-	tree op1 = RECUR (TREE_OPERAND (t, 1));
+	/* If either OP0 or OP1 was value- or type-dependent, suppress
+	   warnings that depend on the range of the types involved.  */
+	tree op0 = TREE_OPERAND (t, 0);
+	tree op1 = TREE_OPERAND (t, 1);
+	auto dep_p = [](tree t) {
+	  ++processing_template_decl;
+	  bool r = (potential_constant_expression (t)
+		    ? value_dependent_expression_p (t)
+		    : type_dependent_expression_p (t));
+	  --processing_template_decl;
+	  return r;
+	};
+	const bool was_dep = dep_p (op0) || dep_p (op1);
+	op0 = RECUR (op0);
+	op1 = RECUR (op1);
 
 	warning_sentinel s1(warn_type_limits, was_dep);
 	warning_sentinel s2(warn_div_by_zero, was_dep);
diff --git a/gcc/testsuite/g++.dg/warn/Wtype-limits6.C b/gcc/testsuite/g++.dg/warn/Wtype-limits6.C
new file mode 100644
index 00000000000..9d5886d5323
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wtype-limits6.C
@@ -0,0 +1,17 @@
+// PR c++/100161
+// { dg-additional-options "-Wtype-limits" }
+
+void f(unsigned);
+
+template<unsigned n>
+void g()
+{
+    for (unsigned i = 0; i < n; i++) { // { dg-bogus "always false" }
+        f(i);
+    }
+}
+
+void h()
+{
+    g<0>();
+}
