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
This commit is contained in:
parent
57decb7e53
commit
d4f0f2055b
@ -1,3 +1,13 @@
|
||||
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>
|
||||
|
||||
PR c++/23333
|
||||
|
@ -284,18 +284,28 @@ build_call (tree function, tree parms)
|
||||
|
||||
function = build_addr_func (function);
|
||||
|
||||
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
|
||||
{
|
||||
sorry ("unable to call pointer to member function here");
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
gcc_assert (TYPE_PTR_P (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);
|
||||
|
||||
if (TREE_CODE (function) == ADDR_EXPR
|
||||
&& 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
|
||||
decl = NULL_TREE;
|
||||
|
||||
@ -314,17 +324,6 @@ build_call (tree function, tree parms)
|
||||
if (decl && DECL_CONSTRUCTOR_P (decl))
|
||||
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
|
||||
for tags in STL, which are used to control overload resolution.
|
||||
We don't need to handle other cases of copying empty classes. */
|
||||
|
127
gcc/cp/init.c
127
gcc/cp/init.c
@ -1332,112 +1332,40 @@ get_type_value (tree name)
|
||||
@@ This function should be rewritten and placed in search.c. */
|
||||
|
||||
tree
|
||||
build_offset_ref (tree type, tree name, bool address_p)
|
||||
build_offset_ref (tree type, tree member, bool address_p)
|
||||
{
|
||||
tree decl;
|
||||
tree member;
|
||||
tree basebinfo = NULL_TREE;
|
||||
tree orig_name = name;
|
||||
|
||||
/* class templates can come in as TEMPLATE_DECLs here. */
|
||||
if (TREE_CODE (name) == TEMPLATE_DECL)
|
||||
return name;
|
||||
if (TREE_CODE (member) == TEMPLATE_DECL)
|
||||
return member;
|
||||
|
||||
if (dependent_type_p (type) || type_dependent_expression_p (name))
|
||||
return build_qualified_name (NULL_TREE, type, name,
|
||||
if (dependent_type_p (type) || type_dependent_expression_p (member))
|
||||
return build_qualified_name (NULL_TREE, type, member,
|
||||
/*template_p=*/false);
|
||||
|
||||
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
gcc_assert (TYPE_P (type));
|
||||
if (! is_aggr_type (type, 1))
|
||||
return error_mark_node;
|
||||
|
||||
if (TREE_CODE (name) == BIT_NOT_EXPR)
|
||||
{
|
||||
if (! check_dtor_name (type, name))
|
||||
error ("qualified type %qT does not match destructor name %<~%T%>",
|
||||
type, TREE_OPERAND (name, 0));
|
||||
name = dtor_identifier;
|
||||
}
|
||||
gcc_assert (DECL_P (member) || BASELINK_P (member));
|
||||
/* Callers should call mark_used before this point. */
|
||||
gcc_assert (!DECL_P (member) || TREE_USED (member));
|
||||
|
||||
if (!COMPLETE_TYPE_P (complete_type (type))
|
||||
&& !TYPE_BEING_DEFINED (type))
|
||||
{
|
||||
error ("incomplete type %qT does not have member %qD", type, name);
|
||||
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);
|
||||
error ("incomplete type %qT does not have member %qD", type, member);
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* Entities other than non-static members need no further
|
||||
processing. */
|
||||
if (TREE_CODE (member) == TYPE_DECL)
|
||||
{
|
||||
TREE_USED (member) = 1;
|
||||
return member;
|
||||
}
|
||||
/* static class members and class-specific enum
|
||||
values can be returned without further ado. */
|
||||
return member;
|
||||
if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
|
||||
{
|
||||
mark_used (member);
|
||||
return convert_from_reference (member);
|
||||
}
|
||||
return convert_from_reference (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)
|
||||
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. */
|
||||
if (BASELINK_P (member))
|
||||
{
|
||||
@ -1452,29 +1383,6 @@ build_offset_ref (tree type, tree name, bool address_p)
|
||||
tree fnfields = member;
|
||||
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))
|
||||
{
|
||||
/* Get rid of a potential OVERLOAD around it. */
|
||||
@ -1494,7 +1402,6 @@ build_offset_ref (tree type, tree name, bool address_p)
|
||||
else
|
||||
perform_or_defer_access_check (basebinfo, t);
|
||||
|
||||
mark_used (t);
|
||||
if (DECL_STATIC_FUNCTION_P (t))
|
||||
return t;
|
||||
member = t;
|
||||
|
@ -1508,9 +1508,18 @@ finish_qualified_id_expr (tree qualifying_class,
|
||||
bool template_p,
|
||||
bool template_arg_p)
|
||||
{
|
||||
gcc_assert (TYPE_P (qualifying_class));
|
||||
|
||||
if (error_operand_p (expr))
|
||||
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)
|
||||
check_template_keyword (expr);
|
||||
|
||||
|
@ -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
|
||||
and the created OFFSET_REF. */
|
||||
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)
|
||||
{
|
||||
tree name = DECL_NAME (fn);
|
||||
if (current_class_type
|
||||
&& TREE_OPERAND (arg, 0) == current_class_ref)
|
||||
/* An expression like &memfn. */
|
||||
@ -4134,7 +4135,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
|
||||
" Say %<&%T::%D%>",
|
||||
base, name);
|
||||
}
|
||||
arg = build_offset_ref (base, name, /*address_p=*/true);
|
||||
arg = build_offset_ref (base, fn, /*address_p=*/true);
|
||||
}
|
||||
|
||||
offset_ref:
|
||||
|
@ -1,3 +1,8 @@
|
||||
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>
|
||||
|
||||
* gcc.target/i386/sse-17.c: New.
|
||||
|
21
gcc/testsuite/g++.dg/template/call4.C
Normal file
21
gcc/testsuite/g++.dg/template/call4.C
Normal file
@ -0,0 +1,21 @@
|
||||
// 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>();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user