c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

Message ID 65e2cd2b.620a0220.3d4c1.2206@mx.google.com
State Accepted
Headers
Series c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881] |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Nathaniel Shead March 2, 2024, 6:54 a.m. UTC
  Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

When streaming in a nested template-template parameter as in the
attached testcase, we end up reaching the containing template-template
parameter in 'tpl_parms_fini'. We should not set the DECL_CONTEXT to
this (nested) template-template parameter, as it should already be the
struct that the outer template-template parameter is declared on.

	PR c++/98881

gcc/cp/ChangeLog:

	* module.cc (trees_out::tpl_parms_fini): Clarify logic purely
	for checking purposes. Don't consider a template template
	parameter as the owning template.
	(trees_in::tpl_parms_fini): Don't consider a template template
	parameter as the owning template.

gcc/testsuite/ChangeLog:

	* g++.dg/modules/tpl-tpl-parm-3_a.H: New test.
	* g++.dg/modules/tpl-tpl-parm-3_b.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
---
 gcc/cp/module.cc                                | 17 ++++++++++++-----
 gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_a.H | 11 +++++++++++
 gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_b.C | 13 +++++++++++++
 3 files changed, 36 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_a.H
 create mode 100644 gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_b.C
  

Patch

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 67f132d28d7..5663d01ed9c 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -10126,10 +10126,14 @@  trees_out::tpl_parms_fini (tree tmpl, unsigned tpl_levels)
 	  tree dflt = TREE_PURPOSE (parm);
 	  tree_node (dflt);
 
-	  if (streaming_p ())
+	  if (CHECKING_P && streaming_p ())
 	    {
+	      /* Sanity check that the DECL_CONTEXT we'll infer when
+		 streaming in is correct.  */
 	      tree decl = TREE_VALUE (parm);
-	      if (TREE_CODE (decl) == TEMPLATE_DECL)
+	      if (TREE_CODE (decl) == TEMPLATE_DECL
+		  /* A template template parm is not the owning template.  */
+		  && !DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
 		{
 		  tree ctx = DECL_CONTEXT (decl);
 		  tree inner = DECL_TEMPLATE_RESULT (decl);
@@ -10164,8 +10168,13 @@  trees_in::tpl_parms_fini (tree tmpl, unsigned tpl_levels)
 	    return false;
 	  TREE_PURPOSE (parm) = dflt;
 
+	  /* Original template template parms have a context
+	     of their owning template.  Reduced ones do not.
+	     But if TMPL is itself a template template parm
+	     then it cannot be the owning template.  */
 	  tree decl = TREE_VALUE (parm);
-	  if (TREE_CODE (decl) == TEMPLATE_DECL)
+	  if (TREE_CODE (decl) == TEMPLATE_DECL
+	      && !DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
 	    {
 	      tree inner = DECL_TEMPLATE_RESULT (decl);
 	      tree tpi = (TREE_CODE (inner) == TYPE_DECL
@@ -10173,8 +10182,6 @@  trees_in::tpl_parms_fini (tree tmpl, unsigned tpl_levels)
 			  : DECL_INITIAL (inner));
 	      bool original = (TEMPLATE_PARM_LEVEL (tpi)
 			       == TEMPLATE_PARM_ORIG_LEVEL (tpi));
-	      /* Original template template parms have a context
-		 of their owning template.  Reduced ones do not.  */
 	      if (original)
 		DECL_CONTEXT (decl) = tmpl;
 	    }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_a.H b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_a.H
new file mode 100644
index 00000000000..21bbc054fa3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_a.H
@@ -0,0 +1,11 @@ 
+// PR c++/98881
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template <typename P> struct X {};
+
+template<template <typename> typename TT>
+struct X<TT<int>> {
+  template<template <typename> typename UU>
+  void f (X<UU<int>>&);
+};
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_b.C b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_b.C
new file mode 100644
index 00000000000..234e822faa9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_b.C
@@ -0,0 +1,13 @@ 
+// PR c++/98881
+// { dg-additional-options "-fmodules-ts" }
+
+import "tpl-tpl-parm-3_a.H";
+
+template <typename T> struct Y {};
+template <typename T> struct Z {};
+
+void foo() {
+  X<Y<int>> y;
+  X<Z<int>> z;
+  y.f(z);
+}