From 6fa8e0896c6ec96eddcedb2b92502a7bbb525c03 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Thu, 18 Nov 2021 10:04:27 -0500 Subject: [PATCH] c++: unqual lookup performed twice w/ template-id ADL [PR102670] Here we're incorrectly performing unqualified lookup of 'adl' again at substitution time for the call adl(t) (for which name lookup at parse time found nothing) which causes us to reject the testcase because the second unqualified lookup finds the later-declared variable template 'adl', leading to confusion. Fixed thusly. The testcase concepts-recursive-sat1.C needed to be adjusted to use ADL proper instead of relying on this incorrect second unqualified lookup. PR c++/102670 gcc/cp/ChangeLog: * pt.c (tsubst_copy_and_build) : When looking for an identifier callee in the koenig_p case, also look through TEMPLATE_ID_EXPR. Use tsubst_copy to substitute through the template arguments of the template-id. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-recursive-sat1.C: Adjust to use ADL proper. * g++.dg/cpp2a/fn-template23.C: New test. --- gcc/cp/pt.c | 11 +++++- .../g++.dg/cpp2a/concepts-recursive-sat1.C | 15 +++++--- gcc/testsuite/g++.dg/cpp2a/fn-template23.C | 36 +++++++++++++++++++ 3 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/fn-template23.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b27eea33272e..2e31663c277b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -20267,7 +20267,10 @@ tsubst_copy_and_build (tree t, /*done=*/false, /*address_p=*/false); } - else if (koenig_p && identifier_p (function)) + else if (koenig_p + && (identifier_p (function) + || (TREE_CODE (function) == TEMPLATE_ID_EXPR + && identifier_p (TREE_OPERAND (function, 0))))) { /* Do nothing; calling tsubst_copy_and_build on an identifier would incorrectly perform unqualified lookup again. @@ -20280,6 +20283,12 @@ tsubst_copy_and_build (tree t, FIXME but doing that causes c++/15272, so we need to stop using IDENTIFIER_NODE in that situation. */ qualified_p = false; + + if (TREE_CODE (function) == TEMPLATE_ID_EXPR) + /* Use tsubst_copy to substitute through the template arguments + of the template-id without performing unqualified lookup of + the template name. */ + function = tsubst_copy (function, args, complain, in_decl); } else { diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C index 22696c30d816..0103e7a591f8 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C @@ -3,16 +3,21 @@ template concept Foo = requires(T t) { foo(t); }; // { dg-error "template instantiation depth" } -template - requires Foo -int foo(T t) +namespace ns { - return foo(t); + struct S { }; + + template + requires Foo + int foo(T t) + { + return foo(t); + } } int main(int, char**) { - return foo<1>(1); + return foo<1>(ns::S{}); } // { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/cpp2a/fn-template23.C b/gcc/testsuite/g++.dg/cpp2a/fn-template23.C new file mode 100644 index 000000000000..b85d4c96dab6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/fn-template23.C @@ -0,0 +1,36 @@ +// PR c++/102670 +// { dg-do compile { target c++20 } } + +namespace ns { + struct S { }; + + template + constexpr int adl(const S &) { + return I; + } +} + +namespace redirect { + template + concept can_call_adl = requires(T t) { + adl(t); + }; + + template + struct adl_fn { + template T> + constexpr decltype(auto) operator()(T t) const { + return adl(t); + } + }; + + namespace { + template + constexpr inline adl_fn adl{}; + } +} + +int main() { + static_assert(redirect::can_call_adl); + redirect::adl<3>(ns::S{}); +} -- 2.47.2