aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/call.cc13
-rw-r--r--gcc/cp/pt.cc6
-rw-r--r--gcc/testsuite/g++.dg/template/conv18.C14
3 files changed, 29 insertions, 4 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index d6eed5e..8fe8ef3 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -6023,6 +6023,17 @@ perfect_candidate_p (z_candidate *cand)
return true;
}
+/* True iff one of CAND's argument conversions is NULL. */
+
+static bool
+missing_conversion_p (const z_candidate *cand)
+{
+ for (unsigned i = 0; i < cand->num_convs; ++i)
+ if (!cand->convs[i])
+ return true;
+ return false;
+}
+
/* Add each of the viable functions in FNS (a FUNCTION_DECL or
OVERLOAD) to the CANDIDATES, returning an updated list of
CANDIDATES. The ARGS are the arguments provided to the call;
@@ -6200,7 +6211,7 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
if (cand->viable == -1
&& shortcut_bad_convs
- && !cand->convs[cand->reversed () ? 0 : cand->num_convs - 1])
+ && missing_conversion_p (cand))
{
/* This candidate has been tentatively marked non-strictly viable,
and we didn't compute all argument conversions for it (having
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index f7ee33a..67a49c7 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -152,7 +152,7 @@ static tree coerce_innermost_template_parms (tree, tree, tree, tsubst_flags_t,
bool, bool);
static void tsubst_enum (tree, tree, tree);
static bool check_instantiated_args (tree, tree, tsubst_flags_t);
-static int check_non_deducible_conversion (tree, tree, int, int,
+static int check_non_deducible_conversion (tree, tree, unification_kind_t, int,
struct conversion **, bool);
static int maybe_adjust_types_for_deduction (tree, unification_kind_t,
tree*, tree*, tree);
@@ -22287,7 +22287,7 @@ maybe_adjust_types_for_deduction (tree tparms,
unify_one_argument. */
static int
-check_non_deducible_conversion (tree parm, tree arg, int strict,
+check_non_deducible_conversion (tree parm, tree arg, unification_kind_t strict,
int flags, struct conversion **conv_p,
bool explain_p)
{
@@ -22307,7 +22307,7 @@ check_non_deducible_conversion (tree parm, tree arg, int strict,
if (can_convert_arg (type, parm, NULL_TREE, flags, complain))
return unify_success (explain_p);
}
- else if (strict != DEDUCE_EXACT)
+ else if (strict == DEDUCE_CALL)
{
bool ok = false;
tree conv_arg = TYPE_P (arg) ? NULL_TREE : arg;
diff --git a/gcc/testsuite/g++.dg/template/conv18.C b/gcc/testsuite/g++.dg/template/conv18.C
new file mode 100644
index 0000000..f59f6fd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/conv18.C
@@ -0,0 +1,14 @@
+// PR c++/104622
+// { dg-additional-options "-fpermissive" }
+
+template<class T>
+struct type_identity {
+ typedef T type;
+};
+
+template<class T> void f(typename type_identity<T>::type*, T, int*);
+
+int main() {
+ const int p = 0;
+ f(&p, 0, 0); // { dg-warning "invalid conversion" }
+}