C++ cleanups before C++17 noexcept in types.

* call.c (standard_conversion): Reorganize pointer conversions.
	* pt.c (convert_nontype_argument_function): Convert to ref here.
	(convert_nontype_argument): Not here.
	(convert_template_argument): Add original type to error message.
	(RECUR_AND_CHECK_FAILURE): Remove trailing semicolon.
	(unify): Compare function-qualifiers.
	* typeck.c (same_type_ignoring_top_level_qualifiers_p): Use
	cp_build_qualified_type rather than TYPE_MAIN_VARIANT.

From-SVN: r241943
This commit is contained in:
Jason Merrill 2016-11-07 18:09:21 -05:00 committed by Jason Merrill
parent 4ab71abd26
commit 452811eb53
5 changed files with 70 additions and 41 deletions

View file

@ -1,5 +1,14 @@
2016-11-07 Jason Merrill <jason@redhat.com>
* call.c (standard_conversion): Reorganize pointer conversions.
* pt.c (convert_nontype_argument_function): Convert to ref here.
(convert_nontype_argument): Not here.
(convert_template_argument): Add original type to error message.
(RECUR_AND_CHECK_FAILURE): Remove trailing semicolon.
(unify): Compare function-qualifiers.
* typeck.c (same_type_ignoring_top_level_qualifiers_p): Use
cp_build_qualified_type rather than TYPE_MAIN_VARIANT.
* pt.c (push_tinst_level_loc): Add template instantiations to the
announce_function stream.

View file

