aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-08-28 11:38:29 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-08-28 11:38:29 -0400
commite90abaa0a28ccc5581f5b7c7abc789c8fb84764c (patch)
tree66c53e1699feba9e99d474d7b0964f8cd338cec1 /gcc
parent2aef967bc8e30972f0ddf792e6045d716078b55a (diff)
downloadgcc-e90abaa0a28ccc5581f5b7c7abc789c8fb84764c.zip
gcc-e90abaa0a28ccc5581f5b7c7abc789c8fb84764c.tar.gz
gcc-e90abaa0a28ccc5581f5b7c7abc789c8fb84764c.tar.bz2
Core DR 342 PR c++/48582
Core DR 342 PR c++/48582 * pt.c (check_valid_ptrmem_cst_expr): A null member pointer value is valid in C++11. (convert_nontype_argument): Likewise. Implicitly convert nullptr and do constant folding. * mangle.c (write_template_arg_literal): Mangle null member pointer values as 0. * call.c (null_member_pointer_value_p): New. * cp-tree.h: Declare it. From-SVN: r178144
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/call.c17
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/mangle.c46
-rw-r--r--gcc/cp/pt.c19
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle50.C25
7 files changed, 107 insertions, 20 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 10e64ef..2e0d6ab 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,16 @@
+2011-08-26 Jason Merrill <jason@redhat.com>
+
+ Core DR 342
+ PR c++/48582
+ * pt.c (check_valid_ptrmem_cst_expr): A null member pointer value
+ is valid in C++11.
+ (convert_nontype_argument): Likewise. Implicitly convert nullptr
+ and do constant folding.
+ * mangle.c (write_template_arg_literal): Mangle null member
+ pointer values as 0.
+ * call.c (null_member_pointer_value_p): New.
+ * cp-tree.h: Declare it.
+
2011-08-25 Jason Merrill <jason@redhat.com>
* call.c (convert_like_real): Remove redundant complain checks.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index dc35824..8421260 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -553,6 +553,23 @@ null_ptr_cst_p (tree t)
return false;
}
+/* Returns true iff T is a null member pointer value (4.11). */
+
+bool
+null_member_pointer_value_p (tree t)
+{
+ tree type = TREE_TYPE (t);
+ if (!type)
+ return false;
+ else if (TYPE_PTRMEMFUNC_P (type))
+ return (TREE_CODE (t) == CONSTRUCTOR
+ && integer_zerop (CONSTRUCTOR_ELT (t, 0)->value));
+ else if (TYPE_PTRMEM_P (type))
+ return integer_all_onesp (t);
+ else
+ return false;
+}
+
/* Returns nonzero if PARMLIST consists of only default parms,
ellipsis, and/or undeduced parameter packs. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8595943..d125642 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4722,6 +4722,7 @@ extern tree build_addr_func (tree);
extern tree build_call_a (tree, int, tree*);
extern tree build_call_n (tree, int, ...);
extern bool null_ptr_cst_p (tree);
+extern bool null_member_pointer_value_p (tree);
extern bool sufficient_parms_p (const_tree);
extern tree type_decays_to (tree);
extern tree build_user_type_conversion (tree, tree, int);
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 4c7cc79..1fcd999 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2762,29 +2762,34 @@ write_template_arg_literal (const tree value)
write_char ('L');
write_type (TREE_TYPE (value));
- switch (TREE_CODE (value))
- {
- case CONST_DECL:
- write_integer_cst (DECL_INITIAL (value));
- break;
+ /* Write a null member pointer value as (type)0, regardless of its
+ real representation. */
+ if (null_member_pointer_value_p (value))
+ write_integer_cst (integer_zero_node);
+ else
+ switch (TREE_CODE (value))
+ {
+ case CONST_DECL:
+ write_integer_cst (DECL_INITIAL (value));
+ break;
- case INTEGER_CST:
- gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node)
- || integer_zerop (value) || integer_onep (value));
- write_integer_cst (value);
- break;
+ case INTEGER_CST:
+ gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node)
+ || integer_zerop (value) || integer_onep (value));
+ write_integer_cst (value);
+ break;
- case REAL_CST:
- write_real_cst (value);
- break;
+ case REAL_CST:
+ write_real_cst (value);
+ break;
- case STRING_CST:
- sorry ("string literal in function template signature");
- break;
+ case STRING_CST:
+ sorry ("string literal in function template signature");
+ break;
- default:
- gcc_unreachable ();
- }
+ default:
+ gcc_unreachable ();
+ }
write_char ('E');
}
@@ -2845,7 +2850,8 @@ write_template_arg (tree node)
/* A template appearing as a template arg is a template template arg. */
write_template_template_arg (node);
else if ((TREE_CODE_CLASS (code) == tcc_constant && code != PTRMEM_CST)
- || (abi_version_at_least (2) && code == CONST_DECL))
+ || (abi_version_at_least (2) && code == CONST_DECL)
+ || null_member_pointer_value_p (node))
write_template_arg_literal (node);
else if (DECL_P (node))
{
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3c6b2c5..1f43ff1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5240,6 +5240,8 @@ check_valid_ptrmem_cst_expr (tree type, tree expr,
STRIP_NOPS (expr);
if (expr && (null_ptr_cst_p (expr) || TREE_CODE (expr) == PTRMEM_CST))
return true;
+ if (cxx_dialect >= cxx0x && null_member_pointer_value_p (expr))
+ return true;
if (complain & tf_error)
{
error ("%qE is not a valid template argument for type %qT",
@@ -5550,6 +5552,17 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
else
expr = mark_rvalue_use (expr);
+ /* 14.3.2/5: The null pointer{,-to-member} conversion is applied
+ to a non-type argument of "nullptr". */
+ if (expr == nullptr_node
+ && (TYPE_PTR_P (type) || TYPE_PTR_TO_MEMBER_P (type)))
+ expr = convert (type, expr);
+
+ /* In C++11, non-type template arguments can be arbitrary constant
+ expressions. But don't fold a PTRMEM_CST to a CONSTRUCTOR yet. */
+ if (cxx_dialect >= cxx0x && TREE_CODE (expr) != PTRMEM_CST)
+ expr = maybe_constant_value (expr);
+
/* HACK: Due to double coercion, we can get a
NOP_EXPR<REFERENCE_TYPE>(ADDR_EXPR<POINTER_TYPE> (arg)) here,
which is the tree that we built on the first call (see
@@ -5658,6 +5671,8 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
if (DECL_P (expr) && DECL_TEMPLATE_PARM_P (expr))
/* Non-type template parameters are OK. */
;
+ else if (cxx_dialect >= cxx0x && integer_zerop (expr))
+ /* Null pointer values are OK in C++11. */;
else if (TREE_CODE (expr) != ADDR_EXPR
&& TREE_CODE (expr_type) != ARRAY_TYPE)
{
@@ -5785,6 +5800,10 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
return error_mark_node;
}
+ if (cxx_dialect >= cxx0x && integer_zerop (expr))
+ /* Null pointer values are OK in C++11. */
+ return perform_qualification_conversions (type, expr);
+
expr = convert_nontype_argument_function (type, expr);
if (!expr || expr == error_mark_node)
return expr;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3481657..03a45a4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2011-08-26 Jason Merrill <jason@redhat.com>
+
+ Core DR 342
+ PR c++/48582
+ * g++.dg/abi/mangle50.C: New.
+
2011-08-27 Uros Bizjak <ubizjak@gmail.com>
PR target/50202
diff --git a/gcc/testsuite/g++.dg/abi/mangle50.C b/gcc/testsuite/g++.dg/abi/mangle50.C
new file mode 100644
index 0000000..df7afb9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle50.C
@@ -0,0 +1,25 @@
+// DR 342, PR c++/48582
+// { dg-options -std=c++0x }
+
+struct A;
+template < void * = nullptr > void f() { }
+template < void (A::*)() = nullptr > void g() { }
+template < int A::* = nullptr > void h() { }
+
+int main()
+{
+ // { dg-final { scan-assembler "_Z1fILPv0EEvv" } }
+ f();
+ f<nullptr>();
+
+ // { dg-final { scan-assembler "_Z1gILM1AFvvE0EEvv" } }
+ g();
+ g<nullptr>();
+
+ // { dg-final { scan-assembler "_Z1fILPv0EEvv" } }
+ h();
+ h<nullptr>();
+
+ constexpr void * ptr = nullptr;
+ f<ptr>();
+}