public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Patrick Palka <ppalka@redhat.com>
To: gcc-patches@gcc.gnu.org
Cc: jason@redhat.com, Patrick Palka <ppalka@redhat.com>
Subject: [PATCH] c++: NSDMI instantiation from template context [PR109506]
Date: Thu, 27 Apr 2023 12:39:56 -0400	[thread overview]
Message-ID: <20230427163956.3051552-1-ppalka@redhat.com> (raw)

The testcase from this PR fails to link when -fchecking=2 with the error:

  /usr/bin/ld: /tmp/ccpHiXEY.o: in function `bar<int>::bar()':
  ...: undefined reference to `foo<int>::foo()'

ultimately because we end up instantiating the NSDMI for bar<int>::alloc_
from the template context func1<T> for which in_template_function is
true and thus mark_used is inhibited from scheduling other templates for
instantiation.  So we end up never instantiating foo<int>'s ctor.

Although maybe_instantiate_nsdmi_init does call push_to_top_level, which
would have gotten us out of the template context, it doesn't happen in
this case because currently_open_class (ctx) is true, thanks to an
earlier call to push_scope from synthesized_method_walk.

We could perhaps arrange to call push_to_top_level unconditionally in
maybe_instantiate_nsdmi_init or even from from synthesized_method_walk,
but that seems rather heavyweight for this situation.  Ideally we just
want a way to allow mark_used to work here despite being in a template
context.

To that end, this patch first generalizes the in_template_function test
in mark_used to instead test current_template_parms, which has two
benefits: it works for all template contexts, not just function template
contexts, and it can be cheaply disabled by simply clearing
current_template_parms.  This patch then makes us disable this test from
maybe_instantiate_nsdmi_init.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?  This doesn't seem worth backporting since the bug seems to
manifest only with -fchecking=2.

	PR c++/109506

gcc/cp/ChangeLog:

	* decl2.cc (mark_used): Check current_template_parms instead
	of in_template_function.
	* init.cc (maybe_instantiate_nsdmi_init): Clear
	current_template_parms before instantiating.

gcc/testsuite/ChangeLog:

	* g++.dg/warn/Waddress-of-packed-member2.C: No longer expect
	a "used but never defined" warning due to the use from an
	uninstantiated template.
	* g++.dg/template/non-dependent25.C: New test.
---
 gcc/cp/decl2.cc                               |  6 ++++-
 gcc/cp/init.cc                                |  3 +++
 gcc/testsuite/g++.dg/cpp0x/nsdmi-template26.C | 23 +++++++++++++++++++
 .../g++.dg/warn/Waddress-of-packed-member2.C  |  2 +-
 4 files changed, 32 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template26.C

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 9594be4092c..b9d37d76bf6 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -5781,7 +5781,11 @@ mark_used (tree decl, tsubst_flags_t complain /* = tf_warning_or_error */)
 	  && DECL_OMP_DECLARE_REDUCTION_P (decl)))
     maybe_instantiate_decl (decl);
 
-  if (processing_template_decl || in_template_function ())
+  /* We don't want to instantiate templates based on uses from other
+     uninstantiated templates.  Since processing_template_decl is cleared
+     during instantiate_non_dependent_expr, we check current_template_parms
+     as well.  */
+  if (processing_template_decl || current_template_parms)
     return true;
 
   /* Check this too in case we're within instantiate_non_dependent_expr.  */
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 1dd24e30d7c..ef32ef2a8c2 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -610,6 +610,9 @@ maybe_instantiate_nsdmi_init (tree member, tsubst_flags_t complain)
 	      push_deferring_access_checks (dk_no_deferred);
 	      pushed = true;
 	    }
+	  /* Make sure current_template_parms is cleared so that mark_used
+	     is uninhibited.  */
+	  auto ctpo = make_temp_override (current_template_parms, NULL_TREE);
 
 	  /* If we didn't push_to_top_level, still step out of constructor
 	     scope so build_base_path doesn't try to use its __in_chrg.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template26.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template26.C
new file mode 100644
index 00000000000..d9e17ea6724
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template26.C
@@ -0,0 +1,23 @@
+// PR c++/109506
+// { dg-do link { target c++11 } }
+// { dg-additional-options "-fchecking=2" }
+
+template<class T>
+struct foo {
+  foo() { };
+};
+
+template<class T>
+class bar {
+  foo<int> alloc_{};
+};
+
+template<class T>
+bar<int> func1() {
+  return bar<int>{};
+}
+
+int main() {
+  func1<int>();
+}
+
diff --git a/gcc/testsuite/g++.dg/warn/Waddress-of-packed-member2.C b/gcc/testsuite/g++.dg/warn/Waddress-of-packed-member2.C
index e9bf7cac04c..d619b28cfe1 100644
--- a/gcc/testsuite/g++.dg/warn/Waddress-of-packed-member2.C
+++ b/gcc/testsuite/g++.dg/warn/Waddress-of-packed-member2.C
@@ -1,7 +1,7 @@
 // PR c++/89973
 // { dg-do compile { target c++14 } }
 
-constexpr int a(); // { dg-warning "used but never defined" }
+constexpr int a();
 
 template <typename>
 constexpr void *b = a(); // { dg-error "invalid conversion" }
-- 
2.40.1.423.g2807bd2c10


             reply	other threads:[~2023-04-27 16:40 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-27 16:39 Patrick Palka [this message]
2023-04-27 22:35 ` Sam James

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230427163956.3051552-1-ppalka@redhat.com \
    --to=ppalka@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jason@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).