diff options
author | Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> | 2004-12-15 15:21:11 +0000 |
---|---|---|
committer | Kriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org> | 2004-12-15 15:21:11 +0000 |
commit | 6e432b319e1f52ea03345c691334c9ac80fcef85 (patch) | |
tree | fc3c8123f4c13382b40067d4d1ac457e3358cc0c /gcc/cp/pt.c | |
parent | 06d5588c56e70b6f89f3cdab25c381b237759bd7 (diff) | |
download | gcc-6e432b319e1f52ea03345c691334c9ac80fcef85.zip gcc-6e432b319e1f52ea03345c691334c9ac80fcef85.tar.gz gcc-6e432b319e1f52ea03345c691334c9ac80fcef85.tar.bz2 |
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
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r-- | gcc/cp/pt.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5da2806..db9b08f 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 T> class C { + template <class U> friend void C1<U>::f (); // case 1 + friend void C2<T>::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; |