@ -1212,19 +1212,40 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
tree to_pointee;
tree from_pointee;
if (tcode == POINTER_TYPE)
{
to_pointee = TREE_TYPE (to);
from_pointee = TREE_TYPE (from);
/* Since this is the target of a pointer, it can't have function
qualifiers, so any TYPE_QUALS must be for attributes const or
noreturn. Strip them. */
if (TREE_CODE (to_pointee) == FUNCTION_TYPE
&& TYPE_QUALS (to_pointee))
to_pointee = build_qualified_type (to_pointee, TYPE_UNQUALIFIED);
if (TREE_CODE (from_pointee) == FUNCTION_TYPE
&& TYPE_QUALS (from_pointee))
from_pointee = build_qualified_type (from_pointee, TYPE_UNQUALIFIED);
}
else
{
to_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (to);
from_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (from);
}
if (tcode == POINTER_TYPE
&& same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
TREE_TYPE (to)))
&& same_type_ignoring_top_level_qualifiers_p (from_pointee,
to_pointee))
;
else if (VOID_TYPE_P (TREE_TYPE (to))
else if (VOID_TYPE_P (to_pointee)
&& !TYPE_PTRDATAMEM_P (from)
&& TREE_CODE (TREE_TYPE (from)) != FUNCTION_TYPE)
&& TREE_CODE (from_pointee) != FUNCTION_TYPE)
{
tree nfrom = TREE_TYPE (from);
/* Don't try to apply restrict to void. */
int quals = cp_type_quals (nfrom) & ~TYPE_QUAL_RESTRICT;
from = build_pointer_type
(cp_build_qualified_type (void_type_node, quals));
from_pointee = cp_build_qualified_type (void_type_node, quals);
from = build_pointer_type (from_pointee);
conv = build_conv (ck_ptr, from, conv);
}
else if (TYPE_PTRDATAMEM_P (from))
@ -1234,18 +1255,16 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
if (DERIVED_FROM_P (fbase, tbase)
&& (same_type_ignoring_top_level_qualifiers_p
(TYPE_PTRMEM_POINTED_TO_TYPE (from),
TYPE_PTRMEM_POINTED_TO_TYPE (to))))
(from_pointee, to_pointee)))
{
from = build_ptrmem_type (tbase,
TYPE_PTRMEM_POINTED_TO_TYPE (from));
from = build_ptrmem_type (tbase, from_pointee);
conv = build_conv (ck_pmem, from, conv);
}
else if (!same_type_p (fbase, tbase))
return NULL;
}
else if (CLASS_TYPE_P (TREE_TYPE (from))
&& CLASS_TYPE_P (TREE_TYPE (to))
else if (CLASS_TYPE_P (from_pointee)
&& CLASS_TYPE_P (to_pointee)
/* [conv.ptr]
An rvalue of type "pointer to cv D," where D is a
@ -1257,38 +1276,28 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
that necessitates this conversion is ill-formed.
Therefore, we use DERIVED_FROM_P, and do not check
access or uniqueness. */
&& DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
&& DERIVED_FROM_P (to_pointee, from_pointee))
{
from =
cp_build_qualified_type (TREE_TYPE (to),
cp_type_quals (TREE_TYPE (from)));
from = build_pointer_type (from);
from_pointee
= cp_build_qualified_type (to_pointee,
cp_type_quals (from_pointee));
from = build_pointer_type (from_pointee);
conv = build_conv (ck_ptr, from, conv);
conv->base_p = true;
}
else if (tx_safe_fn_type_p (TREE_TYPE (from)))
else if (tx_safe_fn_type_p (from_pointee))
{
/* A prvalue of type "pointer to transaction_safe function" can be
converted to a prvalue of type "pointer to function". */
tree unsafe = tx_unsafe_fn_variant (TREE_TYPE (from));
if (same_type_p (unsafe, TREE_TYPE (to)))
tree unsafe = tx_unsafe_fn_variant (from_pointee);
if (same_type_p (unsafe, to_pointee))
{
from_pointee = unsafe;
from = build_pointer_type (unsafe);
conv = build_conv (ck_tsafe, from, conv);
}
}
if (tcode == POINTER_TYPE)
{
to_pointee = TREE_TYPE (to);
from_pointee = TREE_TYPE (from);
}
else
{
to_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (to);
from_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (from);
}
if (same_type_p (from, to))
/* OK */;
else if (c_cast_p && comp_ptr_ttypes_const (to, from))

View file

@ -5913,11 +5913,11 @@ convert_nontype_argument_function (tree type, tree expr,
error ("%qE is not a valid template argument for type %qT",
expr, type);
if (TYPE_PTR_P (type))
error ("it must be the address of a function with "
"external linkage");
inform (input_location, "it must be the address of a function "
"with external linkage");
else
error ("it must be the name of a function with "
"external linkage");
inform (input_location, "it must be the name of a function with "
"external linkage");
}
return NULL_TREE;
}
@ -5939,6 +5939,11 @@ convert_nontype_argument_function (tree type, tree expr,
return NULL_TREE;
}
if (TREE_CODE (type) == REFERENCE_TYPE)
fn = build_address (fn);
if (!same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (fn)))
fn = build_nop (type, fn);
return fn;
}
@ -6648,8 +6653,6 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
expr = convert_nontype_argument_function (type, expr, complain);
if (!expr || expr == error_mark_node)
return expr;
expr = build_nop (type, build_address (expr));
}
/* [temp.arg.nontype]/5, bullet 6
@ -7325,7 +7328,8 @@ convert_template_argument (tree parm,
if (val == NULL_TREE)
val = error_mark_node;
else if (val == error_mark_node && (complain & tf_error))
error ("could not convert template argument %qE to %qT", orig_arg, t);
error ("could not convert template argument %qE from %qT to %qT",
orig_arg, TREE_TYPE (orig_arg), t);
if (INDIRECT_REF_P (val))
{
@ -19354,7 +19358,7 @@ template_parm_level_and_index (tree parm, int* level, int* index)
do { \
if (unify (TP, TA, P, A, S, EP)) \
return 1; \
} while (0);
} while (0)
/* Unifies the remaining arguments in PACKED_ARGS with the pack
expansion at the end of PACKED_PARMS. Returns 0 if the type
@ -20312,6 +20316,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
class_of_this_parm (arg),
class_of_this_parm (parm))))
return unify_cv_qual_mismatch (explain_p, parm, arg);
if (TREE_CODE (arg) == FUNCTION_TYPE
&& type_memfn_quals (parm) != type_memfn_quals (arg))
return unify_cv_qual_mismatch (explain_p, parm, arg);
if (type_memfn_rqual (parm) != type_memfn_rqual (arg))
return unify_type_mismatch (explain_p, parm, arg);
RECUR_AND_CHECK_FAILURE (tparms, targs, TREE_TYPE (parm),
TREE_TYPE (arg), UNIFY_ALLOW_NONE, explain_p);

View file

@ -1457,7 +1457,9 @@ same_type_ignoring_top_level_qualifiers_p (tree type1, tree type2)
if (type1 == error_mark_node || type2 == error_mark_node)
return false;
return same_type_p (TYPE_MAIN_VARIANT (type1), TYPE_MAIN_VARIANT (type2));
type1 = cp_build_qualified_type (type1, TYPE_UNQUALIFIED);
type2 = cp_build_qualified_type (type2, TYPE_UNQUALIFIED);
return same_type_p (type1, type2);
}
/* Returns 1 if TYPE1 is at least as qualified as TYPE2. */

View file

@ -5,7 +5,7 @@ fptr zeroptr = 0;
template<typename T, fptr F> struct foo { };
template<typename T> struct foo<T,zeroptr> { };
// { dg-error "not a valid template argument" "not valid" { target *-*-* } 6 }
// { dg-error "must be the address" "must be the address " { target *-*-* } 6 }
// { dg-message "must be the address" "must be the address " { target *-*-* } 6 }
// The rest is needed to trigger the ICE in 4.0 to 4.3:
void f() { }