From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 4756A3858C78 for ; Mon, 18 Sep 2023 13:33:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4756A3858C78 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1695043989; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pOjWB8yDZXC+i2mRj1mX/51YTJgC6iX4SSYsvHSj/WA=; b=PEcC9lqx8YThHKuFN+N7UhlUND7Bh2h/qri2sTogL1dsKp3+zTAtazfYPI9d61/Hnn+Fsp ShpOw528y6ni7oCUwqaWXW4NZHQq+hzLLOtsZy2l+TlhUjewcsXkpJkmtqEJGT1YILX39x CDLXlpKXtPj/NWuOQxrwwc9oFHKTux0= Received: from mail-oa1-f70.google.com (mail-oa1-f70.google.com [209.85.160.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-637-wq6KQ8qRMAKvWCNpmETIXQ-1; Mon, 18 Sep 2023 09:33:06 -0400 X-MC-Unique: wq6KQ8qRMAKvWCNpmETIXQ-1 Received: by mail-oa1-f70.google.com with SMTP id 586e51a60fabf-1d6cf10016cso2397599fac.1 for ; Mon, 18 Sep 2023 06:33:04 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695043984; x=1695648784; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=pOjWB8yDZXC+i2mRj1mX/51YTJgC6iX4SSYsvHSj/WA=; b=dZqj37TWVd/pKsh1AlVtuJOvaqP3Zu2FKU7iajh1HPyFu06ohB1CT7jMTwO03XxZSz NBMOFpBJNM+Yd7Wq0YZO0AdJUzPuTwwhD5UJXj26AXhH8Pyo807J+ECyZDEHCaYBYFTw W00M1ROmFFbyI8lxb0QLAnEI96q3SlRr3NaZmjN1KXcZabH04W+31Pe1byvipSK2V5xa t8SPptKSmZFqGAByzhkEZrk07QmM9fVQ7bwlc81HqLcTPo3YIwFxnEIv77s16eq9mH10 F/afVJd5whAb3k57M+C8TuYQYfn7+qLHS7wAWku/iM2yCU91DIB9SuQk0g/ubfFokaqz JSRQ== X-Gm-Message-State: AOJu0YwecFLyyrWUjYP+fE6oQgsqHiCoPdvp7hdLOT/tzdftdCoYgXpZ n3z6hcZd5u9JOwbKLSLZqp2gxoWmShsmOM6jay8EevNXTCO6jZ0KDL3n/hqFSiXVpExk6k02WAp SO9pIS7zz8K6oCrM= X-Received: by 2002:a05:6870:64a7:b0:1d5:a17e:f62 with SMTP id cz39-20020a05687064a700b001d5a17e0f62mr11898060oab.24.1695043983818; Mon, 18 Sep 2023 06:33:03 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFTPbnOFLj7fxZ2PAiPo2YbtNl0PezhlRasplT4OAE+WjGwXex6/Hx9jk3f7DSNzXxWfmji9w== X-Received: by 2002:a05:6870:64a7:b0:1d5:a17e:f62 with SMTP id cz39-20020a05687064a700b001d5a17e0f62mr11898025oab.24.1695043983306; Mon, 18 Sep 2023 06:33:03 -0700 (PDT) Received: from [192.168.1.108] (130-44-146-16.s12558.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.146.16]) by smtp.gmail.com with ESMTPSA id u20-20020a0cdd14000000b006581e82a628sm893900qvk.134.2023.09.18.06.33.00 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 18 Sep 2023 06:33:01 -0700 (PDT) Message-ID: <07e75ee3-6917-b499-cc66-518398fd79c7@redhat.com> Date: Mon, 18 Sep 2023 09:33:00 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.15.1 Subject: Re: [PATCH] c++: non-dependent assignment checking [PR63198, PR18474] To: Patrick Palka Cc: gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org References: <20230917185140.1333132-1-ppalka@redhat.com> <13272bff-9f95-4dfd-d724-ff67cc568532@redhat.com> From: Jason Merrill In-Reply-To: X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 9/18/23 09:12, Patrick Palka wrote: > On Sun, 17 Sep 2023, Jason Merrill wrote: > >> On 9/17/23 14:51, Patrick Palka wrote: >>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for >>> trunk? Patch generatde with -w to avoid noisy whitespace changes. >>> >>> -- >8 -- >>> >>> This patch makes us recognize and check non-dependent simple assigments >>> ahead of time, like we already do for compound assignments. This means >>> the templated representation of such assignments will now usually have >>> an implicit INDIRECT_REF (due to the reference return type), which the >>> -Wparentheses code needs to handle. As a drive-by improvement, this >>> patch also makes maybe_convert_cond issue -Wparentheses warnings ahead >>> of time. >>> >>> This revealed some libstdc++ tests were attempting to modify a data >>> member from a uninstantiated const member function; naively fixed by >>> making the data member mutable. >>> >>> PR c++/63198 >>> PR c++/18474 >>> >>> gcc/cp/ChangeLog: >>> >>> * semantics.cc (maybe_convert_cond): Look through implicit >>> INDIRECT_REF when deciding whether to issue a -Wparentheses >>> warning, and consider templated assignment expressions as well. >>> (finish_parenthesized_expr): Look through implicit INDIRECT_REF >>> when suppressing -Wparentheses warning. >>> * typeck.cc (build_x_modify_expr): Check simple assignments >>> ahead time too, not just compound assignments. Give the second >>> operand of MODOP_EXPR a non-null type so that it's not considered >>> always instantiation-dependent. >>> >>> gcc/testsuite/ChangeLog: >>> >>> * g++.dg/cpp0x/static_assert15.C: Expect diagnostic for >>> non-constant static_assert condition. >>> * g++.dg/expr/unary2.C: Remove xfails. >>> * g++.dg/template/init7.C: Make initializer type-dependent to >>> preserve intent of test. >>> * g++.dg/template/recurse3.C: Likewise for the erroneous >>> statement. >>> * g++.dg/template/non-dependent26.C: New test. >>> * g++.dg/warn/Wparentheses-32.C: New test. >>> >>> libstdc++/ChangeLog: >>> >>> * testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc: >>> Make seed_seq::called member mutable. >>> * >>> testsuite/26_numerics/random/independent_bits_engine/cons/seed_seq2.cc: >>> Likewise. >>> * >>> testsuite/26_numerics/random/linear_congruential_engine/cons/seed_seq2.cc >>> Likewise. >>> * >>> testsuite/26_numerics/random/mersenne_twister_engine/cons/seed_seq2.cc: >>> Likewise. >>> * testsuite/26_numerics/random/shuffle_order_engine/cons/seed_seq2.cc: >>> Likewise. >>> * >>> testsuite/26_numerics/random/subtract_with_carry_engine/cons/seed_seq2.cc: >>> Likewise. >>> * >>> testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/seed_seq2.cc >>> Likewise. >>> --- >>> gcc/cp/semantics.cc | 17 +++++++---- >>> gcc/cp/typeck.cc | 23 +++++++-------- >>> gcc/testsuite/g++.dg/cpp0x/static_assert15.C | 2 +- >>> gcc/testsuite/g++.dg/expr/unary2.C | 8 ++---- >>> gcc/testsuite/g++.dg/template/init7.C | 2 +- >>> .../g++.dg/template/non-dependent26.C | 25 +++++++++++++++++ >>> gcc/testsuite/g++.dg/template/recurse3.C | 8 +++--- >>> gcc/testsuite/g++.dg/warn/Wparentheses-32.C | 28 +++++++++++++++++++ >>> .../discard_block_engine/cons/seed_seq2.cc | 2 +- >>> .../independent_bits_engine/cons/seed_seq2.cc | 2 +- >>> .../cons/seed_seq2.cc | 2 +- >>> .../mersenne_twister_engine/cons/seed_seq2.cc | 2 +- >>> .../shuffle_order_engine/cons/seed_seq2.cc | 2 +- >>> .../cons/seed_seq2.cc | 2 +- >>> .../cons/seed_seq2.cc | 2 +- >>> 15 files changed, 91 insertions(+), 36 deletions(-) >>> create mode 100644 gcc/testsuite/g++.dg/template/non-dependent26.C >>> create mode 100644 gcc/testsuite/g++.dg/warn/Wparentheses-32.C >>> >>> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc >>> index 0f7f4e87ae4..b57c1ac868b 100644 >>> --- a/gcc/cp/semantics.cc >>> +++ b/gcc/cp/semantics.cc >>> diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc >>> index 459739d5866..74f5fced060 100644 >>> --- a/gcc/cp/typeck.cc >>> +++ b/gcc/cp/typeck.cc >>> @@ -9739,15 +9739,15 @@ build_x_modify_expr (location_t loc, tree lhs, enum >>> tree_code modifycode, >>> rhs = build_non_dependent_expr (rhs); >>> } >>> - if (modifycode != NOP_EXPR) >>> - { >>> - tree op = build_nt (modifycode, NULL_TREE, NULL_TREE); >>> - tree rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL, >>> + tree rval; >>> + if (modifycode == NOP_EXPR) >>> + rval = cp_build_modify_expr (loc, lhs, modifycode, rhs, complain); >>> + else >>> + rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL, >>> lhs, rhs, op, lookups, &overload, complain); >>> - if (rval) >>> - { >>> if (rval == error_mark_node) >>> - return rval; >>> + return error_mark_node; >>> + if (modifycode != NOP_EXPR) >>> suppress_warning (rval /* What warning? */); >> >> Did you try disabling this to see if it's still needed? > > Looks like it's not needed as far as bootstrap + regtest is concerned. > FWIW this line originally was added in > https://gcc.gnu.org/pipermail/gcc-patches/2004-July/144621.html > to suppress -Wparentheses warnings for non-templated compound assignment > operator expressions. > > Here's a patch that also gets rid of that suppress_warning call: OK. > -- >8 -- > > Subject: [PATCH] c++: non-dependent assignment checking [PR63198, PR18474] > > PR c++/63198 > PR c++/18474 > > gcc/cp/ChangeLog: > > * semantics.cc (maybe_convert_cond): Look through implicit > INDIRECT_REF when deciding whether to issue a -Wparentheses > warning, and consider templated assignment expressions as well. > (finish_parenthesized_expr): Look through implicit INDIRECT_REF > when suppressing -Wparentheses warning. > * typeck.cc (build_x_modify_expr): Check simple assignments > ahead time too, not just compound assignments. Give the second > operand of MODOP_EXPR a non-null type so that it's not considered > always instantiation-dependent. Don't call suppress_warning. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp0x/static_assert15.C: Expect diagnostic for > non-constant static_assert condition. > * g++.dg/expr/unary2.C: Remove xfails. > * g++.dg/template/init7.C: Make initializer type-dependent to > preserve intent of test. > * g++.dg/template/recurse3.C: Likewise for the erroneous > statement. > * g++.dg/template/non-dependent26.C: New test. > * g++.dg/warn/Wparentheses-32.C: New test. > > libstdc++/ChangeLog: > > * testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc: > Make data member seed_seq::called mutable. > * testsuite/26_numerics/random/independent_bits_engine/cons/seed_seq2.cc: > Likewise. > * testsuite/26_numerics/random/linear_congruential_engine/cons/seed_seq2.cc > Likewise. > * testsuite/26_numerics/random/mersenne_twister_engine/cons/seed_seq2.cc: > Likewise. > * testsuite/26_numerics/random/shuffle_order_engine/cons/seed_seq2.cc: > Likewise. > * testsuite/26_numerics/random/subtract_with_carry_engine/cons/seed_seq2.cc: > Likewise. > * testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/seed_seq2.cc > Likewise. > --- > gcc/cp/semantics.cc | 19 ++++++--- > gcc/cp/typeck.cc | 41 ++++++++----------- > gcc/testsuite/g++.dg/cpp0x/static_assert15.C | 2 +- > gcc/testsuite/g++.dg/expr/unary2.C | 8 ++-- > gcc/testsuite/g++.dg/template/init7.C | 2 +- > .../g++.dg/template/non-dependent26.C | 25 +++++++++++ > gcc/testsuite/g++.dg/template/recurse3.C | 8 ++-- > gcc/testsuite/g++.dg/warn/Wparentheses-32.C | 28 +++++++++++++ > .../discard_block_engine/cons/seed_seq2.cc | 2 +- > .../independent_bits_engine/cons/seed_seq2.cc | 2 +- > .../cons/seed_seq2.cc | 2 +- > .../mersenne_twister_engine/cons/seed_seq2.cc | 2 +- > .../shuffle_order_engine/cons/seed_seq2.cc | 2 +- > .../cons/seed_seq2.cc | 2 +- > .../cons/seed_seq2.cc | 2 +- > 15 files changed, 100 insertions(+), 47 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/template/non-dependent26.C > create mode 100644 gcc/testsuite/g++.dg/warn/Wparentheses-32.C > > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc > index 0f7f4e87ae4..4109ac33654 100644 > --- a/gcc/cp/semantics.cc > +++ b/gcc/cp/semantics.cc > @@ -881,13 +881,17 @@ maybe_convert_cond (tree cond) > /* Do the conversion. */ > cond = convert_from_reference (cond); > > - if ((TREE_CODE (cond) == MODIFY_EXPR || is_assignment_op_expr_p (cond)) > + tree inner = REFERENCE_REF_P (cond) ? TREE_OPERAND (cond, 0) : cond; > + if ((TREE_CODE (inner) == MODIFY_EXPR > + || (TREE_CODE (inner) == MODOP_EXPR > + && TREE_CODE (TREE_OPERAND (inner, 1)) == NOP_EXPR) > + || is_assignment_op_expr_p (inner)) > && warn_parentheses > - && !warning_suppressed_p (cond, OPT_Wparentheses) > - && warning_at (cp_expr_loc_or_input_loc (cond), > + && !warning_suppressed_p (inner, OPT_Wparentheses) > + && warning_at (cp_expr_loc_or_input_loc (inner), > OPT_Wparentheses, "suggest parentheses around " > "assignment used as truth value")) > - suppress_warning (cond, OPT_Wparentheses); > + suppress_warning (inner, OPT_Wparentheses); > > return condition_conversion (cond); > } > @@ -2155,8 +2159,11 @@ cp_expr > finish_parenthesized_expr (cp_expr expr) > { > if (EXPR_P (expr)) > - /* This inhibits warnings in c_common_truthvalue_conversion. */ > - suppress_warning (expr, OPT_Wparentheses); > + { > + /* This inhibits warnings in c_common_truthvalue_conversion. */ > + tree inner = REFERENCE_REF_P (expr) ? TREE_OPERAND (expr, 0) : *expr; > + suppress_warning (inner, OPT_Wparentheses); > + } > > if (TREE_CODE (expr) == OFFSET_REF > || TREE_CODE (expr) == SCOPE_REF) > diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc > index 459739d5866..8132bd7fccc 100644 > --- a/gcc/cp/typeck.cc > +++ b/gcc/cp/typeck.cc > @@ -9721,13 +9721,13 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, > if (lhs == error_mark_node || rhs == error_mark_node) > return cp_expr (error_mark_node, loc); > > + tree op = build_min (modifycode, void_type_node, NULL_TREE, NULL_TREE); > + > if (processing_template_decl) > { > - if (modifycode == NOP_EXPR > - || type_dependent_expression_p (lhs) > + if (type_dependent_expression_p (lhs) > || type_dependent_expression_p (rhs)) > { > - tree op = build_min_nt_loc (loc, modifycode, NULL_TREE, NULL_TREE); > tree rval = build_min_nt_loc (loc, MODOP_EXPR, lhs, op, rhs); > if (modifycode != NOP_EXPR) > TREE_TYPE (rval) > @@ -9739,29 +9739,24 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, > rhs = build_non_dependent_expr (rhs); > } > > - if (modifycode != NOP_EXPR) > + tree rval; > + if (modifycode == NOP_EXPR) > + rval = cp_build_modify_expr (loc, lhs, modifycode, rhs, complain); > + else > + rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL, > + lhs, rhs, op, lookups, &overload, complain); > + if (rval == error_mark_node) > + return error_mark_node; > + if (processing_template_decl) > { > - tree op = build_nt (modifycode, NULL_TREE, NULL_TREE); > - tree rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL, > - lhs, rhs, op, lookups, &overload, complain); > - if (rval) > - { > - if (rval == error_mark_node) > - return rval; > - suppress_warning (rval /* What warning? */); > - if (processing_template_decl) > - { > - if (overload != NULL_TREE) > - return (build_min_non_dep_op_overload > - (MODIFY_EXPR, rval, overload, orig_lhs, orig_rhs)); > + if (overload != NULL_TREE) > + return (build_min_non_dep_op_overload > + (MODIFY_EXPR, rval, overload, orig_lhs, orig_rhs)); > > - return (build_min_non_dep > - (MODOP_EXPR, rval, orig_lhs, op, orig_rhs)); > - } > - return rval; > - } > + return (build_min_non_dep > + (MODOP_EXPR, rval, orig_lhs, op, orig_rhs)); > } > - return cp_build_modify_expr (loc, lhs, modifycode, rhs, complain); > + return rval; > } > > /* Helper function for get_delta_difference which assumes FROM is a base > diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert15.C b/gcc/testsuite/g++.dg/cpp0x/static_assert15.C > index a740f73fd4a..d5f50d07c91 100644 > --- a/gcc/testsuite/g++.dg/cpp0x/static_assert15.C > +++ b/gcc/testsuite/g++.dg/cpp0x/static_assert15.C > @@ -5,6 +5,6 @@ template > struct a { > constexpr void b() { > int c; > - static_assert(c %= 1, ""); > + static_assert(c %= 1, ""); // { dg-error "constant" } > } > }; > diff --git a/gcc/testsuite/g++.dg/expr/unary2.C b/gcc/testsuite/g++.dg/expr/unary2.C > index 5962bfe19c9..4db68375944 100644 > --- a/gcc/testsuite/g++.dg/expr/unary2.C > +++ b/gcc/testsuite/g++.dg/expr/unary2.C > @@ -1,9 +1,7 @@ > +// PR c++/18474 > // { dg-do compile } > // Unary plus/minus are not lvalues. > > -// In templates we require an instantiation to emit the diagnostic. This > -// is wrong and it is PR 18474. > - > int n; > > void f(void) > @@ -15,6 +13,6 @@ void f(void) > template > void g(void) > { > - -n = 0; // { dg-error "lvalue" "" { xfail *-*-* } } > - +n = 0; // { dg-error "lvalue" "" { xfail *-*-* } } > + -n = 0; // { dg-error "lvalue" "" } > + +n = 0; // { dg-error "lvalue" "" } > } > diff --git a/gcc/testsuite/g++.dg/template/init7.C b/gcc/testsuite/g++.dg/template/init7.C > index bb26c8f92b5..94fc22f578c 100644 > --- a/gcc/testsuite/g++.dg/template/init7.C > +++ b/gcc/testsuite/g++.dg/template/init7.C > @@ -6,4 +6,4 @@ template struct A > static const int i=0; > }; > > -template const int A::i = 0=0; /* { dg-error "duplicate initialization" } */ > +template const int A::i = T()=0; /* { dg-error "duplicate initialization" } */ > diff --git a/gcc/testsuite/g++.dg/template/non-dependent26.C b/gcc/testsuite/g++.dg/template/non-dependent26.C > new file mode 100644 > index 00000000000..1faa39a4b1a > --- /dev/null > +++ b/gcc/testsuite/g++.dg/template/non-dependent26.C > @@ -0,0 +1,25 @@ > +// Verify non-dependent assignment expressions are recognized as such > +// and are checked ahead of time. > +// PR c++/63198 > +// { dg-do compile { target c++11 } } > + > +struct X { using t1 = int; }; > +struct Y { X operator=(const Y&); } y; > +template void f1(decltype(y = y)::t1); > + > +int n; > +template void f2(decltype(n = n)::t1); // { dg-error "not a class" } > +template void f3(decltype(n += n)::t1); // { dg-error "not a class" } > + > +template > +void g() { > + const int n; > + n = 42; // { dg-error "read-only" } > + > + const X x; > + x = {}; // { dg-error "no match" } > + > + const Y y; > + y = {}; // { dg-error "no match" } > + Y{} = X{}; // { dg-error "no match" } > +} > diff --git a/gcc/testsuite/g++.dg/template/recurse3.C b/gcc/testsuite/g++.dg/template/recurse3.C > index f1db7c5cbca..70c6152d063 100644 > --- a/gcc/testsuite/g++.dg/template/recurse3.C > +++ b/gcc/testsuite/g++.dg/template/recurse3.C > @@ -1,14 +1,14 @@ > // PR c++/44609 > // { dg-options -ftemplate-depth=10 } > > -template > +template > void f() > { > - 0 = 0; // { dg-error "lvalue required" } > - f(); // { dg-bogus "instantiation depth" } > + T(0) = 0; // { dg-error "lvalue required" } > + f(); // { dg-bogus "instantiation depth" } > } > > int main() > { > - f<0>(); > + f(); > } > diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-32.C b/gcc/testsuite/g++.dg/warn/Wparentheses-32.C > new file mode 100644 > index 00000000000..719a9d9e73a > --- /dev/null > +++ b/gcc/testsuite/g++.dg/warn/Wparentheses-32.C > @@ -0,0 +1,28 @@ > +// Verify we issue -Wparentheses warnings at template definition time > +// (for suitable non-dependent expressions). > +// { dg-additional-options "-Wparentheses" } > + > +struct X { operator bool(); }; > +struct Y { Y& operator=(const Y&); operator bool(); }; > +struct Z { int m; operator bool(); }; > + > +template > +void f() { > + int n, m; > + if (n = m) { } // { dg-warning "parentheses" } > + > + X x1, x2; > + if (x1 = x2) { } // { dg-warning "parentheses" } > + > + Y y1, y2; > + if (y1 = y2) { } // { dg-warning "parentheses" } > + > + Z z1, z2; > + if (z1 = z2) { } // { dg-warning "parentheses" } > + > + bool b; > + b = m = n; // { dg-warning "parentheses" "" { xfail *-*-* } } > + b = x1 = x2; // { dg-warning "parentheses" "" { xfail *-*-* } } > + b = y1 = y2; // { dg-warning "parentheses" "" { xfail *-*-* } } > + b = z1 = z2; // { dg-warning "parentheses" "" { xfail *-*-* } } > +} > diff --git a/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc > index 720ce96dc28..0d7e667382d 100644 > --- a/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc > +++ b/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc > @@ -51,7 +51,7 @@ struct seed_seq > // T is convertible to the engine's result_type: > operator T() const noexcept { return T(); } > > - bool called = false; > + mutable bool called = false; > }; > > using engine_type > diff --git a/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/cons/seed_seq2.cc > index f378621805f..2ef563038cc 100644 > --- a/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/cons/seed_seq2.cc > +++ b/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/cons/seed_seq2.cc > @@ -51,7 +51,7 @@ struct seed_seq > // T is convertible to the engine's result_type: > operator T() const noexcept { return T(); } > > - bool called = false; > + mutable bool called = false; > }; > > using engine_type > diff --git a/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/cons/seed_seq2.cc > index c1cfe9da7fb..071ed75d8d8 100644 > --- a/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/cons/seed_seq2.cc > +++ b/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/cons/seed_seq2.cc > @@ -51,7 +51,7 @@ struct seed_seq > // T is convertible to the engine's result_type: > operator T() const noexcept { return T(); } > > - bool called = false; > + mutable bool called = false; > }; > > using engine_type > diff --git a/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/cons/seed_seq2.cc > index 52476026533..2fb9622fda0 100644 > --- a/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/cons/seed_seq2.cc > +++ b/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/cons/seed_seq2.cc > @@ -51,7 +51,7 @@ struct seed_seq > // T is convertible to the engine's result_type: > operator T() const noexcept { return T(); } > > - bool called = false; > + mutable bool called = false; > }; > > using engine_type > diff --git a/libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/cons/seed_seq2.cc > index 1ca783e3044..3fa9c9ad8d3 100644 > --- a/libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/cons/seed_seq2.cc > +++ b/libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/cons/seed_seq2.cc > @@ -51,7 +51,7 @@ struct seed_seq > // T is convertible to the engine's result_type: > operator T() const noexcept { return T(); } > > - bool called = false; > + mutable bool called = false; > }; > > using engine_type > diff --git a/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/cons/seed_seq2.cc > index 08beb3bcf93..25d19a0ba66 100644 > --- a/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/cons/seed_seq2.cc > +++ b/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/cons/seed_seq2.cc > @@ -51,7 +51,7 @@ struct seed_seq > // T is convertible to the engine's result_type: > operator T() const noexcept { return T(); } > > - bool called = false; > + mutable bool called = false; > }; > > using engine_type > diff --git a/libstdc++-v3/testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/seed_seq2.cc > index b629053585e..fe798f2f05b 100644 > --- a/libstdc++-v3/testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/seed_seq2.cc > +++ b/libstdc++-v3/testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/seed_seq2.cc > @@ -52,7 +52,7 @@ struct seed_seq > // T is convertible to the engine's result_type: > operator T() const noexcept { return T(); } > > - bool called = false; > + mutable bool called = false; > }; > > using engine_type