public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for c++/81525, auto and generic lambda
@ 2017-08-09 19:25 Jason Merrill
  2017-10-04 15:34 ` Jason Merrill
  0 siblings, 1 reply; 2+ messages in thread
From: Jason Merrill @ 2017-08-09 19:25 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 251 bytes --]

In this testcase, when building up an extra version of N to refer to
when instantiating the generic lambda, we were mistakenly replacing
the 'auto' with a template argument for the generic lambda.

Tested x86_64-pc-linux-gnu, applying to trunk and 7.

[-- Attachment #2: 81525.diff --]
[-- Type: text/plain, Size: 2245 bytes --]

commit e42e1cc162267b85adfb624daf1b96fc2f5a6f5b
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Aug 7 15:05:51 2017 -0400

            PR c++/81525 - wrong constant value with generic lambda
    
            * pt.c (tsubst_decl) [VAR_DECL]: Avoid clobbering auto.
            (tsubst_copy) [VAR_DECL]: Handle auto.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3d6f4b5..0f899b9 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12875,7 +12875,15 @@ 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;
 	  }
 	if (VAR_P (r))
 	  {
@@ -14656,6 +14664,10 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 			DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
 			  = TREE_CONSTANT (r) = true;
 		      DECL_INITIAL (r) = init;
+		      if (tree auto_node = type_uses_auto (TREE_TYPE (r)))
+			TREE_TYPE (r)
+			  = do_auto_deduction (TREE_TYPE (r), init, auto_node,
+					       complain, adc_variable_type);
 		    }
 		  gcc_assert (cp_unevaluated_operand || TREE_STATIC (r)
 			      || decl_constant_var_p (r)
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C
new file mode 100644
index 0000000..52f4373
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const4.C
@@ -0,0 +1,20 @@
+// PR c++/81525
+// { dg-do compile { 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 (A<0>{});
+}
+template <typename T>
+void bar (T) {
+  constexpr auto N = a<1>;
+  auto f = [&] (auto i) {
+    static_assert (static_cast<int>(N) == 1, "");
+  };
+  foo (f);
+}
+int main () { bar (0); }

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: C++ PATCH for c++/81525, auto and generic lambda
  2017-08-09 19:25 C++ PATCH for c++/81525, auto and generic lambda Jason Merrill
@ 2017-10-04 15:34 ` Jason Merrill
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2017-10-04 15:34 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 764 bytes --]

On Wed, Aug 9, 2017 at 3:20 PM, Jason Merrill <jason@redhat.com> wrote:
> In this testcase, when building up an extra version of N to refer to
> when instantiating the generic lambda, we were mistakenly replacing
> the 'auto' with a template argument for the generic lambda.
>
> Tested x86_64-pc-linux-gnu, applying to trunk and 7.

Recent testing found a bug in this patch, whereby we would mistakenly
clobber the TREE_VEC_LENGTH of a single-level argument set, or
increase the length rather than decreasing it.  Fixed by using
strip_innermost_template_args and calculating how many levels we
actually want to remove.  On the trunk I've also added an assert that
we shouldn't get into this situation anymore.

Tested x86_64-pc-linux-gnu, applying to trunk and 7.

[-- Attachment #2: 81525-7.diff --]
[-- Type: text/plain, Size: 1997 bytes --]

commit 2e694fe9477fefb4d746943c6996785109f61aa6
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Sep 28 16:07:34 2017 -0400

            PR c++/81525 - broken handling of auto in generic lambda.
    
            * pt.c (tsubst_decl) [VAR_DECL]: Use strip_innermost_template_args.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f3ad6083190..38d7b45eb9b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12896,15 +12896,17 @@ 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)
+		  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 <class X>
+struct A
+{
+  template <class T>
+  static void f()
+  {
+    [](auto b) {
+      auto c = +b;
+    }(42);
+  }
+};
+
+int main()
+{
+  A<int>::f<int>();
+}

[-- Attachment #3: 81525.diff --]
[-- Type: text/plain, Size: 3526 bytes --]

commit c6c77e3c274bc8a1bdd33be58895e1ae08a453a7
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Sep 28 16:07:34 2017 -0400

            PR c++/81525 - broken handling of auto in generic lambda.
    
            * pt.c (tsubst_decl) [VAR_DECL]: Use strip_innermost_template_args.

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 <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 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 <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 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 <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); }

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-10-04 15:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-09 19:25 C++ PATCH for c++/81525, auto and generic lambda Jason Merrill
2017-10-04 15:34 ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).