https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95468
--- Comment #3 from Patrick Palka <ppalka at gcc dot gnu.org> --- The reason we fail to compile the testcase when 'condition' is at class scope instead of at namespace scope is because in the former case, the template argument 'c::condition<bool(true)>' is a CALL_EXPR to a BASELINK, and when doing instantiate_non_dependent_expr_internal on this CALL_EXPR, we don't semantically process the template argument 'bool(true)' within BASELINK because we never call tsubst_baselink because tsubst_copy exits early when args is NULL_TREE. We don't have this problem in the latter case where 'condition' is at namespace scope, because then the template argument 'condition<bool(true)>' is a CALL_EXPR to a TEMPLATE_ID_EXPR, and TEMPLATE_ID_EXPRs are handled directly from tsubst_copy_and_build which doesn't do an early exit when args is NULL_TREE. A potential untested fix therefore is to also handle BASELINK directly from tsubst_copy_and_build: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d7f61289621..e15fca54823 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -19472,6 +19472,11 @@ tsubst_copy_and_build (tree t, case SCOPE_REF: RETURN (tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true, /*address_p=*/false)); + + case BASELINK: + RETURN (tsubst_baselink (t, current_nonlambda_class_type (), + args, complain, in_decl)); + case ARRAY_REF: op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0), args, complain, in_decl); Ideally we might want two versions of tsubst_baselink, one that does template argument substitution and another than additionally performs semantic processing?