This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH]: instantiation via vtable marking
- From: Nathan Sidwell <nathan at acm dot org>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 14 Feb 2018 11:28:31 -0500
- Subject: [C++ PATCH]: instantiation via vtable marking
- Authentication-results: sourceware.org; auth=none
We had encountered a bogus warning about class visibility. Namely a
lambda had captured a variable whose type was in the anonymous
namespace. The problem was that in_main_input_context was returning
false (i.e. we're in a header file), as that was the location of the
outermost template instantiation (yup, the lambda came out of a template
instantiation).
The problem was the location was wrong -- it was pointing to some much
earlier non-template class definition. (funnily enough, the class was to
do with Futures, messing with my head about reaching into the future of
the compilation).
The problem stemmed from the c_parse_final_cleanups. That consists of a
do-until-no-more loop that does a bunch of things. Early in the loop it
maybe_emits_vtables and later in the loop it emits inline function that
need a body. In this case, an earlier non-template class needed its
virtual deleting dtor synthesized and emitted. That sets the
input_location to that of the class. But doesn't immediately restore it.
Then the next iteration of the main loop in c_parse_final_cleanups
discovered a new vtable needed emitting and calls mark_used on the
vfuncs it points at. That caused instantiation of the body of a vfunc
within the template class whose vtable we were emitting. We still had
the stale input_location from the above synthesis.
The upshot of which is we think the cause of the template instantiation
of the vfunc was at the other class definition, and as that was from a
header file, don't think we're in the main input file.
I failed at reducing the testcase.
Anyway, the fix is to set input_location to something definite before
calling mark_used in maybe_emit_vtables. Candidates are:
1) locus_at_end_of_compilation
2) locus of the class owning the vtable
3) locus of the vfunc being marked.
I went with #3 in this patch. Although #2 is attractive, the class
definition could easily be in a header file, which would fail the
is_main_input_context test.
This changes the location of the 'required-from' message in
g++.dg/template/instantiate5.C. It now points at the vfunc. However,
the current location is misleading -- although it's on the 'C<B> c;'
line, that's just happenstance as the last token in the file. If we
append some unrelated C++, we'll point to that. Which isn't really helpful.
committing to trunk.
nathan
--
Nathan Sidwell
2018-02-14 Nathan Sidwell <nathan@acm.org>
gcc/cp/
* decl2.c (mark_vtable_entries): Set input_location to decl's.
(c_parse_final_cleanups): Restore input_location after emitting
vtables.
gcc/testsuite/
* g++.dg/template/instantiate5.C: Adjust required-from loc.
Index: cp/decl2.c
===================================================================
--- cp/decl2.c (revision 257657)
+++ cp/decl2.c (working copy)
@@ -1825,6 +1825,11 @@ mark_vtable_entries (tree decl)
function, so we emit the thunks there instead. */
if (DECL_THUNK_P (fn))
use_thunk (fn, /*emit_p=*/0);
+ /* Set the location, as marking the function could cause
+ instantiation. We do not need to preserve the incoming
+ location, as we're called from c_parse_final_cleanups, which
+ takes care of that. */
+ input_location = DECL_SOURCE_LOCATION (fn);
mark_used (fn);
}
}
@@ -4727,6 +4732,9 @@ c_parse_final_cleanups (void)
reconsider = true;
keyed_classes->unordered_remove (i);
}
+ /* The input_location may have been changed during marking of
+ vtable entries. */
+ input_location = locus_at_end_of_parsing;
/* Write out needed type info variables. We have to be careful
looping through unemitted decls, because emit_tinfo_decl may
Index: testsuite/g++.dg/template/instantiate5.C
===================================================================
--- testsuite/g++.dg/template/instantiate5.C (revision 257657)
+++ testsuite/g++.dg/template/instantiate5.C (working copy)
@@ -18,7 +18,12 @@ struct B
template <typename T> struct C
{
- virtual void bar() const { T::foo(); } // { dg-error "no matching function" }
+ virtual void bar() const // { dg-message "required" }
+ {
+ T::foo(); // { dg-error "no matching function" }
+ }
};
-C<B> c; // { dg-message "required" }
+C<B> c;
+
+int k;