Bug 104823 - [12 Regression] narrowing conversion inside non-dependent decltype operand silently accepted ever since r12-6075
Summary: [12 Regression] narrowing conversion inside non-dependent decltype operand si...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 12.0
: P2 normal
Target Milestone: 12.0
Assignee: Patrick Palka
URL:
Keywords: accepts-invalid, diagnostic
Depends on:
Blocks:
 
Reported: 2022-03-07 15:45 UTC by Patrick Palka
Modified: 2022-03-09 13:58 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-03-07 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Patrick Palka 2022-03-07 15:45:18 UTC
struct S { S(int); };

int id(int v);
double id(double v);

template<class> auto f(double v) -> decltype(S{id(v)});


GCC 11 correctly issues a narrowing conversion warning for this testcase ever since r11-434:

<stdin>:6:50: warning: narrowing conversion of ‘id(v)’ from ‘double’ to ‘int’ [-Wnarrowing]

But in GCC 12 the warning is gone.
Comment 1 Marek Polacek 2022-03-07 16:11:52 UTC
Confirmed.
Comment 2 Patrick Palka 2022-03-07 17:36:06 UTC
r12-6075 is exposing a latent bug with non-dependent decltype folding, namely we instantiate the expression only if it's potentially constant.  In this case, id(v) is not potentially constant because id is not a constexpr function, so we discard the expression without actually instantiating it and therefore never issue the narrowing warning.
Comment 3 Martin Liška 2022-03-08 14:57:44 UTC
(In reply to Patrick Palka from comment #2)
> r12-6075

Patrick, can you please start using latest git gcc-descr version:
	gcc-descr = "!f() { \"`git rev-parse --show-toplevel`/contrib/git-descr.sh\" $@; } ; f"
	gcc-undescr = "!f() { \"`git rev-parse --show-toplevel`/contrib/git-undescr.sh\" $@; } ; f"

So that hashes are appended to revisions:

$ git gcc-descr 
r12-7534-g7cce7b1c3d8291

Thanks
Comment 4 GCC Commits 2022-03-09 13:44:23 UTC
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:ec0f53a3a542e762f8fc8c22b9d345f922be5867

commit r12-7564-gec0f53a3a542e762f8fc8c22b9d345f922be5867
Author: Patrick Palka <ppalka@redhat.com>
Date:   Wed Mar 9 08:42:37 2022 -0500

    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.
Comment 5 Patrick Palka 2022-03-09 13:58:17 UTC
Fixed.