diff options
author | abutcher <abutcher@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-03-17 20:02:26 +0000 |
---|---|---|
committer | abutcher <abutcher@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-03-17 20:02:26 +0000 |
commit | fd6b21e6a0a6e719c4f4bae7e9c4fd12d566bf99 (patch) | |
tree | 5450646a5e8452e3dfb7f016d866c6aa8a69e4f0 /gcc/cp | |
parent | d2caa6844200aa5a47d816b44bc7476a75d03299 (diff) | |
download | ppe42-gcc-fd6b21e6a0a6e719c4f4bae7e9c4fd12d566bf99.tar.gz ppe42-gcc-fd6b21e6a0a6e719c4f4bae7e9c4fd12d566bf99.zip |
Fix PR c++/60390
PR c++/60390
* parser.c (cp_parser_member_declaration): Don't allow
finish_fully_implicit_template to consider friend declarations to be
class member templates.
(synthesize_implicit_template_parm): Handling winding back through class
scope to the class being defined in order to inject a template argument
list.
PR c++/60390
* g++.dg/cpp1y/pr60390.C: New testcase.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@208625 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/parser.c | 42 |
2 files changed, 41 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a240ad9ec76..3cf68583fcc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2014-03-17 Adam Butcher <adam@jessamine.co.uk> + PR c++/60390 + * parser.c (cp_parser_member_declaration): Don't allow + finish_fully_implicit_template to consider friend declarations to be + class member templates. + (synthesize_implicit_template_parm): Handling winding back through class + scope to the class being defined in order to inject a template argument + list. + PR c++/60391 * parser.c (cp_parser_skip_to_end_of_block_or_statement): Unwind generic function scope as per cp_parser_skip_to_end_of_statement. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 519e2090dd2..46e2453e51b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -20527,8 +20527,13 @@ cp_parser_member_declaration (cp_parser* parser) decl = grokfield (declarator, &decl_specifiers, initializer, /*init_const_expr_p=*/true, asm_specification, attributes); - if (parser->fully_implicit_function_template_p) - decl = finish_fully_implicit_template (parser, decl); + if (parser->fully_implicit_function_template_p) + { + if (friend_p) + finish_fully_implicit_template (parser, 0); + else + decl = finish_fully_implicit_template (parser, decl); + } } cp_finalize_omp_declare_simd (parser, decl); @@ -31982,13 +31987,32 @@ synthesize_implicit_template_parm (cp_parser *parser) parent_scope = scope; scope = scope->level_chain; } - if (current_class_type && !LAMBDA_TYPE_P (current_class_type) - && parser->num_classes_being_defined == 0) - while (scope->kind == sk_class) - { - parent_scope = scope; - scope = scope->level_chain; - } + if (current_class_type && !LAMBDA_TYPE_P (current_class_type)) + { + /* If not defining a class, then any class scope is a scope level in + an out-of-line member definition. In this case simply wind back + beyond the first such scope to inject the template argument list. + Otherwise wind back to the class being defined. The latter can + occur in class member friend declarations such as: + + class A { + void foo (auto); + }; + class B { + friend void A::foo (auto); + }; + + The template argument list synthesized for the friend declaration + must be injected in the scope of 'B', just beyond the scope of 'A' + introduced by 'A::'. */ + + while (scope->kind == sk_class + && !TYPE_BEING_DEFINED (scope->this_entity)) + { + parent_scope = scope; + scope = scope->level_chain; + } + } current_binding_level = scope; |