Hi,

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. 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))
Thanks. The latter works almost fine testsuite-wise, besides the "famous" nsdmi-template7.C, for which we definitely want the predicate to return true for y, because the unnamed non-type template parameter could have a name used for its initialization:

struct A {
    template<int=0>
    struct B {
        struct C {
            int x = 0;
      double y = x;
        } c;
    };
};
int main() {
    A::B<>();
}

what happens instead is that PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)) is false. Would the below make sense then?

Thanks,
Paolo.

///////////////////////////
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 210083)
+++ cp/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 (INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (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: cp/pt.c
===================================================================
--- cp/pt.c     (revision 210083)
+++ cp/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))
     {
Index: testsuite/g++.dg/cpp0x/nsdmi-template10.C
===================================================================
--- testsuite/g++.dg/cpp0x/nsdmi-template10.C   (revision 0)
+++ testsuite/g++.dg/cpp0x/nsdmi-template10.C   (working copy)
@@ -0,0 +1,14 @@
+// PR c++/60999
+// { dg-do compile { target c++11 } }
+
+struct B
+{
+  template<int N, int M>
+  struct A;
+
+  template<int M>
+  struct A<1, M>
+  {
+    int X = M;
+  };
+};
Index: testsuite/g++.dg/cpp0x/nsdmi-template9.C
===================================================================
--- testsuite/g++.dg/cpp0x/nsdmi-template9.C    (revision 0)
+++ testsuite/g++.dg/cpp0x/nsdmi-template9.C    (working copy)
@@ -0,0 +1,16 @@
+// PR c++/60999
+// { dg-do compile { target c++11 } }
+
+template <typename A>
+struct foo
+{
+};
+  
+template<>
+struct foo<int>
+{
+  static constexpr int code = 42;
+  unsigned int bar = static_cast<unsigned int>(code);
+};
+  
+foo<int> a;

Reply via email to