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 struct X { + void g () {} + void f () __attribute__((__used__)) {} +}; + +extern X x; // X incomplete here + +template +void Frob (T t) { + x.g(); // X completed here, X::f's body marked for instantiation +} + +// Make sure X::f is emitted +// { dg-final { scan-assembler "_ZN1XIiE1fEv:" } }