Since r10-3793-g1a37b6d9a7e57c, we ICE upon the following valid code with -std=c++17 and above
=== cut here === struct Base { unsigned int *intarray; }; template <typename T> struct Sub : public Base { bool Get(int i) { return (Base::intarray[++i] == 0); } }; === cut here === The problem is that from c++17 on, we use -fstrong-eval-order and need to wrap the array access expression into a SAVE_EXPR, and end up calling contains_placeholder_p with a SCOPE_REF, that it does not handle well. This patch fixes this by skipping the first operand of SCOPE_REFs in contains_placeholder_p. Successfully tested on x86_64-pc-linux-gnu. PR c++/117158 gcc/ChangeLog: * tree.cc (contains_placeholder_p): Skip the first operand of SCOPE_REFs. gcc/testsuite/ChangeLog: * g++.dg/parse/crash77.C: New test. --- gcc/testsuite/g++.dg/parse/crash77.C | 13 +++++++++++++ gcc/tree.cc | 3 +++ 2 files changed, 16 insertions(+) create mode 100644 gcc/testsuite/g++.dg/parse/crash77.C diff --git a/gcc/testsuite/g++.dg/parse/crash77.C b/gcc/testsuite/g++.dg/parse/crash77.C new file mode 100644 index 00000000000..25a426fa6d6 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/crash77.C @@ -0,0 +1,13 @@ +// PR c++/117158 +// { dg-do "compile" } + +struct Base { + unsigned int *intarray; +}; + +template <typename T> +struct Sub : public Base { + bool Get(int i) { + return (Base::intarray[++i] == 0); + } +}; diff --git a/gcc/tree.cc b/gcc/tree.cc index b4c059d3b0d..7f8911002d0 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -4122,6 +4122,9 @@ contains_placeholder_p (const_tree exp) if (!exp) return false; + if (TREE_CODE (exp) == SCOPE_REF) + exp = TREE_OPERAND (exp, 1); + code = TREE_CODE (exp); if (code == PLACEHOLDER_EXPR) return true; -- 2.44.0