From: Kriang Lerdsuwanakij Date: Wed, 15 Dec 2004 15:21:11 +0000 (+0000) Subject: re PR c++/18825 (ICE segmentation fault in wv2) X-Git-Tag: releases/gcc-4.0.0~2142 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6e432b319e1f52ea03345c691334c9ac80fcef85;p=thirdparty%2Fgcc.git re PR c++/18825 (ICE segmentation fault in wv2) PR c++/18825 * pt.c (instantiate_class_template): Set input_location for friend function. (tsubst_friend_function): Don't set input_location here. Make sure the context is complete if necessary. * g++.dg/template/friend32.C: New test. From-SVN: r92200 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a879f4ee2cbd..11e90b8b6c05 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2004-12-15 Kriang Lerdsuwanakij + + PR c++/18825 + * pt.c (instantiate_class_template): Set input_location for + friend function. + (tsubst_friend_function): Don't set input_location here. + Make sure the context is complete if necessary. + 2004-12-15 Nathan Sidwell PR c++/18981 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5da280610b42..db9b08ffb9a1 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5098,9 +5098,6 @@ static tree tsubst_friend_function (tree decl, tree args) { tree new_friend; - location_t saved_loc = input_location; - - input_location = DECL_SOURCE_LOCATION (decl); if (TREE_CODE (decl) == FUNCTION_DECL && DECL_TEMPLATE_INSTANTIATION (decl) @@ -5135,8 +5132,7 @@ tsubst_friend_function (tree decl, tree args) &new_args, /*need_member_template=*/0, TREE_VEC_LENGTH (args)); - new_friend = instantiate_template (tmpl, new_args, tf_error); - goto done; + return instantiate_template (tmpl, new_args, tf_error); } new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE); @@ -5299,19 +5295,40 @@ tsubst_friend_function (tree decl, tree args) new_friend = old_decl; } } - else if (COMPLETE_TYPE_P (DECL_CONTEXT (new_friend))) + else { - /* Check to see that the declaration is really present, and, - possibly obtain an improved declaration. */ - tree fn = check_classfn (DECL_CONTEXT (new_friend), - new_friend, NULL_TREE); - - if (fn) - new_friend = fn; + tree context = DECL_CONTEXT (new_friend); + bool dependent_p; + + /* In the code + template class C { + template friend void C1::f (); // case 1 + friend void C2::f (); // case 2 + }; + we only need to make sure CONTEXT is a complete type for + case 2. To distinguish between the two cases, we note that + CONTEXT of case 1 remains dependent type after tsubst while + this isn't true for case 2. */ + ++processing_template_decl; + dependent_p = dependent_type_p (context); + --processing_template_decl; + + if (!dependent_p + && !complete_type_or_else (context, NULL_TREE)) + return error_mark_node; + + if (COMPLETE_TYPE_P (context)) + { + /* Check to see that the declaration is really present, and, + possibly obtain an improved declaration. */ + tree fn = check_classfn (context, + new_friend, NULL_TREE); + + if (fn) + new_friend = fn; + } } - done: - input_location = saved_loc; return new_friend; } @@ -5816,6 +5833,12 @@ instantiate_class_template (tree type) /* Build new DECL_FRIENDLIST. */ tree r; + /* The the file and line for this declaration, to + assist in error message reporting. Since we + called push_tinst_level above, we don't need to + restore these. */ + input_location = DECL_SOURCE_LOCATION (t); + if (TREE_CODE (t) == TEMPLATE_DECL) { ++processing_template_decl; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 80fb3ccb2027..1f099ebf5c9b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-12-15 Kriang Lerdsuwanakij + + PR c++/18825 + * g++.dg/template/friend32.C: New test. + 2004-12-15 Eric Botcazou * cpp/pragma-once-1.c: New test. diff --git a/gcc/testsuite/g++.dg/template/friend32.C b/gcc/testsuite/g++.dg/template/friend32.C new file mode 100644 index 000000000000..4ce2ba3f2cca --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend32.C @@ -0,0 +1,21 @@ +// { dg-do compile } + +// Origin: Steven Bosscher +// Serge Belyshev + +// PR c++/18825: ICE member as friend + +template class A +{ + void f (); // { dg-error "private" } +}; + +template class B +{ + friend void A::f (); // { dg-error "this context" } +}; + +int f () +{ + B b; // { dg-error "instantiated" } +}