mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-15 14:01:04 +08:00
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:
parent
2aef967bc8
commit
e90abaa0a2
@ -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.
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
{
|
||||
|
19
gcc/cp/pt.c
19
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;
|
||||
|
@ -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
|
||||
|
25
gcc/testsuite/g++.dg/abi/mangle50.C
Normal file
25
gcc/testsuite/g++.dg/abi/mangle50.C
Normal 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>();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user