re PR c++/56095 (Crash casting function pointer as non-type template argument)

PR c++/56095
	* pt.c (convert_nontype_argument_function): Handle invalid input.
	(convert_nontype_argument): Likewise.

From-SVN: r195474
This commit is contained in:
Jason Merrill 2013-01-25 15:01:29 -05:00 committed by Jason Merrill
parent f8fe87bd12
commit d4a180188b
3 changed files with 39 additions and 16 deletions

View File

@ -1,5 +1,9 @@
2013-01-25 Jason Merrill <jason@redhat.com>
PR c++/56095
* pt.c (convert_nontype_argument_function): Handle invalid input.
(convert_nontype_argument): Likewise.
PR c++/56104
* typeck.c (get_member_function_from_ptrfunc): Optimize if the
dynamic type has no virtual functions.

View File

@ -5113,6 +5113,17 @@ convert_nontype_argument_function (tree type, tree expr)
[...]
-- the address of an object or function with external [C++11: or
internal] linkage. */
if (TREE_CODE (fn_no_ptr) != FUNCTION_DECL)
{
error ("%qE is not a valid template argument for type %qT", expr, type);
if (TREE_CODE (type) == POINTER_TYPE)
error ("it must be the address of a function with external linkage");
else
error ("it must be the name of a function with external linkage");
return NULL_TREE;
}
linkage = decl_linkage (fn_no_ptr);
if (cxx_dialect >= cxx0x ? linkage == lk_none : linkage != lk_external)
{
@ -5511,15 +5522,16 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
could actually change the type to something more cv-qualified,
and this is not folded by convert_from_reference. */
tree addr = TREE_OPERAND (probe, 0);
gcc_assert (TREE_CODE (probe_type) == REFERENCE_TYPE);
gcc_assert (TREE_CODE (addr) == ADDR_EXPR);
gcc_assert (TREE_CODE (TREE_TYPE (addr)) == POINTER_TYPE);
gcc_assert (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (probe_type),
TREE_TYPE (TREE_TYPE (addr))));
expr = TREE_OPERAND (addr, 0);
expr_type = TREE_TYPE (expr);
if (TREE_CODE (probe_type) == REFERENCE_TYPE
&& TREE_CODE (addr) == ADDR_EXPR
&& TREE_CODE (TREE_TYPE (addr)) == POINTER_TYPE
&& (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (probe_type),
TREE_TYPE (TREE_TYPE (addr)))))
{
expr = TREE_OPERAND (addr, 0);
expr_type = TREE_TYPE (expr);
}
}
}
@ -5745,13 +5757,6 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
expr = convert_nontype_argument_function (type, expr);
if (!expr || expr == error_mark_node)
return expr;
if (TREE_CODE (expr) != ADDR_EXPR)
{
error ("%qE is not a valid template argument for type %qT", expr, type);
error ("it must be the address of a function with external linkage");
return NULL_TREE;
}
}
/* [temp.arg.nontype]/5, bullet 5

View File

@ -0,0 +1,14 @@
// PR c++/56095
int *a(void) { return 0; }
typedef void voidfn(void);
template <voidfn* b> void z1(void) {}
template <voidfn& b> void z2(void) {}
int main()
{
z1<(voidfn*)a>(); // { dg-error "" }
z1<reinterpret_cast<voidfn*>(a)>(); // { dg-error "" }
z2<(voidfn&)a>(); // { dg-error "" }
z2<reinterpret_cast<voidfn&>(a)>(); // { dg-error "" }
}