aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-01-25 15:01:29 -0500
committerJason Merrill <jason@gcc.gnu.org>2013-01-25 15:01:29 -0500
commitd4a180188bed0a798818ef176c89048343277665 (patch)
tree06b0af402c8c86fa6bd9e2fe9b1d3aac1ff335bf
parentf8fe87bd12b017e0f6be0d1103029e6d89dc7a40 (diff)
downloadgcc-d4a180188bed0a798818ef176c89048343277665.zip
gcc-d4a180188bed0a798818ef176c89048343277665.tar.gz
gcc-d4a180188bed0a798818ef176c89048343277665.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/pt.c37
-rw-r--r--gcc/testsuite/g++.dg/template/fn-ptr2.C14
3 files changed, 39 insertions, 16 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3d30491..1b640ff 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 01d4295..7430289 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
diff --git a/gcc/testsuite/g++.dg/template/fn-ptr2.C b/gcc/testsuite/g++.dg/template/fn-ptr2.C
new file mode 100644
index 0000000..742135a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/fn-ptr2.C
@@ -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 "" }
+}