aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/call.c71
-rw-r--r--gcc/cp/pt.c25
-rw-r--r--gcc/cp/typeck.c4
-rw-r--r--gcc/testsuite/g++.dg/template/func2.C2
5 files changed, 70 insertions, 41 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6f063e7..a65ddec 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d2e99bc..0466cd1 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f910d40..45965aa 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 45b7d26..4ff2bc2 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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. */
diff --git a/gcc/testsuite/g++.dg/template/func2.C b/gcc/testsuite/g++.dg/template/func2.C
index b0f691d..746f0e2 100644
--- a/gcc/testsuite/g++.dg/template/func2.C
+++ b/gcc/testsuite/g++.dg/template/func2.C
@@ -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() { }