public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-3234] c++: fold function template args sooner [PR101460]
@ 2021-08-30 21:23 Jason Merrill
0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2021-08-30 21:23 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:a8de832470f78a40a0e2c8de866a471bf74bf0ab
commit r12-3234-ga8de832470f78a40a0e2c8de866a471bf74bf0ab
Author: Jason Merrill <jason@redhat.com>
Date: Mon Aug 30 09:44:28 2021 -0400
c++: fold function template args sooner [PR101460]
As discussed in the PR, we were giving a lot of unnecessary errors for this
testcase because we didn't try to do constant evaluation until
convert_nontype_argument, which happens for each of the candidates. But
when looking at a template-id as the function operand of a call, we can try
to fold arguments before we get into overload resolution.
PR c++/101460
gcc/cp/ChangeLog:
* cp-tree.h (cxx_constant_value_sfinae): Declare.
* constexpr.c (cxx_constant_value_sfinae): New.
* pt.c (fold_targs_r, maybe_fold_fn_template_args): New.
(tsubst_copy_and_build) [CALL_EXPR]: Call
maybe_fold_fn_template_args.
gcc/testsuite/ChangeLog:
* g++.dg/template/explicit-args6.C: New test.
Diff:
---
gcc/cp/cp-tree.h | 1 +
gcc/cp/constexpr.c | 12 ++++++
gcc/cp/pt.c | 60 ++++++++++++++++++++++++++
gcc/testsuite/g++.dg/template/explicit-args6.C | 34 +++++++++++++++
4 files changed, 107 insertions(+)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 75ee88721b4..6a179375a56 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8266,6 +8266,7 @@ extern bool require_constant_expression (tree);
extern bool require_rvalue_constant_expression (tree);
extern bool require_potential_rvalue_constant_expression (tree);
extern tree cxx_constant_value (tree, tree = NULL_TREE);
+extern tree cxx_constant_value_sfinae (tree, tsubst_flags_t);
extern void cxx_constant_dtor (tree, tree);
extern tree cxx_constant_init (tree, tree = NULL_TREE);
extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false);
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index b9c006217be..9606719bc73 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -7458,6 +7458,18 @@ cxx_constant_value (tree t, tree decl)
return cxx_eval_outermost_constant_expr (t, false, true, true, false, decl);
}
+/* As above, but respect SFINAE. */
+
+tree
+cxx_constant_value_sfinae (tree t, tsubst_flags_t complain)
+{
+ bool sfinae = !(complain & tf_error);
+ tree r = cxx_eval_outermost_constant_expr (t, sfinae, true, true);
+ if (sfinae && !TREE_CONSTANT (r))
+ r = error_mark_node;
+ return r;
+}
+
/* Like cxx_constant_value, but used for evaluation of constexpr destructors
of constexpr variables. The actual initializer of DECL is not modified. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 020a4bf2f6d..d7d0dce691c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19465,6 +19465,63 @@ out:
return r;
}
+/* Subroutine of maybe_fold_fn_template_args. */
+
+static bool
+fold_targs_r (tree targs, tsubst_flags_t complain)
+{
+ int len = TREE_VEC_LENGTH (targs);
+ for (int i = 0; i < len; ++i)
+ {
+ tree &elt = TREE_VEC_ELT (targs, i);
+ if (!elt || TYPE_P (elt)
+ || TREE_CODE (elt) == TEMPLATE_DECL)
+ continue;
+ if (TREE_CODE (elt) == NONTYPE_ARGUMENT_PACK)
+ {
+ if (!fold_targs_r (ARGUMENT_PACK_ARGS (elt), complain))
+ return false;
+ }
+ else if (/* We can only safely preevaluate scalar prvalues. */
+ SCALAR_TYPE_P (TREE_TYPE (elt))
+ && !glvalue_p (elt)
+ && !TREE_CONSTANT (elt))
+ {
+ elt = cxx_constant_value_sfinae (elt, complain);
+ if (elt == error_mark_node)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Try to do constant evaluation of any explicit template arguments in FN
+ before overload resolution, to get any errors only once. Return true iff
+ we didn't have any problems folding. */
+
+static bool
+maybe_fold_fn_template_args (tree fn, tsubst_flags_t complain)
+{
+ if (processing_template_decl || fn == NULL_TREE)
+ return true;
+ if (fn == error_mark_node)
+ return false;
+ if (TREE_CODE (fn) == OFFSET_REF
+ || TREE_CODE (fn) == COMPONENT_REF)
+ fn = TREE_OPERAND (fn, 1);
+ if (BASELINK_P (fn))
+ fn = BASELINK_FUNCTIONS (fn);
+ if (TREE_CODE (fn) != TEMPLATE_ID_EXPR)
+ return true;
+ tree targs = TREE_OPERAND (fn, 1);
+ if (targs == NULL_TREE)
+ return true;
+ if (targs == error_mark_node)
+ return false;
+ return fold_targs_r (targs, complain);
+}
+
/* Like tsubst but deals with expressions and performs semantic
analysis. FUNCTION_P is true if T is the "F" in "F (ARGS)" or
"F<TARGS> (ARGS)". */
@@ -20343,6 +20400,9 @@ tsubst_copy_and_build (tree t,
&& !mark_used (function, complain) && !(complain & tf_error))
RETURN (error_mark_node);
+ if (!maybe_fold_fn_template_args (function, complain))
+ return error_mark_node;
+
/* Put back tf_decltype for the actual call. */
complain |= decltype_flag;
diff --git a/gcc/testsuite/g++.dg/template/explicit-args6.C b/gcc/testsuite/g++.dg/template/explicit-args6.C
new file mode 100644
index 00000000000..d853564e3be
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/explicit-args6.C
@@ -0,0 +1,34 @@
+// PR c++/101460
+// { dg-do compile { target c++11 } }
+
+template<bool> struct enable_if { };
+template<> struct enable_if<true> { using type = void; };
+
+template<bool B>
+using enable_if_t = typename enable_if<B>::type;
+
+struct tuple { };
+struct pair { };
+
+template<unsigned N> enable_if_t<N == 1> get(tuple&) { } // { dg-bogus "candidate" }
+template<unsigned N> enable_if_t<N == 1> get(const tuple&) { } // { dg-bogus "candidate" }
+template<unsigned N> enable_if_t<N == 1> get(pair&) { } // { dg-bogus "candidate" }
+template<unsigned N> enable_if_t<N == 1> get(const pair&) { } // { dg-bogus "candidate" }
+
+template<int N>
+constexpr unsigned
+frob()
+{
+ static_assert(N == 1, "user-friendly diagnostic"); // { dg-error "user-friendly" }
+ // narrowing check, reject negative values
+ return unsigned{N}; // { dg-prune-output "narrowing" }
+} // { dg-prune-output "flows off the end" }
+// { dg-prune-output "not a return-statement" }
+
+template<int N> void get_n(tuple& t) { get<frob<N>()>(t); } // { dg-error "" }
+
+int main()
+{
+ tuple t;
+ get_n<-1>(t);
+}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-08-30 21:23 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-30 21:23 [gcc r12-3234] c++: fold function template args sooner [PR101460] Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).