diff options
author | Jason Merrill <jason@redhat.com> | 2017-10-04 11:37:09 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2017-10-04 11:37:09 -0400 |
commit | 6411847fcf9941ef7312911378839cc8f45e8d9a (patch) | |
tree | ee55bf31da00b85e990bd757ee4278c212071c77 | |
parent | 8139a48e67ec9f178904d2bb83a17bd37ce8fb54 (diff) | |
download | gcc-6411847fcf9941ef7312911378839cc8f45e8d9a.zip gcc-6411847fcf9941ef7312911378839cc8f45e8d9a.tar.gz gcc-6411847fcf9941ef7312911378839cc8f45e8d9a.tar.bz2 |
PR c++/81525 - broken handling of auto in generic lambda.
* pt.c (tsubst_decl) [VAR_DECL]: Use strip_innermost_template_args.
From-SVN: r253414
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/pt.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/lambda-generic-auto1.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4a.C | 20 |
5 files changed, 60 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0d20ea5..b1eaaba 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2017-10-04 Jason Merrill <jason@redhat.com> + + 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 <nathan@acm.org> * call.c (convert_arg_to_ellipsis): Correct comment about passing diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c29c779..36c8c10 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 0000000..b9e98c5 --- /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 <class X> +struct A +{ + template <class T> + static void f() + { + [](auto b) { + auto c = +b; + }(42); + } +}; + +int main() +{ + A<int>::f<int>(); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C index d56f379..1cf8551 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 <int i> struct A { constexpr operator int () const { return i; } @@ -13,7 +13,7 @@ template <typename T> void bar (T) { constexpr auto N = a<1>; auto f = [&] (auto i) { - return static_cast<int>(N) == 1; + if (static_cast<int>(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 0000000..a6afb32 --- /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 <int i> struct A { + constexpr operator int () const { return i; } +}; +template <int i> constexpr A<i> a = {}; + +template <typename F> void foo (F f) { + f (42); +} +template <typename T> +void bar (T) { + constexpr auto N = a<1>; + auto f = [&] (auto i) { + if (static_cast<decltype(i)>(N) != 1) __builtin_abort(); + }; + foo (f); +} +int main () { bar (0); } |