https://gcc.gnu.org/g:6bace0ed49aea613ccd6c4f3c21a9ef0473fe62b
commit r16-5439-g6bace0ed49aea613ccd6c4f3c21a9ef0473fe62b Author: Jakub Jelinek <[email protected]> Date: Thu Nov 20 08:19:32 2025 +0100 c++: Fix error recovery ICE in tsubst_baselink [PR120876] The following testcase ICEs since r12-6080. The problem is that lookup_fnfields can return NULL_TREE on failure, but the maybe_incomplete handling was added before the if (!baselink) handling and assumes that baselink is non-NULL (and BASELINK). The following patch reorders the if (maybe_incomplete) handling with if (!baselink). 2025-11-20 Jakub Jelinek <[email protected]> PR c++/120876 * pt.cc (tsubst_baselink): Move maybe_incomplete handling after !baselink handling. * g++.dg/parse/crash81.C: New test. Diff: --- gcc/cp/pt.cc | 26 +++++++++++++------------- gcc/testsuite/g++.dg/parse/crash81.C | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 0daf43c681b1..27d786d0e777 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -17627,19 +17627,6 @@ tsubst_baselink (tree baselink, tree object_type, bool maybe_incomplete = BASELINK_FUNCTIONS_MAYBE_INCOMPLETE_P (baselink); baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1, complain); - if (maybe_incomplete) - { - /* Filter out from the new lookup set those functions which didn't - appear in the original lookup set (in a less specialized form). - This is needed to preserve the consistency of member lookup - performed in an incomplete-class context, within which - later-declared members ought to remain invisible. */ - BASELINK_FUNCTIONS (baselink) - = filter_memfn_lookup (fns, BASELINK_FUNCTIONS (baselink), - binfo_type); - BASELINK_FUNCTIONS_MAYBE_INCOMPLETE_P (baselink) = true; - } - if (!baselink) { if (complain & tf_error) @@ -17657,6 +17644,19 @@ tsubst_baselink (tree baselink, tree object_type, return error_mark_node; } + if (maybe_incomplete) + { + /* Filter out from the new lookup set those functions which didn't + appear in the original lookup set (in a less specialized form). + This is needed to preserve the consistency of member lookup + performed in an incomplete-class context, within which + later-declared members ought to remain invisible. */ + BASELINK_FUNCTIONS (baselink) + = filter_memfn_lookup (fns, BASELINK_FUNCTIONS (baselink), + binfo_type); + BASELINK_FUNCTIONS_MAYBE_INCOMPLETE_P (baselink) = true; + } + fns = BASELINK_FUNCTIONS (baselink); } else diff --git a/gcc/testsuite/g++.dg/parse/crash81.C b/gcc/testsuite/g++.dg/parse/crash81.C new file mode 100644 index 000000000000..6841162195e0 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/crash81.C @@ -0,0 +1,14 @@ +// PR c++/120876 +// { dg-do compile { target c++11 } } + +template <typename T> +struct S { + static bool foo (decltype (bar (T {}))); // { dg-error "'bar' was not declared in this scope; did you mean 'baz'\\\?" } + static constexpr bool s = foo (0); // { dg-error "declaration of 'S<int>::foo' depends on itself" } +}; + +void +baz () +{ + S <int>::s; +}
