From 6411847fcf9941ef7312911378839cc8f45e8d9a Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 4 Oct 2017 11:37:09 -0400 Subject: [PATCH] PR c++/81525 - broken handling of auto in generic lambda. * pt.c (tsubst_decl) [VAR_DECL]: Use strip_innermost_template_args. From-SVN: r253414 --- gcc/cp/ChangeLog | 5 ++++ gcc/cp/pt.c | 23 +++++++++++-------- .../g++.dg/cpp1y/lambda-generic-auto1.C | 19 +++++++++++++++ .../g++.dg/cpp1y/lambda-generic-const4.C | 4 ++-- .../g++.dg/cpp1y/lambda-generic-const4a.C | 20 ++++++++++++++++ 5 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-auto1.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4a.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0d20ea5d1fa..b1eaaba5bc6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2017-10-04 Jason Merrill + + PR c++/81525 - broken handling of auto in generic lambda. + * pt.c (tsubst_decl) [VAR_DECL]: Use strip_innermost_template_args. + 2017-10-04 Nathan Sidwell * call.c (convert_arg_to_ellipsis): Correct comment about passing diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c29c779a147..36c8c106439 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13042,15 +13042,20 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) && VAR_HAD_UNKNOWN_BOUND (t) && type != error_mark_node) type = strip_array_domain (type); - tree auto_node = type_uses_auto (type); - int len = TREE_VEC_LENGTH (args); - if (auto_node) - /* Mask off any template args past the variable's context so we - don't replace the auto with an unrelated argument. */ - TREE_VEC_LENGTH (args) = TEMPLATE_TYPE_LEVEL (auto_node) - 1; - type = tsubst (type, args, complain, in_decl); - if (auto_node) - TREE_VEC_LENGTH (args) = len; + tree sub_args = args; + if (tree auto_node = type_uses_auto (type)) + { + /* Mask off any template args past the variable's context so we + don't replace the auto with an unrelated argument. */ + int nouter = TEMPLATE_TYPE_LEVEL (auto_node) - 1; + int extra = TMPL_ARGS_DEPTH (args) - nouter; + if (extra > 0) + /* This should never happen with the new lambda instantiation + model, but keep the handling just in case. */ + gcc_assert (!CHECKING_P), + sub_args = strip_innermost_template_args (args, extra); + } + type = tsubst (type, sub_args, complain, in_decl); } if (VAR_P (r)) { diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-auto1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-auto1.C new file mode 100644 index 00000000000..b9e98c551c0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-auto1.C @@ -0,0 +1,19 @@ +// Related to c++/81525 +// { dg-do compile { target c++14 } } + +template +struct A +{ + template + static void f() + { + [](auto b) { + auto c = +b; + }(42); + } +}; + +int main() +{ + A::f(); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C index d56f379c680..1cf85518813 100644 --- a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C @@ -1,5 +1,5 @@ // PR c++/81525 -// { dg-do compile { target c++14 } } +// { dg-do run { target c++14 } } template struct A { constexpr operator int () const { return i; } @@ -13,7 +13,7 @@ template void bar (T) { constexpr auto N = a<1>; auto f = [&] (auto i) { - return static_cast(N) == 1; + if (static_cast(N) != 1) __builtin_abort(); }; foo (f); } diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4a.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4a.C new file mode 100644 index 00000000000..a6afb32584f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4a.C @@ -0,0 +1,20 @@ +// PR c++/81525 +// { dg-do run { target c++14 } } + +template struct A { + constexpr operator int () const { return i; } +}; +template constexpr A a = {}; + +template void foo (F f) { + f (42); +} +template +void bar (T) { + constexpr auto N = a<1>; + auto f = [&] (auto i) { + if (static_cast(N) != 1) __builtin_abort(); + }; + foo (f); +} +int main () { bar (0); } -- 2.30.2