diff mbox

[C++ Patch/RFC PR c++/57887 (and dups)

Message ID 5284C934.9040006@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Nov. 14, 2013, 12:59 p.m. UTC
Hi,

we are getting bug reports about this issue with NSDMIs in template 
classes, like:

struct B
{
template<int N>
struct A
{
int X = N;
};
};

57887.C:6:13: error: ā€˜Nā€™ was not declared in this scope

Looking at cp_parser_class_specifier_1, the comments about the late 
parsing of default arguments (which we are already handling correctly):

/* Make sure that any template parameters are in scope. */
maybe_begin_member_template_processing (decl);

it seems clear to me that something very similar must be done for NSDMIs 
too. Thus I prepared the below, which uses CLASSTYPE_TEMPLATE_INFO to 
adapt the existing code in maybe_begin_member_template_processing. It 
tests fine. How does it look?

Thanks!
Paolo.

///////////////////////

Comments

Jason Merrill Nov. 14, 2013, 2:41 p.m. UTC | #1
On 11/14/2013 07:59 AM, Paolo Carlini wrote:
> /* Make sure that any template parameters are in scope. */
> maybe_begin_member_template_processing (decl);

Hmm, it seems that we use this for non-template member functions of 
template classes as well; I wonder when that happened.  I guess we 
should update the comment to reflect reality.  And perhaps the name of 
the function, though I lean slightly toward leaving that alone.

> it seems clear to me that something very similar must be done for NSDMIs
> too. Thus I prepared the below, which uses CLASSTYPE_TEMPLATE_INFO to
> adapt the existing code in maybe_begin_member_template_processing. It
> tests fine. How does it look?

I don't think we need a new parameter; just pass the FIELD_DECL into 
maybe_end_member_template_processing and adjust it appropriately.

Also, call m_e_m_t_p from cp_parser_late_parsing_nsdmi rather than 
cp_parser_class_specifier_1.

Jason
diff mbox

Patch

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 204780)
+++ cp/cp-tree.h	(working copy)
@@ -5450,8 +5450,8 @@  extern bool maybe_clone_body			(tree);
 /* in pt.c */
 extern bool check_template_shadow		(tree);
 extern tree get_innermost_template_args		(tree, int);
-extern void maybe_begin_member_template_processing (tree);
-extern void maybe_end_member_template_processing (void);
+extern void maybe_begin_member_template_or_nsdmi_processing (tree, bool);
+extern void maybe_end_member_template_or_nsdmi_processing (void);
 extern tree finish_member_template_decl		(tree);
 extern void begin_template_parm_list		(void);
 extern bool begin_specialization		(void);
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 204780)
+++ cp/decl.c	(working copy)
@@ -13127,7 +13127,7 @@  start_preparsed_function (tree decl1, tree attrs,
      the class.)  It is not until after this point that
      PROCESSING_TEMPLATE_DECL is guaranteed to be set up correctly.  */
   if (flags & SF_INCLASS_INLINE)
-    maybe_begin_member_template_processing (decl1);
+    maybe_begin_member_template_or_nsdmi_processing (decl1, /*nsdmi=*/false);
 
   /* Effective C++ rule 15.  */
   if (warn_ecpp
@@ -14049,7 +14049,7 @@  finish_function (int flags)
      maybe_begin_member_template_processing when start_function was
      called.  */
   if (inclass_inline)
-    maybe_end_member_template_processing ();
+    maybe_end_member_template_or_nsdmi_processing ();
 
   /* Leave the scope of the class.  */
   if (ctype)
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 204780)
+++ cp/parser.c	(working copy)
@@ -19254,11 +19254,12 @@  cp_parser_class_specifier_1 (cp_parser* parser)
 	      pushed_scope = push_scope (class_type);
 	    }
 	  /* Make sure that any template parameters are in scope.  */
-	  maybe_begin_member_template_processing (decl);
+	  maybe_begin_member_template_or_nsdmi_processing (decl,
+							   /*nsdmi=*/false);
 	  /* Parse the default argument expressions.  */
 	  cp_parser_late_parsing_default_args (parser, decl);
 	  /* Remove any template parameters from the symbol table.  */
-	  maybe_end_member_template_processing ();
+	  maybe_end_member_template_or_nsdmi_processing ();
 	}
       vec_safe_truncate (unparsed_funs_with_default_args, 0);
       /* Now parse any NSDMIs.  */
@@ -19274,7 +19275,10 @@  cp_parser_class_specifier_1 (cp_parser* parser)
 	      pushed_scope = push_scope (class_type);
 	    }
 	  inject_this_parameter (class_type, TYPE_UNQUALIFIED);
