Fix PR97966 regression

Message ID 10058f5d-f80e-fb6f-ee6c-30a4ee343c98@acm.org
State New
Headers
Series Fix PR97966 regression |

Commit Message

Nathan Sidwell Jan. 5, 2022, 12:16 p.m. UTC
  Marek's fix for PR97966 caused a regression with (non-template) member
functions of template classes.  We need to mark them used in the
instantiated class's scope, rather than the scope we were in before
instantiating, as the latter may itself be in template and change the
behaviour of marking a function as used.

pushed to trunk

nathan
  

Patch

From 10195da73618ab818b66d4d2fade1be46ea39962 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell <nathan@acm.org>
Date: Tue, 4 Jan 2022 13:36:44 -0800
Subject: [PATCH 3/3] Adjust mark used member in instantiated class scope

The fix for PR97966 caused a regression with (non-template) member
functions of template classes.  We need to mark them used in the
instantiated class's scope, rather than the scope we were in before
instantiating, as the latter may itself be in template and change the
behaviour of marking a function as used.

	gcc/cp/
	* pt.c (instantiate_class_template_1): Process attribute((used)) set
	in class's context.
	gcc/testsuite/
	* g++.dg/template/attr-used.C: New.
---
 gcc/cp/pt.c                               | 13 ++++++++-----
 gcc/testsuite/g++.dg/template/attr-used.C | 16 ++++++++++++++++
 2 files changed, 24 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/attr-used.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index c587966adbe..0fa4a162354 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12277,6 +12277,14 @@  instantiate_class_template_1 (tree type)
 
   perform_instantiation_time_access_checks (pattern, args);
   perform_deferred_access_checks (tf_warning_or_error);
+
+  /* Now that we've gone through all the members, instantiate those
+     marked with attribute used.  We must do this in the context of
+     the class -- not the context we pushed from, as that might be
+     inside a template and change the behaviour of mark_used.  */
+  for (tree x : used)
+    mark_used (x);
+
   pop_nested_class ();
   maximum_field_alignment = saved_maximum_field_alignment;
   if (!fn_context)
@@ -12290,11 +12298,6 @@  instantiate_class_template_1 (tree type)
   if (TYPE_CONTAINS_VPTR_P (type) && CLASSTYPE_KEY_METHOD (type))
     vec_safe_push (keyed_classes, type);
 
-  /* Now that we've gone through all the members, instantiate those
-     marked with attribute used.  */
-  for (tree x : used)
-    mark_used (x);
-
   return type;
 }
 
diff --git a/gcc/testsuite/g++.dg/template/attr-used.C b/gcc/testsuite/g++.dg/template/attr-used.C
new file mode 100644
index 00000000000..e12bf4caa3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/attr-used.C
@@ -0,0 +1,16 @@ 
+// { dg-do compile }
+
+template<typename T> struct X {
+  void g () {}
+  void f () __attribute__((__used__)) {}
+};
+
+extern X<int> x; // X<int> incomplete here
+
+template <typename T>
+void Frob (T t) {
+  x.g(); // X<int> completed here, X<int>::f's body marked for instantiation
+}
+
+// Make sure X<int>::f is emitted
+// { dg-final { scan-assembler "_ZN1XIiE1fEv:" } }
-- 
2.30.2