From patchwork Fri Sep 13 00:01:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Pluzhnikov X-Patchwork-Id: 274622 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id E2B222C039B for ; Fri, 13 Sep 2013 10:02:13 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:from:date:message-id :subject:to:cc:content-type; q=dns; s=default; b=ytfbz28MxtZQP7M Dbj17M2fyY+N/n2/kT71A6kA6mknx0kbqCWDDLUI7t3Mc7f7MM0W4pl/LeWJH2sC HbndDuHQj13yFl3WUReCcqLdxlBn1Hqj+RYzHagKhCESXPYGv+Xal5Fzd5YJABfo SCX9PvFIxdNWuRRilSS05AwMQdfQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:from:date:message-id :subject:to:cc:content-type; s=default; bh=JVsT17kNlH8ckTYf2tAex AI/FS8=; b=ebtAh0mZcEF/bsnz3uUgUk4eRxWONn0ew99FSBmMPWh2Ot5NWIZR9 R5SuxOBjzkfvQAH9YcAgzIOE75OzE1MNvKOcD/OCHNadLSF7MutVkzLgo4PjBdfG B/hpY0N0Sfin5+HdLf1xDreI7qYm974t816tntUscSI/3LksLLygms= Received: (qmail 27792 invoked by alias); 13 Sep 2013 00:02:06 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 27775 invoked by uid 89); 13 Sep 2013 00:02:05 -0000 Received: from mail-ie0-f169.google.com (HELO mail-ie0-f169.google.com) (209.85.223.169) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 13 Sep 2013 00:02:05 +0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.7 required=5.0 tests=AWL, BAYES_00, KHOP_THREADED, NO_RELAYS autolearn=ham version=3.3.2 X-HELO: mail-ie0-f169.google.com Received: by mail-ie0-f169.google.com with SMTP id tp5so1144264ieb.14 for ; Thu, 12 Sep 2013 17:02:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc:content-type; bh=LzDNfzSKRPIN51wramkmzPfPUoJFplkztNMg++BGybA=; b=bOVDFl561p1bu70iYCI7BUq4+6DKmofkOJYiRMWgBEh++R62Xp3ZV5/YjZVeYjVjG7 tLG7WFX7icAUHNqpra8G2yPTIp1qpZVt8nM68e9m+1/WArproFA0/6NS95LEBSo0JKKN gLCIdxN3ieJlX3be5D278u0lPsu7zHK+OxXXffv7Pgt16EIJQJ4PoUkQVbZSonviwNdn 6YFGFbvhX7lOXzIgj51DX1YtIwNSb8SfD8wu3tFA1sdxi5Dch1igkEqQ4IRcelvvovN5 Jvda5pQ8SjCs6aym4lgMrVGQLt8iIjlet5dxS0WiMi9GSa9IUWcaIr8HVqVRkqcD1fFU hgkA== X-Gm-Message-State: ALoCoQntKSJ3ZzYrdP9IBXmnJO+ZWCOb8eImYAJLjVkj7tp8crp7FdB3QIC6ozU9CKp8R4fi/6FS6DZkGSE2Vh/Mq02yIW/CZ19PXLkZNUlc8SjQZ3YXEUT+kQJAFQrLvWSKG2oO17pTBmsjnfsfRVUG40rzVHyZV0WND8YSrEM/NC3ntxH0X/XMaUgt6ppzg22cA6aJiQqMu8uMMxQ6DCBX5jOhBSCoZQ== X-Received: by 10.50.30.9 with SMTP id o9mr145049igh.0.1379030520682; Thu, 12 Sep 2013 17:02:00 -0700 (PDT) MIME-Version: 1.0 Received: by 10.64.57.225 with HTTP; Thu, 12 Sep 2013 17:01:29 -0700 (PDT) In-Reply-To: References: From: Paul Pluzhnikov Date: Thu, 12 Sep 2013 17:01:29 -0700 Message-ID: Subject: Re: [patch] Make vector::at() assertion message more useful (try #2) To: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= Cc: gcc-patches List , "libstdc++" On Wed, Sep 4, 2013 at 9:55 PM, Daniel Krügler wrote: >> Did you mean "pessimises code size", or something else? > > Yes. Daniel's idea proved a good one, and I now have a patch that I am happy with, and that will be easy to extend to string::at(), and other __throw_... functions. I've added the new snprintf.cc to c++11/ rather than c++98/ as Paolo suggested, because the only current caller is in c++11/functexcept.cc Thanks, Index: libstdc++-v3/src/c++11/Makefile.am =================================================================== --- libstdc++-v3/src/c++11/Makefile.am (revision 202545) +++ libstdc++-v3/src/c++11/Makefile.am (working copy) @@ -42,6 +42,7 @@ random.cc \ regex.cc \ shared_ptr.cc \ + snprintf.cc \ system_error.cc \ thread.cc Index: libstdc++-v3/src/c++11/functexcept.cc =================================================================== --- libstdc++-v3/src/c++11/functexcept.cc (revision 202545) +++ libstdc++-v3/src/c++11/functexcept.cc (working copy) @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef _GLIBCXX_USE_NLS # include @@ -39,6 +40,12 @@ # define _(msgid) (msgid) #endif +namespace __gnu_cxx +{ + int __snprintf_lite(char *__buf, size_t __bufsize, const char *__fmt, + va_list __ap); +} + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -75,11 +82,27 @@ __throw_length_error(const char* __s __attribute__((unused))) { _GLIBCXX_THROW_OR_ABORT(length_error(_(__s))); } + // Left only to maintain backward-compatible ABI. void __throw_out_of_range(const char* __s __attribute__((unused))) { _GLIBCXX_THROW_OR_ABORT(out_of_range(_(__s))); } void + __throw_out_of_range(const char* __fmt, ...) + { + const size_t __len = __builtin_strlen(__fmt); + // enough for expanding up to 5 size_t's in the format. + const size_t __alloca_size = __len + 100; + char *const __s = static_cast(alloca(__alloca_size)); + va_list __ap; + + va_start(__ap, __fmt); + __gnu_cxx::__snprintf_lite(__s, __alloca_size, __fmt, __ap); + _GLIBCXX_THROW_OR_ABORT(out_of_range(_(__s))); + va_end(__ap); // Not reached. + } + + void __throw_runtime_error(const char* __s __attribute__((unused))) { _GLIBCXX_THROW_OR_ABORT(runtime_error(_(__s))); } Index: libstdc++-v3/src/c++11/snprintf.cc =================================================================== --- libstdc++-v3/src/c++11/snprintf.cc (revision 0) +++ libstdc++-v3/src/c++11/snprintf.cc (revision 0) @@ -0,0 +1,103 @@ +// Debugging support -*- C++ -*- + +// Copyright (C) 2013 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC 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. +// +// GCC 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. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +#include +#include + +namespace std { + template + int + __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit, + ios_base::fmtflags __flags, bool __dec); +} + +namespace __gnu_cxx { + + // Private routine to append decimal representation of VAL to the given + // BUFFER, but not more than BUFSIZE characters. + // Does not NUL-terminate the output buffer. + // Returns number of characters appended, or -1 if BUFSIZE is too small. + int __concat_size_t(char *__buf, size_t __bufsize, size_t __val) + { + // Long enough for decimal representation. + int __ilen = 3 * sizeof(__val); + char *__cs = static_cast(__builtin_alloca(__ilen)); + size_t __len = std::__int_to_char(__cs + __ilen, __val, + std::__num_base::_S_atoms_out, + std::ios_base::dec, true); + if (__bufsize < __len) + return -1; + + __builtin_memcpy(__buf, __cs + __ilen - __len, __len); + return __len; + } + + // Private routine to print into __buf arguments according to format, + // not to exceed __bufsize. + // Only '%%' and '%zu' format specifiers are understood. + // Returns number of characters printed (excluding terminating NUL). + // Always NUL-terminates __buf. + int __snprintf_lite(char *__buf, size_t __bufsize, const char *__fmt, + va_list __ap) + { + char *__d = __buf; + const char *__s = __fmt; + const char *const __limit = __d + __bufsize - 1; // Leave space for NUL. + + while (*__s != '\0' && __d < __limit) + { + if (*__s == '%') + switch (__s[1]) + { + default: // Stray '%'. Just print it. + break; + case '%': // '%%' + __s += 1; + break; + case 'z': + if (__s[2] == 'u') // '%zu' -- expand next size_t arg. + { + const int __len = __concat_size_t(__d, __limit - __d, + va_arg(__ap, size_t)); + if (__len > 0) + __d += __len; + else + goto __out; + + __s += 3; + continue; + } + // Stray '%zX'. Just print it. + break; + } + *__d++ = *__s++; + } + + __out: + *__d = '\0'; + return __d - __buf; + } + +} // __gnu_cxx Index: libstdc++-v3/include/bits/functexcept.h =================================================================== --- libstdc++-v3/include/bits/functexcept.h (revision 202545) +++ libstdc++-v3/include/bits/functexcept.h (working copy) @@ -72,7 +72,7 @@ __throw_length_error(const char*) __attribute__((__noreturn__)); void - __throw_out_of_range(const char*) __attribute__((__noreturn__)); + __throw_out_of_range(const char*, ...) __attribute__((__noreturn__)); void __throw_runtime_error(const char*) __attribute__((__noreturn__)); Index: libstdc++-v3/include/bits/stl_vector.h =================================================================== --- libstdc++-v3/include/bits/stl_vector.h (revision 202545) +++ libstdc++-v3/include/bits/stl_vector.h (working copy) @@ -791,7 +791,9 @@ _M_range_check(size_type __n) const { if (__n >= this->size()) - __throw_out_of_range(__N("vector::_M_range_check")); + __throw_out_of_range(__N("vector::_M_range_check: __n (which is %zu) " + ">= this->size() (which is %zu)"), + __n, this->size()); } public: Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc (revision 202545) +++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc (working copy) @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1308 } +// { dg-error "no matching" "" { target *-*-* } 1310 } #include Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc (revision 202545) +++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc (working copy) @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1349 } +// { dg-error "no matching" "" { target *-*-* } 1351 } #include Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc (revision 202545) +++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc (working copy) @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1234 } +// { dg-error "no matching" "" { target *-*-* } 1236 } #include Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc (revision 202545) +++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc (working copy) @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1234 } +// { dg-error "no matching" "" { target *-*-* } 1236 } #include #include Index: libstdc++-v3/config/abi/pre/gnu.ver =================================================================== --- libstdc++-v3/config/abi/pre/gnu.ver (revision 202545) +++ libstdc++-v3/config/abi/pre/gnu.ver (working copy) @@ -1365,6 +1365,9 @@ # std::get_unexpected() _ZSt14get_unexpectedv; + # std::__throw_out_of_range(char const*, ...) + _ZSt20__throw_out_of_rangePKcz; + } GLIBCXX_3.4.19; # Symbols in the support library (libsupc++) have their own tag. Index: libstdc++-v3/src/c++11/Makefile.in =================================================================== --- libstdc++-v3/src/c++11/Makefile.in (revision 202545) +++ libstdc++-v3/src/c++11/Makefile.in (working copy) @@ -70,7 +70,8 @@ am__objects_1 = chrono.lo condition_variable.lo debug.lo \ functexcept.lo functional.lo future.lo hash_c++0x.lo \ hashtable_c++0x.lo limits.lo mutex.lo placeholders.lo \ - random.lo regex.lo shared_ptr.lo system_error.lo thread.lo + random.lo regex.lo shared_ptr.lo snprintf.lo system_error.lo \ + thread.lo @ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_2 = fstream-inst.lo \ @ENABLE_EXTERN_TEMPLATE_TRUE@ string-inst.lo wstring-inst.lo am_libc__11convenience_la_OBJECTS = $(am__objects_1) $(am__objects_2) @@ -324,6 +325,7 @@ random.cc \ regex.cc \ shared_ptr.cc \ + snprintf.cc \ system_error.cc \ thread.cc