[cfe-commits] [libcxx] r172447 - in /libcxx/trunk: src/string.cpp test/strings/string.conversions/stof.pass.cpp test/strings/string.conversions/stoll.pass.cpp

Howard Hinnant hhinnant at apple.com
Mon Jan 14 10:59:44 PST 2013


Author: hhinnant
Date: Mon Jan 14 12:59:43 2013
New Revision: 172447

URL: http://llvm.org/viewvc/llvm-project?rev=172447&view=rev
Log:
Fix string conversions functions to throw out_of_range properly.  Fixes http://llvm.org/bugs/show_bug.cgi?id=14919.

Modified:
    libcxx/trunk/src/string.cpp
    libcxx/trunk/test/strings/string.conversions/stof.pass.cpp
    libcxx/trunk/test/strings/string.conversions/stoll.pass.cpp

Modified: libcxx/trunk/src/string.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/string.cpp?rev=172447&r1=172446&r2=172447&view=diff
==============================================================================
--- libcxx/trunk/src/string.cpp (original)
+++ libcxx/trunk/src/string.cpp Mon Jan 14 12:59:43 2013
@@ -31,17 +31,17 @@
 {
     char* ptr;
     const char* const p = str.c_str();
+    int errno_save = errno;
+    errno = 0;
     long r = strtol(p, &ptr, base);
-    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
-        ptr = const_cast<char*>(p);
-    if (ptr == p)
-    {
+    swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
-        if (r == 0)
-            throw invalid_argument("stoi: no conversion");
+    if (errno_save == ERANGE || r < numeric_limits<int>::min() ||
+                                numeric_limits<int>::max() < r)
         throw out_of_range("stoi: out of range");
+    if (ptr == p)
+        throw invalid_argument("stoi: no conversion");
 #endif  // _LIBCPP_NO_EXCEPTIONS
-    }
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
     return static_cast<int>(r);
@@ -52,17 +52,17 @@
 {
     wchar_t* ptr;
     const wchar_t* const p = str.c_str();
+    int errno_save = errno;
+    errno = 0;
     long r = wcstol(p, &ptr, base);
-    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
-        ptr = const_cast<wchar_t*>(p);
-    if (ptr == p)
-    {
+    swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
-        if (r == 0)
-            throw invalid_argument("stoi: no conversion");
+    if (errno_save == ERANGE || r < numeric_limits<int>::min() ||
+                                numeric_limits<int>::max() < r)
         throw out_of_range("stoi: out of range");
+    if (ptr == p)
+        throw invalid_argument("stoi: no conversion");
 #endif  // _LIBCPP_NO_EXCEPTIONS
-    }
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
     return static_cast<int>(r);
@@ -73,15 +73,16 @@
 {
     char* ptr;
     const char* const p = str.c_str();
+    int errno_save = errno;
+    errno = 0;
     long r = strtol(p, &ptr, base);
-    if (ptr == p)
-    {
+    swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
-        if (r == 0)
-            throw invalid_argument("stol: no conversion");
+    if (errno_save == ERANGE)
         throw out_of_range("stol: out of range");
+    if (ptr == p)
+        throw invalid_argument("stol: no conversion");
 #endif  // _LIBCPP_NO_EXCEPTIONS
-    }
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
     return r;
@@ -92,15 +93,16 @@
 {
     wchar_t* ptr;
     const wchar_t* const p = str.c_str();
+    int errno_save = errno;
+    errno = 0;
     long r = wcstol(p, &ptr, base);
-    if (ptr == p)
-    {
+    swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
-        if (r == 0)
-            throw invalid_argument("stol: no conversion");
+    if (errno_save == ERANGE)
         throw out_of_range("stol: out of range");
+    if (ptr == p)
+        throw invalid_argument("stol: no conversion");
 #endif  // _LIBCPP_NO_EXCEPTIONS
-    }
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
     return r;
@@ -111,15 +113,16 @@
 {
     char* ptr;
     const char* const p = str.c_str();
+    int errno_save = errno;
+    errno = 0;
     unsigned long r = strtoul(p, &ptr, base);
-    if (ptr == p)
-    {
+    swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
-        if (r == 0)
-            throw invalid_argument("stoul: no conversion");
+    if (errno_save == ERANGE)
         throw out_of_range("stoul: out of range");
+    if (ptr == p)
+        throw invalid_argument("stoul: no conversion");
 #endif  // _LIBCPP_NO_EXCEPTIONS
-    }
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
     return r;
@@ -130,15 +133,16 @@
 {
     wchar_t* ptr;
     const wchar_t* const p = str.c_str();
+    int errno_save = errno;
+    errno = 0;
     unsigned long r = wcstoul(p, &ptr, base);
-    if (ptr == p)
-    {
+    swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
-        if (r == 0)
-            throw invalid_argument("stoul: no conversion");
+    if (errno_save == ERANGE)
         throw out_of_range("stoul: out of range");
+    if (ptr == p)
+        throw invalid_argument("stoul: no conversion");
 #endif  // _LIBCPP_NO_EXCEPTIONS
-    }
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
     return r;
@@ -149,15 +153,16 @@
 {
     char* ptr;
     const char* const p = str.c_str();
+    int errno_save = errno;
+    errno = 0;
     long long r = strtoll(p, &ptr, base);
-    if (ptr == p)
-    {
+    swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
-        if (r == 0)
-            throw invalid_argument("stoll: no conversion");
+    if (errno_save == ERANGE)
         throw out_of_range("stoll: out of range");
+    if (ptr == p)
+        throw invalid_argument("stoll: no conversion");
 #endif  // _LIBCPP_NO_EXCEPTIONS
-    }
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
     return r;
@@ -168,15 +173,16 @@
 {
     wchar_t* ptr;
     const wchar_t* const p = str.c_str();
+    int errno_save = errno;
+    errno = 0;
     long long r = wcstoll(p, &ptr, base);
-    if (ptr == p)
-    {
+    swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
-        if (r == 0)
-            throw invalid_argument("stoll: no conversion");
+    if (errno_save == ERANGE)
         throw out_of_range("stoll: out of range");
+    if (ptr == p)
+        throw invalid_argument("stoll: no conversion");
 #endif  // _LIBCPP_NO_EXCEPTIONS
-    }
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
     return r;
@@ -187,15 +193,16 @@
 {
     char* ptr;
     const char* const p = str.c_str();
+    int errno_save = errno;
+    errno = 0;
     unsigned long long r = strtoull(p, &ptr, base);
-    if (ptr == p)
-    {
+    swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
-        if (r == 0)
-            throw invalid_argument("stoull: no conversion");
+    if (errno_save == ERANGE)
         throw out_of_range("stoull: out of range");
+    if (ptr == p)
+        throw invalid_argument("stoull: no conversion");
 #endif  // _LIBCPP_NO_EXCEPTIONS
-    }
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
     return r;
@@ -206,15 +213,16 @@
 {
     wchar_t* ptr;
     const wchar_t* const p = str.c_str();
+    int errno_save = errno;
+    errno = 0;
     unsigned long long r = wcstoull(p, &ptr, base);
-    if (ptr == p)
-    {
+    swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
-        if (r == 0)
-            throw invalid_argument("stoull: no conversion");
+    if (errno_save == ERANGE)
         throw out_of_range("stoull: out of range");
+    if (ptr == p)
+        throw invalid_argument("stoull: no conversion");
 #endif  // _LIBCPP_NO_EXCEPTIONS
-    }
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
     return r;
@@ -227,7 +235,7 @@
     const char* const p = str.c_str();
     int errno_save = errno;
     errno = 0;
-    double r = strtod(p, &ptr);
+    float r = strtof(p, &ptr);
     swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
     if (errno_save == ERANGE)
@@ -237,7 +245,7 @@
 #endif  // _LIBCPP_NO_EXCEPTIONS
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
-    return static_cast<float>(r);
+    return r;
 }
 
 float
@@ -247,7 +255,7 @@
     const wchar_t* const p = str.c_str();
     int errno_save = errno;
     errno = 0;
-    double r = wcstod(p, &ptr);
+    float r = wcstof(p, &ptr);
     swap(errno, errno_save);
 #ifndef _LIBCPP_NO_EXCEPTIONS
     if (errno_save == ERANGE)
@@ -257,7 +265,7 @@
 #endif  // _LIBCPP_NO_EXCEPTIONS
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
-    return static_cast<float>(r);
+    return r;
 }
 
 double

Modified: libcxx/trunk/test/strings/string.conversions/stof.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/strings/string.conversions/stof.pass.cpp?rev=172447&r1=172446&r2=172447&view=diff
==============================================================================
--- libcxx/trunk/test/strings/string.conversions/stof.pass.cpp (original)
+++ libcxx/trunk/test/strings/string.conversions/stof.pass.cpp Mon Jan 14 12:59:43 2013
@@ -32,23 +32,24 @@
     idx = 0;
     assert(std::stof(L"10g", &idx) == 10);
     assert(idx == 2);
+    idx = 0;
     try
     {
         assert(std::stof("1.e60", &idx) == INFINITY);
-        assert(idx == 5);
+        assert(false);
     }
     catch (const std::out_of_range&)
     {
-        assert(false);
+        assert(idx == 0);
     }
     try
     {
         assert(std::stof(L"1.e60", &idx) == INFINITY);
-        assert(idx == 5);
+        assert(false);
     }
     catch (const std::out_of_range&)
     {
-        assert(false);
+        assert(idx == 0);
     }
     idx = 0;
     try

Modified: libcxx/trunk/test/strings/string.conversions/stoll.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/strings/string.conversions/stoll.pass.cpp?rev=172447&r1=172446&r2=172447&view=diff
==============================================================================
--- libcxx/trunk/test/strings/string.conversions/stoll.pass.cpp (original)
+++ libcxx/trunk/test/strings/string.conversions/stoll.pass.cpp Mon Jan 14 12:59:43 2013
@@ -86,4 +86,13 @@
     {
         assert(idx == 0);
     }
+    try
+    {
+        std::stoll("99999999999999999999999999", &idx);
+        assert(false);
+    }
+    catch (const std::out_of_range&)
+    {
+        assert(idx == 0);
+    }
 }





More information about the cfe-commits mailing list