diff options
author | Adam Butcher <adam@jessamine.co.uk> | 2014-03-17 20:02:26 +0000 |
---|---|---|
committer | Adam Butcher <abutcher@gcc.gnu.org> | 2014-03-17 20:02:26 +0000 |
commit | e0672441623392903e5cc34bc22116bbd01dfeb2 (patch) | |
tree | 5450646a5e8452e3dfb7f016d866c6aa8a69e4f0 /gcc | |
parent | c66f2ba1ba6bf0b3ca6b092ee964461d6c7bb93f (diff) | |
download | gcc-e0672441623392903e5cc34bc22116bbd01dfeb2.zip gcc-e0672441623392903e5cc34bc22116bbd01dfeb2.tar.gz gcc-e0672441623392903e5cc34bc22116bbd01dfeb2.tar.bz2 |
re PR c++/60390 ([c++1y] ICE with declaring function with auto parameter as friend)
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.
From-SVN: r208625
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/parser.c | 42 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/pr60390.C | 26 |
4 files changed, 70 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a240ad9..3cf6858 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 519e209..46e2453 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a327e94..49bc001 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2014-03-17 Adam Butcher <adam@jessamine.co.uk> + PR c++/60390 + * g++.dg/cpp1y/pr60390.C: New testcase. + PR c++/60391 * g++.dg/cpp1y/pr60391.C: New testcase. diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60390.C b/gcc/testsuite/g++.dg/cpp1y/pr60390.C new file mode 100644 index 0000000..5cd5539 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr60390.C @@ -0,0 +1,26 @@ +// PR c++/60390 +// { dg-do compile { target c++1y } } +// { dg-options "" } + +struct A +{ + void foo (auto); +}; + +class B +{ + int m; + friend void A::foo (auto); +}; + +void A::foo (auto i) +{ + B b; + b.m = i; +} + +int main () +{ + A a; + a.foo (7); +} |