This is the mail archive of the gcc-prs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

libstdc++/5331: Returned iterator from num_get<>::get is not advanced.



>Number:         5331
>Category:       libstdc++
>Synopsis:       Returned iterator from num_get<>::get is not advanced.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Jan 09 03:06:01 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     David Seymour
>Release:        3.1 20011231 (experimental)
>Organization:
>Environment:
System: Linux quokka.home.bogonet 2.4.9-6 #1 Thu Oct 18 09:39:55 EDT 2001 i686 unknown
Architecture: i686

	
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: ../egcs/configure --prefix=/opt/gcc-3.1 --enable-threads --enable-version-specific-runtime-libs
>Description:
	The returned iterator from num_get<>::get (all signatures) is
	not advanced past the scanned number, as required by the
	standard (22.2.2.1). Note not noticeable for input iterators,
	only manifests for forward (and better) iterators.

>How-To-Repeat:
dave@quokka:~/tries> cat num_get.cc
#include <iostream>
#include <string>
#include <sstream>
#include <locale>

int main()
{
  using namespace std;

  typedef string::const_iterator iter_type;
  typedef num_get<char, iter_type> num_get_type;
  long i = 0;
  ios_base::iostate err = ios_base::goodbit;

  const string str = "42foo";
  istringstream iss; // need an ios, add my num_get facet
  iss.imbue(locale(iss.getloc(), new num_get_type));

  const num_get_type& ng = use_facet<num_get_type>(iss.getloc());
  iter_type end = ng.get(str.begin(), str.end(), iss, err, i);
  string rem(end, str.end());
  
  cout << "err = " << err << ", should be " << ios_base::goodbit << "\n";
  cout << "i = " << i << ", should be 42\n";
  cout << "rem = `" << rem << "' should be `foo'\n";
}
dave@quokka:~/tries> g++ -v -Wall -g -o num_get num_get.cc
Reading specs from /opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/specs
Configured with: ../egcs/configure --prefix=/opt/gcc-3.1 --enable-threads --enable-version-specific-runtime-libs
Thread model: posix
gcc version 3.1 20011231 (experimental)
 /opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/cc1plus -v -D__GNUC__=3 -D__GNUC_MINOR__=1 -D__GNUC_PATCHLEVEL__=0 -D__ELF__ -Dunix -Dlinux -D__ELF__ -D__unix__ -D__linux__ -D__unix -D__linux -Asystem=posix -D__NO_INLINE__ -D__STDC_HOSTED__=1 -Wall -D_GNU_SOURCE -Acpu=i386 -Amachine=i386 -Di386 -D__i386 -D__i386__ -D__tune_i686__ -D__tune_pentiumpro__ num_get.cc -D__GNUG__=3 -D__DEPRECATED -D__EXCEPTIONS -D__GXX_ABI_VERSION=100 -quiet -dumpbase num_get.cc -g -Wall -version -o /home/dave/.tmp/ccKjZ388.s
GNU CPP version 3.1 20011231 (experimental) (cpplib) (i386 Linux/ELF)
GNU C++ version 3.1 20011231 (experimental) (i686-pc-linux-gnu)
	compiled by GNU C version 3.1 20011231 (experimental).
ignoring nonexistent directory "/opt/gcc-3.1/i686-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/include/g++
 /opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/include/g++/i686-pc-linux-gnu
 /opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/include/g++/backward
 /usr/local/include
 /opt/gcc-3.1/include
 /opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/include
 /usr/include
End of search list.
 /opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/../../../../i686-pc-linux-gnu/bin/as -V -Qy -o /home/dave/.tmp/ccV60cIG.o /home/dave/.tmp/ccKjZ388.s
GNU assembler version 2.11.93 (i686-pc-linux-gnu) using BFD version 2.11.93 20011224
 /opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/collect2 -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o num_get /usr/lib/crt1.o /usr/lib/crti.o /opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/crtbegin.o -L/opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1 -L/opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/../../../../i686-pc-linux-gnu/lib -L/opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/../../.. /home/dave/.tmp/ccV60cIG.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /opt/gcc-3.1/lib/gcc-lib/i686-pc-linux-gnu/3.1/crtend.o /usr/lib/crtn.o
dave@quokka:~/tries> ./num_get
err = 0, should be 0
i = 42, should be 42
rem = `42foo' should be `foo'
dave@quokka:~/tries> 
	
>Fix:
The following patch works for me.  Change in ABI for an internal
interface though and don't quite understand how such changes play out
with non inline templates.

Index: locale_facets.h
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/include/bits/locale_facets.h,v
retrieving revision 1.34
diff -u -3 -p -r1.34 locale_facets.h
--- locale_facets.h	2001/12/15 07:05:03	1.34
+++ locale_facets.h	2002/01/09 01:24:29
@@ -641,11 +641,11 @@ namespace std
     protected:
       virtual ~num_get() { }
 
-      void 
+      iter_type 
       _M_extract_float(iter_type, iter_type, ios_base&, ios_base::iostate&, 
 		       string& __xtrc) const;
 
-      void 
+      iter_type 
       _M_extract_int(iter_type, iter_type, ios_base&, ios_base::iostate&, 
 		     char* __xtrc, int __max, int& __base) const;
 
