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.
///////////////////////
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;
+ };
+};