[PATCH] [libc++] reject <chrono> literals that can't be represented
Richard Smith
richard at metafoo.co.uk
Tue Nov 11 12:05:21 PST 2014
[time.duration.literals]p3 says:
"If any of these suffixes are applied to an integer literal and the
resulting chrono::duration value cannot be represented in the result type
because of overflow, the program is ill-formed."
That's unimplementable in standard C++, but implementable with Clang using
the enable_if attribute. This patch also rejects
(void) operator""ns(0x8000000000000000ull);
... and it's not entirely clear whether that's permissible, but this is the
best we can do at the moment (and I think it's a good thing to reject the
above code).
Thoughts?
(We could do the same thing for floating-point <chrono> literals, but the
standard doesn't allow us to do so.)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20141111/ea5da80e/attachment.html>
-------------- next part --------------
Index: include/__config
===================================================================
--- include/__config (revision 221699)
+++ include/__config (working copy)
@@ -206,6 +206,10 @@
#define _LIBCPP_ALWAYS_INLINE __attribute__ ((__visibility__("hidden"), __always_inline__))
#endif
+#if !defined(_LIBCPP_ENABLE_IF) && __has_attribute(enable_if)
+#define _LIBCPP_ENABLE_IF(__cond, __msg) __attribute__((enable_if(__cond, __msg)))
+#endif
+
#if defined(__clang__)
#if defined(__APPLE__) && !defined(__i386__) && !defined(__x86_64__) && \
Index: include/chrono
===================================================================
--- include/chrono (revision 221699)
+++ include/chrono (working copy)
@@ -1018,6 +1018,30 @@
return chrono::duration<long double, nano> (__ns);
}
+ // If any of these suffixes are applied to an integer literal and the
+ // resulting value cannot be represented, the program is ill-formed.
+ // We cannot enforce this within standard C++, but we can do so with
+ // a Clang extension.
+#ifdef _LIBCPP_ENABLE_IF
+ void operator"" h(unsigned long long __h)
+ _LIBCPP_ENABLE_IF(__h > chrono::hours::max().count(), "")
+ = delete;
+ void operator"" min(unsigned long long __m)
+ _LIBCPP_ENABLE_IF(__m > chrono::minutes::max().count(), "")
+ = delete;
+ void operator"" s(unsigned long long __s)
+ _LIBCPP_ENABLE_IF(__s > chrono::seconds::max().count(), "")
+ = delete;
+ void operator"" ms(unsigned long long __ms)
+ _LIBCPP_ENABLE_IF(__ms > chrono::milliseconds::max().count(), "")
+ = delete;
+ void operator"" us(unsigned long long __us)
+ _LIBCPP_ENABLE_IF(__us > chrono::microseconds::max().count(), "")
+ = delete;
+ void operator"" ns(unsigned long long __ns)
+ _LIBCPP_ENABLE_IF(__ns > chrono::nanoseconds::max().count(), "")
+ = delete;
+#endif
}}
namespace chrono { // hoist the literals into namespace std::chrono
Index: test/testit
===================================================================
--- test/testit (revision 221699)
+++ test/testit (working copy)
@@ -159,6 +159,7 @@
}
afunc no
+wait
echo "****************************************************"
echo "Results for `pwd`:"
Index: test/utilities/time/time.duration/time.duration.literals/h_overflow.fail.cpp
===================================================================
--- test/utilities/time/time.duration/time.duration.literals/h_overflow.fail.cpp (revision 0)
+++ test/utilities/time/time.duration/time.duration.literals/h_overflow.fail.cpp (working copy)
@@ -0,0 +1,27 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <chrono>
+#include <cassert>
+
+int main()
+{
+#if _LIBCPP_STD_VER > 11 && defined(_LIBCPP_ENABLE_IF) && LONG_MAX == 0x7FFFFFFFFFFFFFFF
+ using namespace std::literals::chrono_literals;
+
+ (void) 0x8000000000000000h; // should fail w/"out of range" error
+#elif _LIBCPP_STD_VER > 11 && defined(_LIBCPP_ENABLE_IF) && LONG_MAX == 0x7FFFFFFF
+ using namespace std::literals::chrono_literals;
+
+ (void) 0x80000000h; // should fail w/"out of range" error
+#else
+#error
+#endif
+}
+
Index: test/utilities/time/time.duration/time.duration.literals/min_overflow.fail.cpp
===================================================================
--- test/utilities/time/time.duration/time.duration.literals/min_overflow.fail.cpp (revision 0)
+++ test/utilities/time/time.duration/time.duration.literals/min_overflow.fail.cpp (working copy)
@@ -0,0 +1,27 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <chrono>
+#include <cassert>
+
+int main()
+{
+#if _LIBCPP_STD_VER > 11 && defined(_LIBCPP_ENABLE_IF) && LONG_MAX == 0x7FFFFFFFFFFFFFFF
+ using namespace std::literals::chrono_literals;
+
+ (void) 0x8000000000000000min; // should fail w/"out of range" error
+#elif _LIBCPP_STD_VER > 11 && defined(_LIBCPP_ENABLE_IF) && LONG_MAX == 0x7FFFFFFF
+ using namespace std::literals::chrono_literals;
+
+ (void) 0x80000000min; // should fail w/"out of range" error
+#else
+#error
+#endif
+}
+
Index: test/utilities/time/time.duration/time.duration.literals/ms_overflow.fail.cpp
===================================================================
--- test/utilities/time/time.duration/time.duration.literals/ms_overflow.fail.cpp (revision 0)
+++ test/utilities/time/time.duration/time.duration.literals/ms_overflow.fail.cpp (working copy)
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <chrono>
+#include <cassert>
+
+int main()
+{
+#if _LIBCPP_STD_VER > 11 && defined(_LIBCPP_ENABLE_IF) && LLONG_MAX == 0x7FFFFFFFFFFFFFFF
+ using namespace std::literals::chrono_literals;
+
+ (void) 0x8000000000000000ms; // should fail w/"out of range" error
+#else
+#error
+#endif
+}
+
Index: test/utilities/time/time.duration/time.duration.literals/ns_overflow.fail.cpp
===================================================================
--- test/utilities/time/time.duration/time.duration.literals/ns_overflow.fail.cpp (revision 0)
+++ test/utilities/time/time.duration/time.duration.literals/ns_overflow.fail.cpp (working copy)
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <chrono>
+#include <cassert>
+
+int main()
+{
+#if _LIBCPP_STD_VER > 11 && defined(_LIBCPP_ENABLE_IF) && LLONG_MAX == 0x7FFFFFFFFFFFFFFF
+ using namespace std::literals::chrono_literals;
+
+ (void) 0x8000000000000000ns; // should fail w/"out of range" error
+#else
+#error
+#endif
+}
+
Index: test/utilities/time/time.duration/time.duration.literals/overflow.pass.cpp
===================================================================
--- test/utilities/time/time.duration/time.duration.literals/overflow.pass.cpp (revision 0)
+++ test/utilities/time/time.duration/time.duration.literals/overflow.pass.cpp (working copy)
@@ -0,0 +1,35 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <chrono>
+#include <cassert>
+#include <limits.h>
+
+int main()
+{
+#if _LIBCPP_STD_VER > 11 && defined(_LIBCPP_ENABLE_IF)
+ using namespace std::literals::chrono_literals;
+
+#if LLONG_MAX == 0x7FFFFFFFFFFFFFFF
+ (void) 0x7FFFFFFFFFFFFFFFns;
+ (void) 0x7FFFFFFFFFFFFFFFus;
+ (void) 0x7FFFFFFFFFFFFFFFms;
+ (void) 0x7FFFFFFFFFFFFFFFs;
+#endif
+
+#if LONG_MAX == 0x7FFFFFFFFFFFFFFF
+ (void) 0x7FFFFFFFFFFFFFFFmin;
+ (void) 0x7FFFFFFFFFFFFFFFh;
+#elif LONG_MAX = 0x7FFFFFFF
+ (void) 0x7FFFFFFFmin;
+ (void) 0x7FFFFFFFh;
+#endif
+#endif
+}
+
Index: test/utilities/time/time.duration/time.duration.literals/s_overflow.fail.cpp
===================================================================
--- test/utilities/time/time.duration/time.duration.literals/s_overflow.fail.cpp (revision 0)
+++ test/utilities/time/time.duration/time.duration.literals/s_overflow.fail.cpp (working copy)
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <chrono>
+#include <cassert>
+
+int main()
+{
+#if _LIBCPP_STD_VER > 11 && defined(_LIBCPP_ENABLE_IF) && LLONG_MAX == 0x7FFFFFFFFFFFFFFF
+ using namespace std::literals::chrono_literals;
+
+ (void) 0x8000000000000000s; // should fail w/"out of range" error
+#else
+#error
+#endif
+}
+
Index: test/utilities/time/time.duration/time.duration.literals/us_overflow.fail.cpp
===================================================================
--- test/utilities/time/time.duration/time.duration.literals/us_overflow.fail.cpp (revision 0)
+++ test/utilities/time/time.duration/time.duration.literals/us_overflow.fail.cpp (working copy)
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <chrono>
+#include <cassert>
+
+int main()
+{
+#if _LIBCPP_STD_VER > 11 && defined(_LIBCPP_ENABLE_IF) && LLONG_MAX == 0x7FFFFFFFFFFFFFFF
+ using namespace std::literals::chrono_literals;
+
+ (void) 0x8000000000000000us; // should fail w/"out of range" error
+#else
+#error
+#endif
+}
+
More information about the cfe-commits
mailing list