From patchwork Thu Aug 4 20:56:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Fran=C3=A7ois_Dumont?= X-Patchwork-Id: 56549 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7867F3856262 for ; Thu, 4 Aug 2022 20:56:36 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7867F3856262 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1659646596; bh=I+cBlC0LjMSebc5s6BtQ3DZ7fGuNm+blSQjawL2WDrw=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=NtYUwl9MB+F2W8YjPFjW/CLNgO6FyCbA+Kq9LKx3Y0fFxnFOSUwiDpq8D1O6xHtLM fUo3GGaNHd8A+VJ8FJI2HkWUbU9yNRTNMOaw4+X4M9EaVHeBNQ1ZF1ETlx6KQBJ1bM UyIwr5XWsoNxsTxZjKceabIkSDQr0NoPEmahZMfk= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by sourceware.org (Postfix) with ESMTPS id 40FA13858407; Thu, 4 Aug 2022 20:56:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 40FA13858407 Received: by mail-wr1-x436.google.com with SMTP id l22so1103116wrz.7; Thu, 04 Aug 2022 13:56:05 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=subject:from:cc:to:content-language:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc; bh=I+cBlC0LjMSebc5s6BtQ3DZ7fGuNm+blSQjawL2WDrw=; b=7PxzAPjSmcGuzpaIG6n4V4AHWuj/e4GVTjcaXjfOX+g/Nax5UnH6W85nu/fsJKOKpL 96ZYeZsP4a2Sula2W3C0Yxm27zU9jF0jWLUzY3YfXvSt+3K6o0ekkLtxOjQMSo0MAM5l znN20dBOfdC0GTYfd0K5tl3Rb0CzwOyt+7zZOqzhgeYJHueIW/87QPQ29Dfg7oRj6qQg xrtd/hkWy/CpsrhwfaJqHP36mKIzpCX+OXoCSTC6ZcOGR7kBbsfpG1Xh2qWwGEfZK6PO kMLOuH3Fo8aHfvsPVrOTEDTf7qZ5DluL36+bJUVvn+QnID9luA3T18ClLzvhpBEJdP15 FPfA== X-Gm-Message-State: ACgBeo3r3UkQo7kAP4remAbsCu2xQShHTox+sjNqw53hd+J5cEASJ1tn h14MqtzaYdCV0iPhrDsz7zUew51erPI= X-Google-Smtp-Source: AA6agR639SNbiO0ASKTfHaFFQmlPrgWEI2cQapZEGzrHwf33/Kh+IDLFfQuRCLhUMgqmq5bD3JiVMw== X-Received: by 2002:adf:d1e8:0:b0:21d:ddc1:3701 with SMTP id g8-20020adfd1e8000000b0021dddc13701mr2414140wrd.153.1659646563795; Thu, 04 Aug 2022 13:56:03 -0700 (PDT) Received: from ?IPV6:2a01:e0a:1dc:b1c0:58e1:6932:2415:706b? ([2a01:e0a:1dc:b1c0:58e1:6932:2415:706b]) by smtp.googlemail.com with ESMTPSA id b17-20020a05600010d100b002206b4df832sm2022600wrx.110.2022.08.04.13.56.02 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 04 Aug 2022 13:56:03 -0700 (PDT) Message-ID: <3b6d1c3d-8bc7-e5e5-0a76-58d960f86e3f@gmail.com> Date: Thu, 4 Aug 2022 22:56:02 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.11.0 Content-Language: en-US To: "libstdc++@gcc.gnu.org" Subject: [PATCH][_GLIBCXX_DEBUG] Refine singular iterator state X-Spam-Status: No, score=-8.8 required=5.0 tests=BAYES_00, BODY_8BITS, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: =?utf-8?q?Fran=C3=A7ois_Dumont_via_Gcc-patches?= From: =?utf-8?q?Fran=C3=A7ois_Dumont?= Reply-To: =?utf-8?q?Fran=C3=A7ois_Dumont?= Cc: gcc-patches Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This an old patch I had prepared a long time ago, I don't think I ever submitted it.     libstdc++: [_GLIBCXX_DEBUG] Do not consider detached iterators as value-initialized     An attach iterator has its _M_version set to something != 0. This value shall be preserved     when detaching it so that the iterator does not look like a value initialized one.     libstdc++-v3/ChangeLog:             * include/debug/formatter.h (__singular_value_init): New _Iterator_state enum entry.             (_Parameter<>(const _Safe_iterator<>&, const char*, _Is_iterator)): Check if iterator             parameter is value-initialized.             (_Parameter<>(const _Safe_local_iterator<>&, const char*, _Is_iterator)): Likewise.             * include/debug/safe_iterator.h (_Safe_iterator<>::_M_value_initialized()): New. Adapt             checks.             * include/debug/safe_local_iterator.h (_Safe_local_iterator<>::_M_value_initialized()): New.             Adapt checks.             * src/c++11/debug.cc (_Safe_iterator_base::_M_reset): Do not reset _M_version.             (print_field(PrintContext&, const _Parameter&, const char*)): Adapt state_names.             * testsuite/23_containers/deque/debug/iterator1_neg.cc: New test.             * testsuite/23_containers/deque/debug/iterator2_neg.cc: New test.             * testsuite/23_containers/forward_list/debug/iterator1_neg.cc: New test.             * testsuite/23_containers/forward_list/debug/iterator2_neg.cc: New test. Tested under Linux x86_64 _GLIBCXX_DEBUG mode. Ok to commit ? François diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h index 80e8ba46d1e..748d4fbfea4 100644 --- a/libstdc++-v3/include/debug/formatter.h +++ b/libstdc++-v3/include/debug/formatter.h @@ -185,6 +185,7 @@ namespace __gnu_debug __rbegin, // dereferenceable, and at the reverse-beginning __rmiddle, // reverse-dereferenceable, not at the reverse-beginning __rend, // reverse-past-the-end + __singular_value_init, // singular, value initialized __last_state }; @@ -280,7 +281,12 @@ namespace __gnu_debug _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); if (__it._M_singular()) - _M_variant._M_iterator._M_state = __singular; + { + if (__it._M_value_initialized()) + _M_variant._M_iterator._M_state = __singular_value_init; + else + _M_variant._M_iterator._M_state = __singular; + } else { if (__it._M_is_before_begin()) @@ -308,7 +314,12 @@ namespace __gnu_debug _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); if (__it._M_singular()) - _M_variant._M_iterator._M_state = __singular; + { + if (__it._M_value_initialized()) + _M_variant._M_iterator._M_state = __singular_value_init; + else + _M_variant._M_iterator._M_state = __singular; + } else { if (__it._M_is_end()) diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h index d613933e236..33f7a86478a 100644 --- a/libstdc++-v3/include/debug/safe_iterator.h +++ b/libstdc++-v3/include/debug/safe_iterator.h @@ -41,8 +41,8 @@ #define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, _BadMsgId, _DiffMsgId) \ _GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular() \ - || (_Lhs.base() == _Iterator() \ - && _Rhs.base() == _Iterator()), \ + || (_Lhs._M_value_initialized() \ + && _Rhs._M_value_initialized()), \ _M_message(_BadMsgId) \ ._M_iterator(_Lhs, #_Lhs) \ ._M_iterator(_Rhs, #_Rhs)); \ @@ -177,7 +177,7 @@ namespace __gnu_debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x.base() == _Iterator(), + || __x._M_value_initialized(), _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); @@ -193,7 +193,7 @@ namespace __gnu_debug : _Iter_base() { _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x.base() == _Iterator(), + || __x._M_value_initialized(), _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); @@ -220,7 +220,7 @@ namespace __gnu_debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x.base() == _MutableIterator(), + || __x._M_value_initialized(), _M_message(__msg_init_const_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); @@ -236,7 +236,7 @@ namespace __gnu_debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x.base() == _Iterator(), + || __x._M_value_initialized(), _M_message(__msg_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); @@ -266,7 +266,7 @@ namespace __gnu_debug operator=(_Safe_iterator&& __x) noexcept { _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x.base() == _Iterator(), + || __x._M_value_initialized(), _M_message(__msg_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); @@ -405,6 +405,11 @@ namespace __gnu_debug _M_incrementable() const { return !this->_M_singular() && !_M_is_end(); } + /// Is the iterator value-initialized? + bool + _M_value_initialized() const + { return _M_version == 0 && base() == _Iter_base(); } + // Can we advance the iterator @p __n steps (@p __n may be negative) bool _M_can_advance(difference_type __n, bool __strict = false) const; diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h index b5318f50b6a..6e3c4eb1505 100644 --- a/libstdc++-v3/include/debug/safe_local_iterator.h +++ b/libstdc++-v3/include/debug/safe_local_iterator.h @@ -33,8 +33,8 @@ #define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs) \ _GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular() \ - || (_Lhs.base() == _Iterator{} \ - && _Rhs.base() == _Iterator{}), \ + || (_Lhs._M_value_initialized() \ + && _Rhs._M_value_initialized()), \ _M_message(__msg_iter_compare_bad) \ ._M_iterator(_Lhs, "lhs") \ ._M_iterator(_Rhs, "rhs")); \ @@ -127,7 +127,7 @@ namespace __gnu_debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x.base() == _Iterator(), + || __x._M_value_initialized(), _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); @@ -142,7 +142,7 @@ namespace __gnu_debug : _Iter_base() { _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x.base() == _Iterator(), + || __x._M_value_initialized(), _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); @@ -167,7 +167,7 @@ namespace __gnu_debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x.base() == _MutableIterator(), + || __x._M_value_initialized(), _M_message(__msg_init_const_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); @@ -183,7 +183,7 @@ namespace __gnu_debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x.base() == _Iterator(), + || __x._M_value_initialized(), _M_message(__msg_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); @@ -212,7 +212,7 @@ namespace __gnu_debug operator=(_Safe_local_iterator&& __x) noexcept { _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x.base() == _Iterator(), + || __x._M_value_initialized(), _M_message(__msg_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); @@ -343,6 +343,11 @@ namespace __gnu_debug _M_incrementable() const { return !this->_M_singular() && !_M_is_end(); } + /// Is the iterator value-initialized? + bool + _M_value_initialized() const + { return _M_version == 0 && base() == _Iter_base{}; } + // Is the iterator range [*this, __rhs) valid? bool _M_valid_range(const _Safe_local_iterator& __rhs, diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc index 4706defedf1..cf8e6f48081 100644 --- a/libstdc++-v3/src/c++11/debug.cc +++ b/libstdc++-v3/src/c++11/debug.cc @@ -426,7 +426,8 @@ namespace __gnu_debug _M_reset() throw () { __atomic_store_n(&_M_sequence, (_Safe_sequence_base*)0, __ATOMIC_RELEASE); - _M_version = 0; + // Detach iterator shall not look like a value-initialized one. + // _M_version = 0; _M_prior = 0; _M_next = 0; } @@ -767,7 +768,8 @@ namespace "before-begin", "dereferenceable (start-of-reverse-sequence)", "dereferenceable (reverse)", - "past-the-reverse-end" + "past-the-reverse-end", + "singular (value-initialized)" }; print_word(ctx, state_names[iterator._M_state]); } diff --git a/libstdc++-v3/testsuite/23_containers/deque/debug/iterator1_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/debug/iterator1_neg.cc new file mode 100644 index 00000000000..097a035c461 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/debug/iterator1_neg.cc @@ -0,0 +1,39 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . +// +// { dg-do run { xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include + +#include + +void test01() +{ + typedef typename std::deque::iterator It; + std::deque dq; + dq.push_back(1); + + It it = It(); + VERIFY( dq.begin() != it ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/deque/debug/iterator2_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/debug/iterator2_neg.cc new file mode 100644 index 00000000000..097b5ba15cb --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/debug/iterator2_neg.cc @@ -0,0 +1,42 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . +// +// { dg-do run { xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include + +#include + +void test01() +{ + typedef typename std::deque::iterator It; + It it; + { + std::deque dq; + it = dq.begin(); + } + + It value_init_it = It(); + VERIFY( it != value_init_it ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/iterator1_neg.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/iterator1_neg.cc new file mode 100644 index 00000000000..5472b0ed231 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/iterator1_neg.cc @@ -0,0 +1,39 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . +// +// { dg-do run { xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include + +#include + +void test01() +{ + typedef typename std::forward_list::iterator It; + std::forward_list fl; + fl.push_front(1); + + It it = It(); + VERIFY( fl.begin() != it ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/iterator2_neg.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/iterator2_neg.cc new file mode 100644 index 00000000000..74278eb8cc8 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/iterator2_neg.cc @@ -0,0 +1,42 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . +// +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include + +#include + +void test01() +{ + typedef typename std::forward_list::iterator It; + It it; + { + std::forward_list fl; + it = fl.begin(); + } + + It value_init_it{}; + VERIFY( it != value_init_it ); +} + +int main() +{ + test01(); + return 0; +}