aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>2004-12-15 15:21:11 +0000
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>2004-12-15 15:21:11 +0000
commit6e432b319e1f52ea03345c691334c9ac80fcef85 (patch)
treefc3c8123f4c13382b40067d4d1ac457e3358cc0c /gcc/cp/pt.c
parent06d5588c56e70b6f89f3cdab25c381b237759bd7 (diff)
downloadgcc-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.c53
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;