re PR c++/25369 (use of inline function in template class leads to undefined reference)

PR c++/25369
	* g++.dg/template/ptrmem16.C: New test.
	PR c++/25369
	* tree.c (really_overloaded_fn): Tweak comment.
	* pt.c (tsubst_call_declarator_parms): Remove.
	(tsubst_copy): Call mark_used on the member referenced by an
	OFFSET_REF.
	* semantics.c (finish_qualified_id_expr): Simplify.
	* decl2.c (mark_used): Accept BASELINKs.

From-SVN: r109010
This commit is contained in:
Mark Mitchell 2005-12-23 07:40:04 +00:00 committed by Mark Mitchell
parent dd55e286d4
commit 7eab6e7b91
7 changed files with 54 additions and 42 deletions

View File

@ -1,5 +1,13 @@
2005-12-22 Mark Mitchell <mark@codesourcery.com>
PR c++/25369
* tree.c (really_overloaded_fn): Tweak comment.
* pt.c (tsubst_call_declarator_parms): Remove.
(tsubst_copy): Call mark_used on the member referenced by an
OFFSET_REF.
* semantics.c (finish_qualified_id_expr): Simplify.
* decl2.c (mark_used): Accept BASELINKs.
PR c++/25364
* typeck.c (build_unary_op): Pass DECLs not names to
build_offset_refs.

View File

@ -3233,14 +3233,27 @@ check_default_args (tree x)
}
}
/* Mark DECL as "used" in the program. If DECL is a specialization or
implicitly declared class member, generate the actual definition. */
/* Mark DECL (eithet a _DECL or a BASELINK) as "used" in the program.
If DECL is a specialization or implicitly declared class member,
generate the actual definition. */
void
mark_used (tree decl)
{
HOST_WIDE_INT saved_processing_template_decl = 0;
/* If DECL is a BASELINK for a single function, then treat it just
like the DECL for the function. Otherwise, if the BASELINK is
for an overloaded function, we don't know which function was
actually used until after overload resolution. */
if (TREE_CODE (decl) == BASELINK)
{
decl = BASELINK_FUNCTIONS (decl);
if (really_overloaded_fn (decl))
return;
decl = OVL_CURRENT (decl);
}
TREE_USED (decl) = 1;
/* If we don't need a value, then we don't need to synthesize DECL. */
if (skip_evaluation)

View File

@ -144,7 +144,6 @@ static void check_specialization_scope (void);
static tree process_partial_specialization (tree);
static void set_current_access_from_decl (tree);
static void check_default_tmpl_args (tree, tree, int, int);
static tree tsubst_call_declarator_parms (tree, tree, tsubst_flags_t, tree);
static tree get_template_base (tree, tree, tree, tree);
static int verify_class_unification (tree, tree, tree);
static tree try_class_unification (tree, tree, tree, tree);
@ -6946,39 +6945,6 @@ tsubst_exception_specification (tree fntype,
return new_specs;
}
/* Substitute into the PARMS of a call-declarator. */
static tree
tsubst_call_declarator_parms (tree parms,
tree args,
tsubst_flags_t complain,
tree in_decl)
{
tree new_parms;
tree type;
tree defarg;
if (!parms || parms == void_list_node)
return parms;
new_parms = tsubst_call_declarator_parms (TREE_CHAIN (parms),
args, complain, in_decl);
/* Figure out the type of this parameter. */
type = tsubst (TREE_VALUE (parms), args, complain, in_decl);
/* Figure out the default argument as well. Note that we use
tsubst_expr since the default argument is really an expression. */
defarg = tsubst_expr (TREE_PURPOSE (parms), args, complain, in_decl);
/* Chain this parameter on to the front of those we have already
processed. We don't use hash_tree_cons because that function
doesn't check TREE_PARMLIST. */
new_parms = tree_cons (defarg, type, new_parms);
return new_parms;
}
/* Take the tree structure T and replace template parameters used
therein with the argument vector ARGS. IN_DECL is an associated
decl for diagnostics. If an error occurs, returns ERROR_MARK_NODE.
@ -8111,6 +8077,10 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
in response to the saved STMT_IS_FULL_EXPR_P setting. */
gcc_unreachable ();
case OFFSET_REF:
mark_used (TREE_OPERAND (t, 1));
return t;
default:
return t;
}

View File

@ -1513,12 +1513,8 @@ finish_qualified_id_expr (tree qualifying_class,
if (error_operand_p (expr))
return error_mark_node;
if (DECL_P (expr))
if (DECL_P (expr) || BASELINK_P (expr))
mark_used (expr);
else if (BASELINK_P (expr)
&& TREE_CODE (BASELINK_FUNCTIONS (expr)) != TEMPLATE_ID_EXPR
&& !really_overloaded_fn (BASELINK_FUNCTIONS (expr)))
mark_used (OVL_CURRENT (BASELINK_FUNCTIONS (expr)));
if (template_p)
check_template_keyword (expr);

View File

@ -843,9 +843,9 @@ is_overloaded_fn (tree x)
int
really_overloaded_fn (tree x)
{
/* A baselink is also considered an overloaded function. */
if (TREE_CODE (x) == OFFSET_REF)
x = TREE_OPERAND (x, 1);
/* A baselink is also considered an overloaded function. */
if (BASELINK_P (x))
x = BASELINK_FUNCTIONS (x);

View File

@ -1,3 +1,8 @@
2005-12-22 Mark Mitchell <mark@codesourcery.com>
PR c++/25369
* g++.dg/template/ptrmem16.C: New test.
2005-12-23 Paul Thomas <pault@gcc.gnu.org>
PR fortran/25029

View File

@ -0,0 +1,20 @@
// PR c++/25369
// { dg-do link }
template <typename> struct A
{
void foo() {}
};
void bar(void (A<int>::*)()) {}
template <int> void baz()
{
bar(&A<int>::foo);
}
int main()
{
baz<0>();
return 0;
}