diff mbox

[C++] PR 60999

Message ID 5367BB74.6060805@oracle.com
State New
Headers show

Commit Message

Paolo Carlini May 5, 2014, 4:25 p.m. UTC
Hi,

On 05/05/2014 03:32 PM, Jason Merrill wrote:
> On 05/03/2014 06:55 PM, Paolo Carlini wrote:
>> On 05/03/2014 11:14 PM, Jason Merrill wrote:
>>> Do you want CLASSTYPE_IS_TEMPLATE here?
>
>> Uhm, you mean something simple like the attached? Because certainly I
>> tried it and didn't fully work (nsdmi-template7.C?) and for sure we
>> would regress on the below (which we should probably also add to
>> testsuite, I had it two days ago in my experiments...).
>
> Ah, yes, CLASSTYPE_IS_TEMPLATE is false for partial specializations. 
> What we want is a predicate to check for a class template or partial 
> specialization.

Good, but is it Ok to use uses_template_parms for that? A few days ago I 
struggled to find something simpler ready to use, to no avail (well, 
this is probably well known to you, but there are surprisingly few 
places in pt.c where we explain either in comments or in obvious code 
that we are handling full (vs partial) specializations).

(Well, minor improvement of the below, I think it would be ok to call 
dependent_type_p directly, but processing_template_decl must be 1 around 
it anyway)

Paolo.

Comments

Jason Merrill May 5, 2014, 8:48 p.m. UTC | #1
On 05/05/2014 12:25 PM, Paolo Carlini wrote:
> Good, but is it Ok to use uses_template_parms for that? A few days ago I
> struggled to find something simpler ready to use, to no avail (well,
> this is probably well known to you, but there are surprisingly few
> places in pt.c where we explain either in comments or in obvious code
> that we are handling full (vs partial) specializations).

> +/* True if the given class type is a template or a partial specialization.  */
> +#define CLASSTYPE_IS_TEMPLATE_OR_PARTIAL_SPECIALIZATION(NODE)  \
> +  (CLASSTYPE_TEMPLATE_INFO (NODE)    \
> +   && uses_template_parms (NODE))

I think this would be true for a non-template member class of a template 
class.  I think we want something like

CLASSTYPE_TEMPLATE_INFO (NODE)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))
&& uses_template_parms (INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (NODE))
Paolo Carlini May 6, 2014, 8:23 a.m. UTC | #2
Hi again,

On 05/05/2014 10:48 PM, Jason Merrill wrote:
> On 05/05/2014 12:25 PM, Paolo Carlini wrote:
>> Good, but is it Ok to use uses_template_parms for that? A few days ago I
>> struggled to find something simpler ready to use, to no avail (well,
>> this is probably well known to you, but there are surprisingly few
>> places in pt.c where we explain either in comments or in obvious code
>> that we are handling full (vs partial) specializations).
>
>> +/* True if the given class type is a template or a partial 
>> specialization.  */
>> +#define CLASSTYPE_IS_TEMPLATE_OR_PARTIAL_SPECIALIZATION(NODE) \
>> +  (CLASSTYPE_TEMPLATE_INFO (NODE)    \
>> +   && uses_template_parms (NODE))
>
> I think this would be true for a non-template member class of a 
> template class.
On further thought (yesterday was a little tired, sorry), I think that 
nsdmi-template7.C is telling us that, in fact, we *do* want something 
true when we are handling an NSDMI inside a non-template class of a 
template class! Because in that case too the user code may want to use 
the template parameters in the initialization of the NSDMI. Well, 
assuming this is by and large right, we do *not* want a predicate for 
template or partial specialization, maybe a predicate for "dependent 
context", see what I mean?!? In any case, in practice, something rather 
close to my first try ;) (after all, the simple pattern is already used 
in tsubst for typedefs...)

Paolo.
Jason Merrill May 6, 2014, 5:40 p.m. UTC | #3
On 05/06/2014 04:23 AM, Paolo Carlini wrote:
> On further thought (yesterday was a little tired, sorry), I think that
> nsdmi-template7.C is telling us that, in fact, we *do* want something
> true when we are handling an NSDMI inside a non-template class of a
> template class!

Right, sorry, I was thinking we only had to look at the innermost 
parameters, but in fact we need to push all levels of parameters.

I've been resistant to your change because it wouldn't fix a 
specialization of a member template of another class template. 
Currently that is ill-formed, but there have been mumblings in Core 
about allowing it in the future.  But supporting that would probably 
involve making such a specialization a template itself, so go ahead.

But please add a comment clarifying that the test is there to avoid 
looking past an explicit specialization.

Jason
diff mbox

Patch

Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 210068)
+++ cp-tree.h	(working copy)
@@ -3160,6 +3160,11 @@  more_aggr_init_expr_args_p (const aggr_init_expr_a
    && !CLASSTYPE_USE_TEMPLATE (NODE) \
    && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))
 
+/* True if the given class type is a template or a partial specialization.  */
+#define CLASSTYPE_IS_TEMPLATE_OR_PARTIAL_SPECIALIZATION(NODE)  \
+  (CLASSTYPE_TEMPLATE_INFO (NODE)    \
+   && uses_template_parms (NODE))
+
 /* The name used by the user to name the typename type.  Typically,
    this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the
    corresponding TYPE_DECL.  However, this may also be a
Index: pt.c
===================================================================
--- pt.c	(revision 210068)
+++ pt.c	(working copy)
@@ -462,9 +462,12 @@  maybe_begin_member_template_processing (tree decl)
   bool nsdmi = TREE_CODE (decl) == FIELD_DECL;
 
   if (nsdmi)
-    decl = (CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
-	    ? CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (decl))
-	    : NULL_TREE);
+    {
+      tree ctx = DECL_CONTEXT (decl);
+      decl = (CLASSTYPE_IS_TEMPLATE_OR_PARTIAL_SPECIALIZATION (ctx)
+	      ? CLASSTYPE_TI_TEMPLATE (ctx)
+	      : NULL_TREE);
+    }
 
   if (inline_needs_template_parms (decl, nsdmi))
     {
@@ -11519,8 +11522,8 @@  tsubst (tree t, tree args, tsubst_flags_t complain
 	  r = instantiate_alias_template (tmpl, gen_args, complain);
 	}
       else if (DECL_CLASS_SCOPE_P (decl)
-	       && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
-	       && uses_template_parms (DECL_CONTEXT (decl)))
+	       && (CLASSTYPE_IS_TEMPLATE_OR_PARTIAL_SPECIALIZATION
+		   (DECL_CONTEXT (decl))))
 	{
 	  tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
 	  tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);