[Lldb-commits] [lldb] 001c78d - [lldb][formatters] Add support for printing NSConstantDate and fix distantPast value

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Wed Jul 15 01:28:38 PDT 2020


Author: Raphael Isemann
Date: 2020-07-15T10:28:10+02:00
New Revision: 001c78de35cc0637eb58b3d855bc9897acccdc64

URL: https://github.com/llvm/llvm-project/commit/001c78de35cc0637eb58b3d855bc9897acccdc64
DIFF: https://github.com/llvm/llvm-project/commit/001c78de35cc0637eb58b3d855bc9897acccdc64.diff

LOG: [lldb][formatters] Add support for printing NSConstantDate and fix distantPast value

Summary:

Certain `NSDate` constructors return a special `NSConstantDate` class which
currently ends up being unformatted as it's not in the list of supported classes
for the NSDate formatter. This patch adds that class to the supported class list
so LLDB produces a summary for it.

One of these special constructors is `[NSDate distantPast]` which returns the
date for `0001-01-01 00:00:00 UTC`. LLDB has a special case for formatting this
date but for some reason we did hardcode the wrong summary string in that
special case. Maybe the summary string was correct back when the code was
written but it isn't correct anymore (`distantPast` isn't actually defined to be
a special date but just some 'a guaranteed temporal boundary.' so maybe someone
changed the value in the last 10 years).

If someone else is wondering why we even have this special case for
`distantPast` but not for the future. The reason seems to be that our date
formatting for really old dates is off by 24 hours. So for example, adding one
second to `distantPast` will cause LLDB to print `0000-12-30 00:00:01 UTC`
(which is 24 hours behind the expected result). So to make our code appear to be
correct it seems we just hardcoded the most common NSDate result from that time
span. I'll replace that logic with a generic solution in a probably more
invasive follow up patch.

I also took the freedom to replace the magic value `-63114076800` with some
constant + documentation. I heard there are some people that don't know from the
top of their head that there are 63114076800 seconds between 1. Jan 0001 and 1.
January 2001 in whatever calendar system NSDate is using.

Reviewers: mib, davide

Reviewed By: mib

Subscribers: JDevlieghere

Differential Revision: https://reviews.llvm.org/D83217

Added: 
    

Modified: 
    lldb/source/Plugins/Language/ObjC/Cocoa.cpp
    lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py
    lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
index da910f48e59a..648fc4adf24f 100644
--- a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
+++ b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -818,13 +818,14 @@ bool lldb_private::formatters::NSDateSummaryProvider(
   static const ConstString g___NSDate("__NSDate");
   static const ConstString g___NSTaggedDate("__NSTaggedDate");
   static const ConstString g_NSCalendarDate("NSCalendarDate");
+  static const ConstString g_NSConstantDate("NSConstantDate");
 
   if (class_name.IsEmpty())
     return false;
 
   uint64_t info_bits = 0, value_bits = 0;
   if ((class_name == g_NSDate) || (class_name == g___NSDate) ||
-      (class_name == g___NSTaggedDate)) {
+      (class_name == g___NSTaggedDate) || (class_name == g_NSConstantDate)) {
     if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits)) {
       date_value_bits = ((value_bits << 8) | (info_bits << 4));
       memcpy(&date_value, &date_value_bits, sizeof(date_value_bits));
@@ -850,8 +851,14 @@ bool lldb_private::formatters::NSDateSummaryProvider(
   } else
     return false;
 
-  if (date_value == -63114076800) {
-    stream.Printf("0001-12-30 00:00:00 +0000");
+  // FIXME: It seems old dates are not formatted according to NSDate's calendar
+  // so we hardcode distantPast's value so that it looks like LLDB is doing
+  // the right thing.
+
+  // The relative time in seconds from Cocoa Epoch to [NSDate distantPast].
+  const double RelSecondsFromCocoaEpochToNSDateDistantPast = -63114076800;
+  if (date_value == RelSecondsFromCocoaEpochToNSDateDistantPast) {
+    stream.Printf("0001-01-01 00:00:00 UTC");
     return true;
   }
 

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py
index 61394c05f5d5..cdce4798e986 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSDate.py
@@ -67,3 +67,6 @@ def nsdate_data_formatter_commands(self):
             substrs=[
                 '(CFMutableBitVectorRef) mut_bv = ',
                 '1110 0110 1011 0000 1101 1010 1000 1111 0011 0101 1101 0001 00'])
+
+        self.expect_expr("distant_past", result_summary="0001-01-01 00:00:00 UTC")
+        self.expect_expr("distant_future", result_summary="4001-01-01 00:00:00 UTC")

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m
index a44a7837f771..169b3aed4f22 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m
@@ -663,6 +663,9 @@ int main(int argc, const char *argv[]) {
   NSDate *date_1970_plus_05 = [NSDate dateWithTimeIntervalSince1970:0.5];
   NSDate *date_1970_plus_04 = [NSDate dateWithTimeIntervalSince1970:0.4];
 
+  NSDate *distant_past = [NSDate distantPast];
+  NSDate *distant_future = [NSDate distantFuture];
+
   CFAbsoluteTime date1_abs = CFDateGetAbsoluteTime(date1);
   CFAbsoluteTime date2_abs = CFDateGetAbsoluteTime(date2);
   CFAbsoluteTime date3_abs = CFDateGetAbsoluteTime(date3);


        


More information about the lldb-commits mailing list