Commit d4f0f205 by Mark Mitchell Committed by Mark Mitchell

re PR c++/25364 (ICE with function pointer as template parameter)

	PR c++/25364
	* typeck.c (build_unary_op): Pass DECLs not names to
	build_offset_refs.
	* init.c (build_offset_ref): Do not do name lookup.  Do not call
	mark_used.
	* call.c (build_call): Simplify and tidy.
	* semantics.c (finish_qualified_id_expr): Call mark_used.
	PR c++/25364
	* g++.dg/template/call4.C: New test.

From-SVN: r108973
parent 57decb7e
2005-12-22 Mark Mitchell <mark@codesourcery.com>
PR c++/25364
* typeck.c (build_unary_op): Pass DECLs not names to
build_offset_refs.
* init.c (build_offset_ref): Do not do name lookup. Do not call
mark_used.
* call.c (build_call): Simplify and tidy.
* semantics.c (finish_qualified_id_expr): Call mark_used.
2005-12-22 Volker Reichelt <reichelt@igpm.rwth-aachen.de> 2005-12-22 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
PR c++/23333 PR c++/23333
......
...@@ -284,18 +284,28 @@ build_call (tree function, tree parms) ...@@ -284,18 +284,28 @@ build_call (tree function, tree parms)
function = build_addr_func (function); function = build_addr_func (function);
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function))) gcc_assert (TYPE_PTR_P (TREE_TYPE (function)));
{
sorry ("unable to call pointer to member function here");
return error_mark_node;
}
fntype = TREE_TYPE (TREE_TYPE (function)); fntype = TREE_TYPE (TREE_TYPE (function));
gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE
|| TREE_CODE (fntype) == METHOD_TYPE);
result_type = TREE_TYPE (fntype); result_type = TREE_TYPE (fntype);
if (TREE_CODE (function) == ADDR_EXPR if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL) && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
decl = TREE_OPERAND (function, 0); {
decl = TREE_OPERAND (function, 0);
if (!TREE_USED (decl))
{
/* We invoke build_call directly for several library
functions. These may have been declared normally if
we're building libgcc, so we can't just check
DECL_ARTIFICIAL. */
gcc_assert (DECL_ARTIFICIAL (decl)
|| !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)),
"__", 2));
mark_used (decl);
}
}
else else
decl = NULL_TREE; decl = NULL_TREE;
...@@ -314,17 +324,6 @@ build_call (tree function, tree parms) ...@@ -314,17 +324,6 @@ build_call (tree function, tree parms)
if (decl && DECL_CONSTRUCTOR_P (decl)) if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1; is_constructor = 1;
if (decl && ! TREE_USED (decl))
{
/* We invoke build_call directly for several library functions.
These may have been declared normally if we're building libgcc,
so we can't just check DECL_ARTIFICIAL. */
gcc_assert (DECL_ARTIFICIAL (decl)
|| !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)),
"__", 2));
mark_used (decl);
}
/* Don't pass empty class objects by value. This is useful /* Don't pass empty class objects by value. This is useful
for tags in STL, which are used to control overload resolution. for tags in STL, which are used to control overload resolution.
We don't need to handle other cases of copying empty classes. */ We don't need to handle other cases of copying empty classes. */
......
...@@ -1332,112 +1332,40 @@ get_type_value (tree name) ...@@ -1332,112 +1332,40 @@ get_type_value (tree name)
@@ This function should be rewritten and placed in search.c. */ @@ This function should be rewritten and placed in search.c. */
tree tree
build_offset_ref (tree type, tree name, bool address_p) build_offset_ref (tree type, tree member, bool address_p)
{ {
tree decl; tree decl;
tree member;
tree basebinfo = NULL_TREE; tree basebinfo = NULL_TREE;
tree orig_name = name;
/* class templates can come in as TEMPLATE_DECLs here. */ /* class templates can come in as TEMPLATE_DECLs here. */
if (TREE_CODE (name) == TEMPLATE_DECL) if (TREE_CODE (member) == TEMPLATE_DECL)
return name; return member;
if (dependent_type_p (type) || type_dependent_expression_p (name)) if (dependent_type_p (type) || type_dependent_expression_p (member))
return build_qualified_name (NULL_TREE, type, name, return build_qualified_name (NULL_TREE, type, member,
/*template_p=*/false); /*template_p=*/false);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR) gcc_assert (TYPE_P (type));
{
/* If the NAME is a TEMPLATE_ID_EXPR, we are looking at
something like `a.template f<int>' or the like. For the most
part, we treat this just like a.f. We do remember, however,
the template-id that was used. */
name = TREE_OPERAND (orig_name, 0);
if (DECL_P (name))
name = DECL_NAME (name);
else
{
if (TREE_CODE (name) == COMPONENT_REF)
name = TREE_OPERAND (name, 1);
if (TREE_CODE (name) == OVERLOAD)
name = DECL_NAME (OVL_CURRENT (name));
}
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
}
if (type == NULL_TREE)
return error_mark_node;
/* Handle namespace names fully here. */
if (TREE_CODE (type) == NAMESPACE_DECL)
{
tree t = lookup_namespace_name (type, name);
if (t == error_mark_node)
return t;
if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
/* Reconstruct the TEMPLATE_ID_EXPR. */
t = build2 (TEMPLATE_ID_EXPR, TREE_TYPE (t),
t, TREE_OPERAND (orig_name, 1));
if (! type_unknown_p (t))
{
mark_used (t);
t = convert_from_reference (t);
}
return t;
}
if (! is_aggr_type (type, 1)) if (! is_aggr_type (type, 1))
return error_mark_node; return error_mark_node;
if (TREE_CODE (name) == BIT_NOT_EXPR) gcc_assert (DECL_P (member) || BASELINK_P (member));
{ /* Callers should call mark_used before this point. */
if (! check_dtor_name (type, name)) gcc_assert (!DECL_P (member) || TREE_USED (member));
error ("qualified type %qT does not match destructor name %<~%T%>",
type, TREE_OPERAND (name, 0));
name = dtor_identifier;
}
if (!COMPLETE_TYPE_P (complete_type (type)) if (!COMPLETE_TYPE_P (complete_type (type))
&& !TYPE_BEING_DEFINED (type)) && !TYPE_BEING_DEFINED (type))
{ {
error ("incomplete type %qT does not have member %qD", type, name); error ("incomplete type %qT does not have member %qD", type, member);
return error_mark_node;
}
/* Set up BASEBINFO for member lookup. */
decl = maybe_dummy_object (type, &basebinfo);
if (BASELINK_P (name) || DECL_P (name))
member = name;
else
{
member = lookup_member (basebinfo, name, 1, 0);
if (member == error_mark_node)
return error_mark_node;
}
if (!member)
{
error ("%qD is not a member of type %qT", name, type);
return error_mark_node; return error_mark_node;
} }
/* Entities other than non-static members need no further
processing. */
if (TREE_CODE (member) == TYPE_DECL) if (TREE_CODE (member) == TYPE_DECL)
{ return member;
TREE_USED (member) = 1;
return member;
}
/* static class members and class-specific enum
values can be returned without further ado. */
if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL) if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
{ return convert_from_reference (member);
mark_used (member);
return convert_from_reference (member);
}
if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member)) if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member))
{ {
...@@ -1445,6 +1373,9 @@ build_offset_ref (tree type, tree name, bool address_p) ...@@ -1445,6 +1373,9 @@ build_offset_ref (tree type, tree name, bool address_p)
return error_mark_node; return error_mark_node;
} }
/* Set up BASEBINFO for member lookup. */
decl = maybe_dummy_object (type, &basebinfo);
/* A lot of this logic is now handled in lookup_member. */ /* A lot of this logic is now handled in lookup_member. */
if (BASELINK_P (member)) if (BASELINK_P (member))
{ {
...@@ -1452,29 +1383,6 @@ build_offset_ref (tree type, tree name, bool address_p) ...@@ -1452,29 +1383,6 @@ build_offset_ref (tree type, tree name, bool address_p)
tree fnfields = member; tree fnfields = member;
tree t = BASELINK_FUNCTIONS (fnfields); tree t = BASELINK_FUNCTIONS (fnfields);
if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
{
/* The FNFIELDS are going to contain functions that aren't
necessarily templates, and templates that don't
necessarily match the explicit template parameters. We
save all the functions, and the explicit parameters, and
then figure out exactly what to instantiate with what
arguments in instantiate_type. */
if (TREE_CODE (t) != OVERLOAD)
/* The code in instantiate_type which will process this
expects to encounter OVERLOADs, not raw functions. */
t = ovl_cons (t, NULL_TREE);
t = build2 (TEMPLATE_ID_EXPR, TREE_TYPE (t), t,
TREE_OPERAND (orig_name, 1));
t = build2 (OFFSET_REF, unknown_type_node, decl, t);
PTRMEM_OK_P (t) = 1;
return t;
}
if (TREE_CODE (t) != TEMPLATE_ID_EXPR && !really_overloaded_fn (t)) if (TREE_CODE (t) != TEMPLATE_ID_EXPR && !really_overloaded_fn (t))
{ {
/* Get rid of a potential OVERLOAD around it. */ /* Get rid of a potential OVERLOAD around it. */
...@@ -1494,7 +1402,6 @@ build_offset_ref (tree type, tree name, bool address_p) ...@@ -1494,7 +1402,6 @@ build_offset_ref (tree type, tree name, bool address_p)
else else
perform_or_defer_access_check (basebinfo, t); perform_or_defer_access_check (basebinfo, t);
mark_used (t);
if (DECL_STATIC_FUNCTION_P (t)) if (DECL_STATIC_FUNCTION_P (t))
return t; return t;
member = t; member = t;
......
...@@ -1508,9 +1508,18 @@ finish_qualified_id_expr (tree qualifying_class, ...@@ -1508,9 +1508,18 @@ finish_qualified_id_expr (tree qualifying_class,
bool template_p, bool template_p,
bool template_arg_p) bool template_arg_p)
{ {
gcc_assert (TYPE_P (qualifying_class));
if (error_operand_p (expr)) if (error_operand_p (expr))
return error_mark_node; return error_mark_node;
if (DECL_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) if (template_p)
check_template_keyword (expr); check_template_keyword (expr);
......
...@@ -4117,10 +4117,11 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) ...@@ -4117,10 +4117,11 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
is used here to remove this const from the diagnostics is used here to remove this const from the diagnostics
and the created OFFSET_REF. */ and the created OFFSET_REF. */
tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0))); tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0)));
tree name = DECL_NAME (get_first_fn (TREE_OPERAND (arg, 1))); tree fn = get_first_fn (TREE_OPERAND (arg, 1));
if (! flag_ms_extensions) if (! flag_ms_extensions)
{ {
tree name = DECL_NAME (fn);
if (current_class_type if (current_class_type
&& TREE_OPERAND (arg, 0) == current_class_ref) && TREE_OPERAND (arg, 0) == current_class_ref)
/* An expression like &memfn. */ /* An expression like &memfn. */
...@@ -4134,7 +4135,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) ...@@ -4134,7 +4135,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
" Say %<&%T::%D%>", " Say %<&%T::%D%>",
base, name); base, name);
} }
arg = build_offset_ref (base, name, /*address_p=*/true); arg = build_offset_ref (base, fn, /*address_p=*/true);
} }
offset_ref: offset_ref:
......
2005-12-22 Mark Mitchell <mark@codesourcery.com>
PR c++/25364
* g++.dg/template/call4.C: New test.
2005-12-22 Dale Johannesen <dalej@apple.com> 2005-12-22 Dale Johannesen <dalej@apple.com>
* gcc.target/i386/sse-17.c: New. * gcc.target/i386/sse-17.c: New.
// PR c++/25364
class OFX_PropertySuiteV1
{
static int propGetDouble ();
};
template<int dimension,
class T,
int (*PROPGET)()
>
struct OFX_AnimatedNumberParam
{
virtual int paramSetValueAtTime()
{
return PROPGET();
}
};
void f()
{
new OFX_AnimatedNumberParam<2,double,OFX_PropertySuiteV1::propGetDouble>();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment