On 3/2/24 01:54, Nathaniel Shead wrote:
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.
So in the case where tmpl is a template template parameter we want
DECL_CONTEXT (parm) to be the same as DECL_CONTEXT (tmpl)? Let's check
that instead of ignoring it.
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 <nathanielosh...@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
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);
+}