aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-10-04 11:37:09 -0400
committerJason Merrill <jason@gcc.gnu.org>2017-10-04 11:37:09 -0400
commit6411847fcf9941ef7312911378839cc8f45e8d9a (patch)
treeee55bf31da00b85e990bd757ee4278c212071c77
parent8139a48e67ec9f178904d2bb83a17bd37ce8fb54 (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/cp/pt.c23
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-auto1.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4a.C20
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); }