c++: non-constant non-dependent decltype folding [PR104823]
authorPatrick Palka <ppalka@redhat.com>
Wed, 9 Mar 2022 13:42:37 +0000 (08:42 -0500)
committerPatrick Palka <ppalka@redhat.com>
Wed, 9 Mar 2022 13:42:37 +0000 (08:42 -0500)
commitec0f53a3a542e762f8fc8c22b9d345f922be5867
tree88d4edff9617692746c9a9347b6bfc2ae02bfc7e
parente32869a17b788bee9ca782b174a546b1db17b5ea
c++: non-constant non-dependent decltype folding [PR104823]

When processing a non-dependent decltype operand we want to instantiate
it even if it's non-constant, since non-dependent decltype is always
resolved ahead of time.  But currently finish_decltype_type uses
instantiate_non_dependent_expr, which instantiates only potentially
constant expressions, and this causes us to miss diagnosing the narrowing
conversion in S{id(v)} in the below testcase because we never instantiate
this non-constant non-dependent decltype operand.

In light of

  > On Mon, 7 Mar 2022, Jason Merrill wrote:
  >> On 3/7/22 14:41, Patrick Palka wrote:
  >>> instantiate_non_dependent_expr 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.

this patch drops the potentially-constant check in i_n_d_e and turns
its dependence check into a checking_assert, since most callers already
check that the argument is non-dependent; thus i_n_d_e now instantiates
even non-constant expressions and always returns non-templated trees.
This patch also relaxes the dependence check in i_n_d_e to use the
_uneval version (since that's what finish_decltype_type uses) and
strengthens the dependence checks used by other callers accordingly.

In cp_parser_parenthesized_expression_list_elt we were calling
instantiate_non_dependent_expr (when parsing an attribute list) without
first checking for non-dependence.  We could fix this by guarding the
call appropriately, but I noticed we also fold non-dependent attributes
later from cp_check_const_attribute, so this earlier folding is at best
redundant.  And it currently causes us to reject constexpr-attribute4.C
below due to the second folding seeing non-templated trees.  Thus the
right solution here seems to be to remove this unguarded call to i_n_d_e
so that we end up instantiating non-dependent attributes only once.

Finally, after calling i_n_d_e in finish_decltype_type 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

PR c++/104823

gcc/cp/ChangeLog:

* except.cc (build_noexcept_spec): Strengthen dependence check
to instantiation_dependent_expression_p.
* parser.cc (cp_parser_parenthesized_expression_list_elt):
Remove fold_expr_p parameter, and don't call
instantiate_non_dependent_expr.
(cp_parser_parenthesized_expression_list): Adjust accordingly.
* pt.cc (expand_integer_pack): Strengthen dependence check
to instantiation_dependent_expression_p.
(instantiate_non_dependent_expr_internal): Adjust comment.
(instantiate_non_dependent_expr_sfinae): Likewise.  Drop
the potentially-constant check, and relax and turn the
dependence check into a checking assert.
(instantiate_non_dependent_or_null): Adjust comment.
* semantics.cc (finish_decltype_type): Keep
processing_template_decl cleared after calling
instantiate_non_dependent_expr_sfinae.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/Wnarrowing19.C: New test.
gcc/cp/except.cc
gcc/cp/parser.cc
gcc/cp/pt.cc
gcc/cp/semantics.cc
gcc/testsuite/g++.dg/cpp0x/Wnarrowing19.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/constexpr-attribute4.C [new file with mode: 0644]