===================================================================
@@ -0,0 +1,22 @@
+// PR c++/39970
+
+struct blah { int member; };
+blah global;
+blah* pglobal;
+
+template <int param = global.member> // { dg-error "class member access operator" }
+class template1_blah;
+
+template <int* param = &global.member> // { dg-error "class member access operator" }
+class template2_blah;
+
+template <int param = pglobal->member> // { dg-error "class member access operator" }
+class template3_blah;
+
+int blah::* pm = &blah::member;
+
+template <int param = global.*pm> // { dg-error "pointer-to-member operator" }
+class template4_blah;
+
+template <int param = pglobal->*pm> // { dg-error "pointer-to-member operator" }
+class template5_blah;
===================================================================
@@ -503,6 +503,8 @@ cp_debug_parser (FILE *file, cp_parser *parser)
cp_debug_print_flag (file, "Local names and 'this' forbidden in "
"current context",
parser->local_variables_forbidden_p);
+ cp_debug_print_flag (file, "In template default argument",
+ parser->in_template_default_argument_p);
cp_debug_print_flag (file, "In unbraced linkage specification",
parser->in_unbraced_linkage_specification_p);
cp_debug_print_flag (file, "Parsing a declarator",
@@ -3278,6 +3280,10 @@ cp_parser_new (void)
/* Local variable names are not forbidden. */
parser->local_variables_forbidden_p = false;
+ /* We are not processing the default argument for
+ a non-type template parameter. */
+ parser->in_template_default_argument_p = false;
+
/* We are not processing an `extern "C"' declaration. */
parser->in_unbraced_linkage_specification_p = false;
@@ -4266,6 +4272,14 @@ cp_parser_primary_expression (cp_parser *parser,
return error_mark_node;
id_expr_token = token;
token = cp_lexer_peek_token (parser->lexer);
+ if (parser->in_template_default_argument_p
+ && parser->integral_constant_expression_p
+ && (token->type == CPP_DOT_STAR || token->type == CPP_DEREF_STAR))
+ {
+ error_at (token->location,
+ "pointer-to-member operator is not allowed here");
+ return error_mark_node;
+ }
done = (token->type != CPP_OPEN_SQUARE
&& token->type != CPP_OPEN_PAREN
&& token->type != CPP_DOT
@@ -5776,6 +5790,11 @@ cp_parser_postfix_expression (cp_parser *parser, b
postfix-expression -> template [opt] id-expression
postfix-expression -> pseudo-destructor-name */
+ if (parser->in_template_default_argument_p
+ && parser->integral_constant_expression_p)
+ error_at (token->location,
+ "class member access operator is not allowed here");
+
/* Consume the `.' or `->' operator. */
cp_lexer_consume_token (parser->lexer);
@@ -17372,6 +17391,7 @@ cp_parser_default_argument (cp_parser *parser, boo
tree default_argument = NULL_TREE;
bool saved_greater_than_is_operator_p;
bool saved_local_variables_forbidden_p;
+ bool saved_in_template_default_argument_p;
bool non_constant_p, is_direct_init;
/* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is
@@ -17382,6 +17402,12 @@ cp_parser_default_argument (cp_parser *parser, boo
appear in a default argument. */
saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
parser->local_variables_forbidden_p = true;
+ if (template_parm_p)
+ {
+ saved_in_template_default_argument_p
+ = parser->in_template_default_argument_p;
+ parser->in_template_default_argument_p = true;
+ }
/* Parse the assignment-expression. */
if (template_parm_p)
push_deferring_access_checks (dk_no_deferred);
@@ -17393,6 +17419,9 @@ cp_parser_default_argument (cp_parser *parser, boo
pop_deferring_access_checks ();
parser->greater_than_is_operator_p = saved_greater_than_is_operator_p;
parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
+ if (template_parm_p)
+ parser->in_template_default_argument_p
+ = saved_in_template_default_argument_p;
return default_argument;
}
===================================================================
@@ -282,6 +282,10 @@ typedef struct GTY(()) cp_parser {
current context. */
bool local_variables_forbidden_p;
+ /* TRUE if we are parsing the default argument for a non-type
+ template parameter. */
+ bool in_template_default_argument_p;
+
/* TRUE if the declaration we are parsing is part of a
linkage-specification of the form `extern string-literal
declaration'. */