From 452811eb53e9c0457f99f4f23a4ca10354c088e1 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 7 Nov 2016 18:09:21 -0500 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 9 ++++ gcc/cp/call.c | 71 +++++++++++++++------------ gcc/cp/pt.c | 25 +++++++--- gcc/cp/typeck.c | 4 +- gcc/testsuite/g++.dg/template/func2.C | 2 +- 5 files changed, 70 insertions(+), 41 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6f063e7534a..a65ddec3343 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,14 @@ 2016-11-07 Jason Merrill + * 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 d2e99bccf5a..0466cd13e38 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 f910d40055f..45965aa788d 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 45b7d264088..4ff2bc2d26e 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 b0f691d242b..746f0e279a7 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 struct foo { }; template struct foo { }; // { 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() { } -- 2.30.2