[clang] [clang-tools-extra] [libc] [libc][c11] implement ctime (PR #107285)
Зишан Мирза via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 5 11:41:03 PDT 2024
https://github.com/zimirza updated https://github.com/llvm/llvm-project/pull/107285
>From b982621407a1ab1746a023809aae5c6a2b983679 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Tue, 3 Sep 2024 22:47:30 +0200
Subject: [PATCH 01/27] [libc][c11] implement ctime (#86567)
---
libc/src/time/CMakeLists.txt | 11 ++
libc/src/time/ctime.cpp | 23 ++++
libc/src/time/ctime.h | 21 +++
libc/src/time/time_utils.h | 46 +++++++
libc/test/src/time/ctime_test.cpp | 215 ++++++++++++++++++++++++++++++
5 files changed, 316 insertions(+)
create mode 100644 libc/src/time/ctime.cpp
create mode 100644 libc/src/time/ctime.h
create mode 100644 libc/test/src/time/ctime_test.cpp
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index 5680718715974e..befe67677f3ec7 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -36,6 +36,17 @@ add_entrypoint_object(
libc.include.time
)
+add_entrypoint_object(
+ ctime
+ SRCS
+ ctime.cpp
+ HDRS
+ ctime.h
+ DEPENDS
+ .time_utils
+ libc.include.time
+)
+
add_entrypoint_object(
difftime
SRCS
diff --git a/libc/src/time/ctime.cpp b/libc/src/time/ctime.cpp
new file mode 100644
index 00000000000000..f3181816ad9ab1
--- /dev/null
+++ b/libc/src/time/ctime.cpp
@@ -0,0 +1,23 @@
+//===-- Implementation of asctime function --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/time/ctime.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/time/time_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+using LIBC_NAMESPACE::time_utils::TimeConstants;
+
+LLVM_LIBC_FUNCTION(char *, ctime, (const struct tm *timeptr)) {
+ static char buffer[TimeConstants::CTIME_BUFFER_SIZE];
+ return time_utils::ctime(timeptr, buffer, TimeConstants::CTIME_MAX_BYTES);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/ctime.h b/libc/src/time/ctime.h
new file mode 100644
index 00000000000000..ec5530ffb5bc71
--- /dev/null
+++ b/libc/src/time/ctime.h
@@ -0,0 +1,21 @@
+//===-- Implementation header of ctime ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_TIME_CTIME_H
+#define LLVM_LIBC_SRC_TIME_CTIME_H
+
+#include "src/__support/macros/config.h"
+#include <time.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+char *ctime(const struct tm *timeptr);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TIME_CTIME_H
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 47f55f7d389122..6fa590fefac8d0 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -62,6 +62,9 @@ struct TimeConstants {
static constexpr int ASCTIME_BUFFER_SIZE = 256;
static constexpr int ASCTIME_MAX_BYTES = 26;
+ static constexpr int CTIME_BUFFER_SIZE = 256;
+ static constexpr int CTIME_MAX_BYTES = 26;
+
/* 2000-03-01 (mod 400 year, immediately after feb29 */
static constexpr int64_t SECONDS_UNTIL2000_MARCH_FIRST =
(946684800LL + SECONDS_PER_DAY * (31 + 29));
@@ -145,6 +148,49 @@ LIBC_INLINE char *asctime(const struct tm *timeptr, char *buffer,
return buffer;
}
+LIBC_INLINE char *ctime(const struct tm *timeptr, char *buffer,
+ size_t bufferLength) {
+ if (timeptr == nullptr || buffer == nullptr) {
+ invalid_value();
+ return nullptr;
+ }
+ if (timeptr->tm_wday < 0 ||
+ timeptr->tm_wday > (TimeConstants::DAYS_PER_WEEK - 1)) {
+ invalid_value();
+ return nullptr;
+ }
+ if (timeptr->tm_mon < 0 ||
+ timeptr->tm_mon > (TimeConstants::MONTHS_PER_YEAR - 1)) {
+ invalid_value();
+ return nullptr;
+ }
+
+ // TODO(rtenneti): i18n the following strings.
+ static const char *week_days_name[TimeConstants::DAYS_PER_WEEK] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+
+ static const char *months_name[TimeConstants::MONTHS_PER_YEAR] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+ // TODO(michaelr): look into removing this call to __builtin_snprintf that may
+ // be emitted as a call to snprintf. Alternatively, look into using our
+ // internal printf machinery.
+ int written_size = __builtin_snprintf(
+ buffer, bufferLength, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
+ week_days_name[timeptr->tm_wday], months_name[timeptr->tm_mon],
+ timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec,
+ TimeConstants::TIME_YEAR_BASE + timeptr->tm_year);
+ if (written_size < 0)
+ return nullptr;
+ if (static_cast<size_t>(written_size) >= bufferLength) {
+ out_of_range();
+ return nullptr;
+ }
+ return buffer;
+}
+
+
LIBC_INLINE struct tm *gmtime_internal(const time_t *timer, struct tm *result) {
int64_t seconds = *timer;
// Update the tm structure's year, month, day, etc. from seconds.
diff --git a/libc/test/src/time/ctime_test.cpp b/libc/test/src/time/ctime_test.cpp
new file mode 100644
index 00000000000000..bbf915188eacee
--- /dev/null
+++ b/libc/test/src/time/ctime_test.cpp
@@ -0,0 +1,215 @@
+//===-- Unittests for ctime ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// make check-libc LIBC_TEST_TARGET=call_ctime VERBOSE=1
+#include "src/errno/libc_errno.h"
+#include "src/time/ctime.h"
+#include "test/UnitTest/Test.h"
+#include "test/src/time/TmHelper.h"
+
+static inline char *call_ctime(struct tm *tm_data, int year, int month,
+ int mday, int hour, int min, int sec, int wday,
+ int yday) {
+ LIBC_NAMESPACE::tmhelper::testing::initialize_tm_data(
+ tm_data, year, month, mday, hour, min, sec, wday, yday);
+ return LIBC_NAMESPACE::ctime(tm_data);
+}
+
+TEST(LlvmLibcCtime, Nullptr) {
+ char *result;
+ result = LIBC_NAMESPACE::ctime(nullptr);
+ ASSERT_ERRNO_EQ(EINVAL);
+ ASSERT_STREQ(nullptr, result);
+}
+
+// Weekdays are in the range 0 to 6. Test passing invalid value in wday.
+TEST(LlvmLibcCtime, InvalidWday) {
+ struct tm tm_data;
+
+ // Test with wday = -1.
+ call_ctime(&tm_data,
+ 1970, // year
+ 1, // month
+ 1, // day
+ 0, // hr
+ 0, // min
+ 0, // sec
+ -1, // wday
+ 0); // yday
+ ASSERT_ERRNO_EQ(EINVAL);
+
+ // Test with wday = 7.
+ call_ctime(&tm_data,
+ 1970, // year
+ 1, // month
+ 1, // day
+ 0, // hr
+ 0, // min
+ 0, // sec
+ 7, // wday
+ 0); // yday
+ ASSERT_ERRNO_EQ(EINVAL);
+}
+
+// Months are from January to December. Test passing invalid value in month.
+TEST(LlvmLibcCtime, InvalidMonth) {
+ struct tm tm_data;
+
+ // Test with month = 0.
+ call_ctime(&tm_data,
+ 1970, // year
+ 0, // month
+ 1, // day
+ 0, // hr
+ 0, // min
+ 0, // sec
+ 4, // wday
+ 0); // yday
+ ASSERT_ERRNO_EQ(EINVAL);
+
+ // Test with month = 13.
+ call_ctime(&tm_data,
+ 1970, // year
+ 13, // month
+ 1, // day
+ 0, // hr
+ 0, // min
+ 0, // sec
+ 4, // wday
+ 0); // yday
+ ASSERT_ERRNO_EQ(EINVAL);
+}
+
+TEST(LlvmLibcCtime, ValidWeekdays) {
+ struct tm tm_data;
+ char *result;
+ // 1970-01-01 00:00:00.
+ result = call_ctime(&tm_data,
+ 1970, // year
+ 1, // month
+ 1, // day
+ 0, // hr
+ 0, // min
+ 0, // sec
+ 4, // wday
+ 0); // yday
+ ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
+
+ // 1970-01-03 00:00:00.
+ result = call_ctime(&tm_data,
+ 1970, // year
+ 1, // month
+ 3, // day
+ 0, // hr
+ 0, // min
+ 0, // sec
+ 6, // wday
+ 0); // yday
+ ASSERT_STREQ("Sat Jan 3 00:00:00 1970\n", result);
+
+ // 1970-01-04 00:00:00.
+ result = call_ctime(&tm_data,
+ 1970, // year
+ 1, // month
+ 4, // day
+ 0, // hr
+ 0, // min
+ 0, // sec
+ 0, // wday
+ 0); // yday
+ ASSERT_STREQ("Sun Jan 4 00:00:00 1970\n", result);
+}
+
+TEST(LlvmLibcCtime, ValidMonths) {
+ struct tm tm_data;
+ char *result;
+ // 1970-01-01 00:00:00.
+ result = call_ctime(&tm_data,
+ 1970, // year
+ 1, // month
+ 1, // day
+ 0, // hr
+ 0, // min
+ 0, // sec
+ 4, // wday
+ 0); // yday
+ ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
+
+ // 1970-02-01 00:00:00.
+ result = call_ctime(&tm_data,
+ 1970, // year
+ 2, // month
+ 1, // day
+ 0, // hr
+ 0, // min
+ 0, // sec
+ 0, // wday
+ 0); // yday
+ ASSERT_STREQ("Sun Feb 1 00:00:00 1970\n", result);
+
+ // 1970-12-31 23:59:59.
+ result = call_ctime(&tm_data,
+ 1970, // year
+ 12, // month
+ 31, // day
+ 23, // hr
+ 59, // min
+ 59, // sec
+ 4, // wday
+ 0); // yday
+ ASSERT_STREQ("Thu Dec 31 23:59:59 1970\n", result);
+}
+
+TEST(LlvmLibcCtime, EndOf32BitEpochYear) {
+ struct tm tm_data;
+ char *result;
+ // Test for maximum value of a signed 32-bit integer.
+ // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC.
+ result = call_ctime(&tm_data,
+ 2038, // year
+ 1, // month
+ 19, // day
+ 3, // hr
+ 14, // min
+ 7, // sec
+ 2, // wday
+ 7); // yday
+ ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result);
+}
+
+TEST(LlvmLibcCtime, Max64BitYear) {
+ if (sizeof(time_t) == 4)
+ return;
+ // Mon Jan 1 12:50:50 2170 (200 years from 1970),
+ struct tm tm_data;
+ char *result;
+ result = call_ctime(&tm_data,
+ 2170, // year
+ 1, // month
+ 1, // day
+ 12, // hr
+ 50, // min
+ 50, // sec
+ 1, // wday
+ 50); // yday
+ ASSERT_STREQ("Mon Jan 1 12:50:50 2170\n", result);
+
+ // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year.
+ // This test would cause buffer overflow and thus asctime returns nullptr.
+ result = call_ctime(&tm_data,
+ 2147483647, // year
+ 1, // month
+ 1, // day
+ 12, // hr
+ 50, // min
+ 50, // sec
+ 2, // wday
+ 50); // yday
+ ASSERT_ERRNO_EQ(EOVERFLOW);
+ ASSERT_STREQ(nullptr, result);
+}
>From bbbd2a9ca60d1e492b5f0c7cb909770e6d504703 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Wed, 4 Sep 2024 18:51:34 +0200
Subject: [PATCH 02/27] [libc][c11] implement ctime
remove buffer length
---
libc/src/time/time_utils.h | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 6fa590fefac8d0..6b2480bc1c0fb0 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -148,8 +148,7 @@ LIBC_INLINE char *asctime(const struct tm *timeptr, char *buffer,
return buffer;
}
-LIBC_INLINE char *ctime(const struct tm *timeptr, char *buffer,
- size_t bufferLength) {
+LIBC_INLINE char *ctime(const struct tm *timeptr, char *buffer) {
if (timeptr == nullptr || buffer == nullptr) {
invalid_value();
return nullptr;
@@ -177,13 +176,13 @@ LIBC_INLINE char *ctime(const struct tm *timeptr, char *buffer,
// be emitted as a call to snprintf. Alternatively, look into using our
// internal printf machinery.
int written_size = __builtin_snprintf(
- buffer, bufferLength, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
+ buffer, strlen(buffer), "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
week_days_name[timeptr->tm_wday], months_name[timeptr->tm_mon],
timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec,
TimeConstants::TIME_YEAR_BASE + timeptr->tm_year);
if (written_size < 0)
return nullptr;
- if (static_cast<size_t>(written_size) >= bufferLength) {
+ if (static_cast<size_t>(written_size) >= strlen(buffer)) {
out_of_range();
return nullptr;
}
>From e146ac1516944cad0c2e419dd7868b854fb93778 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Wed, 4 Sep 2024 19:11:37 +0200
Subject: [PATCH 03/27] [libc][c11] implement ctime
fix: buffer length
---
libc/src/time/time_utils.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 6b2480bc1c0fb0..2386d149072475 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -176,7 +176,7 @@ LIBC_INLINE char *ctime(const struct tm *timeptr, char *buffer) {
// be emitted as a call to snprintf. Alternatively, look into using our
// internal printf machinery.
int written_size = __builtin_snprintf(
- buffer, strlen(buffer), "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
+ buffer, strlen(buffer)+32, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
week_days_name[timeptr->tm_wday], months_name[timeptr->tm_mon],
timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec,
TimeConstants::TIME_YEAR_BASE + timeptr->tm_year);
>From eb02ef75d5fcec26900d40701c96d0a27abd041c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Wed, 4 Sep 2024 19:27:58 +0200
Subject: [PATCH 04/27] [libc][c11] implement ctime
add buffer length
---
libc/src/time/time_utils.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 2386d149072475..c4c8b771f865fc 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -148,7 +148,7 @@ LIBC_INLINE char *asctime(const struct tm *timeptr, char *buffer,
return buffer;
}
-LIBC_INLINE char *ctime(const struct tm *timeptr, char *buffer) {
+LIBC_INLINE char *ctime(const struct tm *timeptr, char *buffer, size_t buffer_length) {
if (timeptr == nullptr || buffer == nullptr) {
invalid_value();
return nullptr;
@@ -176,13 +176,13 @@ LIBC_INLINE char *ctime(const struct tm *timeptr, char *buffer) {
// be emitted as a call to snprintf. Alternatively, look into using our
// internal printf machinery.
int written_size = __builtin_snprintf(
- buffer, strlen(buffer)+32, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
+ buffer, buffer_length, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
week_days_name[timeptr->tm_wday], months_name[timeptr->tm_mon],
timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec,
TimeConstants::TIME_YEAR_BASE + timeptr->tm_year);
if (written_size < 0)
return nullptr;
- if (static_cast<size_t>(written_size) >= strlen(buffer)) {
+ if (static_cast<size_t>(written_size) >= buffer_length) {
out_of_range();
return nullptr;
}
>From 12adb50dc09d9d500ffad40dc58e2a6d94e7073c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Wed, 4 Sep 2024 19:43:41 +0200
Subject: [PATCH 05/27] [libc][c11] implement ctime
fix: ctime implementation
---
libc/src/time/time_utils.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index c4c8b771f865fc..4cf32ee64cec11 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -148,11 +148,14 @@ LIBC_INLINE char *asctime(const struct tm *timeptr, char *buffer,
return buffer;
}
-LIBC_INLINE char *ctime(const struct tm *timeptr, char *buffer, size_t buffer_length) {
- if (timeptr == nullptr || buffer == nullptr) {
+LIBC_INLINE char *ctime(const time_t *t_ptr, char *buffer,
+ size_t buffer_length) {
+ if (t_ptr == nullptr || buffer == nullptr) {
invalid_value();
return nullptr;
}
+ const struct tm *timeptr;
+ timeptr = localtime(t_ptr);
if (timeptr->tm_wday < 0 ||
timeptr->tm_wday > (TimeConstants::DAYS_PER_WEEK - 1)) {
invalid_value();
@@ -189,7 +192,6 @@ LIBC_INLINE char *ctime(const struct tm *timeptr, char *buffer, size_t buffer_le
return buffer;
}
-
LIBC_INLINE struct tm *gmtime_internal(const time_t *timer, struct tm *result) {
int64_t seconds = *timer;
// Update the tm structure's year, month, day, etc. from seconds.
>From b10a47054c26a047e524a424badde2aeb894483b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Wed, 4 Sep 2024 19:55:59 +0200
Subject: [PATCH 06/27] [libc][c11] implement ctime
fix: tests
---
libc/test/src/time/ctime_test.cpp | 46 +++++++++++++++----------------
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/libc/test/src/time/ctime_test.cpp b/libc/test/src/time/ctime_test.cpp
index bbf915188eacee..bcc4fe16f795b2 100644
--- a/libc/test/src/time/ctime_test.cpp
+++ b/libc/test/src/time/ctime_test.cpp
@@ -12,12 +12,12 @@
#include "test/UnitTest/Test.h"
#include "test/src/time/TmHelper.h"
-static inline char *call_ctime(struct tm *tm_data, int year, int month,
+static inline char *call_ctime(struct time_t *t, int year, int month,
int mday, int hour, int min, int sec, int wday,
int yday) {
LIBC_NAMESPACE::tmhelper::testing::initialize_tm_data(
- tm_data, year, month, mday, hour, min, sec, wday, yday);
- return LIBC_NAMESPACE::ctime(tm_data);
+ localtime(t), year, month, mday, hour, min, sec, wday, yday);
+ return LIBC_NAMESPACE::ctime(t);
}
TEST(LlvmLibcCtime, Nullptr) {
@@ -29,10 +29,10 @@ TEST(LlvmLibcCtime, Nullptr) {
// Weekdays are in the range 0 to 6. Test passing invalid value in wday.
TEST(LlvmLibcCtime, InvalidWday) {
- struct tm tm_data;
+ struct time_t t;
// Test with wday = -1.
- call_ctime(&tm_data,
+ call_ctime(&t,
1970, // year
1, // month
1, // day
@@ -44,7 +44,7 @@ TEST(LlvmLibcCtime, InvalidWday) {
ASSERT_ERRNO_EQ(EINVAL);
// Test with wday = 7.
- call_ctime(&tm_data,
+ call_ctime(&t,
1970, // year
1, // month
1, // day
@@ -58,10 +58,10 @@ TEST(LlvmLibcCtime, InvalidWday) {
// Months are from January to December. Test passing invalid value in month.
TEST(LlvmLibcCtime, InvalidMonth) {
- struct tm tm_data;
+ struct time_t t;
// Test with month = 0.
- call_ctime(&tm_data,
+ call_ctime(&t,
1970, // year
0, // month
1, // day
@@ -73,7 +73,7 @@ TEST(LlvmLibcCtime, InvalidMonth) {
ASSERT_ERRNO_EQ(EINVAL);
// Test with month = 13.
- call_ctime(&tm_data,
+ call_ctime(&t,
1970, // year
13, // month
1, // day
@@ -86,10 +86,10 @@ TEST(LlvmLibcCtime, InvalidMonth) {
}
TEST(LlvmLibcCtime, ValidWeekdays) {
- struct tm tm_data;
+ struct time_t t;
char *result;
// 1970-01-01 00:00:00.
- result = call_ctime(&tm_data,
+ result = call_ctime(&t,
1970, // year
1, // month
1, // day
@@ -101,7 +101,7 @@ TEST(LlvmLibcCtime, ValidWeekdays) {
ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
// 1970-01-03 00:00:00.
- result = call_ctime(&tm_data,
+ result = call_ctime(&t,
1970, // year
1, // month
3, // day
@@ -113,7 +113,7 @@ TEST(LlvmLibcCtime, ValidWeekdays) {
ASSERT_STREQ("Sat Jan 3 00:00:00 1970\n", result);
// 1970-01-04 00:00:00.
- result = call_ctime(&tm_data,
+ result = call_ctime(&t,
1970, // year
1, // month
4, // day
@@ -126,10 +126,10 @@ TEST(LlvmLibcCtime, ValidWeekdays) {
}
TEST(LlvmLibcCtime, ValidMonths) {
- struct tm tm_data;
+ struct time_t t;
char *result;
// 1970-01-01 00:00:00.
- result = call_ctime(&tm_data,
+ result = call_ctime(&t,
1970, // year
1, // month
1, // day
@@ -141,7 +141,7 @@ TEST(LlvmLibcCtime, ValidMonths) {
ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
// 1970-02-01 00:00:00.
- result = call_ctime(&tm_data,
+ result = call_ctime(&t,
1970, // year
2, // month
1, // day
@@ -153,7 +153,7 @@ TEST(LlvmLibcCtime, ValidMonths) {
ASSERT_STREQ("Sun Feb 1 00:00:00 1970\n", result);
// 1970-12-31 23:59:59.
- result = call_ctime(&tm_data,
+ result = call_ctime(&t,
1970, // year
12, // month
31, // day
@@ -166,11 +166,11 @@ TEST(LlvmLibcCtime, ValidMonths) {
}
TEST(LlvmLibcCtime, EndOf32BitEpochYear) {
- struct tm tm_data;
+ struct time_t t;
char *result;
// Test for maximum value of a signed 32-bit integer.
// Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC.
- result = call_ctime(&tm_data,
+ result = call_ctime(&t,
2038, // year
1, // month
19, // day
@@ -186,9 +186,9 @@ TEST(LlvmLibcCtime, Max64BitYear) {
if (sizeof(time_t) == 4)
return;
// Mon Jan 1 12:50:50 2170 (200 years from 1970),
- struct tm tm_data;
+ struct time_t t;
char *result;
- result = call_ctime(&tm_data,
+ result = call_ctime(&t,
2170, // year
1, // month
1, // day
@@ -200,8 +200,8 @@ TEST(LlvmLibcCtime, Max64BitYear) {
ASSERT_STREQ("Mon Jan 1 12:50:50 2170\n", result);
// Test for Tue Jan 1 12:50:50 in 2,147,483,647th year.
- // This test would cause buffer overflow and thus asctime returns nullptr.
- result = call_ctime(&tm_data,
+ // This test would cause buffer overflow and thus ctime returns nullptr.
+ result = call_ctime(&t,
2147483647, // year
1, // month
1, // day
>From bd482baa9922c0aeb34c617fcbc943fb6c811bb5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Wed, 4 Sep 2024 20:01:34 +0200
Subject: [PATCH 07/27] [libc][ctime] ctime implementation
fix: function declaration
---
libc/src/time/ctime.cpp | 6 +++---
libc/src/time/ctime.h | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libc/src/time/ctime.cpp b/libc/src/time/ctime.cpp
index f3181816ad9ab1..5997018689c802 100644
--- a/libc/src/time/ctime.cpp
+++ b/libc/src/time/ctime.cpp
@@ -1,4 +1,4 @@
-//===-- Implementation of asctime function --------------------------------===//
+//===-- Implementation of ctime function --------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -15,9 +15,9 @@ namespace LIBC_NAMESPACE_DECL {
using LIBC_NAMESPACE::time_utils::TimeConstants;
-LLVM_LIBC_FUNCTION(char *, ctime, (const struct tm *timeptr)) {
+LLVM_LIBC_FUNCTION(char *, ctime, (const time_t *t)) {
static char buffer[TimeConstants::CTIME_BUFFER_SIZE];
- return time_utils::ctime(timeptr, buffer, TimeConstants::CTIME_MAX_BYTES);
+ return time_utils::ctime(&t, buffer, TimeConstants::CTIME_MAX_BYTES);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/ctime.h b/libc/src/time/ctime.h
index ec5530ffb5bc71..b4e31ae852fe76 100644
--- a/libc/src/time/ctime.h
+++ b/libc/src/time/ctime.h
@@ -14,7 +14,7 @@
namespace LIBC_NAMESPACE_DECL {
-char *ctime(const struct tm *timeptr);
+char *ctime(const time_t *t);
} // namespace LIBC_NAMESPACE_DECL
>From a1d86d2430dc46bd8154307a6a63bcc9a632de07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Wed, 4 Sep 2024 20:09:03 +0200
Subject: [PATCH 08/27] [libc][c11] ctime implementation
format code with `clang-format`
---
libc/test/src/time/ctime_test.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/libc/test/src/time/ctime_test.cpp b/libc/test/src/time/ctime_test.cpp
index bcc4fe16f795b2..19daa88ddeb4d6 100644
--- a/libc/test/src/time/ctime_test.cpp
+++ b/libc/test/src/time/ctime_test.cpp
@@ -12,9 +12,8 @@
#include "test/UnitTest/Test.h"
#include "test/src/time/TmHelper.h"
-static inline char *call_ctime(struct time_t *t, int year, int month,
- int mday, int hour, int min, int sec, int wday,
- int yday) {
+static inline char *call_ctime(struct time_t *t, int year, int month, int mday,
+ int hour, int min, int sec, int wday, int yday) {
LIBC_NAMESPACE::tmhelper::testing::initialize_tm_data(
localtime(t), year, month, mday, hour, min, sec, wday, yday);
return LIBC_NAMESPACE::ctime(t);
>From de83e31dc35dde34ed920444d63facb4d1bdc7dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Wed, 4 Sep 2024 20:23:15 +0200
Subject: [PATCH 09/27] [libc][c11] implement ctime
implement `ctime_r`
---
libc/src/time/ctime.cpp | 2 +-
libc/src/time/ctime.h | 2 +-
libc/src/time/ctime_r.cpp | 22 +++++++++++
libc/src/time/ctime_r.h | 21 ++++++++++
libc/test/src/time/ctime_r_test.cpp | 60 +++++++++++++++++++++++++++++
libc/test/src/time/ctime_test.cpp | 2 +-
6 files changed, 106 insertions(+), 3 deletions(-)
create mode 100644 libc/src/time/ctime_r.cpp
create mode 100644 libc/src/time/ctime_r.h
create mode 100644 libc/test/src/time/ctime_r_test.cpp
diff --git a/libc/src/time/ctime.cpp b/libc/src/time/ctime.cpp
index 5997018689c802..7089d5f7ff0c38 100644
--- a/libc/src/time/ctime.cpp
+++ b/libc/src/time/ctime.cpp
@@ -1,4 +1,4 @@
-//===-- Implementation of ctime function --------------------------------===//
+//===-- Implementation of ctime function ----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/src/time/ctime.h b/libc/src/time/ctime.h
index b4e31ae852fe76..4afc8fddc8c44a 100644
--- a/libc/src/time/ctime.h
+++ b/libc/src/time/ctime.h
@@ -1,4 +1,4 @@
-//===-- Implementation header of ctime ------------------------*- C++ -*-===//
+//===-- Implementation header of ctime --------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/src/time/ctime_r.cpp b/libc/src/time/ctime_r.cpp
new file mode 100644
index 00000000000000..c25217d8d22cfc
--- /dev/null
+++ b/libc/src/time/ctime_r.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation of ctime_r function --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/time/ctime_r.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/time/time_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+using LIBC_NAMESPACE::time_utils::TimeConstants;
+
+LLVM_LIBC_FUNCTION(char *, ctime_r, (const time_t *t, char *buffer)) {
+ return time_utils::ctime(t, buffer, TimeConstants::CTIME_MAX_BYTES);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/ctime_r.h b/libc/src/time/ctime_r.h
new file mode 100644
index 00000000000000..688646c8d12674
--- /dev/null
+++ b/libc/src/time/ctime_r.h
@@ -0,0 +1,21 @@
+//===-- Implementation header of ctime_r ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_TIME_ASCTIME_R_H
+#define LLVM_LIBC_SRC_TIME_ASCTIME_R_H
+
+#include "src/__support/macros/config.h"
+#include <time.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+char *ctime_r(const time_t *t, char *buffer);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TIME_CTIME_R_H
diff --git a/libc/test/src/time/ctime_r_test.cpp b/libc/test/src/time/ctime_r_test.cpp
new file mode 100644
index 00000000000000..ab742368f02cc3
--- /dev/null
+++ b/libc/test/src/time/ctime_r_test.cpp
@@ -0,0 +1,60 @@
+//===-- Unittests for ctime_r ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/errno/libc_errno.h"
+#include "src/time/ctime_r.h"
+#include "src/time/time_utils.h"
+#include "test/UnitTest/Test.h"
+#include "test/src/time/TmHelper.h"
+
+using LIBC_NAMESPACE::time_utils::TimeConstants;
+
+static inline char *call_ctime_r(time_t *t, int year, int month, int mday,
+ int hour, int min, int sec, int wday, int yday,
+ char *buffer) {
+ LIBC_NAMESPACE::tmhelper::testing::initialize_tm_data(
+ localtime(t), year, month, mday, hour, min, sec, wday, yday);
+ return LIBC_NAMESPACE::ctime_r(t, buffer);
+}
+
+// ctime and ctime_r share the same code and thus didn't repeat all the
+// tests from ctime. Added couple of validation tests.
+TEST(LlvmLibcCtimeR, Nullptr) {
+ char *result;
+ result = LIBC_NAMESPACE::ctime_r(nullptr, nullptr);
+ ASSERT_ERRNO_EQ(EINVAL);
+ ASSERT_STREQ(nullptr, result);
+
+ char buffer[TimeConstants::CTIME_BUFFER_SIZE];
+ result = LIBC_NAMESPACE::ctime_r(nullptr, buffer);
+ ASSERT_ERRNO_EQ(EINVAL);
+ ASSERT_STREQ(nullptr, result);
+
+ time_t t;
+ result = LIBC_NAMESPACE::ctime_r(&tm_data, nullptr);
+ ASSERT_ERRNO_EQ(EINVAL);
+ ASSERT_STREQ(nullptr, result);
+}
+
+TEST(LlvmLibcCtimeR, ValidDate) {
+ char buffer[TimeConstants::CTIME_BUFFER_SIZE];
+ struct time_t t;
+ char *result;
+ // 1970-01-01 00:00:00. Test with a valid buffer size.
+ result = call_ctime_r(&t,
+ 1970, // year
+ 1, // month
+ 1, // day
+ 0, // hr
+ 0, // min
+ 0, // sec
+ 4, // wday
+ 0, // yday
+ buffer);
+ ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
+}
diff --git a/libc/test/src/time/ctime_test.cpp b/libc/test/src/time/ctime_test.cpp
index 19daa88ddeb4d6..6d1282e181baba 100644
--- a/libc/test/src/time/ctime_test.cpp
+++ b/libc/test/src/time/ctime_test.cpp
@@ -1,4 +1,4 @@
-//===-- Unittests for ctime ---------------------------------------------===//
+//===-- Unittests for ctime -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
>From b7d6c7398ee6dd7f9de72819577a14d224c803d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Wed, 4 Sep 2024 20:25:49 +0200
Subject: [PATCH 10/27] [libc][c11] implement ctime
fix: `ctime_r` header file
---
libc/src/time/ctime_r.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/src/time/ctime_r.h b/libc/src/time/ctime_r.h
index 688646c8d12674..93acad13c28e44 100644
--- a/libc/src/time/ctime_r.h
+++ b/libc/src/time/ctime_r.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIBC_SRC_TIME_ASCTIME_R_H
-#define LLVM_LIBC_SRC_TIME_ASCTIME_R_H
+#ifndef LLVM_LIBC_SRC_TIME_CTIME_R_H
+#define LLVM_LIBC_SRC_TIME_CTIME_R_H
#include "src/__support/macros/config.h"
#include <time.h>
>From 948786a3f51c5619c58a4c307ac17411a1ef82a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Wed, 4 Sep 2024 20:27:31 +0200
Subject: [PATCH 11/27] [libc][c11] implement ctime
add `ctime_r` to `cmake`
---
libc/src/time/CMakeLists.txt | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index befe67677f3ec7..1605a6b897c14b 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -47,6 +47,17 @@ add_entrypoint_object(
libc.include.time
)
+add_entrypoint_object(
+ ctime_r
+ SRCS
+ ctime_r.cpp
+ HDRS
+ ctime_r.h
+ DEPENDS
+ .time_utils
+ libc.include.time
+)
+
add_entrypoint_object(
difftime
SRCS
>From 574583a7f8db33516bbee82414e71943d7588e59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 13:02:46 +0200
Subject: [PATCH 12/27] [libc][c11] implement ctime
add `ctime` and `ctime_r` to build system
---
libc/config/linux/x86_64/entrypoints.txt | 2 ++
libc/newhdrgen/yaml/time.yaml | 13 +++++++++++++
libc/spec/stdc.td | 13 +++++++++++++
3 files changed, 28 insertions(+)
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 3fd88fc0020e55..2a38db5bcdad8c 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1003,6 +1003,8 @@ if(LLVM_LIBC_FULL_BUILD)
# time.h entrypoints
libc.src.time.asctime
libc.src.time.asctime_r
+ libc.src.time.ctime
+ libc.src.time.ctime_r
libc.src.time.clock
libc.src.time.clock_gettime
libc.src.time.difftime
diff --git a/libc/newhdrgen/yaml/time.yaml b/libc/newhdrgen/yaml/time.yaml
index d2344671831c7a..69b40bef3160dd 100644
--- a/libc/newhdrgen/yaml/time.yaml
+++ b/libc/newhdrgen/yaml/time.yaml
@@ -24,6 +24,19 @@ functions:
arguments:
- type: struct tm *
- type: char *
+ - name: ctime
+ standard:
+ - stdc
+ return_type: char *
+ arguments:
+ - type: const time_t *
+ - name: ctime_r
+ standard:
+ - stdc
+ return_type: char *
+ arguments:
+ - type: const time_t *
+ - type: char *
- name: clock
standard:
- stdc
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index a4ae3e1ff7d9c6..f5ae14ab12d705 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -1600,6 +1600,19 @@ def StdC : StandardSpec<"stdc"> {
ArgSpec<CharPtr>,
]
>,
+ FunctionSpec<
+ "ctime",
+ RetValSpec<CharPtr>,
+ [ArgSpec<StructTmPtr>]
+ >,
+ FunctionSpec<
+ "ctime_r",
+ RetValSpec<CharPtr>,
+ [
+ ArgSpec<StructTmPtr>,
+ ArgSpec<CharPtr>,
+ ]
+ >,
FunctionSpec<
"clock",
RetValSpec<ClockT>,
>From 7743993d6017e94a4c138008d3f13ff0048bad24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 13:04:07 +0200
Subject: [PATCH 13/27] [libc][c11] implement ctime
refactor `ctime` and `ctime_r` to use `asctime`
---
libc/src/time/ctime.cpp | 4 ++--
libc/src/time/ctime.h | 2 +-
libc/src/time/time_utils.h | 44 --------------------------------------
3 files changed, 3 insertions(+), 47 deletions(-)
diff --git a/libc/src/time/ctime.cpp b/libc/src/time/ctime.cpp
index 7089d5f7ff0c38..ceea1e01bec0f8 100644
--- a/libc/src/time/ctime.cpp
+++ b/libc/src/time/ctime.cpp
@@ -15,9 +15,9 @@ namespace LIBC_NAMESPACE_DECL {
using LIBC_NAMESPACE::time_utils::TimeConstants;
-LLVM_LIBC_FUNCTION(char *, ctime, (const time_t *t)) {
+LLVM_LIBC_FUNCTION(char *, ctime, (const time_t *t_ptr)) {
static char buffer[TimeConstants::CTIME_BUFFER_SIZE];
- return time_utils::ctime(&t, buffer, TimeConstants::CTIME_MAX_BYTES);
+ return time_utils::asctime(localtime(&t_ptr), buffer, TimeConstants::CTIME_MAX_BYTES);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/ctime.h b/libc/src/time/ctime.h
index 4afc8fddc8c44a..d5be450d03f231 100644
--- a/libc/src/time/ctime.h
+++ b/libc/src/time/ctime.h
@@ -14,7 +14,7 @@
namespace LIBC_NAMESPACE_DECL {
-char *ctime(const time_t *t);
+char *ctime(const time_t *t_ptr);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 4cf32ee64cec11..688fac28fd2293 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -148,50 +148,6 @@ LIBC_INLINE char *asctime(const struct tm *timeptr, char *buffer,
return buffer;
}
-LIBC_INLINE char *ctime(const time_t *t_ptr, char *buffer,
- size_t buffer_length) {
- if (t_ptr == nullptr || buffer == nullptr) {
- invalid_value();
- return nullptr;
- }
- const struct tm *timeptr;
- timeptr = localtime(t_ptr);
- if (timeptr->tm_wday < 0 ||
- timeptr->tm_wday > (TimeConstants::DAYS_PER_WEEK - 1)) {
- invalid_value();
- return nullptr;
- }
- if (timeptr->tm_mon < 0 ||
- timeptr->tm_mon > (TimeConstants::MONTHS_PER_YEAR - 1)) {
- invalid_value();
- return nullptr;
- }
-
- // TODO(rtenneti): i18n the following strings.
- static const char *week_days_name[TimeConstants::DAYS_PER_WEEK] = {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
-
- static const char *months_name[TimeConstants::MONTHS_PER_YEAR] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-
- // TODO(michaelr): look into removing this call to __builtin_snprintf that may
- // be emitted as a call to snprintf. Alternatively, look into using our
- // internal printf machinery.
- int written_size = __builtin_snprintf(
- buffer, buffer_length, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
- week_days_name[timeptr->tm_wday], months_name[timeptr->tm_mon],
- timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec,
- TimeConstants::TIME_YEAR_BASE + timeptr->tm_year);
- if (written_size < 0)
- return nullptr;
- if (static_cast<size_t>(written_size) >= buffer_length) {
- out_of_range();
- return nullptr;
- }
- return buffer;
-}
-
LIBC_INLINE struct tm *gmtime_internal(const time_t *timer, struct tm *result) {
int64_t seconds = *timer;
// Update the tm structure's year, month, day, etc. from seconds.
>From 2db41fce94abf0c600a274cd7f66161656f92539 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 13:10:02 +0200
Subject: [PATCH 14/27] [libc][c11] implement ctime
fix: `ctime_r`
---
libc/src/time/ctime.cpp | 2 +-
libc/src/time/ctime_r.cpp | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libc/src/time/ctime.cpp b/libc/src/time/ctime.cpp
index ceea1e01bec0f8..d4bcc6a5bc014e 100644
--- a/libc/src/time/ctime.cpp
+++ b/libc/src/time/ctime.cpp
@@ -17,7 +17,7 @@ using LIBC_NAMESPACE::time_utils::TimeConstants;
LLVM_LIBC_FUNCTION(char *, ctime, (const time_t *t_ptr)) {
static char buffer[TimeConstants::CTIME_BUFFER_SIZE];
- return time_utils::asctime(localtime(&t_ptr), buffer, TimeConstants::CTIME_MAX_BYTES);
+ return time_utils::asctime(localtime(t_ptr), buffer, TimeConstants::CTIME_MAX_BYTES);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/ctime_r.cpp b/libc/src/time/ctime_r.cpp
index c25217d8d22cfc..b046b04a2e333b 100644
--- a/libc/src/time/ctime_r.cpp
+++ b/libc/src/time/ctime_r.cpp
@@ -15,8 +15,8 @@ namespace LIBC_NAMESPACE_DECL {
using LIBC_NAMESPACE::time_utils::TimeConstants;
-LLVM_LIBC_FUNCTION(char *, ctime_r, (const time_t *t, char *buffer)) {
- return time_utils::ctime(t, buffer, TimeConstants::CTIME_MAX_BYTES);
+LLVM_LIBC_FUNCTION(char *, ctime_r, (const time_t *t_ptr, char *buffer)) {
+ return time_utils::asctime(localtime(t_ptr), buffer, TimeConstants::CTIME_MAX_BYTES);
}
} // namespace LIBC_NAMESPACE_DECL
>From 1fd0113bc57e004de03e7a637d5d5a14871b7ef8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 13:14:14 +0200
Subject: [PATCH 15/27] [libc][c11] implement ctime
add `ctime` and `ctime_r` to `aarch64` and `riscv` architecture
---
libc/config/linux/aarch64/entrypoints.txt | 2 ++
libc/config/linux/riscv/entrypoints.txt | 2 ++
2 files changed, 4 insertions(+)
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 60aa7f5ccb319a..64fbe1a250c0ba 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -948,6 +948,8 @@ if(LLVM_LIBC_FULL_BUILD)
# time.h entrypoints
libc.src.time.asctime
libc.src.time.asctime_r
+ libc.src.time.ctime
+ libc.src.time.ctime_r
libc.src.time.clock
libc.src.time.clock_gettime
libc.src.time.difftime
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 9a2746dcb86f87..ff3d821c664c5b 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -883,6 +883,8 @@ if(LLVM_LIBC_FULL_BUILD)
# time.h entrypoints
libc.src.time.asctime
libc.src.time.asctime_r
+ libc.src.time.ctime
+ libc.src.time.ctime_r
libc.src.time.clock
libc.src.time.clock_gettime
libc.src.time.difftime
>From 2f1a873fe1edfdb169839b7cf78d1d04365d8d83 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 14:04:59 +0200
Subject: [PATCH 16/27] [libc][c11] implement ctime
add `ctime` and `ctime_r` to more architectures
---
libc/config/baremetal/arm/entrypoints.txt | 2 ++
libc/config/baremetal/riscv/entrypoints.txt | 2 ++
2 files changed, 4 insertions(+)
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index af9a8bc9925441..68030f7f1775b5 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -203,6 +203,8 @@ set(TARGET_LIBC_ENTRYPOINTS
# time.h entrypoints
libc.src.time.asctime
libc.src.time.asctime_r
+ libc.src.time.ctime
+ libc.src.time.ctime_r
libc.src.time.difftime
libc.src.time.gmtime
libc.src.time.gmtime_r
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 6ebe2e4a29025f..5894b591072ef0 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -199,6 +199,8 @@ set(TARGET_LIBC_ENTRYPOINTS
# time.h entrypoints
libc.src.time.asctime
libc.src.time.asctime_r
+ libc.src.time.ctime
+ libc.src.time.ctime_r
libc.src.time.difftime
libc.src.time.gmtime
libc.src.time.gmtime_r
>From cd65c212e4d109b8670f14c9340f4dc63994e15f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 14:06:10 +0200
Subject: [PATCH 17/27] [libc][c11] implement ctime
- add symbols for `ctime` and `ctime_r`
- add `ctime` and `ctime_r` to clang formatted files list
- add `ctime` to env32-c test
---
clang/docs/tools/clang-formatted-files.txt | 4 ++++
clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc | 2 ++
clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc | 3 +++
clang/test/Analysis/cert/env34-c.c | 1 +
4 files changed, 10 insertions(+)
diff --git a/clang/docs/tools/clang-formatted-files.txt b/clang/docs/tools/clang-formatted-files.txt
index fc07357986d989..2261a726235c1b 100644
--- a/clang/docs/tools/clang-formatted-files.txt
+++ b/clang/docs/tools/clang-formatted-files.txt
@@ -3062,6 +3062,10 @@ libc/src/time/asctime.cpp
libc/src/time/asctime.h
libc/src/time/asctime_r.cpp
libc/src/time/asctime_r.h
+libc/src/time/ctime.cpp
+libc/src/time/ctime.h
+libc/src/time/ctime_r.cpp
+libc/src/time/ctime_r.h
libc/src/time/gmtime.cpp
libc/src/time/gmtime.h
libc/src/time/gmtime_r.cpp
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc b/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
index 463ce921f0672f..849aad0b227da6 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
@@ -220,6 +220,8 @@ SYMBOL(and, None, <iso646.h>)
SYMBOL(and_eq, None, <iso646.h>)
SYMBOL(asctime, None, <time.h>)
SYMBOL(asctime_s, None, <time.h>)
+SYMBOL(ctime, None, <time.h>)
+SYMBOL(ctime_s, None, <time.h>)
SYMBOL(asin, None, <math.h>)
SYMBOL(asinf, None, <math.h>)
SYMBOL(asinh, None, <math.h>)
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc b/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
index b46bd2e4d7a4b5..7f0e32b6233e9c 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
@@ -617,6 +617,9 @@ SYMBOL(as_writable_bytes, std::, <span>)
SYMBOL(asctime, std::, <ctime>)
SYMBOL(asctime, None, <ctime>)
SYMBOL(asctime, None, <time.h>)
+SYMBOL(ctime, std::, <ctime>)
+SYMBOL(ctime, None, <ctime>)
+SYMBOL(ctime, None, <time.h>)
SYMBOL(asin, std::, <cmath>)
SYMBOL(asin, None, <cmath>)
SYMBOL(asin, None, <math.h>)
diff --git a/clang/test/Analysis/cert/env34-c.c b/clang/test/Analysis/cert/env34-c.c
index d307f0d8f4bb01..79facfe547fa12 100644
--- a/clang/test/Analysis/cert/env34-c.c
+++ b/clang/test/Analysis/cert/env34-c.c
@@ -16,6 +16,7 @@ lconv *localeconv(void);
typedef struct {
} tm;
char *asctime(const tm *timeptr);
+char *ctime(const time_t *timeptr);
int strcmp(const char*, const char*);
extern void foo(char *e);
>From 207e1e0d49c54ecef2a80d8d95659cdd7ef68ca4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 14:34:17 +0200
Subject: [PATCH 18/27] [libc][c11] implement ctime
add header for `time_t`
---
clang/test/Analysis/cert/env34-c.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/test/Analysis/cert/env34-c.c b/clang/test/Analysis/cert/env34-c.c
index 79facfe547fa12..618c089624675e 100644
--- a/clang/test/Analysis/cert/env34-c.c
+++ b/clang/test/Analysis/cert/env34-c.c
@@ -3,6 +3,7 @@
// RUN: -analyzer-config security.cert.env.InvalidPtr:InvalidatingGetEnv=true \
// RUN: -analyzer-output=text -verify -Wno-unused %s
+#include <time.h>
#include "../Inputs/system-header-simulator.h"
char *getenv(const char *name);
char *setlocale(int category, const char *locale);
>From 925a6a6be58bc75493ecfd8da2e94e1423cf7c6d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 14:58:51 +0200
Subject: [PATCH 19/27] [libc][c11] implement ctime
removed `ctime` from analysis test
---
clang/test/Analysis/cert/env34-c.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/clang/test/Analysis/cert/env34-c.c b/clang/test/Analysis/cert/env34-c.c
index 618c089624675e..d307f0d8f4bb01 100644
--- a/clang/test/Analysis/cert/env34-c.c
+++ b/clang/test/Analysis/cert/env34-c.c
@@ -3,7 +3,6 @@
// RUN: -analyzer-config security.cert.env.InvalidPtr:InvalidatingGetEnv=true \
// RUN: -analyzer-output=text -verify -Wno-unused %s
-#include <time.h>
#include "../Inputs/system-header-simulator.h"
char *getenv(const char *name);
char *setlocale(int category, const char *locale);
@@ -17,7 +16,6 @@ lconv *localeconv(void);
typedef struct {
} tm;
char *asctime(const tm *timeptr);
-char *ctime(const time_t *timeptr);
int strcmp(const char*, const char*);
extern void foo(char *e);
>From 82ab5543f3895c15085605f8b6c877c87c058b40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 16:13:43 +0200
Subject: [PATCH 20/27] [libc][c11] implement ctime
fix: `time_t` definition in `stdc.td`
---
libc/spec/stdc.td | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index f5ae14ab12d705..a8d319d6f8380a 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -3,6 +3,8 @@ def StdC : StandardSpec<"stdc"> {
NamedType StructTmType = NamedType<"struct tm">;
PtrType StructTmPtr = PtrType<StructTmType>;
PtrType TimeTTypePtr = PtrType<TimeTType>;
+ NamedType StructTimeTType = NamedType<"time_t">;
+ PtrType StructTimeTPtr = PtrType<StructTimeTType>;
NamedType ClockT = NamedType<"clock_t">;
NamedType LocaleT = NamedType<"locale_t">;
@@ -1603,13 +1605,13 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<
"ctime",
RetValSpec<CharPtr>,
- [ArgSpec<StructTmPtr>]
+ [ArgSpec<StructTimeTPtr>]
>,
FunctionSpec<
"ctime_r",
RetValSpec<CharPtr>,
[
- ArgSpec<StructTmPtr>,
+ ArgSpec<StructTimeTPtr>,
ArgSpec<CharPtr>,
]
>,
>From 6fa3bc0bf292486b38c4365445e136a3afad26ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 16:49:58 +0200
Subject: [PATCH 21/27] [libc][c11] implement ctime
fix: removed `ctime_s`
---
clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc b/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
index 849aad0b227da6..b1f7dc286429cd 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
@@ -221,7 +221,6 @@ SYMBOL(and_eq, None, <iso646.h>)
SYMBOL(asctime, None, <time.h>)
SYMBOL(asctime_s, None, <time.h>)
SYMBOL(ctime, None, <time.h>)
-SYMBOL(ctime_s, None, <time.h>)
SYMBOL(asin, None, <math.h>)
SYMBOL(asinf, None, <math.h>)
SYMBOL(asinh, None, <math.h>)
>From a16d1a965ea0a9642b135a2bd09252955402b3ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 16:51:08 +0200
Subject: [PATCH 22/27] [libc][c11] implement ctime
add `ctime` and `ctime_r` to unsafe functions check
---
clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
index ea7eaa0b0ff811..a23f7ea87abe10 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
@@ -42,7 +42,7 @@ static StringRef getReplacementFor(StringRef FunctionName,
// Try to find a better replacement from Annex K first.
StringRef AnnexKReplacementFunction =
StringSwitch<StringRef>(FunctionName)
- .Cases("asctime", "asctime_r", "asctime_s")
+ .Cases("asctime", "asctime_r", "asctime_s", "ctime", "ctime_r")
.Case("gets", "gets_s")
.Default({});
if (!AnnexKReplacementFunction.empty())
>From f41a8ed581ac5a56fdb5e5360d99498850c77de6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 20:19:06 +0200
Subject: [PATCH 23/27] [libc][c11] implement ctime
fix: tests
---
libc/test/src/time/ctime_test.cpp | 194 ++----------------------------
1 file changed, 8 insertions(+), 186 deletions(-)
diff --git a/libc/test/src/time/ctime_test.cpp b/libc/test/src/time/ctime_test.cpp
index 6d1282e181baba..c55fdb1b614aeb 100644
--- a/libc/test/src/time/ctime_test.cpp
+++ b/libc/test/src/time/ctime_test.cpp
@@ -12,10 +12,7 @@
#include "test/UnitTest/Test.h"
#include "test/src/time/TmHelper.h"
-static inline char *call_ctime(struct time_t *t, int year, int month, int mday,
- int hour, int min, int sec, int wday, int yday) {
- LIBC_NAMESPACE::tmhelper::testing::initialize_tm_data(
- localtime(t), year, month, mday, hour, min, sec, wday, yday);
+static inline char *call_ctime(struct time_t *t) {
return LIBC_NAMESPACE::ctime(t);
}
@@ -26,189 +23,14 @@ TEST(LlvmLibcCtime, Nullptr) {
ASSERT_STREQ(nullptr, result);
}
-// Weekdays are in the range 0 to 6. Test passing invalid value in wday.
-TEST(LlvmLibcCtime, InvalidWday) {
- struct time_t t;
-
- // Test with wday = -1.
- call_ctime(&t,
- 1970, // year
- 1, // month
- 1, // day
- 0, // hr
- 0, // min
- 0, // sec
- -1, // wday
- 0); // yday
- ASSERT_ERRNO_EQ(EINVAL);
-
- // Test with wday = 7.
- call_ctime(&t,
- 1970, // year
- 1, // month
- 1, // day
- 0, // hr
- 0, // min
- 0, // sec
- 7, // wday
- 0); // yday
- ASSERT_ERRNO_EQ(EINVAL);
-}
-
-// Months are from January to December. Test passing invalid value in month.
-TEST(LlvmLibcCtime, InvalidMonth) {
- struct time_t t;
-
- // Test with month = 0.
- call_ctime(&t,
- 1970, // year
- 0, // month
- 1, // day
- 0, // hr
- 0, // min
- 0, // sec
- 4, // wday
- 0); // yday
- ASSERT_ERRNO_EQ(EINVAL);
-
- // Test with month = 13.
- call_ctime(&t,
- 1970, // year
- 13, // month
- 1, // day
- 0, // hr
- 0, // min
- 0, // sec
- 4, // wday
- 0); // yday
- ASSERT_ERRNO_EQ(EINVAL);
-}
-
-TEST(LlvmLibcCtime, ValidWeekdays) {
- struct time_t t;
- char *result;
- // 1970-01-01 00:00:00.
- result = call_ctime(&t,
- 1970, // year
- 1, // month
- 1, // day
- 0, // hr
- 0, // min
- 0, // sec
- 4, // wday
- 0); // yday
+TEST(LlvmLibcCtime, ValidUnixTimestamp0) {
+ struct time_t t = 0;
+ char* result = call_ctime(&t);
ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
-
- // 1970-01-03 00:00:00.
- result = call_ctime(&t,
- 1970, // year
- 1, // month
- 3, // day
- 0, // hr
- 0, // min
- 0, // sec
- 6, // wday
- 0); // yday
- ASSERT_STREQ("Sat Jan 3 00:00:00 1970\n", result);
-
- // 1970-01-04 00:00:00.
- result = call_ctime(&t,
- 1970, // year
- 1, // month
- 4, // day
- 0, // hr
- 0, // min
- 0, // sec
- 0, // wday
- 0); // yday
- ASSERT_STREQ("Sun Jan 4 00:00:00 1970\n", result);
-}
-
-TEST(LlvmLibcCtime, ValidMonths) {
- struct time_t t;
- char *result;
- // 1970-01-01 00:00:00.
- result = call_ctime(&t,
- 1970, // year
- 1, // month
- 1, // day
- 0, // hr
- 0, // min
- 0, // sec
- 4, // wday
- 0); // yday
- ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
-
- // 1970-02-01 00:00:00.
- result = call_ctime(&t,
- 1970, // year
- 2, // month
- 1, // day
- 0, // hr
- 0, // min
- 0, // sec
- 0, // wday
- 0); // yday
- ASSERT_STREQ("Sun Feb 1 00:00:00 1970\n", result);
-
- // 1970-12-31 23:59:59.
- result = call_ctime(&t,
- 1970, // year
- 12, // month
- 31, // day
- 23, // hr
- 59, // min
- 59, // sec
- 4, // wday
- 0); // yday
- ASSERT_STREQ("Thu Dec 31 23:59:59 1970\n", result);
}
-TEST(LlvmLibcCtime, EndOf32BitEpochYear) {
- struct time_t t;
- char *result;
- // Test for maximum value of a signed 32-bit integer.
- // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC.
- result = call_ctime(&t,
- 2038, // year
- 1, // month
- 19, // day
- 3, // hr
- 14, // min
- 7, // sec
- 2, // wday
- 7); // yday
- ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result);
-}
-
-TEST(LlvmLibcCtime, Max64BitYear) {
- if (sizeof(time_t) == 4)
- return;
- // Mon Jan 1 12:50:50 2170 (200 years from 1970),
- struct time_t t;
- char *result;
- result = call_ctime(&t,
- 2170, // year
- 1, // month
- 1, // day
- 12, // hr
- 50, // min
- 50, // sec
- 1, // wday
- 50); // yday
- ASSERT_STREQ("Mon Jan 1 12:50:50 2170\n", result);
-
- // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year.
- // This test would cause buffer overflow and thus ctime returns nullptr.
- result = call_ctime(&t,
- 2147483647, // year
- 1, // month
- 1, // day
- 12, // hr
- 50, // min
- 50, // sec
- 2, // wday
- 50); // yday
- ASSERT_ERRNO_EQ(EOVERFLOW);
- ASSERT_STREQ(nullptr, result);
+TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) {
+ struct time_t t = 2147483647;
+ char* result = call_ctime(&t);
+ ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result);
}
>From cf3afc2770496d8e76a617add8b86c39195763d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 20:19:43 +0200
Subject: [PATCH 24/27] [libc][c11] implement ctime
use asctime constants and remove ctime constants
---
libc/src/time/ctime.cpp | 10 +++++-----
libc/src/time/ctime.h | 1 -
libc/src/time/ctime_r.cpp | 2 +-
libc/src/time/time_utils.h | 3 ---
4 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/libc/src/time/ctime.cpp b/libc/src/time/ctime.cpp
index d4bcc6a5bc014e..dffebc20f47a58 100644
--- a/libc/src/time/ctime.cpp
+++ b/libc/src/time/ctime.cpp
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#include "src/time/ctime.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/time/time_utils.h"
+#include "ctime.h"
+#include "../__support/common.h"
+#include "../__support/macros/config.h"
+#include "time_utils.h"
namespace LIBC_NAMESPACE_DECL {
@@ -17,7 +17,7 @@ using LIBC_NAMESPACE::time_utils::TimeConstants;
LLVM_LIBC_FUNCTION(char *, ctime, (const time_t *t_ptr)) {
static char buffer[TimeConstants::CTIME_BUFFER_SIZE];
- return time_utils::asctime(localtime(t_ptr), buffer, TimeConstants::CTIME_MAX_BYTES);
+ return time_utils::asctime(localtime(t_ptr), buffer, TimeConstants::ASCTIME_MAX_BYTES);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/ctime.h b/libc/src/time/ctime.h
index d5be450d03f231..6e9f5fa5d1382a 100644
--- a/libc/src/time/ctime.h
+++ b/libc/src/time/ctime.h
@@ -10,7 +10,6 @@
#define LLVM_LIBC_SRC_TIME_CTIME_H
#include "src/__support/macros/config.h"
-#include <time.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/time/ctime_r.cpp b/libc/src/time/ctime_r.cpp
index b046b04a2e333b..2fb7c814a822cc 100644
--- a/libc/src/time/ctime_r.cpp
+++ b/libc/src/time/ctime_r.cpp
@@ -16,7 +16,7 @@ namespace LIBC_NAMESPACE_DECL {
using LIBC_NAMESPACE::time_utils::TimeConstants;
LLVM_LIBC_FUNCTION(char *, ctime_r, (const time_t *t_ptr, char *buffer)) {
- return time_utils::asctime(localtime(t_ptr), buffer, TimeConstants::CTIME_MAX_BYTES);
+ return time_utils::asctime(localtime(t_ptr), buffer, TimeConstants::ASCTIME_MAX_BYTES);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 688fac28fd2293..47f55f7d389122 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -62,9 +62,6 @@ struct TimeConstants {
static constexpr int ASCTIME_BUFFER_SIZE = 256;
static constexpr int ASCTIME_MAX_BYTES = 26;
- static constexpr int CTIME_BUFFER_SIZE = 256;
- static constexpr int CTIME_MAX_BYTES = 26;
-
/* 2000-03-01 (mod 400 year, immediately after feb29 */
static constexpr int64_t SECONDS_UNTIL2000_MARCH_FIRST =
(946684800LL + SECONDS_PER_DAY * (31 + 29));
>From 2ff2fa15e8ce647a5f2c5089e52184943ffd6c0b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 20:23:33 +0200
Subject: [PATCH 25/27] [libc][c11] implement ctime
use `TimeTTypePtr` and remove `StructTimeTPtr`
---
libc/spec/stdc.td | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index a8d319d6f8380a..c7b697d438a89e 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -3,8 +3,6 @@ def StdC : StandardSpec<"stdc"> {
NamedType StructTmType = NamedType<"struct tm">;
PtrType StructTmPtr = PtrType<StructTmType>;
PtrType TimeTTypePtr = PtrType<TimeTType>;
- NamedType StructTimeTType = NamedType<"time_t">;
- PtrType StructTimeTPtr = PtrType<StructTimeTType>;
NamedType ClockT = NamedType<"clock_t">;
NamedType LocaleT = NamedType<"locale_t">;
@@ -1605,13 +1603,13 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<
"ctime",
RetValSpec<CharPtr>,
- [ArgSpec<StructTimeTPtr>]
+ [ArgSpec<TimeTTypePtr>]
>,
FunctionSpec<
"ctime_r",
RetValSpec<CharPtr>,
[
- ArgSpec<StructTimeTPtr>,
+ ArgSpec<TimeTTypePtr>,
ArgSpec<CharPtr>,
]
>,
>From 677775d55044af0c67d766d6e6348b71ef33efcd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 20:31:35 +0200
Subject: [PATCH 26/27] [libc][c11] implement ctime
remove `ctime` and `ctime_r` from `clang-tidy`
this will be done in https://github.com/llvm/llvm-project/issues/107445
---
clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
index a23f7ea87abe10..3d326c5a3b5743 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
@@ -42,7 +42,7 @@ static StringRef getReplacementFor(StringRef FunctionName,
// Try to find a better replacement from Annex K first.
StringRef AnnexKReplacementFunction =
StringSwitch<StringRef>(FunctionName)
- .Cases("asctime", "asctime_r", "asctime_s", "ctime", "ctime_r")
+ .Cases("asctime", "asctime_r", "asctime_s")
.Case("gets", "gets_s")
.Default({});
if (!AnnexKReplacementFunction.empty())
>From f6b3037227a5ffca301cc53760b42679e534b54d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=97=D0=B8=D1=88=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=80=D0=B7?=
=?UTF-8?q?=D0=B0?= <149377404+zimirza at users.noreply.github.com>
Date: Thu, 5 Sep 2024 20:40:24 +0200
Subject: [PATCH 27/27] [libc][c11] implement ctime
fix: tests
---
libc/test/src/time/ctime_r_test.cpp | 21 ++++-----------------
1 file changed, 4 insertions(+), 17 deletions(-)
diff --git a/libc/test/src/time/ctime_r_test.cpp b/libc/test/src/time/ctime_r_test.cpp
index ab742368f02cc3..fe5426fc5e553d 100644
--- a/libc/test/src/time/ctime_r_test.cpp
+++ b/libc/test/src/time/ctime_r_test.cpp
@@ -14,11 +14,7 @@
using LIBC_NAMESPACE::time_utils::TimeConstants;
-static inline char *call_ctime_r(time_t *t, int year, int month, int mday,
- int hour, int min, int sec, int wday, int yday,
- char *buffer) {
- LIBC_NAMESPACE::tmhelper::testing::initialize_tm_data(
- localtime(t), year, month, mday, hour, min, sec, wday, yday);
+static inline char *call_ctime_r(time_t *t, char *buffer) {
return LIBC_NAMESPACE::ctime_r(t, buffer);
}
@@ -41,20 +37,11 @@ TEST(LlvmLibcCtimeR, Nullptr) {
ASSERT_STREQ(nullptr, result);
}
-TEST(LlvmLibcCtimeR, ValidDate) {
+TEST(LlvmLibcCtimeR, ValidUnixTimestamp) {
char buffer[TimeConstants::CTIME_BUFFER_SIZE];
- struct time_t t;
+ struct time_t t = 0;
char *result;
// 1970-01-01 00:00:00. Test with a valid buffer size.
- result = call_ctime_r(&t,
- 1970, // year
- 1, // month
- 1, // day
- 0, // hr
- 0, // min
- 0, // sec
- 4, // wday
- 0, // yday
- buffer);
+ result = call_ctime_r(&t, buffer);
ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
}
More information about the cfe-commits
mailing list