On 02/05/2016 07:54 AM, Patrick Palka wrote:
On Thu, 4 Feb 2016, Patrick Palka wrote:
The compiler correctly detects and diagnoses invalid constructor calls
such as C::C () in a non-template context but it fails to do so while
processing a class template. [ Section 3.4.3.1 of the standard is what
makes these forms of constructor calls illegal -- see
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68948#c9 ]
In a non-template context this diagnosis would take place in
build_new_method_call, called from finish_call_expr, but while
processing a class template we may exit early out of finish_call_expr
and never call build_new_method_call.
Thus we never diagnose this invalid constructor call during template
processing. So then during instantiation of the enclosing template we
call tsubst_baselink on this constructor call, during which the call to
lookup_fnfields returns NULL (because it finds the injected class type C
not the constructor C). Because the lookup failed, tsubst_baselink
returns error_mark_node and this node persists all the way through to
gimplification where it silently gets discarded.
This patch fixes this problem by diagnosing these invalid constructor
calls in tsubst_baselink. Alternatively, we can rewire finish_call_expr
avoid exiting early while processing a template if the call in question
is a constructor call. I'm not sure which approach is better. This
approach seems more conservative, since it's just attaching an error
message to an existing error path.
And here is the other approach, which rewires finish_call_expr:
I like the second approach better, but you're right that the first is
more conservative, so let's go with the first for GCC 6 and switch to
the second for GCC 7.
Jason