Index: testsuite/g++.dg/parse/template27.C =================================================================== --- testsuite/g++.dg/parse/template27.C (revision 0) +++ testsuite/g++.dg/parse/template27.C (revision 0) @@ -0,0 +1,22 @@ +// PR c++/39970 + +struct blah { int member; }; +blah global; +blah* pglobal; + +template // { dg-error "class member access operator" } +class template1_blah; + +template // { dg-error "class member access operator" } +class template2_blah; + +template member> // { dg-error "class member access operator" } +class template3_blah; + +int blah::* pm = &blah::member; + +template // { dg-error "pointer-to-member operator" } +class template4_blah; + +template *pm> // { dg-error "pointer-to-member operator" } +class template5_blah; Index: cp/parser.c =================================================================== --- cp/parser.c (revision 186780) +++ cp/parser.c (working copy) @@ -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; } Index: cp/parser.h =================================================================== --- cp/parser.h (revision 186780) +++ cp/parser.h (working copy) @@ -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'. */