+	  maybe_begin_member_template_or_nsdmi_processing (class_type,
+							   /*nsdmi=*/true);
 	  cp_parser_late_parsing_nsdmi (parser, decl);
+	  maybe_end_member_template_or_nsdmi_processing ();
 	}
       vec_safe_truncate (unparsed_nsdmis, 0);
       current_class_ptr = save_ccp;
@@ -23219,7 +23223,8 @@  cp_parser_late_parsing_for_member (cp_parser* pars
   push_unparsed_function_queues (parser);
 
   /* Make sure that any template parameters are in scope.  */
-  maybe_begin_member_template_processing (member_function);
+  maybe_begin_member_template_or_nsdmi_processing (member_function,
+						   /*nsdmi=*/false);
 
   /* If the body of the function has not yet been parsed, parse it
      now.  */
@@ -23274,7 +23279,7 @@  cp_parser_late_parsing_for_member (cp_parser* pars
     }
 
   /* Remove any template parameters from the symbol table.  */
-  maybe_end_member_template_processing ();
+  maybe_end_member_template_or_nsdmi_processing ();
 
   /* Restore the queue.  */
   pop_unparsed_function_queues (parser);
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 204780)
+++ cp/pt.c	(working copy)
@@ -151,7 +151,7 @@  static int for_each_template_parm (tree, tree_fn_t
 				   struct pointer_set_t*, bool);
 static tree expand_template_argument_pack (tree);
 static tree build_template_parm_index (int, int, int, tree, tree);
-static bool inline_needs_template_parms (tree);
+static bool inline_needs_template_parms (tree, bool);
 static void push_inline_template_parms_recursive (tree, int);
 static tree retrieve_local_specialization (tree);
 static void register_local_specialization (tree, tree);
@@ -377,9 +377,9 @@  template_class_depth (tree type)
    Returns true if processing DECL needs us to push template parms.  */
 
 static bool
-inline_needs_template_parms (tree decl)
+inline_needs_template_parms (tree decl, bool nsdmi)
 {
-  if (! DECL_TEMPLATE_INFO (decl))
+  if (!decl || (!nsdmi && ! DECL_TEMPLATE_INFO (decl)))
     return false;
 
   return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (most_general_template (decl)))
@@ -452,12 +452,16 @@  push_inline_template_parms_recursive (tree parmlis
    a friend template defined in a class definition.  */
 
 void
-maybe_begin_member_template_processing (tree decl)
+maybe_begin_member_template_or_nsdmi_processing (tree decl, bool nsdmi)
 {
   tree parms;
   int levels = 0;
 
-  if (inline_needs_template_parms (decl))
+  if (nsdmi)
+    decl = (CLASSTYPE_TEMPLATE_INFO (decl)
+	    ? TREE_TYPE (CLASSTYPE_TEMPLATE_INFO (decl)) : NULL_TREE);
+
+  if (inline_needs_template_parms (decl, nsdmi))
     {
       parms = DECL_TEMPLATE_PARMS (most_general_template (decl));
       levels = TMPL_PARMS_DEPTH (parms) - processing_template_decl;
@@ -479,7 +483,7 @@  void
 /* Undo the effects of maybe_begin_member_template_processing.  */
 
 void
-maybe_end_member_template_processing (void)
+maybe_end_member_template_or_nsdmi_processing (void)
 {
   int i;
   int last;
Index: testsuite/g++.dg/cpp0x/nsdmi-template3.C
===================================================================
--- testsuite/g++.dg/cpp0x/nsdmi-template3.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/nsdmi-template3.C	(working copy)
@@ -0,0 +1,16 @@ 
+// PR c++/58760
+// { dg-do compile { target c++11 } }
+
+enum en
+{
+  a,b,c
+};
+ 
+struct B
+{
+  template<en N>
+  struct A
+  {
+    const int X = N;
+  };
+};
Index: testsuite/g++.dg/cpp0x/nsdmi-template4.C
===================================================================
--- testsuite/g++.dg/cpp0x/nsdmi-template4.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/nsdmi-template4.C	(working copy)
@@ -0,0 +1,24 @@ 
+// PR c++/57887
+// { dg-do compile { target c++11 } }
+
+struct B
+{
+  template<int N>
+  struct A
+  {
+    int X = N;
+  };
+};
+
+template<int M>
+struct C
+{
+  int Y = M;
+
+  template<int N>
+  struct A
+  {
+    int X = N;
+    int Y = M;
+  };
+};