On 3/7/22 14:41, Patrick Palka wrote:
instantiate_non_dependent_expr_sfinae instantiates only potentially
constant expressions
Hmm, that now strikes me as a problematic interface, as we don't know
whether what we get back is template or non-template trees.
Maybe we want to change instantiate_non_dependent_expr to
checking_assert that the argument is non-dependent (callers are already
checking that), and drop the potentially-constant test?
but when processing a non-dependent decltype
operand we want to instantiate it even if it's non-constant since
such non-dependent decltype is always resolved ahead of time.
Currently finish_decltype_type uses the former function, which causes us
to miss issuing a narrowing diagnostic for S{id(v)} in the below testcase
because we never instantiate this non-constant non-dependent decltype
operand.
So this patch makes finish_decltype_type use i_n_d_e_internal instead of
_sfinae. And afterward, we need to keep processing_template_decl cleared
for sake of the later call to lvalue_kind, which handles templated and
non-templated COND_EXPR differently. Otherwise we'd incorrectly reject
the declaration of g in cpp0x/cond2.C with:
error: āgā declared as function returning a function
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?
PR c++/104823
gcc/cp/ChangeLog:
* semantics.cc (finish_decltype_type): Use i_n_d_e_internal
instead of _sfinae when instantiating a non-dependent decltype
operand, and keep processing_template_decl cleared afterward.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/Wnarrowing19.C: New test.
---
gcc/cp/semantics.cc | 11 ++++++++++-
gcc/testsuite/g++.dg/cpp0x/Wnarrowing19.C | 8 ++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wnarrowing19.C
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 07cae993efe..66d90c2f7be 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11217,6 +11217,8 @@ finish_decltype_type (tree expr, bool
id_expression_or_member_access_p,
/* decltype is an unevaluated context. */
cp_unevaluated u;
+ processing_template_decl_sentinel ptds (/*reset=*/false);
+
/* Depending on the resolution of DR 1172, we may later need to distinguish
instantiation-dependent but not type-dependent expressions so that, say,
A<decltype(sizeof(T))>::U doesn't require 'typename'. */
@@ -11232,7 +11234,14 @@ finish_decltype_type (tree expr, bool
id_expression_or_member_access_p,
}
else if (processing_template_decl)
{
- expr = instantiate_non_dependent_expr_sfinae (expr, complain);
+ /* Instantiate the non-dependent operand to diagnose any ill-formed
+ expressions. And keep processing_template_decl cleared for the rest
+ of the function (for sake of the call to lvalue_kind below, which
+ handles templated and non-templated COND_EXPR differently). */
+ processing_template_decl = 0;
+ /* Since we want to do this even for non-constant expressions, we
+ use i_n_d_e_internal here instead of _sfinae. */
+ expr = instantiate_non_dependent_expr_internal (expr, complain);
if (expr == error_mark_node)
return error_mark_node;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing19.C
b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing19.C
new file mode 100644
index 00000000000..bd9fd2eb6f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing19.C
@@ -0,0 +1,8 @@
+// PR c++/104823
+// { dg-do compile { target c++11 } }
+
+struct S { S(int); };
+
+double id(double v);
+
+template<class> auto f(double v) -> decltype(S{id(v)}); // { dg-error
"narrowing" }