diff mbox

[c++] : Fix PR/61198: Crash when selecting specializations through aliases.

Message ID CAEwic4a4pcYYNVJ2E3A7wmcqy1-LGYoCa+oc6xOEVTvib9S+Xw@mail.gmail.com
State New
Headers show

Commit Message

Kai Tietz Dec. 18, 2014, 3:10 p.m. UTC
Hi,

this patch adds handling of aliases within templates and tries to
resolve specialization for them.

ChangeLog

2014-12-18  Kai Tietz  <ktietz@redhat.com>

    PR c++/61198
    * pt.c (retrieve_specialization): Handle using.

Tested on x86_64-w64-mingw32.  Ok for apply?

Regards,
Kai

ChangeLog testsuite

2014-12-18  Kai Tietz  <ktietz@redhat.com>

    PR c++/61198
    * g++.dg/template/using29.C: New file.

// { dg-do compile }

template<int herp, typename derp_t>
struct broken
{
        template<typename target_t>
        using rebind = broken<herp, target_
};

template<typename derp_t>
struct broken<2, derp_t>
{
        template<typename target_t>
        using rebind = broken<2, target_t>;
};

int main(int argc, char **argv)
{
        broken<2, float>::rebind<double> u;

        return 0;
}

Comments

Jason Merrill Dec. 18, 2014, 5:26 p.m. UTC | #1
On 12/18/2014 10:10 AM, Kai Tietz wrote:
> +      if (TMPL_ARGS_DEPTH (args) > TMPL_PARMS_DEPTH (tmpl_parms))
> +    args = get_innermost_template_args
> +        (args, TMPL_PARMS_DEPTH (tmpl_parms));

It seems unlikely to be correct to arbitrarily strip off outer template 
args.  Where did the mismatch come from?

Jason
Kai Tietz Dec. 18, 2014, 6:16 p.m. UTC | #2
2014-12-18 18:26 GMT+01:00 Jason Merrill <jason@redhat.com>:
> On 12/18/2014 10:10 AM, Kai Tietz wrote:
>>
>> +      if (TMPL_ARGS_DEPTH (args) > TMPL_PARMS_DEPTH (tmpl_parms))
>> +    args = get_innermost_template_args
>> +        (args, TMPL_PARMS_DEPTH (tmpl_parms));
>
>
> It seems unlikely to be correct to arbitrarily strip off outer template
> args.  Where did the mismatch come from?
>
> Jason
>

Hmm, we are comming from #2 tsubst_decl (cp/pt.c:11278)
#3 instantiate_template_1 (cp/pt.c:15945)
#4 instantiate_template (cp/pt.c:15995)
#5 instantiate_alias_template (cp/pt.c:11827)
#6: lookup_template_class_1
#7: lookup_template_class
#8: finish_template_type
#9: cp_parser_template_id
....

Well, in general I would have assumed to be able to get alias decl of
tmpl. Wasn't able to find a simple way to get it. So, by looking into
source I found that most cases handling args > tmpl-args by using
inner_most_template_args instead. Defaulting to
innermost_template_args looks indeed a bit wrong, but seemed to work.

Kai
Jason Merrill Dec. 18, 2014, 11:14 p.m. UTC | #3
On 12/18/2014 01:16 PM, Kai Tietz wrote:
> Well, in general I would have assumed to be able to get alias decl of
> tmpl. Wasn't able to find a simple way to get it. So, by looking into
> source I found that most cases handling args > tmpl-args by using
> inner_most_template_args instead. Defaulting to
> innermost_template_args looks indeed a bit wrong, but seemed to work.

It's wrong, it just papers over the bug.  There shouldn't be a mismatch 
at this point.

The problem seems to be that most_general_template isn't actually 
returning the most general template, so we're trying to instantiate the 
partially-instantiated alias template with a full set of arguments: thus 
the mismatch.

Jason
diff mbox

Patch

Index: pt.c
===================================================================
--- pt.c    (Revision 218832)
+++ pt.c    (Arbeitskopie)
@@ -1033,6 +1033,8 @@  optimize_specialization_lookup_p (tree tmpl)
 static tree
 retrieve_specialization (tree tmpl, tree args, hashval_t hash)
 {
+  tree tmpl_parms;
+
   if (tmpl == NULL_TREE)
     return NULL_TREE;

@@ -1044,10 +1046,20 @@  retrieve_specialization (tree tmpl, tree args, has

   /* There should be as many levels of arguments as there are
      levels of parameters.  */
-  gcc_assert (TMPL_ARGS_DEPTH (args)
-          == (TREE_CODE (tmpl) == TEMPLATE_DECL
-          ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
-          : template_class_depth (DECL_CONTEXT (tmpl))));
+  if (TREE_CODE (tmpl) == TEMPLATE_DECL)
+    {
+      tmpl_parms = DECL_TEMPLATE_PARMS (tmpl);
+      if (TMPL_ARGS_DEPTH (args) > TMPL_PARMS_DEPTH (tmpl_parms))
+    args = get_innermost_template_args
+        (args, TMPL_PARMS_DEPTH (tmpl_parms));
+      gcc_assert (TMPL_ARGS_DEPTH (args)
+          == TMPL_PARMS_DEPTH (tmpl_parms));
+    }
+  else
+    {
+      tmpl_parms = DECL_CONTEXT (tmpl);
+      gcc_assert (TMPL_ARGS_DEPTH (args) == template_class_depth (tmpl_parms));
+    }

   if (optimize_specialization_lookup_p (tmpl))
     {