Add support for C++0x nullptr.
gcc: * c-common.c (c_common_reswords): Add nullptr. * c-common.h: Add RID_NULLPTR. Reorganize C++0x rids. * dwarf2out.c (is_base_type): Handle NULLPTR_TYPE. (gen_type_die_with_usage): Likewise. * dbxout.c (dbxout_type): Likewise. * sdbout.c (plain_type_1): Likewise. gcc/cp: * cp-tree.def: Add NULLPTR_TYPE. * cp-tree.h: Add nullptr_node. (cp_tree_index): Add CPTI_NULLPTR. (SCALAR_TYPE_P): Add NULLPTR_TYPE. * call.c (null_ptr_cst_p): Handle nullptr. (standard_conversion): Likewise. (convert_arg_to_ellipsis): Likewise. * mangle.c (write_type): Likewise. * name-lookup.c (arg_assoc_type): Likewise. * parser.c (cp_parser_primary_expression): Likewise. * typeck.c (cp_build_binary_op): Likewise. (build_reinterpret_cast_1): Likewise. * error.c (dump_type): Likewise. (dump_type_prefix, dump_type_suffix): Likewise. * decl.c (cxx_init_decl_processing): Likewise. * cxx-pretty-print.c (pp_cxx_constant): Likewise. * cvt.c (ocp_convert): Likewise. * rtti.c (typeinfo_in_lib_p, emit_support_tinfos): Put nullptr_t tinfo in libsupc++. libstdc++-v3: * config/abi/pre/gnu.ver: Add typeinfo for decltype(nullptr). libiberty: * cp-demangle.c (cplus_demangle_builtin_types): Add nullptr. (cplus_demangle_type): Handle nullptr. From-SVN: r159131
This commit is contained in:
parent
0d1141a39e
commit
14c2101daa
|
@ -1,3 +1,13 @@
|
|||
2010-05-06 Magnus Fromreide <magfr@lysator.liu.se>
|
||||
Jason Merrill <jason@redhat.com>
|
||||
|
||||
* c-common.c (c_common_reswords): Add nullptr.
|
||||
* c-common.h: Add RID_NULLPTR. Reorganize C++0x rids.
|
||||
* dwarf2out.c (is_base_type): Handle NULLPTR_TYPE.
|
||||
(gen_type_die_with_usage): Likewise.
|
||||
* dbxout.c (dbxout_type): Likewise.
|
||||
* sdbout.c (plain_type_1): Likewise.
|
||||
|
||||
2010-05-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* gimplify.c (gimplify_expr): Set GS_ALL_DONE when appropriate.
|
||||
|
|
|
@ -656,6 +656,7 @@ const struct c_common_resword c_common_reswords[] =
|
|||
{ "mutable", RID_MUTABLE, D_CXXONLY | D_CXXWARN },
|
||||
{ "namespace", RID_NAMESPACE, D_CXXONLY | D_CXXWARN },
|
||||
{ "new", RID_NEW, D_CXXONLY | D_CXXWARN },
|
||||
{ "nullptr", RID_NULLPTR, D_CXXONLY | D_CXX0X | D_CXXWARN },
|
||||
{ "operator", RID_OPERATOR, D_CXXONLY | D_CXXWARN },
|
||||
{ "private", RID_PRIVATE, D_CXX_OBJC | D_CXXWARN },
|
||||
{ "protected", RID_PROTECTED, D_CXX_OBJC | D_CXXWARN },
|
||||
|
|
|
@ -114,7 +114,7 @@ enum rid
|
|||
RID_IS_UNION,
|
||||
|
||||
/* C++0x */
|
||||
RID_STATIC_ASSERT, RID_CONSTEXPR, RID_DECLTYPE,
|
||||
RID_CONSTEXPR, RID_DECLTYPE, RID_NULLPTR, RID_STATIC_ASSERT,
|
||||
|
||||
/* Objective-C */
|
||||
RID_AT_ENCODE, RID_AT_END,
|
||||
|
@ -155,8 +155,8 @@ enum rid
|
|||
RID_FIRST_MODIFIER = RID_STATIC,
|
||||
RID_LAST_MODIFIER = RID_ONEWAY,
|
||||
|
||||
RID_FIRST_CXX0X = RID_STATIC_ASSERT,
|
||||
RID_LAST_CXX0X = RID_DECLTYPE,
|
||||
RID_FIRST_CXX0X = RID_CONSTEXPR,
|
||||
RID_LAST_CXX0X = RID_STATIC_ASSERT,
|
||||
RID_FIRST_AT = RID_AT_ENCODE,
|
||||
RID_LAST_AT = RID_AT_IMPLEMENTATION,
|
||||
RID_FIRST_PQ = RID_IN,
|
||||
|
|
|
@ -1,3 +1,27 @@
|
|||
2010-05-06 Magnus Fromreide <magfr@lysator.liu.se>
|
||||
Jason Merrill <jason@redhat.com>
|
||||
|
||||
Add support for C++0x nullptr.
|
||||
* cp-tree.def: Add NULLPTR_TYPE.
|
||||
* cp-tree.h: Add nullptr_node.
|
||||
(cp_tree_index): Add CPTI_NULLPTR.
|
||||
(SCALAR_TYPE_P): Add NULLPTR_TYPE.
|
||||
* call.c (null_ptr_cst_p): Handle nullptr.
|
||||
(standard_conversion): Likewise.
|
||||
(convert_arg_to_ellipsis): Likewise.
|
||||
* mangle.c (write_type): Likewise.
|
||||
* name-lookup.c (arg_assoc_type): Likewise.
|
||||
* parser.c (cp_parser_primary_expression): Likewise.
|
||||
* typeck.c (cp_build_binary_op): Likewise.
|
||||
(build_reinterpret_cast_1): Likewise.
|
||||
* error.c (dump_type): Likewise.
|
||||
(dump_type_prefix, dump_type_suffix): Likewise.
|
||||
* decl.c (cxx_init_decl_processing): Likewise.
|
||||
* cxx-pretty-print.c (pp_cxx_constant): Likewise.
|
||||
* cvt.c (ocp_convert): Likewise.
|
||||
* rtti.c (typeinfo_in_lib_p, emit_support_tinfos): Put
|
||||
nullptr_t tinfo in libsupc++.
|
||||
|
||||
2010-05-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* semantics.c (simplify_aggr_init_expr): Use INIT_EXPR.
|
||||
|
|
|
@ -460,9 +460,11 @@ null_ptr_cst_p (tree t)
|
|||
/* [conv.ptr]
|
||||
|
||||
A null pointer constant is an integral constant expression
|
||||
(_expr.const_) rvalue of integer type that evaluates to zero. */
|
||||
(_expr.const_) rvalue of integer type that evaluates to zero or
|
||||
an rvalue of type std::nullptr_t. */
|
||||
t = integral_constant_value (t);
|
||||
if (t == null_node)
|
||||
if (t == null_node
|
||||
|| TREE_CODE (TREE_TYPE (t)) == NULLPTR_TYPE)
|
||||
return true;
|
||||
if (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t))
|
||||
{
|
||||
|
@ -776,7 +778,12 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
|
|||
if (same_type_p (from, to))
|
||||
return conv;
|
||||
|
||||
if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to))
|
||||
/* [conv.ptr]
|
||||
A null pointer constant can be converted to a pointer type; ... A
|
||||
null pointer constant of integral type can be converted to an
|
||||
rvalue of type std::nullptr_t. */
|
||||
if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to)
|
||||
|| tcode == NULLPTR_TYPE)
|
||||
&& expr && null_ptr_cst_p (expr))
|
||||
conv = build_conv (ck_std, to, conv);
|
||||
else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE)
|
||||
|
@ -911,17 +918,20 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
|
|||
|
||||
An rvalue of arithmetic, unscoped enumeration, pointer, or
|
||||
pointer to member type can be converted to an rvalue of type
|
||||
bool. */
|
||||
bool. ... An rvalue of type std::nullptr_t can be converted
|
||||
to an rvalue of type bool; */
|
||||
if (ARITHMETIC_TYPE_P (from)
|
||||
|| UNSCOPED_ENUM_P (from)
|
||||
|| fcode == POINTER_TYPE
|
||||
|| TYPE_PTR_TO_MEMBER_P (from))
|
||||
|| TYPE_PTR_TO_MEMBER_P (from)
|
||||
|| fcode == NULLPTR_TYPE)
|
||||
{
|
||||
conv = build_conv (ck_std, to, conv);
|
||||
if (fcode == POINTER_TYPE
|
||||
|| TYPE_PTRMEM_P (from)
|
||||
|| (TYPE_PTRMEMFUNC_P (from)
|
||||
&& conv->rank < cr_pbool))
|
||||
&& conv->rank < cr_pbool)
|
||||
|| fcode == NULLPTR_TYPE)
|
||||
conv->rank = cr_pbool;
|
||||
return conv;
|
||||
}
|
||||
|
@ -5192,6 +5202,8 @@ convert_arg_to_ellipsis (tree arg)
|
|||
< TYPE_PRECISION (double_type_node))
|
||||
&& !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (arg))))
|
||||
arg = convert_to_real (double_type_node, arg);
|
||||
else if (TREE_CODE (TREE_TYPE (arg)) == NULLPTR_TYPE)
|
||||
arg = null_pointer_node;
|
||||
else if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg)))
|
||||
arg = perform_integral_promotions (arg);
|
||||
|
||||
|
@ -6788,9 +6800,8 @@ compare_ics (conversion *ics1, conversion *ics2)
|
|||
Two conversion sequences with the same rank are indistinguishable
|
||||
unless one of the following rules applies:
|
||||
|
||||
--A conversion that is not a conversion of a pointer, or pointer
|
||||
to member, to bool is better than another conversion that is such
|
||||
a conversion.
|
||||
--A conversion that does not a convert a pointer, pointer to member,
|
||||
or std::nullptr_t to bool is better than one that does.
|
||||
|
||||
The ICS_STD_RANK automatically handles the pointer-to-bool rule,
|
||||
so that we do not have to check it explicitly. */
|
||||
|
|
|
@ -449,6 +449,9 @@ DEFTREECODE (DECLTYPE_TYPE, "decltype_type", tcc_type, 0)
|
|||
instantiation time. */
|
||||
DEFTREECODE (TEMPLATE_INFO, "template_info", tcc_exceptional, 0)
|
||||
|
||||
/* The type of a nullptr expression. This is a C++0x extension. */
|
||||
DEFTREECODE (NULLPTR_TYPE, "decltype(nullptr)", tcc_type, 0)
|
||||
|
||||
/*
|
||||
Local variables:
|
||||
mode:c
|
||||
|
|
|
@ -775,6 +775,8 @@ enum cp_tree_index
|
|||
|
||||
CPTI_KEYED_CLASSES,
|
||||
|
||||
CPTI_NULLPTR,
|
||||
|
||||
CPTI_MAX
|
||||
};
|
||||
|
||||
|
@ -809,6 +811,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
|
|||
#define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL]
|
||||
#define global_delete_fndecl cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL]
|
||||
#define current_aggr cp_global_trees[CPTI_AGGR_TAG]
|
||||
#define nullptr_node cp_global_trees[CPTI_NULLPTR]
|
||||
|
||||
/* We cache these tree nodes so as to call get_identifier less
|
||||
frequently. */
|
||||
|
@ -3001,8 +3004,9 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
|
|||
|
||||
/* [basic.types]
|
||||
|
||||
Arithmetic types, enumeration types, pointer types, and
|
||||
pointer-to-member types, are collectively called scalar types.
|
||||
Arithmetic types, enumeration types, pointer types,
|
||||
pointer-to-member types, and std::nullptr_t are collectively called
|
||||
scalar types.
|
||||
|
||||
Keep these checks in ascending code order. */
|
||||
#define SCALAR_TYPE_P(TYPE) \
|
||||
|
@ -3010,7 +3014,8 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
|
|||
|| TREE_CODE (TYPE) == ENUMERAL_TYPE \
|
||||
|| ARITHMETIC_TYPE_P (TYPE) \
|
||||
|| TYPE_PTR_P (TYPE) \
|
||||
|| TYPE_PTRMEMFUNC_P (TYPE))
|
||||
|| TYPE_PTRMEMFUNC_P (TYPE) \
|
||||
|| TREE_CODE (TYPE) == NULLPTR_TYPE)
|
||||
|
||||
/* Determines whether this type is a C++0x scoped enumeration
|
||||
type. Scoped enumerations types are introduced via "enum class" or
|
||||
|
|
|
@ -704,6 +704,8 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
|
|||
|
||||
return fold_if_not_in_template (convert_to_integer (type, e));
|
||||
}
|
||||
if (code == NULLPTR_TYPE && e && null_ptr_cst_p (e))
|
||||
return nullptr_node;
|
||||
if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
|
||||
return fold_if_not_in_template (cp_convert_to_pointer (type, e));
|
||||
if (code == VECTOR_TYPE)
|
||||
|
|
|
@ -339,6 +339,14 @@ pp_cxx_constant (cxx_pretty_printer *pp, tree t)
|
|||
}
|
||||
break;
|
||||
|
||||
case INTEGER_CST:
|
||||
if (TREE_CODE (TREE_TYPE (t)) == NULLPTR_TYPE)
|
||||
{
|
||||
pp_string (pp, "nullptr");
|
||||
break;
|
||||
}
|
||||
/* else fall through. */
|
||||
|
||||
default:
|
||||
pp_c_constant (pp_c_base (pp), t);
|
||||
break;
|
||||
|
|
|
@ -3526,6 +3526,17 @@ cxx_init_decl_processing (void)
|
|||
push_cp_library_fn (VEC_NEW_EXPR, newtype);
|
||||
global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
|
||||
push_cp_library_fn (VEC_DELETE_EXPR, deltype);
|
||||
|
||||
{
|
||||
tree nullptr_type_node = make_node (NULLPTR_TYPE);
|
||||
TYPE_SIZE (nullptr_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode));
|
||||
TYPE_SIZE_UNIT (nullptr_type_node) = size_int (GET_MODE_SIZE (ptr_mode));
|
||||
TYPE_UNSIGNED (nullptr_type_node) = 1;
|
||||
TYPE_PRECISION (nullptr_type_node) = GET_MODE_BITSIZE (ptr_mode);
|
||||
SET_TYPE_MODE (nullptr_type_node, Pmode);
|
||||
nullptr_node = make_node (INTEGER_CST);
|
||||
TREE_TYPE (nullptr_node) = nullptr_type_node;
|
||||
}
|
||||
}
|
||||
|
||||
abort_fndecl
|
||||
|
|
|
@ -475,6 +475,10 @@ dump_type (tree t, int flags)
|
|||
pp_cxx_right_paren (cxx_pp);
|
||||
break;
|
||||
|
||||
case NULLPTR_TYPE:
|
||||
pp_string (cxx_pp, "std::nullptr_t");
|
||||
break;
|
||||
|
||||
default:
|
||||
pp_unsupported_tree (cxx_pp, t);
|
||||
/* Fall through to error. */
|
||||
|
@ -703,6 +707,7 @@ dump_type_prefix (tree t, int flags)
|
|||
case DECLTYPE_TYPE:
|
||||
case TYPE_PACK_EXPANSION:
|
||||
case FIXED_POINT_TYPE:
|
||||
case NULLPTR_TYPE:
|
||||
dump_type (t, flags);
|
||||
pp_base (cxx_pp)->padding = pp_before;
|
||||
break;
|
||||
|
@ -805,6 +810,7 @@ dump_type_suffix (tree t, int flags)
|
|||
case DECLTYPE_TYPE:
|
||||
case TYPE_PACK_EXPANSION:
|
||||
case FIXED_POINT_TYPE:
|
||||
case NULLPTR_TYPE:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -1759,6 +1759,7 @@ write_local_name (tree function, const tree local_entity,
|
|||
<type> ::= Dt <expression> # decltype of an id-expression or
|
||||
# class member access
|
||||
<type> ::= DT <expression> # decltype of an expression
|
||||
<type> ::= Dn # decltype of nullptr
|
||||
|
||||
TYPE is a type node. */
|
||||
|
||||
|
@ -1932,6 +1933,10 @@ write_type (tree type)
|
|||
write_char ('E');
|
||||
break;
|
||||
|
||||
case NULLPTR_TYPE:
|
||||
write_string ("Dn");
|
||||
break;
|
||||
|
||||
case TYPEOF_TYPE:
|
||||
sorry ("mangling typeof, use decltype instead");
|
||||
break;
|
||||
|
|
|
@ -4859,6 +4859,7 @@ arg_assoc_type (struct arg_lookup *k, tree type)
|
|||
case BOOLEAN_TYPE:
|
||||
case FIXED_POINT_TYPE:
|
||||
case DECLTYPE_TYPE:
|
||||
case NULLPTR_TYPE:
|
||||
return false;
|
||||
case RECORD_TYPE:
|
||||
if (TYPE_PTRMEMFUNC_P (type))
|
||||
|
|
|
@ -3368,6 +3368,11 @@ cp_parser_primary_expression (cp_parser *parser,
|
|||
cp_lexer_consume_token (parser->lexer);
|
||||
return null_node;
|
||||
|
||||
/* The `nullptr' literal. */
|
||||
case RID_NULLPTR:
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
return nullptr_node;
|
||||
|
||||
/* Recognize the `this' keyword. */
|
||||
case RID_THIS:
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
|
|
@ -1044,6 +1044,7 @@ typeinfo_in_lib_p (tree type)
|
|||
case BOOLEAN_TYPE:
|
||||
case REAL_TYPE:
|
||||
case VOID_TYPE:
|
||||
case NULLPTR_TYPE:
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
@ -1449,6 +1450,9 @@ create_tinfo_types (void)
|
|||
void
|
||||
emit_support_tinfos (void)
|
||||
{
|
||||
/* Dummy static variable so we can put nullptr in the array; it will be
|
||||
set before we actually start to walk the array. */
|
||||
static tree nullptr_type_node;
|
||||
static tree *const fundamentals[] =
|
||||
{
|
||||
&void_type_node,
|
||||
|
@ -1461,6 +1465,7 @@ emit_support_tinfos (void)
|
|||
&long_long_integer_type_node, &long_long_unsigned_type_node,
|
||||
&float_type_node, &double_type_node, &long_double_type_node,
|
||||
&dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node,
|
||||
&nullptr_type_node,
|
||||
0
|
||||
};
|
||||
int ix;
|
||||
|
@ -1477,6 +1482,7 @@ emit_support_tinfos (void)
|
|||
if (!dtor || DECL_EXTERNAL (dtor))
|
||||
return;
|
||||
doing_runtime = 1;
|
||||
nullptr_type_node = TREE_TYPE (nullptr_node);
|
||||
for (ix = 0; fundamentals[ix]; ix++)
|
||||
{
|
||||
tree bltn = *fundamentals[ix];
|
||||
|
|
|
@ -3993,6 +3993,9 @@ cp_build_binary_op (location_t location,
|
|||
}
|
||||
result_type = type1;
|
||||
}
|
||||
else if (null_ptr_cst_p (op0) && null_ptr_cst_p (op1))
|
||||
/* One of the operands must be of nullptr_t type. */
|
||||
result_type = TREE_TYPE (nullptr_node);
|
||||
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
|
||||
{
|
||||
result_type = type0;
|
||||
|
@ -4192,12 +4195,13 @@ cp_build_binary_op (location_t location,
|
|||
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
|
||||
result_type = composite_pointer_type (type0, type1, op0, op1,
|
||||
CPO_COMPARISON, complain);
|
||||
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
|
||||
&& integer_zerop (op1))
|
||||
else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1))
|
||||
result_type = type0;
|
||||
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
|
||||
&& integer_zerop (op0))
|
||||
else if (code1 == POINTER_TYPE && null_ptr_cst_p (op0))
|
||||
result_type = type1;
|
||||
else if (null_ptr_cst_p (op0) && null_ptr_cst_p (op1))
|
||||
/* One of the operands must be of nullptr_t type. */
|
||||
result_type = TREE_TYPE (nullptr_node);
|
||||
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
|
||||
{
|
||||
result_type = type0;
|
||||
|
@ -6020,8 +6024,11 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
|
|||
|
||||
/* [expr.reinterpret.cast]
|
||||
A pointer can be converted to any integral type large enough to
|
||||
hold it. */
|
||||
if (CP_INTEGRAL_TYPE_P (type) && TYPE_PTR_P (intype))
|
||||
hold it. ... A value of type std::nullptr_t can be converted to
|
||||
an integral type; the conversion has the same meaning and
|
||||
validity as a conversion of (void*)0 to the integral type. */
|
||||
if (CP_INTEGRAL_TYPE_P (type)
|
||||
&& (TYPE_PTR_P (intype) || TREE_CODE (intype) == NULLPTR_TYPE))
|
||||
{
|
||||
if (TYPE_PRECISION (type) < TYPE_PRECISION (intype))
|
||||
{
|
||||
|
@ -6031,6 +6038,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
|
|||
else
|
||||
return error_mark_node;
|
||||
}
|
||||
if (TREE_CODE (intype) == NULLPTR_TYPE)
|
||||
return build_int_cst (type, 0);
|
||||
}
|
||||
/* [expr.reinterpret.cast]
|
||||
A value of integral or enumeration type can be explicitly
|
||||
|
|
|
@ -1867,6 +1867,7 @@ dbxout_type (tree type, int full)
|
|||
{
|
||||
case VOID_TYPE:
|
||||
case LANG_TYPE:
|
||||
case NULLPTR_TYPE:
|
||||
/* For a void type, just define it as itself; i.e., "5=5".
|
||||
This makes us consider it defined
|
||||
without saying what it is. The debugger will make it
|
||||
|
|
|
@ -12108,6 +12108,7 @@ is_base_type (tree type)
|
|||
case ENUMERAL_TYPE:
|
||||
case FUNCTION_TYPE:
|
||||
case METHOD_TYPE:
|
||||
case NULLPTR_TYPE:
|
||||
case POINTER_TYPE:
|
||||
case REFERENCE_TYPE:
|
||||
case OFFSET_TYPE:
|
||||
|
@ -19171,6 +19172,18 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
|
|||
when appropriate. */
|
||||
return;
|
||||
|
||||
case NULLPTR_TYPE:
|
||||
{
|
||||
dw_die_ref type_die = lookup_type_die (type);
|
||||
if (type_die == NULL)
|
||||
{
|
||||
type_die = new_die (DW_TAG_unspecified_type, comp_unit_die, type);
|
||||
add_name_attribute (type_die, "decltype(nullptr)");
|
||||
equate_type_number_to_die (type, type_die);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case VOID_TYPE:
|
||||
case INTEGER_TYPE:
|
||||
case REAL_TYPE:
|
||||
|
|
|
@ -3077,7 +3077,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
|
|||
it is invalid to pass a non-present argument on, even
|
||||
though there is no technical reason for this in gfortran.
|
||||
See Fortran 2003, Section 12.4.1.6 item (7)+(8). */
|
||||
tree present, nullptr, type;
|
||||
tree present, null_ptr, type;
|
||||
|
||||
if (attr->allocatable
|
||||
&& (fsym == NULL || !fsym->attr.allocatable))
|
||||
|
@ -3101,10 +3101,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
|
|||
present = fold_build2 (EQ_EXPR, boolean_type_node, present,
|
||||
fold_convert (type, null_pointer_node));
|
||||
type = TREE_TYPE (parmse.expr);
|
||||
nullptr = fold_build2 (EQ_EXPR, boolean_type_node, parmse.expr,
|
||||
fold_convert (type, null_pointer_node));
|
||||
null_ptr = fold_build2 (EQ_EXPR, boolean_type_node, parmse.expr,
|
||||
fold_convert (type, null_pointer_node));
|
||||
cond = fold_build2 (TRUTH_ORIF_EXPR, boolean_type_node,
|
||||
present, nullptr);
|
||||
present, null_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -493,6 +493,7 @@ plain_type_1 (tree type, int level)
|
|||
switch (TREE_CODE (type))
|
||||
{
|
||||
case VOID_TYPE:
|
||||
case NULLPTR_TYPE:
|
||||
return T_VOID;
|
||||
case BOOLEAN_TYPE:
|
||||
case INTEGER_TYPE:
|
||||
|
|
|
@ -1,3 +1,31 @@
|
|||
2010-05-06 Magnus Fromreide <magfr@lysator.liu.se>
|
||||
Jason Merrill <jason@redhat.com>
|
||||
|
||||
* g++.dg/cpp0x/nullptr01.C: New.
|
||||
* g++.dg/cpp0x/nullptr02.C: New.
|
||||
* g++.dg/cpp0x/nullptr03.C: New.
|
||||
* g++.dg/cpp0x/nullptr04.C: New.
|
||||
* g++.dg/cpp0x/nullptr05.C: New.
|
||||
* g++.dg/cpp0x/nullptr06.C: New.
|
||||
* g++.dg/cpp0x/nullptr07.C: New.
|
||||
* g++.dg/cpp0x/nullptr08.C: New.
|
||||
* g++.dg/cpp0x/nullptr09.C: New.
|
||||
* g++.dg/cpp0x/nullptr10.C: New.
|
||||
* g++.dg/cpp0x/nullptr11.C: New.
|
||||
* g++.dg/cpp0x/nullptr12.C: New.
|
||||
* g++.dg/cpp0x/nullptr13.C: New.
|
||||
* g++.dg/cpp0x/nullptr14.C: New.
|
||||
* g++.dg/cpp0x/nullptr15.C: New.
|
||||
* g++.dg/cpp0x/nullptr16.C: New.
|
||||
* g++.dg/cpp0x/nullptr17.C: New.
|
||||
* g++.dg/cpp0x/nullptr18.C: New.
|
||||
* g++.dg/cpp0x/nullptr19.C: New.
|
||||
* g++.dg/cpp0x/nullptr20.C: New.
|
||||
* g++.dg/cpp0x/nullptr21.C: New.
|
||||
* g++.dg/cpp0x/nullptr22.C: New.
|
||||
* g++.dg/debug/nullptr01.C: New.
|
||||
* gcc.dg/Wcxx-compat-2.c: Test nullptr and constexpr.
|
||||
|
||||
2010-05-06 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/40406
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test assignment to pointer
|
||||
|
||||
char* const cp1 = nullptr;
|
||||
char* const cp2 = __null;
|
||||
char* const cp3 = 0;
|
|
@ -0,0 +1,10 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test assignment to nullptr_t
|
||||
|
||||
typedef decltype(nullptr) nullptr_t;
|
||||
|
||||
const nullptr_t np1 = nullptr;
|
||||
const nullptr_t np2 = __null;
|
||||
const nullptr_t np3 = 0;
|
|
@ -0,0 +1,6 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test assignment to int
|
||||
|
||||
const int n = nullptr; // { dg-error "cannot convert " }
|
|
@ -0,0 +1,9 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test cast to int
|
||||
|
||||
const int n4 = static_cast<const int>(nullptr); // { dg-error "invalid static_cast " }
|
||||
const short int n5 = reinterpret_cast<short int>(nullptr); // { dg-error "loses precision" }
|
||||
const long int n6 = reinterpret_cast<long int>(nullptr);
|
||||
const long int n7 = (long int)nullptr;
|
|
@ -0,0 +1,12 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test assignment to method pointer
|
||||
|
||||
class F { };
|
||||
|
||||
typedef void (F::*pmf)();
|
||||
|
||||
const pmf pmf1 = nullptr;
|
||||
const pmf pmf2 = __null;
|
||||
const pmf pmf3 = 0;
|
|
@ -0,0 +1,13 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test compare to pointer
|
||||
|
||||
#define assert_true(b) do { char c[2 * bool(b) - 1]; } while(0)
|
||||
|
||||
char* const cp1 = nullptr;
|
||||
|
||||
void fun()
|
||||
{
|
||||
assert_true(cp1 == nullptr);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test compare to int
|
||||
|
||||
void fun()
|
||||
{
|
||||
int n = 0;
|
||||
if( n == nullptr ); // { dg-error "invalid operands of types " }
|
||||
const int m = 1;
|
||||
if( m == nullptr ); // { dg-error "invalid operands of types " }
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test conversion to bool
|
||||
|
||||
#define assert_true(b) do { char c[2 * bool(b) - 1]; } while(0)
|
||||
|
||||
void fun()
|
||||
{
|
||||
assert_true(nullptr ? false : true);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test compare to literal 0
|
||||
|
||||
void fun()
|
||||
{
|
||||
if( nullptr == 0 );
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test arithmetic operations
|
||||
|
||||
void fun()
|
||||
{
|
||||
nullptr = 0; // { dg-error "lvalue required as left operand" }
|
||||
nullptr + 2; // { dg-error "invalid operands of types " }
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test relational operators
|
||||
|
||||
#define assert_true(b) do { char c[2 * bool(b) - 1]; } while(0)
|
||||
#define assert_false(b) do { char c[1 - 2 * bool(b)]; } while(0)
|
||||
|
||||
void fun()
|
||||
{
|
||||
assert_true(nullptr == nullptr);
|
||||
assert_false(nullptr != nullptr);
|
||||
assert_false(nullptr < nullptr);
|
||||
assert_false(nullptr > nullptr);
|
||||
assert_true(nullptr <= nullptr);
|
||||
assert_true(nullptr >= nullptr);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test sizeof
|
||||
|
||||
static_assert(sizeof(nullptr) == sizeof(void*), "sizeof(nullptr) is wrong");
|
|
@ -0,0 +1,11 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test typeid
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
void fun()
|
||||
{
|
||||
typeid(nullptr);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test overload preference char*/int
|
||||
|
||||
template <typename T, typename U> struct tType_equal;
|
||||
template <typename T> struct tType_equal<T, T> { typedef void type; };
|
||||
|
||||
template <typename T, typename U>
|
||||
inline typename tType_equal<T, U>::type
|
||||
type_equal(U) { }
|
||||
|
||||
char* f( char* );
|
||||
int f( int );
|
||||
long int f( long int );
|
||||
|
||||
void test_f()
|
||||
{
|
||||
// Overloading cases
|
||||
//
|
||||
type_equal<char*>(f(nullptr));
|
||||
type_equal<int>(f(0));
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test template deduction
|
||||
|
||||
template <typename T, typename U> struct tType_equal;
|
||||
template <typename T> struct tType_equal<T, T> { typedef void type; };
|
||||
|
||||
template <typename T, typename U>
|
||||
inline typename tType_equal<T, U>::type
|
||||
type_equal(U) { }
|
||||
|
||||
template<typename T> T* g( T* t );
|
||||
|
||||
void test_g()
|
||||
{
|
||||
// Deduction to nullptr_t, no deduction to pointer type
|
||||
//
|
||||
g(nullptr); // { dg-error "no matching function for call to " }
|
||||
type_equal<float*>(g((float*)nullptr));
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test template deduction
|
||||
|
||||
typedef decltype(nullptr) nullptr_t;
|
||||
|
||||
template <typename T, typename U> struct tType_equal;
|
||||
template <typename T> struct tType_equal<T, T> { typedef void type; };
|
||||
|
||||
template <typename T, typename U>
|
||||
inline typename tType_equal<T, U>::type
|
||||
type_equal(U) { }
|
||||
|
||||
template<typename T> T h( T t );
|
||||
|
||||
void test_h()
|
||||
{
|
||||
type_equal<int>(h(0));
|
||||
type_equal<nullptr_t>(h(nullptr));
|
||||
type_equal<float*>(h((float*)nullptr));
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test that bool is a better overload match than int
|
||||
|
||||
template <typename T, typename U> struct tType_equal;
|
||||
template <typename T> struct tType_equal<T, T> { typedef void type; };
|
||||
|
||||
template <typename T, typename U>
|
||||
inline typename tType_equal<T, U>::type
|
||||
type_equal(U) { }
|
||||
|
||||
int i( int );
|
||||
long int i( long int );
|
||||
bool i( bool );
|
||||
|
||||
void test_i()
|
||||
{
|
||||
// Overload to bool, not int
|
||||
type_equal<bool>(i(nullptr));
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test overload of pointer versus bool when applied on a nullptr_t
|
||||
|
||||
template <typename T, typename U> struct tType_equal;
|
||||
template <typename T> struct tType_equal<T, T> { typedef void type; };
|
||||
|
||||
template <typename T, typename U>
|
||||
inline typename tType_equal<T, U>::type
|
||||
type_equal(U) { }
|
||||
|
||||
char* j( char* );
|
||||
bool j( bool );
|
||||
|
||||
void test_j()
|
||||
{
|
||||
type_equal<char*>(j(nullptr));
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test overload of pointer versus nullptr_t when applied on a literal 0/__null
|
||||
|
||||
typedef decltype(nullptr) nullptr_t;
|
||||
|
||||
char* k( char* ); /* { dg-message "note" } { dg-message "note" } */
|
||||
nullptr_t k( nullptr_t ); /* { dg-message "note" } { dg-message "note" } */
|
||||
|
||||
void test_k()
|
||||
{
|
||||
k(0); /* { dg-error "is ambiguous" } */
|
||||
k(__null); /* { dg-error "is ambiguous" } */
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// { dg-do run }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test passing to ellipisis
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
int main()
|
||||
{
|
||||
char buf1[64];
|
||||
char buf2[64];
|
||||
|
||||
std::snprintf(buf1, sizeof(buf1), "%p", (void*)0);
|
||||
std::snprintf(buf2, sizeof(buf2), "%p", nullptr);
|
||||
return std::strcmp(buf1, buf2) != 0;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// { dg-do run }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// Test throw and catch
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
typedef decltype(nullptr) nullptr_t;
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
throw nullptr;
|
||||
} catch (void*) {
|
||||
printf("Test 1 Fail");
|
||||
} catch (bool) {
|
||||
printf("Test 1 Fail");
|
||||
} catch (int) {
|
||||
printf("Test 1 Fail");
|
||||
} catch (long int) {
|
||||
printf("Test 1 Fail");
|
||||
} catch (nullptr_t) {
|
||||
printf("Test 1 OK");
|
||||
} catch (...) {
|
||||
printf("Test 1 Fail");
|
||||
} // { dg-output "Test 1 OK" }
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x -Wall -Wformat=2 -Wstrict-null-sentinel" }
|
||||
|
||||
// Test various warnings
|
||||
|
||||
void f1(const char*, ...) __attribute__((format(printf, 1, 2)));
|
||||
void f2(const char*) __attribute__((nonnull));
|
||||
void f3(const char*, ...) __attribute__((sentinel));
|
||||
|
||||
void f()
|
||||
{
|
||||
f1("%p", nullptr);
|
||||
f2(nullptr); // { dg-warning "null argument where non-null required " }
|
||||
f3("x", "y", __null); // { dg-warning "missing sentinel in function call" }
|
||||
f3("x", "y", nullptr);
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
// { dg-options "-std=gnu++98 -Wc++0x-compat" }
|
||||
int static_assert; // { dg-warning "will become a keyword" }
|
||||
int nullptr; // { dg-warning "will become a keyword" }
|
||||
|
||||
void foo()
|
||||
{
|
||||
static_assert = 5;
|
||||
nullptr = 5;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// Test that debugging backends don't crash on NULLPTR_TYPE.
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
typedef decltype(nullptr) nullptr_t;
|
||||
|
||||
nullptr_t np1;
|
||||
void f (nullptr_t) { }
|
||||
template <class T> struct A { };
|
||||
template <class T> nullptr_t g(T t);
|
||||
template <> nullptr_t g(A<nullptr_t>)
|
||||
{
|
||||
nullptr_t local;
|
||||
}
|
||||
// { dg-final { scan-assembler "_Z1fDn" } }
|
||||
// { dg-final { scan-assembler "_Z1gI1AIDnEES1_T_" } }
|
|
@ -7,6 +7,7 @@ int char16_t; /* { dg-warning "5:keyword" } */
|
|||
int char32_t; /* { dg-warning "5:keyword" } */
|
||||
int class; /* { dg-warning "5:keyword" } */
|
||||
int const_cast; /* { dg-warning "5:keyword" } */
|
||||
int constexpr; /* { dg-warning "5:keyword" } */
|
||||
int decltype; /* { dg-warning "5:keyword" } */
|
||||
int delete; /* { dg-warning "5:keyword" } */
|
||||
int dynamic_cast; /* { dg-warning "5:keyword" } */
|
||||
|
@ -17,6 +18,7 @@ int friend; /* { dg-warning "5:keyword" } */
|
|||
int mutable; /* { dg-warning "5:keyword" } */
|
||||
int namespace; /* { dg-warning "5:keyword" } */
|
||||
int new; /* { dg-warning "5:keyword" } */
|
||||
int nullptr; /* { dg-warning "5:keyword" } */
|
||||
int operator; /* { dg-warning "5:keyword" } */
|
||||
int private; /* { dg-warning "5:keyword" } */
|
||||
int protected; /* { dg-warning "5:keyword" } */
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2010-05-06 Magnus Fromreide <magfr@lysator.liu.se>
|
||||
Jason Merrill <jason@redhat.com>
|
||||
|
||||
* cp-demangle.c (cplus_demangle_builtin_types): Add nullptr.
|
||||
(cplus_demangle_type): Handle nullptr.
|
||||
* testsuite/demangle-expected: Test it.
|
||||
|
||||
2010-04-23 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* lbasename.c (lbasename): Split into ...
|
||||
|
|
|
@ -1987,6 +1987,8 @@ cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] =
|
|||
/* 29 */ { NL ("half"), NL ("half"), D_PRINT_FLOAT },
|
||||
/* 30 */ { NL ("char16_t"), NL ("char16_t"), D_PRINT_DEFAULT },
|
||||
/* 31 */ { NL ("char32_t"), NL ("char32_t"), D_PRINT_DEFAULT },
|
||||
/* 32 */ { NL ("decltype(nullptr)"), NL ("decltype(nullptr)"),
|
||||
D_PRINT_DEFAULT },
|
||||
};
|
||||
|
||||
CP_STATIC_IF_GLIBCPP_V3
|
||||
|
@ -2221,6 +2223,12 @@ cplus_demangle_type (struct d_info *di)
|
|||
ret = d_vector_type (di);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
/* decltype(nullptr) */
|
||||
ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[32]);
|
||||
di->expansion += ret->u.s_builtin.type->len;
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ struct d_info
|
|||
extern const struct demangle_operator_info cplus_demangle_operators[];
|
||||
#endif
|
||||
|
||||
#define D_BUILTIN_TYPE_COUNT (32)
|
||||
#define D_BUILTIN_TYPE_COUNT (33)
|
||||
|
||||
CP_STATIC_IF_GLIBCPP_V3
|
||||
const struct demangle_builtin_type_info
|
||||
|
|
|
@ -3938,6 +3938,9 @@ decltype ((operator+)({parm#1}, {parm#1})) f<A>(A)
|
|||
--format=gnu-v3
|
||||
_Z1hI1AEDTcldtfp_miEET_
|
||||
decltype (({parm#1}.(operator-))()) h<A>(A)
|
||||
--format=gnu-v3
|
||||
_Z1fDn
|
||||
f(decltype(nullptr))
|
||||
#
|
||||
# Ada (GNAT) tests.
|
||||
#
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2010-05-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* config/abi/pre/gnu.ver: Add typeinfo for decltype(nullptr).
|
||||
|
||||
2010-05-06 Jonathan Wakely <jwakely.gcc@gmail.com>
|
||||
|
||||
* include/bits/basic_string.h: Escape class names in doxygen docs.
|
||||
|
|
|
@ -1307,12 +1307,9 @@ CXXABI_1.3.3 {
|
|||
|
||||
CXXABI_1.3.4 {
|
||||
|
||||
# typeinfo for decimal floating point types
|
||||
_ZTID[fde];
|
||||
_ZTIPD[fde];
|
||||
_ZTIPKD[fde];
|
||||
_ZTID[fde];
|
||||
_ZTIPD[fde];
|
||||
_ZTIPKD[fde];
|
||||
# typeinfo for decimal floating point types and decltype(nullptr)
|
||||
_ZTID[fden];
|
||||
_ZTIPD[fden];
|
||||
_ZTIPKD[fden];
|
||||
|
||||
} CXXABI_1.3.3;
|
||||
|
|
Loading…
Reference in New Issue