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))
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
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))
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;
}
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;
}
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
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))
{
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
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);