Index: locale_facets.tcc
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/include/bits/locale_facets.tcc,v
retrieving revision 1.47
diff -u -3 -p -r1.47 locale_facets.tcc
--- locale_facets.tcc	2001/12/27 12:13:23	1.47
+++ locale_facets.tcc	2002/01/09 01:24:34
@@ -88,7 +88,7 @@ namespace std
 
 
   template<typename _CharT, typename _InIter>
-    void
+    _InIter
     num_get<_CharT, _InIter>::
     _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
 		     ios_base::iostate& __err, string& __xtrc) const
@@ -213,10 +213,11 @@ namespace std
       __xtrc += char();
       if (__beg == __end)
         __err |= ios_base::eofbit;
+      return __beg;
     }
 
   template<typename _CharT, typename _InIter>
-    void
+    _InIter
     num_get<_CharT, _InIter>::
     _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
 		   ios_base::iostate& __err, char* __xtrc, int __max, 
@@ -369,6 +370,7 @@ namespace std
       __xtrc[__pos] = char();
       if (__beg == __end)
         __err |= ios_base::eofbit;
+      return __beg;
     }
 
 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
@@ -394,8 +396,8 @@ namespace std
 	  // that can be represented without change" so we have to add 1 to it
 	  // in order to obtain the max number of digits. The same for the
 	  // other do_get for integral types below.
-          _M_extract_int(__beg, __end, __io, __err, __xtrc, 
-			 numeric_limits<bool>::digits10 + 1, __base);
+          __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
+				 numeric_limits<bool>::digits10 + 1, __base);
 
           // Stage 2: convert and store results.
           char* __sanity;
@@ -459,8 +461,8 @@ namespace std
       // integral types.
       char __xtrc[32];
       int __base;
-      _M_extract_int(__beg, __end, __io, __err, __xtrc, 
-		     numeric_limits<long>::digits10 + 1, __base);
+      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
+			     numeric_limits<long>::digits10 + 1, __base);
 
       // Stage 2: convert and store results.
       char* __sanity;
@@ -485,8 +487,9 @@ namespace std
       // integral types.
       char __xtrc[32];
       int __base;
-      _M_extract_int(__beg, __end, __io, __err, __xtrc, 
-		     numeric_limits<unsigned short>::digits10 + 1, __base);
+      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
+			     numeric_limits<unsigned short>::digits10 + 1,
+			     __base);
 
       // Stage 2: convert and store results.
       char* __sanity;
@@ -512,8 +515,9 @@ namespace std
       // integral types.
       char __xtrc[32];
       int __base;
-      _M_extract_int(__beg, __end, __io, __err, __xtrc, 
-		     numeric_limits<unsigned int>::digits10 + 1, __base);
+      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
+			     numeric_limits<unsigned int>::digits10 + 1,
+			     __base);
 
       // Stage 2: convert and store results.
       char* __sanity;
@@ -539,8 +543,9 @@ namespace std
       // integral types.
       char __xtrc[32];
       int __base;
-      _M_extract_int(__beg, __end, __io, __err, __xtrc, 
-		     numeric_limits<unsigned long>::digits10 + 1, __base);
+      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
+			     numeric_limits<unsigned long>::digits10 + 1,
+			     __base);
 
       // Stage 2: convert and store results.
       char* __sanity;
@@ -566,8 +571,8 @@ namespace std
       // integral types.
       char __xtrc[32];
       int __base;
-      _M_extract_int(__beg, __end, __io, __err, __xtrc, 
-		     numeric_limits<long long>::digits10 + 1, __base);
+      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
+			     numeric_limits<long long>::digits10 + 1, __base);
 
       // Stage 2: convert and store results.
       char* __sanity;
@@ -592,8 +597,9 @@ namespace std
       // integral types.
       char __xtrc[32];
       int __base;
-      _M_extract_int(__beg, __end, __io, __err, __xtrc,
-		     numeric_limits<unsigned long long>::digits10 + 1, __base);
+      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc,
+			     numeric_limits<unsigned long long>::digits10 + 1,
+			     __base);
 
       // Stage 2: convert and store results.
       char* __sanity;
@@ -617,7 +623,7 @@ namespace std
       // Stage 1: extract and determine the conversion specifier.
       string __xtrc;
       __xtrc.reserve(32);
-      _M_extract_float(__beg, __end, __io, __err, __xtrc);
+      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
 
       // Stage 2: convert and store results.
       char* __sanity;
@@ -644,7 +650,7 @@ namespace std
       // Stage 1: extract and determine the conversion specifier.
       string __xtrc;
       __xtrc.reserve(32);
-      _M_extract_float(__beg, __end, __io, __err, __xtrc);
+      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
 
       // Stage 2: convert and store results.
       char* __sanity;
@@ -667,7 +673,7 @@ namespace std
       // Stage 1: extract and determine the conversion specifier.
       string __xtrc;
       __xtrc.reserve(32);
-      _M_extract_float(__beg, __end, __io, __err, __xtrc);
+      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
 
 #if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
       // Stage 2: convert and store results.
@@ -721,8 +727,9 @@ namespace std
       // integral types.
       char __xtrc[32];
       int __base;
-      _M_extract_int(__beg, __end, __io, __err, __xtrc, 
-		     numeric_limits<unsigned long>::digits10 + 1, __base);
+      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
+			     numeric_limits<unsigned long>::digits10 + 1,
+			     __base);
 
       // Stage 2: convert and store results.
       char* __sanity;
>Release-Note:
>Audit-Trail:
>Unformatted:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]