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
This commit is contained in:
Jason Merrill 2011-08-28 11:38:29 -04:00 committed by Jason Merrill
parent 2aef967bc8
commit e90abaa0a2
7 changed files with 107 additions and 20 deletions

View File

@ -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.

View File

@ -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. */

View File

@ -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);

View File

@ -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))
{

View File

@ -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;

View File

@ -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

View File

@ -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>();
}