[PATCH] D75558: [clang-tidy] Update abseil-duration-unnecessary-conversion check to find more cases.

2020-03-13 Thread Hyrum Wright via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3860b2a0bd09: [clang-tidy] Update Abseil Duration Conversion 
check to find more cases. (authored by hwright).

Changed prior to commit:
  https://reviews.llvm.org/D75558?vs=247988=250252#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75558/new/

https://reviews.llvm.org/D75558

Files:
  clang-tools-extra/clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
  
clang-tools-extra/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
  
clang-tools-extra/test/clang-tidy/checkers/abseil-duration-unnecessary-conversion.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/abseil-duration-unnecessary-conversion.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/abseil-duration-unnecessary-conversion.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/abseil-duration-unnecessary-conversion.cpp
@@ -100,6 +100,44 @@
   d2 = VALUE(d1);
 #undef VALUE
 
+  // Multiplication
+  d2 = absl::Nanoseconds(absl::ToDoubleNanoseconds(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Microseconds(absl::ToInt64Microseconds(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Milliseconds(absl::ToDoubleMilliseconds(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Seconds(absl::ToInt64Seconds(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Minutes(absl::ToDoubleMinutes(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Hours(absl::ToInt64Hours(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Nanoseconds(2 * absl::ToDoubleNanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+  d2 = absl::Microseconds(2 * absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+  d2 = absl::Milliseconds(2 * absl::ToDoubleMilliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+  d2 = absl::Seconds(2 * absl::ToInt64Seconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+  d2 = absl::Minutes(2 * absl::ToDoubleMinutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+  d2 = absl::Hours(2 * absl::ToInt64Hours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+
   // These should not match
   d2 = absl::Seconds(absl::ToDoubleMilliseconds(d1));
   d2 = absl::Seconds(4);
@@ -108,4 +146,6 @@
   d2 = absl::Seconds(d1 / absl::Seconds(30));
   d2 = absl::Hours(absl::FDivDuration(d1, absl::Minutes(1)));
   d2 = absl::Milliseconds(absl::FDivDuration(d1, absl::Milliseconds(20)));
+  d2 = absl::Seconds(absl::ToInt64Milliseconds(d1) * 2);
+  d2 = absl::Milliseconds(absl::ToDoubleSeconds(d1) * 2);
 }
Index: clang-tools-extra/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
+++ clang-tools-extra/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
@@ -40,6 +40,17 @@
   // Suggestion - Remove division and conversion
   absl::Duration d2 = d1;
 
+Unwrapping scalar operations:
+
+.. code-block:: c++
+
+  // Original - Multiplication by a scalar
+  absl::Duration d1;
+  absl::Duration d2 = absl::Seconds(absl::ToInt64Seconds(d1) * 2);
+
+  // Suggestion - Remove unnecessary conversion
+  absl::Duration d2 = d1 * 2;
+
 Note: Converting to an integer and back to an ``absl::Duration`` might be a
 truncating 

[PATCH] D75558: [clang-tidy] Update abseil-duration-unnecessary-conversion check to find more cases.

2020-03-03 Thread Hyrum Wright via Phabricator via cfe-commits
hwright created this revision.
hwright added reviewers: aaron.ballman, ymandel.
Herald added subscribers: cfe-commits, xazax.hun.
Herald added a project: clang.

This check now handles cases where there's a scalar multiplication happening 
between the two conversions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D75558

Files:
  clang-tools-extra/clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
  
clang-tools-extra/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
  
clang-tools-extra/test/clang-tidy/checkers/abseil-duration-unnecessary-conversion.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/abseil-duration-unnecessary-conversion.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/abseil-duration-unnecessary-conversion.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/abseil-duration-unnecessary-conversion.cpp
@@ -100,6 +100,44 @@
   d2 = VALUE(d1);
 #undef VALUE
 
+  // Multiplication
+  d2 = absl::Nanoseconds(absl::ToDoubleNanoseconds(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Microseconds(absl::ToInt64Microseconds(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Milliseconds(absl::ToDoubleMilliseconds(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Seconds(absl::ToInt64Seconds(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Minutes(absl::ToDoubleMinutes(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Hours(absl::ToInt64Hours(d1) * 2);
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1 * 2
+  d2 = absl::Nanoseconds(2 * absl::ToDoubleNanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+  d2 = absl::Microseconds(2 * absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+  d2 = absl::Milliseconds(2 * absl::ToDoubleMilliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+  d2 = absl::Seconds(2 * absl::ToInt64Seconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+  d2 = absl::Minutes(2 * absl::ToDoubleMinutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+  d2 = absl::Hours(2 * absl::ToInt64Hours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = 2 * d1
+
   // These should not match
   d2 = absl::Seconds(absl::ToDoubleMilliseconds(d1));
   d2 = absl::Seconds(4);
@@ -108,4 +146,6 @@
   d2 = absl::Seconds(d1 / absl::Seconds(30));
   d2 = absl::Hours(absl::FDivDuration(d1, absl::Minutes(1)));
   d2 = absl::Milliseconds(absl::FDivDuration(d1, absl::Milliseconds(20)));
+  d2 = absl::Seconds(absl::ToInt64Milliseconds(d1) * 2);
+  d2 = absl::Milliseconds(absl::ToDoubleSeconds(d1) * 2);
 }
Index: clang-tools-extra/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
+++ clang-tools-extra/docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
@@ -40,6 +40,17 @@
   // Suggestion - Remove division and conversion
   absl::Duration d2 = d1;
 
+Unwrapping scalar operations:
+
+.. code-block:: c++
+
+  // Original - Multiplication by a scalar
+  absl::Duration d1;
+  absl::Duration d2 = absl::Seconds(absl::ToInt64Seconds(d1) * 2);
+
+  // Suggestion - Remove unnecessary conversion
+  absl::Duration d2 = d1 * 2;
+
 Note: Converting to an integer and back to an ``absl::Duration`` might be a
 truncating operation if the value is not aligned to the scale of conversion.
 In the rare case 

[PATCH] D59183: [clang-tidy] Expand cases covered by the abseil-duration-unnecessary-conversion check

2019-03-14 Thread Hyrum Wright via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCTE356141: [clang-tidy] Add additional patterns to the 
abseil-duration-unnecessary… (authored by hwright, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D59183?vs=190456=190613#toc

Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59183/new/

https://reviews.llvm.org/D59183

Files:
  clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
  docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-unnecessary-conversion.cpp

Index: test/clang-tidy/Inputs/absl/time/time.h
===
--- test/clang-tidy/Inputs/absl/time/time.h
+++ test/clang-tidy/Inputs/absl/time/time.h
@@ -21,6 +21,7 @@
 template  Duration operator*(Duration lhs, T rhs);
 template  Duration operator*(T lhs, Duration rhs);
 template  Duration operator/(Duration lhs, T rhs);
+int64_t operator/(Duration lhs, Duration rhs);
 
 class Time{};
 
@@ -86,4 +87,6 @@
 inline Time operator-(Time lhs, Duration rhs);
 inline Duration operator-(Time lhs, Time rhs);
 
+double FDivDuration(Duration num, Duration den);
+
 }  // namespace absl
Index: test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
===
--- test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
+++ test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
@@ -8,42 +8,80 @@
   // Floating point
   d2 = absl::Hours(absl::ToDoubleHours(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Minutes(absl::ToDoubleMinutes(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Seconds(absl::ToDoubleSeconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Milliseconds(absl::ToDoubleMilliseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Microseconds(absl::ToDoubleMicroseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Nanoseconds(absl::ToDoubleNanoseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
 
   // Integer point
   d2 = absl::Hours(absl::ToInt64Hours(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Minutes(absl::ToInt64Minutes(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Seconds(absl::ToInt64Seconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Milliseconds(absl::ToInt64Milliseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Microseconds(absl::ToInt64Microseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Nanoseconds(absl::ToInt64Nanoseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
+
+  d2 = absl::Hours(d1 / absl::Hours(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1
+  d2 = absl::Minutes(d1 / absl::Minutes(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1
+  d2 = absl::Seconds(d1 / absl::Seconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration 

[PATCH] D59183: [clang-tidy] Expand cases covered by the abseil-duration-unnecessary-conversion check

2019-03-13 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: test/clang-tidy/abseil-duration-unnecessary-conversion.cpp:48
 
+  d2 = absl::Hours(d1 / absl::Hours(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration 
conversions [abseil-duration-unnecessary-conversion]

hokein wrote:
> An off-topic comment: do we have this code pattern in the codebase? From my 
> understanding, the usage like this is really rare. 
This mostly shows up in migrations.  When an existing API takes an integer, and 
caller already has a `Duration`, they sometimes use `dur / absl::Seconds(1)` to 
get back in integer at the callsite.   After a migration, we end up with 
`absl::Seconds(dur /absl::Seconds(1))`, which should really just be `dur`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59183/new/

https://reviews.llvm.org/D59183



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59183: [clang-tidy] Expand cases covered by the abseil-duration-unnecessary-conversion check

2019-03-13 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 190456.
hwright marked 4 inline comments as done.
hwright added a comment.

Addressed reviewer comments


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59183/new/

https://reviews.llvm.org/D59183

Files:
  clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
  docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-unnecessary-conversion.cpp

Index: test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
===
--- test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
+++ test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
@@ -8,42 +8,80 @@
   // Floating point
   d2 = absl::Hours(absl::ToDoubleHours(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Minutes(absl::ToDoubleMinutes(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Seconds(absl::ToDoubleSeconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Milliseconds(absl::ToDoubleMilliseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Microseconds(absl::ToDoubleMicroseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Nanoseconds(absl::ToDoubleNanoseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
 
   // Integer point
   d2 = absl::Hours(absl::ToInt64Hours(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Minutes(absl::ToInt64Minutes(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Seconds(absl::ToInt64Seconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Milliseconds(absl::ToInt64Milliseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Microseconds(absl::ToInt64Microseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
   d2 = absl::Nanoseconds(absl::ToInt64Nanoseconds(d1));
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
-  // CHECK-FIXES: d1
+  // CHECK-FIXES: d2 = d1
+
+  d2 = absl::Hours(d1 / absl::Hours(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1
+  d2 = absl::Minutes(d1 / absl::Minutes(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1
+  d2 = absl::Seconds(d1 / absl::Seconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1
+  d2 = absl::Milliseconds(d1 / absl::Milliseconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1
+  d2 = absl::Microseconds(d1 / absl::Microseconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1
+  d2 = absl::Nanoseconds(d1 / absl::Nanoseconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d2 = d1
+
+  d2 = absl::Hours(absl::FDivDuration(d1, absl::Hours(1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: 

[PATCH] D58977: [clang-tidy] Add the abseil-time-comparison check

2019-03-11 Thread Hyrum Wright via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCTE355835: [clang-tidy] Add the abseil-time-compare check 
(authored by hwright, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D58977?vs=190075=190113#toc

Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58977/new/

https://reviews.llvm.org/D58977

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/TimeComparisonCheck.cpp
  clang-tidy/abseil/TimeComparisonCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-time-comparison.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-time-comparison.cpp

Index: clang-tidy/abseil/CMakeLists.txt
===
--- clang-tidy/abseil/CMakeLists.txt
+++ clang-tidy/abseil/CMakeLists.txt
@@ -17,6 +17,7 @@
   RedundantStrcatCallsCheck.cpp
   StrCatAppendCheck.cpp
   StringFindStartswithCheck.cpp
+  TimeComparisonCheck.cpp
   TimeSubtractionCheck.cpp
   UpgradeDurationConversionsCheck.cpp
 
Index: clang-tidy/abseil/TimeComparisonCheck.h
===
--- clang-tidy/abseil/TimeComparisonCheck.h
+++ clang-tidy/abseil/TimeComparisonCheck.h
@@ -0,0 +1,35 @@
+//===--- TimeComparisonCheck.h - clang-tidy -*- 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_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMECOMPARECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMECOMPARECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Prefer comparison in the `absl::Time` domain instead of the numeric
+/// domain.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-time-comparison.html
+class TimeComparisonCheck : public ClangTidyCheck {
+public:
+  TimeComparisonCheck(StringRef Name, ClangTidyContext *Context)
+  : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult ) override;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMECOMPARECHECK_H
Index: clang-tidy/abseil/DurationComparisonCheck.cpp
===
--- clang-tidy/abseil/DurationComparisonCheck.cpp
+++ clang-tidy/abseil/DurationComparisonCheck.cpp
@@ -19,14 +19,10 @@
 namespace abseil {
 
 void DurationComparisonCheck::registerMatchers(MatchFinder *Finder) {
-  auto Matcher =
-  binaryOperator(anyOf(hasOperatorName(">"), hasOperatorName(">="),
-   hasOperatorName("=="), hasOperatorName("<="),
-   hasOperatorName("<")),
- hasEitherOperand(ignoringImpCasts(callExpr(
- callee(functionDecl(DurationConversionFunction())
-.bind("function_decl"))
-  .bind("binop");
+  auto Matcher = expr(comparisonOperatorWithCallee(functionDecl(
+  functionDecl(DurationConversionFunction())
+  .bind("function_decl"
+ .bind("binop");
 
   Finder->addMatcher(Matcher, this);
 }
Index: clang-tidy/abseil/AbseilTidyModule.cpp
===
--- clang-tidy/abseil/AbseilTidyModule.cpp
+++ clang-tidy/abseil/AbseilTidyModule.cpp
@@ -23,6 +23,7 @@
 #include "RedundantStrcatCallsCheck.h"
 #include "StringFindStartswithCheck.h"
 #include "StrCatAppendCheck.h"
+#include "TimeComparisonCheck.h"
 #include "TimeSubtractionCheck.h"
 #include "UpgradeDurationConversionsCheck.h"
 
@@ -60,6 +61,8 @@
 "abseil-str-cat-append");
 CheckFactories.registerCheck(
 "abseil-string-find-startswith");
+CheckFactories.registerCheck(
+"abseil-time-comparison");
 CheckFactories.registerCheck(
 "abseil-time-subtraction");
 CheckFactories.registerCheck(
Index: clang-tidy/abseil/TimeComparisonCheck.cpp
===
--- clang-tidy/abseil/TimeComparisonCheck.cpp
+++ clang-tidy/abseil/TimeComparisonCheck.cpp
@@ -0,0 +1,61 @@
+//===--- TimeComparisonCheck.cpp - clang-tidy
+//===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// 

[PATCH] D58977: [clang-tidy] Add the abseil-time-comparison check

2019-03-11 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 190075.
hwright marked an inline comment as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58977/new/

https://reviews.llvm.org/D58977

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/TimeComparisonCheck.cpp
  clang-tidy/abseil/TimeComparisonCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-time-comparison.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-time-comparison.cpp

Index: test/clang-tidy/abseil-time-comparison.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-time-comparison.cpp
@@ -0,0 +1,129 @@
+// RUN: %check_clang_tidy %s abseil-time-comparison %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  double x;
+  absl::Duration d1, d2;
+  bool b;
+  absl::Time t1, t2;
+
+  // Check against the RHS
+  b = x > absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) > t1;
+  b = x >= absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) >= t1;
+  b = x == absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) == t1;
+  b = x <= absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) <= t1;
+  b = x < absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) < t1;
+  b = x == absl::ToUnixSeconds(t1 - d2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) == t1 - d2;
+  b = absl::ToUnixSeconds(t1) > absl::ToUnixSeconds(t2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 > t2;
+
+  // Check against the LHS
+  b = absl::ToUnixSeconds(t1) < x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 < absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) <= x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 <= absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) == x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 == absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) >= x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 >= absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) > x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 > absl::FromUnixSeconds(x);
+
+  // Comparison against zero
+  b = absl::ToUnixSeconds(t1) < 0.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 < absl::UnixEpoch();
+  b = absl::ToUnixSeconds(t1) < 0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 < absl::UnixEpoch();
+
+  // Scales other than Seconds
+  b = x > absl::ToUnixMicros(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixMicros(x) > t1;
+  b = x >= absl::ToUnixMillis(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixMillis(x) >= t1;
+  b = x == absl::ToUnixNanos(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixNanos(x) == t1;
+  b = x <= absl::ToUnixMinutes(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixMinutes(x) <= t1;
+  b = x < absl::ToUnixHours(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixHours(x) < t1;
+
+  // A long expression
+  bool some_condition;
+  int very_very_very_very_long_variable_name;
+  absl::Time SomeTime;
+  if (some_condition && 

[PATCH] D59183: [clang-tidy] Expand cases covered by the abseil-duration-unnecessary-conversion check

2019-03-09 Thread Hyrum Wright via Phabricator via cfe-commits
hwright created this revision.
hwright added a reviewer: hokein.
Herald added subscribers: cfe-commits, xazax.hun.
Herald added a project: clang.

This adds coverage for expressions of these forms

  absl::Duration d2, d1;
  d2 = absl::Seconds(d1 / absl::Seconds(1));
  d2 = absl::Seconds(absl::FDivDuration(d1, absl::Seconds(1)));


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D59183

Files:
  clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
  docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-unnecessary-conversion.cpp

Index: test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
===
--- test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
+++ test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
@@ -45,6 +45,44 @@
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
   // CHECK-FIXES: d1
 
+  d2 = absl::Hours(d1 / absl::Hours(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Minutes(d1 / absl::Minutes(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Seconds(d1 / absl::Seconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Milliseconds(d1 / absl::Milliseconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Microseconds(d1 / absl::Microseconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Nanoseconds(d1 / absl::Nanoseconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+
+  d2 = absl::Hours(absl::FDivDuration(d1, absl::Hours(1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Minutes(absl::FDivDuration(d1, absl::Minutes(1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Seconds(absl::FDivDuration(d1, absl::Seconds(1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Milliseconds(absl::FDivDuration(d1, absl::Milliseconds(1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Microseconds(absl::FDivDuration(d1, absl::Microseconds(1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Nanoseconds(absl::FDivDuration(d1, absl::Nanoseconds(1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove unnecessary absl::Duration conversions [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+
   // As macro argument
 #define PLUS_FIVE_S(x) x + absl::Seconds(5)
   d2 = PLUS_FIVE_S(absl::Seconds(absl::ToInt64Seconds(d1)));
@@ -66,4 +104,8 @@
   d2 = absl::Seconds(absl::ToDoubleMilliseconds(d1));
   d2 = absl::Seconds(4);
   int i = absl::ToInt64Milliseconds(d1);
+  d2 = absl::Hours(d1 / absl::Minutes(1));
+  d2 = absl::Seconds(d1 / absl::Seconds(30));
+  d2 = absl::Hours(absl::FDivDuration(d1, absl::Minutes(1)));
+  d2 = absl::Milliseconds(absl::FDivDuration(d1, absl::Milliseconds(20)));
 }
Index: test/clang-tidy/Inputs/absl/time/time.h
===
--- test/clang-tidy/Inputs/absl/time/time.h
+++ test/clang-tidy/Inputs/absl/time/time.h
@@ -21,6 +21,7 @@
 template  Duration operator*(Duration lhs, T rhs);
 template  Duration operator*(T lhs, Duration rhs);
 template  Duration operator/(Duration lhs, T rhs);
+int64_t operator/(Duration lhs, Duration rhs);
 
 class Time{};
 
@@ -86,4 +87,6 @@
 inline Time operator-(Time lhs, Duration rhs);
 inline Duration operator-(Time lhs, Time rhs);
 
+double FDivDuration(Duration num, Duration den);
+
 }  // namespace absl
Index: docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
===
--- 

[PATCH] D58977: [clang-tidy] Add the abseil-time-comparison check

2019-03-08 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 189862.
hwright marked 6 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58977/new/

https://reviews.llvm.org/D58977

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/TimeComparisonCheck.cpp
  clang-tidy/abseil/TimeComparisonCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-time-comparison.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-time-comparison.cpp

Index: test/clang-tidy/abseil-time-comparison.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-time-comparison.cpp
@@ -0,0 +1,129 @@
+// RUN: %check_clang_tidy %s abseil-time-comparison %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  double x;
+  absl::Duration d1, d2;
+  bool b;
+  absl::Time t1, t2;
+
+  // Check against the RHS
+  b = x > absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) > t1;
+  b = x >= absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) >= t1;
+  b = x == absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) == t1;
+  b = x <= absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) <= t1;
+  b = x < absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) < t1;
+  b = x == absl::ToUnixSeconds(t1 - d2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) == t1 - d2;
+  b = absl::ToUnixSeconds(t1) > absl::ToUnixSeconds(t2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 > t2;
+
+  // Check against the LHS
+  b = absl::ToUnixSeconds(t1) < x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 < absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) <= x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 <= absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) == x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 == absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) >= x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 >= absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) > x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 > absl::FromUnixSeconds(x);
+
+  // Comparison against zero
+  b = absl::ToUnixSeconds(t1) < 0.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 < absl::UnixEpoch();
+  b = absl::ToUnixSeconds(t1) < 0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 < absl::UnixEpoch();
+
+  // Scales other than Seconds
+  b = x > absl::ToUnixMicros(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixMicros(x) > t1;
+  b = x >= absl::ToUnixMillis(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixMillis(x) >= t1;
+  b = x == absl::ToUnixNanos(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixNanos(x) == t1;
+  b = x <= absl::ToUnixMinutes(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixMinutes(x) <= t1;
+  b = x < absl::ToUnixHours(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixHours(x) < t1;
+
+  // A long expression
+  bool some_condition;
+  int very_very_very_very_long_variable_name;
+  absl::Time SomeTime;
+  if (some_condition && very_very_very_very_long_variable_name
+ < absl::ToUnixSeconds(SomeTime)) {
+  // CHECK-MESSAGES: 

[PATCH] D58977: [clang-tidy] Add the abseil-time-comparison check

2019-03-08 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/TimeComparisonCheck.cpp:23
+  auto Matcher =
+  binaryOperator(anyOf(hasOperatorName(">"), hasOperatorName(">="),
+   hasOperatorName("=="), hasOperatorName("<="),

ioeric wrote:
> `DurationComparisonCheck.cpp` has a very similar matcher pattern.
> 
> Maybe pull out a common matcher for this? E.g. 
> `comparisonOperatorWithCallee(...)`?
> 
My one concern about doing so is that it would move the name bindings into a 
separate location away from the callback consuming those bindings.

Since this is only the second instance of this pattern, would it be reasonable 
to wait until there's a third to combine them?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58977/new/

https://reviews.llvm.org/D58977



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D58977: [clang-tidy] Add the abseil-time-comparison check

2019-03-05 Thread Hyrum Wright via Phabricator via cfe-commits
hwright created this revision.
hwright added reviewers: hokein, ioeric.
Herald added subscribers: cfe-commits, jdoerfert, xazax.hun, mgorny.
Herald added a project: clang.

This is an analog of the `abseil-duration-comparison` check, but for the 
`absl::Time` domain.  It has a similar implementation and tests.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D58977

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/TimeComparisonCheck.cpp
  clang-tidy/abseil/TimeComparisonCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-time-comparison.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-time-comparison.cpp

Index: test/clang-tidy/abseil-time-comparison.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-time-comparison.cpp
@@ -0,0 +1,129 @@
+// RUN: %check_clang_tidy %s abseil-time-comparison %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  double x;
+  absl::Duration d1, d2;
+  bool b;
+  absl::Time t1, t2;
+
+  // Check against the RHS
+  b = x > absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) > t1;
+  b = x >= absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) >= t1;
+  b = x == absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) == t1;
+  b = x <= absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) <= t1;
+  b = x < absl::ToUnixSeconds(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) < t1;
+  b = x == absl::ToUnixSeconds(t1 - d2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixSeconds(x) == t1 - d2;
+  b = absl::ToUnixSeconds(t1) > absl::ToUnixSeconds(t2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 > t2;
+
+  // Check against the LHS
+  b = absl::ToUnixSeconds(t1) < x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 < absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) <= x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 <= absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) == x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 == absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) >= x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 >= absl::FromUnixSeconds(x);
+  b = absl::ToUnixSeconds(t1) > x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 > absl::FromUnixSeconds(x);
+
+  // Comparison against zero
+  b = absl::ToUnixSeconds(t1) < 0.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 < absl::UnixEpoch();
+  b = absl::ToUnixSeconds(t1) < 0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: t1 < absl::UnixEpoch();
+
+  // Scales other than Seconds
+  b = x > absl::ToUnixMicros(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixMicros(x) > t1;
+  b = x >= absl::ToUnixMillis(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixMillis(x) >= t1;
+  b = x == absl::ToUnixNanos(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixNanos(x) == t1;
+  b = x <= absl::ToUnixMinutes(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixMinutes(x) <= t1;
+  b = x < absl::ToUnixHours(t1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the time domain [abseil-time-comparison]
+  // CHECK-FIXES: absl::FromUnixHours(x) < t1;
+
+  // A long expression
+  bool some_condition;
+  int 

[PATCH] D58137: [clang-tidy] Add the abseil-time-subtraction check

2019-02-27 Thread Hyrum Wright via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCTE355024: [clang-tidy] Add the abseil-time-subtraction check 
(authored by hwright, committed by ).

Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58137/new/

https://reviews.llvm.org/D58137

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/TimeSubtractionCheck.cpp
  clang-tidy/abseil/TimeSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-time-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-time-subtraction.cpp

Index: test/clang-tidy/abseil-time-subtraction.cpp
===
--- test/clang-tidy/abseil-time-subtraction.cpp
+++ test/clang-tidy/abseil-time-subtraction.cpp
@@ -0,0 +1,117 @@
+// RUN: %check_clang_tidy %s abseil-time-subtraction %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void g(absl::Duration d);
+
+void f() {
+  absl::Time t;
+  int x, y;
+  absl::Duration d;
+
+  d = absl::Hours(absl::ToUnixHours(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixHours(x));
+  d = absl::Minutes(absl::ToUnixMinutes(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMinutes(x));
+  d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x));
+  d = absl::Milliseconds(absl::ToUnixMillis(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMillis(x));
+  d = absl::Microseconds(absl::ToUnixMicros(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMicros(x));
+  d = absl::Nanoseconds(absl::ToUnixNanos(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixNanos(x));
+
+  y = x - absl::ToUnixHours(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Hours(absl::FromUnixHours(x) - t);
+  y = x - absl::ToUnixMinutes(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Minutes(absl::FromUnixMinutes(x) - t);
+  y = x - absl::ToUnixSeconds(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t);
+  y = x - absl::ToUnixMillis(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Milliseconds(absl::FromUnixMillis(x) - t);
+  y = x - absl::ToUnixMicros(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Microseconds(absl::FromUnixMicros(x) - t);
+  y = x - absl::ToUnixNanos(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Nanoseconds(absl::FromUnixNanos(x) - t);
+
+  // Check parenthesis placement
+  d = 5 * absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = 5 * (t - absl::FromUnixSeconds(x));
+  d = absl::Seconds(absl::ToUnixSeconds(t) - x) / 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x)) / 5;
+
+  // No extra parens around arguments
+  g(absl::Seconds(absl::ToUnixSeconds(t) - x));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(t - absl::FromUnixSeconds(x));
+  g(absl::Seconds(x - absl::ToUnixSeconds(t)));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(absl::FromUnixSeconds(x) - t);
+
+  // More complex subexpressions
+  d = absl::Hours(absl::ToUnixHours(t) - 5 * x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // 

[PATCH] D58137: [clang-tidy] Add the abseil-time-subtraction check

2019-02-26 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked an inline comment as done.
hwright added inline comments.



Comment at: clang-tidy/abseil/TimeSubtractionCheck.cpp:97
+void TimeSubtractionCheck::check(const MatchFinder::MatchResult ) {
+  const auto *BinOp = Result.Nodes.getNodeAs("binop");
+  std::string inverse_name =

hwright wrote:
> JonasToth wrote:
> > hwright wrote:
> > > JonasToth wrote:
> > > > Could you please split this function up into smaller ones. There are 
> > > > three or four distinct cases that are easier to comprehend in isolation.
> > > The actual bodies of these if-statements are only one or two separate 
> > > statements themselves.  Moving those to separate functions seems like it 
> > > would just obfuscate things a bit.
> > IMHO they are complicated statements and hide what is being done. Wrapping 
> > them in a function with a name that states what is done seems appropriate.
> I would agree that they are complicated statements, which is why there are 
> multi-line comments explaining what is being doing.  Moving a two-line 
> compound statement into a separate function which is only called once seems 
> more confusing than simplifying.  More information can be expressed in a 
> prose comment than a single concise function name, no?
I've pulled out the common duplicated functionality which actually emits the 
diagnostic, and I think that's simplified these branches a bit more.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58137/new/

https://reviews.llvm.org/D58137



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D58137: [clang-tidy] Add the abseil-time-subtraction check

2019-02-26 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 188372.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58137/new/

https://reviews.llvm.org/D58137

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/TimeSubtractionCheck.cpp
  clang-tidy/abseil/TimeSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-time-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-time-subtraction.cpp

Index: test/clang-tidy/abseil-time-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-time-subtraction.cpp
@@ -0,0 +1,117 @@
+// RUN: %check_clang_tidy %s abseil-time-subtraction %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void g(absl::Duration d);
+
+void f() {
+  absl::Time t;
+  int x, y;
+  absl::Duration d;
+
+  d = absl::Hours(absl::ToUnixHours(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixHours(x));
+  d = absl::Minutes(absl::ToUnixMinutes(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMinutes(x));
+  d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x));
+  d = absl::Milliseconds(absl::ToUnixMillis(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMillis(x));
+  d = absl::Microseconds(absl::ToUnixMicros(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMicros(x));
+  d = absl::Nanoseconds(absl::ToUnixNanos(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixNanos(x));
+
+  y = x - absl::ToUnixHours(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Hours(absl::FromUnixHours(x) - t);
+  y = x - absl::ToUnixMinutes(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Minutes(absl::FromUnixMinutes(x) - t);
+  y = x - absl::ToUnixSeconds(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t);
+  y = x - absl::ToUnixMillis(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Milliseconds(absl::FromUnixMillis(x) - t);
+  y = x - absl::ToUnixMicros(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Microseconds(absl::FromUnixMicros(x) - t);
+  y = x - absl::ToUnixNanos(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Nanoseconds(absl::FromUnixNanos(x) - t);
+
+  // Check parenthesis placement
+  d = 5 * absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = 5 * (t - absl::FromUnixSeconds(x));
+  d = absl::Seconds(absl::ToUnixSeconds(t) - x) / 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x)) / 5;
+
+  // No extra parens around arguments
+  g(absl::Seconds(absl::ToUnixSeconds(t) - x));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(t - absl::FromUnixSeconds(x));
+  g(absl::Seconds(x - absl::ToUnixSeconds(t)));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(absl::FromUnixSeconds(x) - t);
+
+  // More complex subexpressions
+  d = absl::Hours(absl::ToUnixHours(t) - 5 * x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixHours(5 * x));
+
+  // These should not trigger; they are likely bugs
+  d = absl::Milliseconds(absl::ToUnixSeconds(t) - x);
+  d = absl::Seconds(absl::ToUnixMicros(t) - x);
+
+  // 

[PATCH] D58137: [clang-tidy] Add the abseil-time-subtraction check

2019-02-25 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/TimeSubtractionCheck.cpp:97
+void TimeSubtractionCheck::check(const MatchFinder::MatchResult ) {
+  const auto *BinOp = Result.Nodes.getNodeAs("binop");
+  std::string inverse_name =

JonasToth wrote:
> hwright wrote:
> > JonasToth wrote:
> > > Could you please split this function up into smaller ones. There are 
> > > three or four distinct cases that are easier to comprehend in isolation.
> > The actual bodies of these if-statements are only one or two separate 
> > statements themselves.  Moving those to separate functions seems like it 
> > would just obfuscate things a bit.
> IMHO they are complicated statements and hide what is being done. Wrapping 
> them in a function with a name that states what is done seems appropriate.
I would agree that they are complicated statements, which is why there are 
multi-line comments explaining what is being doing.  Moving a two-line compound 
statement into a separate function which is only called once seems more 
confusing than simplifying.  More information can be expressed in a prose 
comment than a single concise function name, no?



Comment at: test/clang-tidy/abseil-time-subtraction.cpp:12
+
+  d = absl::Hours(absl::ToUnixHours(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time 
domain [abseil-time-subtraction]

JonasToth wrote:
> hwright wrote:
> > JonasToth wrote:
> > > please add tests where `x` itself is a calculation with different 
> > > precedence of its operators (multiplication, addition) to ensure these 
> > > cases are transformed properly as well.
> > This doesn't actually matter in this case: `x` will be wrapped in a 
> > function call.
> > 
> > It does matter in the case where we //unwrap// the first argument (below) 
> > and I've already got a test which uses multiplication in this case.  I've 
> > also added one for division.
> Yes, it should not matter if `x` is an expr itself or just a variable. Thats 
> why it should be tested its actually true.
Added, though this seems more a test of the matcher infrastructure than the 
tool itself.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58137/new/

https://reviews.llvm.org/D58137



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D58137: [clang-tidy] Add the abseil-time-subtraction check

2019-02-25 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 188289.
hwright marked 5 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58137/new/

https://reviews.llvm.org/D58137

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/TimeSubtractionCheck.cpp
  clang-tidy/abseil/TimeSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-time-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-time-subtraction.cpp

Index: test/clang-tidy/abseil-time-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-time-subtraction.cpp
@@ -0,0 +1,117 @@
+// RUN: %check_clang_tidy %s abseil-time-subtraction %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void g(absl::Duration d);
+
+void f() {
+  absl::Time t;
+  int x, y;
+  absl::Duration d;
+
+  d = absl::Hours(absl::ToUnixHours(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixHours(x));
+  d = absl::Minutes(absl::ToUnixMinutes(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMinutes(x));
+  d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x));
+  d = absl::Milliseconds(absl::ToUnixMillis(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMillis(x));
+  d = absl::Microseconds(absl::ToUnixMicros(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMicros(x));
+  d = absl::Nanoseconds(absl::ToUnixNanos(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixNanos(x));
+
+  y = x - absl::ToUnixHours(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Hours(absl::FromUnixHours(x) - t);
+  y = x - absl::ToUnixMinutes(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Minutes(absl::FromUnixMinutes(x) - t);
+  y = x - absl::ToUnixSeconds(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t);
+  y = x - absl::ToUnixMillis(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Milliseconds(absl::FromUnixMillis(x) - t);
+  y = x - absl::ToUnixMicros(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Microseconds(absl::FromUnixMicros(x) - t);
+  y = x - absl::ToUnixNanos(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Nanoseconds(absl::FromUnixNanos(x) - t);
+
+  // Check parenthesis placement
+  d = 5 * absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = 5 * (t - absl::FromUnixSeconds(x));
+  d = absl::Seconds(absl::ToUnixSeconds(t) - x) / 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x)) / 5;
+
+  // No extra parens around arguments
+  g(absl::Seconds(absl::ToUnixSeconds(t) - x));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(t - absl::FromUnixSeconds(x));
+  g(absl::Seconds(x - absl::ToUnixSeconds(t)));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(absl::FromUnixSeconds(x) - t);
+
+  // More complex subexpressions
+  d = absl::Hours(absl::ToUnixHours(t) - 5 * x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixHours(5 * x));
+
+  // These should not trigger; they are likely bugs
+  d = absl::Milliseconds(absl::ToUnixSeconds(t) - x);
+  d = 

[PATCH] D58137: [clang-tidy] Add the abseil-time-subtraction check

2019-02-22 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/TimeSubtractionCheck.cpp:97
+void TimeSubtractionCheck::check(const MatchFinder::MatchResult ) {
+  const auto *BinOp = Result.Nodes.getNodeAs("binop");
+  std::string inverse_name =

JonasToth wrote:
> Could you please split this function up into smaller ones. There are three or 
> four distinct cases that are easier to comprehend in isolation.
The actual bodies of these if-statements are only one or two separate 
statements themselves.  Moving those to separate functions seems like it would 
just obfuscate things a bit.



Comment at: clang-tidy/abseil/TimeSubtractionCheck.h:19
+/// Finds and fixes `absl::Time` subtraction expressions to do subtraction
+/// in the Time domain instead of the numeric domain.
+///

JonasToth wrote:
> nit: 'Time' domain
This doesn't refer to a type, but a library system, so it probably isn't 
appropriate to quote it.

(Just has how one wouldn't quote "frequency" when talking about "the frequency 
domain" of a Fourier transform.)



Comment at: test/clang-tidy/abseil-time-subtraction.cpp:12
+
+  d = absl::Hours(absl::ToUnixHours(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time 
domain [abseil-time-subtraction]

JonasToth wrote:
> please add tests where `x` itself is a calculation with different precedence 
> of its operators (multiplication, addition) to ensure these cases are 
> transformed properly as well.
This doesn't actually matter in this case: `x` will be wrapped in a function 
call.

It does matter in the case where we //unwrap// the first argument (below) and 
I've already got a test which uses multiplication in this case.  I've also 
added one for division.



Comment at: test/clang-tidy/abseil-time-subtraction.cpp:78
+  // CHECK-FIXES: return absl::FromUnixSeconds(x) - t;
+}

JonasToth wrote:
> please add tests for templates and macros.
I've add tests for macros, though I'm not sure what cases you have in mind 
regarding templates.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58137/new/

https://reviews.llvm.org/D58137



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D58137: [clang-tidy] Add the abseil-time-subtraction check

2019-02-22 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 187967.
hwright marked 15 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58137/new/

https://reviews.llvm.org/D58137

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/TimeSubtractionCheck.cpp
  clang-tidy/abseil/TimeSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-time-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-time-subtraction.cpp

Index: test/clang-tidy/abseil-time-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-time-subtraction.cpp
@@ -0,0 +1,112 @@
+// RUN: %check_clang_tidy %s abseil-time-subtraction %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void g(absl::Duration d);
+
+void f() {
+  absl::Time t;
+  int x, y;
+  absl::Duration d;
+
+  d = absl::Hours(absl::ToUnixHours(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixHours(x));
+  d = absl::Minutes(absl::ToUnixMinutes(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMinutes(x));
+  d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x));
+  d = absl::Milliseconds(absl::ToUnixMillis(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMillis(x));
+  d = absl::Microseconds(absl::ToUnixMicros(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMicros(x));
+  d = absl::Nanoseconds(absl::ToUnixNanos(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixNanos(x));
+
+  y = x - absl::ToUnixHours(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Hours(absl::FromUnixHours(x) - t);
+  y = x - absl::ToUnixMinutes(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Minutes(absl::FromUnixMinutes(x) - t);
+  y = x - absl::ToUnixSeconds(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t);
+  y = x - absl::ToUnixMillis(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Milliseconds(absl::FromUnixMillis(x) - t);
+  y = x - absl::ToUnixMicros(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Microseconds(absl::FromUnixMicros(x) - t);
+  y = x - absl::ToUnixNanos(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Nanoseconds(absl::FromUnixNanos(x) - t);
+
+  // Check parenthesis placement
+  d = 5 * absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = 5 * (t - absl::FromUnixSeconds(x));
+  d = absl::Seconds(absl::ToUnixSeconds(t) - x) / 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x)) / 5;
+
+  // No extra parens around arguments
+  g(absl::Seconds(absl::ToUnixSeconds(t) - x));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(t - absl::FromUnixSeconds(x));
+  g(absl::Seconds(x - absl::ToUnixSeconds(t)));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(absl::FromUnixSeconds(x) - t);
+
+  // These should not trigger; they are likely bugs
+  d = absl::Milliseconds(absl::ToUnixSeconds(t) - x);
+  d = absl::Seconds(absl::ToUnixMicros(t) - x);
+
+  // Various macro scenarios
+#define SUB(z, t1) z - absl::ToUnixSeconds(t1)
+  y = SUB(x, t);
+#undef SUB
+
+#define MILLIS(t1) absl::ToUnixMillis(t1)
+  y = x - MILLIS(t);
+#undef MILLIS
+
+#define HOURS(z) 

[PATCH] D58137: [clang-tidy] Add the abseil-time-subtraction check

2019-02-12 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 186569.
hwright marked 3 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58137/new/

https://reviews.llvm.org/D58137

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/TimeSubtractionCheck.cpp
  clang-tidy/abseil/TimeSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-time-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-time-subtraction.cpp

Index: test/clang-tidy/abseil-time-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-time-subtraction.cpp
@@ -0,0 +1,78 @@
+// RUN: %check_clang_tidy %s abseil-time-subtraction %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void g(absl::Duration d);
+
+void f() {
+  absl::Time t;
+  int x, y;
+  absl::Duration d;
+
+  d = absl::Hours(absl::ToUnixHours(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixHours(x));
+  d = absl::Minutes(absl::ToUnixMinutes(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMinutes(x));
+  d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x));
+  d = absl::Milliseconds(absl::ToUnixMillis(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMillis(x));
+  d = absl::Microseconds(absl::ToUnixMicros(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMicros(x));
+  d = absl::Nanoseconds(absl::ToUnixNanos(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixNanos(x));
+
+  y = x - absl::ToUnixHours(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Hours(absl::FromUnixHours(x) - t);
+  y = x - absl::ToUnixMinutes(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Minutes(absl::FromUnixMinutes(x) - t);
+  y = x - absl::ToUnixSeconds(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t);
+  y = x - absl::ToUnixMillis(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Milliseconds(absl::FromUnixMillis(x) - t);
+  y = x - absl::ToUnixMicros(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Microseconds(absl::FromUnixMicros(x) - t);
+  y = x - absl::ToUnixNanos(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Nanoseconds(absl::FromUnixNanos(x) - t);
+
+  // Check parenthesis placement
+  d = 5 * absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = 5 * (t - absl::FromUnixSeconds(x));
+
+  // No extra parens around arguments
+  g(absl::Seconds(absl::ToUnixSeconds(t) - x));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(t - absl::FromUnixSeconds(x));
+  g(absl::Seconds(x - absl::ToUnixSeconds(t)));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(absl::FromUnixSeconds(x) - t);
+
+  // These should not trigger; they are likely bugs
+  d = absl::Milliseconds(absl::ToUnixSeconds(t) - x);
+  d = absl::Seconds(absl::ToUnixMicros(t) - x);
+}
+
+absl::Duration parens_in_return() {
+  absl::Time t;
+  int x;
+
+  return absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: return t - absl::FromUnixSeconds(x);
+  return absl::Seconds(x - absl::ToUnixSeconds(t));
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: return 

[PATCH] D58137: [clang-tidy] Add the abseil-time-subtraction check

2019-02-12 Thread Hyrum Wright via Phabricator via cfe-commits
hwright created this revision.
hwright added reviewers: ioeric, hokein, JonasToth, aaron.ballman.
hwright added a project: clang-tools-extra.
Herald added subscribers: cfe-commits, jdoerfert, xazax.hun, mgorny.
Herald added a project: clang.

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D58137

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/TimeSubtractionCheck.cpp
  clang-tidy/abseil/TimeSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-time-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-time-subtraction.cpp

Index: test/clang-tidy/abseil-time-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-time-subtraction.cpp
@@ -0,0 +1,78 @@
+// RUN: %check_clang_tidy %s abseil-time-subtraction %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void g(absl::Duration d);
+
+void f() {
+  absl::Time t;
+  int x, y;
+  absl::Duration d;
+
+  d = absl::Hours(absl::ToUnixHours(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixHours(x));
+  d = absl::Minutes(absl::ToUnixMinutes(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMinutes(x));
+  d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x));
+  d = absl::Milliseconds(absl::ToUnixMillis(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMillis(x));
+  d = absl::Microseconds(absl::ToUnixMicros(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixMicros(x));
+  d = absl::Nanoseconds(absl::ToUnixNanos(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = (t - absl::FromUnixNanos(x));
+
+  y = x - absl::ToUnixHours(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Hours(absl::FromUnixHours(x) - t);
+  y = x - absl::ToUnixMinutes(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Minutes(absl::FromUnixMinutes(x) - t);
+  y = x - absl::ToUnixSeconds(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t);
+  y = x - absl::ToUnixMillis(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Milliseconds(absl::FromUnixMillis(x) - t);
+  y = x - absl::ToUnixMicros(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Microseconds(absl::FromUnixMicros(x) - t);
+  y = x - absl::ToUnixNanos(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: y = absl::ToInt64Nanoseconds(absl::FromUnixNanos(x) - t);
+
+  // Check parenthesis placement
+  d = 5 * absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: d = 5 * (t - absl::FromUnixSeconds(x));
+
+  // No extra parens around arguments
+  g(absl::Seconds(absl::ToUnixSeconds(t) - x));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(t - absl::FromUnixSeconds(x));
+  g(absl::Seconds(x - absl::ToUnixSeconds(t)));
+  // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: g(absl::FromUnixSeconds(x) - t);
+
+  // These should not trigger; they are likely bugs
+  d = absl::Milliseconds(absl::ToUnixSeconds(t) - x);
+  d = absl::Seconds(absl::ToUnixMicros(t) - x);
+}
+
+absl::Duration parens_in_return() {
+  absl::Time t;
+  int x;
+
+  return absl::Seconds(absl::ToUnixSeconds(t) - x);
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: perform subtraction in the time domain [abseil-time-subtraction]
+  // CHECK-FIXES: return t - absl::FromUnixSeconds(x);
+  return absl::Seconds(x - absl::ToUnixSeconds(t));
+  // CHECK-MESSAGES: 

[PATCH] D57353: [clang-tidy] Add the abseil-duration-unnecessary-conversion check

2019-02-04 Thread Hyrum Wright via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCTE353079: [clang-tidy] Add the 
abseil-duration-unnecessary-conversion check (authored by hwright, committed by 
).
Herald added a project: clang.

Changed prior to commit:
  https://reviews.llvm.org/D57353?vs=185057=185104#toc

Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57353/new/

https://reviews.llvm.org/D57353

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
  clang-tidy/abseil/DurationUnnecessaryConversionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-unnecessary-conversion.cpp

Index: clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
===
--- clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
+++ clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
@@ -0,0 +1,58 @@
+//===--- DurationUnnecessaryConversionCheck.cpp - clang-tidy
+//---===//
+//
+// 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 "DurationUnnecessaryConversionCheck.h"
+#include "DurationRewriter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+void DurationUnnecessaryConversionCheck::registerMatchers(MatchFinder *Finder) {
+  for (const auto  : {"Hours", "Minutes", "Seconds", "Milliseconds",
+"Microseconds", "Nanoseconds"}) {
+std::string DurationFactory = (llvm::Twine("::absl::") + Scale).str();
+std::string FloatConversion =
+(llvm::Twine("::absl::ToDouble") + Scale).str();
+std::string IntegerConversion =
+(llvm::Twine("::absl::ToInt64") + Scale).str();
+
+Finder->addMatcher(
+callExpr(
+callee(functionDecl(hasName(DurationFactory))),
+hasArgument(0, callExpr(callee(functionDecl(hasAnyName(
+FloatConversion, IntegerConversion))),
+hasArgument(0, expr().bind("arg")
+.bind("call"),
+this);
+  }
+}
+
+void DurationUnnecessaryConversionCheck::check(
+const MatchFinder::MatchResult ) {
+  const auto *OuterCall = Result.Nodes.getNodeAs("call");
+  const auto *Arg = Result.Nodes.getNodeAs("arg");
+
+  if (!isNotInMacro(Result, OuterCall))
+return;
+
+  diag(OuterCall->getBeginLoc(), "remove unnecessary absl::Duration conversions")
+  << FixItHint::CreateReplacement(
+ OuterCall->getSourceRange(),
+ tooling::fixit::getText(*Arg, *Result.Context));
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/abseil/CMakeLists.txt
===
--- clang-tidy/abseil/CMakeLists.txt
+++ clang-tidy/abseil/CMakeLists.txt
@@ -10,6 +10,7 @@
   DurationFactoryScaleCheck.cpp
   DurationRewriter.cpp
   DurationSubtractionCheck.cpp
+  DurationUnnecessaryConversionCheck.cpp
   FasterStrsplitDelimiterCheck.cpp
   NoInternalDependenciesCheck.cpp
   NoNamespaceCheck.cpp
Index: clang-tidy/abseil/DurationUnnecessaryConversionCheck.h
===
--- clang-tidy/abseil/DurationUnnecessaryConversionCheck.h
+++ clang-tidy/abseil/DurationUnnecessaryConversionCheck.h
@@ -0,0 +1,35 @@
+//===--- DurationUnnecessaryConversionCheck.h - clang-tidy --*- 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_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMEDOUBLECONVERSIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMEDOUBLECONVERSIONCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Finds and fixes cases where ``absl::Duration`` values are being converted
+/// to numeric types and back again.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-duration-unnecessary-conversion.html
+class DurationUnnecessaryConversionCheck : public ClangTidyCheck {
+public:
+  DurationUnnecessaryConversionCheck(StringRef Name, ClangTidyContext 

[PATCH] D57353: [clang-tidy] Add the abseil-duration-unnecessary-conversion check

2019-02-04 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

@hokein Thanks for the suggestion on the name, I was looking for something a 
little less confusing.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57353/new/

https://reviews.llvm.org/D57353



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57353: [clang-tidy] Add the abseil-duration-unnecessary-conversion check

2019-02-04 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 185057.
hwright marked 4 inline comments as done.
hwright retitled this revision from "[clang-tidy] Add the 
abseil-duration-double-conversion check" to "[clang-tidy] Add the 
abseil-duration-unnecessary-conversion check".
hwright added a comment.

Renamed to `abseil-duration-unnecessary-conversion`


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57353/new/

https://reviews.llvm.org/D57353

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp
  clang-tidy/abseil/DurationUnnecessaryConversionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-unnecessary-conversion.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-unnecessary-conversion.cpp

Index: test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-unnecessary-conversion.cpp
@@ -0,0 +1,69 @@
+// RUN: %check_clang_tidy %s abseil-duration-unnecessary-conversion %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Duration d1, d2;
+
+  // Floating point
+  d2 = absl::Hours(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Minutes(absl::ToDoubleMinutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Seconds(absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Milliseconds(absl::ToDoubleMilliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Microseconds(absl::ToDoubleMicroseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Nanoseconds(absl::ToDoubleNanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+
+  // Integer point
+  d2 = absl::Hours(absl::ToInt64Hours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Minutes(absl::ToInt64Minutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Seconds(absl::ToInt64Seconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Milliseconds(absl::ToInt64Milliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Microseconds(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Nanoseconds(absl::ToInt64Nanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: d1
+
+  // As macro argument
+#define PLUS_FIVE_S(x) x + absl::Seconds(5)
+  d2 = PLUS_FIVE_S(absl::Seconds(absl::ToInt64Seconds(d1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: remove double conversion of absl::Duration [abseil-duration-unnecessary-conversion]
+  // CHECK-FIXES: PLUS_FIVE_S(d1)
+#undef PLUS_FIVE_S
+
+  // Split by macro: should not change
+#define TOSECONDS(x) absl::Seconds(x)
+  d2 = TOSECONDS(absl::ToInt64Seconds(d1));
+#undef TOSECONDS
+
+  // Don't change something inside a macro definition
+#define VALUE(x) absl::Hours(absl::ToInt64Hours(x));
+  d2 = VALUE(d1);
+#undef VALUE
+
+  // These should not match
+  d2 = absl::Seconds(absl::ToDoubleMilliseconds(d1));
+  d2 = absl::Seconds(4);
+  int i = absl::ToInt64Milliseconds(d1);
+}
Index: test/clang-tidy/Inputs/absl/time/time.h
===
--- test/clang-tidy/Inputs/absl/time/time.h
+++ test/clang-tidy/Inputs/absl/time/time.h
@@ -14,6 +14,8 @@
   Duration /=(float r);
   Duration /=(double r);
   template  Duration /=(T r);
+
+  Duration +(Duration d);
 };
 
 template  Duration operator*(Duration lhs, T rhs);
Index: docs/clang-tidy/checks/list.rst

[PATCH] D57353: [clang-tidy] Add the abseil-duration-double-conversion check

2019-01-30 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked 2 inline comments as done.
hwright added inline comments.



Comment at: docs/clang-tidy/checks/abseil-duration-double-conversion.rst:20
+
+
+  // Original - Conversion to integer and back again

MyDeveloperDay wrote:
> hwright wrote:
> > Eugene.Zelenko wrote:
> > > Unnecessary empty line.
> > This is consistent with other documentation in this directory, such as 
> > `abseil-faster-strsplit-delimiter.rst`.
> In your example `abseil-faster-strsplit-delimiter.rst` , The double blank 
> line in the html doesn't give much delineation between the before and after 
> code and the next example.
> 
> {F7867869}
> 
> There probably isn't a convention per say (which is a shame), across the docs 
> we do a mixture of different styles 
> 
> https://clang.llvm.org/extra/clang-tidy/checks/readability-braces-around-statements.html
> https://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-accept.html
> https://clang.llvm.org/extra/clang-tidy/checks/google-objc-function-naming.html
> 
> But there is a desire by some of the regular clang-tidy reviewers to make the 
> documentation consistent
> 
> It may not be ideal but the "Before/After" style, that is used in 
> `modernize-use-emplace`, 
> `modernize-use-using`,`readability-braces-around-statements`,`readability-identifier-naming`
>  and `readability-redundant-function-ptr-dereference` does help a little.
> 
> I'm not saying looks better, but I've added a couple of examples of 
> formatting the strsplit example for comparison, feel free to ignore.
> 
> {F7867960}
> 
> {F7868028}
> 
> 
I like those examples!

Would it be reasonable to update all of the `abseil-duration-*` documentation 
in a separate pass, after this change is submitted?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57353/new/

https://reviews.llvm.org/D57353



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57353: [clang-tidy] Add the abseil-duration-double-conversion check

2019-01-29 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: docs/clang-tidy/checks/abseil-duration-double-conversion.rst:28
+
+Note: Converting to an integer and back to an `absl::Duration` might be a
+truncating operation if the value is not aligned to the scale of conversion.

Eugene.Zelenko wrote:
> Please use `` for language constructs. Same below.
Thanks; I thought I'd caught them all.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57353/new/

https://reviews.llvm.org/D57353



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57353: [clang-tidy] Add the abseil-duration-double-conversion check

2019-01-29 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 184146.
hwright marked 2 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57353/new/

https://reviews.llvm.org/D57353

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationDoubleConversionCheck.cpp
  clang-tidy/abseil/DurationDoubleConversionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-double-conversion.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-double-conversion.cpp

Index: test/clang-tidy/abseil-duration-double-conversion.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-double-conversion.cpp
@@ -0,0 +1,69 @@
+// RUN: %check_clang_tidy %s abseil-duration-double-conversion %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Duration d1, d2;
+
+  // Floating point
+  d2 = absl::Hours(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Minutes(absl::ToDoubleMinutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Seconds(absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Milliseconds(absl::ToDoubleMilliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Microseconds(absl::ToDoubleMicroseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Nanoseconds(absl::ToDoubleNanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+
+  // Integer point
+  d2 = absl::Hours(absl::ToInt64Hours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Minutes(absl::ToInt64Minutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Seconds(absl::ToInt64Seconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Milliseconds(absl::ToInt64Milliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Microseconds(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Nanoseconds(absl::ToInt64Nanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+
+  // As macro argument
+#define PLUS_FIVE_S(x) x + absl::Seconds(5)
+  d2 = PLUS_FIVE_S(absl::Seconds(absl::ToInt64Seconds(d1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: PLUS_FIVE_S(d1)
+#undef PLUS_FIVE_S
+
+  // Split by macro: should not change
+#define TOSECONDS(x) absl::Seconds(x)
+  d2 = TOSECONDS(absl::ToInt64Seconds(d1));
+#undef TOSECONDS
+
+  // Don't change something inside a macro definition
+#define VALUE(x) absl::Hours(absl::ToInt64Hours(x));
+  d2 = VALUE(d1);
+#undef VALUE
+
+  // These should not match
+  d2 = absl::Seconds(absl::ToDoubleMilliseconds(d1));
+  d2 = absl::Seconds(4);
+  int i = absl::ToInt64Milliseconds(d1);
+}
Index: test/clang-tidy/Inputs/absl/time/time.h
===
--- test/clang-tidy/Inputs/absl/time/time.h
+++ test/clang-tidy/Inputs/absl/time/time.h
@@ -14,6 +14,8 @@
   Duration /=(float r);
   Duration /=(double r);
   template  Duration /=(T r);
+
+  Duration +(Duration d);
 };
 
 template  Duration operator*(Duration lhs, T rhs);
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -8,6 +8,7 @@
abseil-duration-comparison
abseil-duration-conversion-cast
abseil-duration-division
+   abseil-duration-double-conversion
abseil-duration-factory-float
abseil-duration-factory-scale

[PATCH] D57353: [clang-tidy] Add the abseil-duration-double-conversion check

2019-01-29 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: docs/clang-tidy/checks/abseil-duration-double-conversion.rst:20
+
+
+  // Original - Conversion to integer and back again

Eugene.Zelenko wrote:
> Unnecessary empty line.
This is consistent with other documentation in this directory, such as 
`abseil-faster-strsplit-delimiter.rst`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57353/new/

https://reviews.llvm.org/D57353



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57353: [clang-tidy] Add the abseil-duration-double-conversion check

2019-01-29 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 184143.
hwright marked 5 inline comments as done.
hwright added a comment.

Address reviewer comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57353/new/

https://reviews.llvm.org/D57353

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationDoubleConversionCheck.cpp
  clang-tidy/abseil/DurationDoubleConversionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-double-conversion.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-double-conversion.cpp

Index: test/clang-tidy/abseil-duration-double-conversion.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-double-conversion.cpp
@@ -0,0 +1,69 @@
+// RUN: %check_clang_tidy %s abseil-duration-double-conversion %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Duration d1, d2;
+
+  // Floating point
+  d2 = absl::Hours(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Minutes(absl::ToDoubleMinutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Seconds(absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Milliseconds(absl::ToDoubleMilliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Microseconds(absl::ToDoubleMicroseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Nanoseconds(absl::ToDoubleNanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+
+  // Integer point
+  d2 = absl::Hours(absl::ToInt64Hours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Minutes(absl::ToInt64Minutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Seconds(absl::ToInt64Seconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Milliseconds(absl::ToInt64Milliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Microseconds(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Nanoseconds(absl::ToInt64Nanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+
+  // As macro argument
+#define PLUS_FIVE_S(x) x + absl::Seconds(5)
+  d2 = PLUS_FIVE_S(absl::Seconds(absl::ToInt64Seconds(d1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: PLUS_FIVE_S(d1)
+#undef PLUS_FIVE_S
+
+  // Split by macro: should not change
+#define TOSECONDS(x) absl::Seconds(x)
+  d2 = TOSECONDS(absl::ToInt64Seconds(d1));
+#undef TOSECONDS
+
+  // Don't change something inside a macro definition
+#define VALUE(x) absl::Hours(absl::ToInt64Hours(x));
+  d2 = VALUE(d1);
+#undef VALUE
+
+  // These should not match
+  d2 = absl::Seconds(absl::ToDoubleMilliseconds(d1));
+  d2 = absl::Seconds(4);
+  int i = absl::ToInt64Milliseconds(d1);
+}
Index: test/clang-tidy/Inputs/absl/time/time.h
===
--- test/clang-tidy/Inputs/absl/time/time.h
+++ test/clang-tidy/Inputs/absl/time/time.h
@@ -14,6 +14,8 @@
   Duration /=(float r);
   Duration /=(double r);
   template  Duration /=(T r);
+
+  Duration +(Duration d);
 };
 
 template  Duration operator*(Duration lhs, T rhs);
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -8,6 +8,7 @@
abseil-duration-comparison
abseil-duration-conversion-cast
abseil-duration-division
+   abseil-duration-double-conversion
abseil-duration-factory-float

[PATCH] D57353: [clang-tidy] Add the abseil-duration-double-conversion check

2019-01-28 Thread Hyrum Wright via Phabricator via cfe-commits
hwright created this revision.
hwright added reviewers: hokein, JonasToth, aaron.ballman.
hwright added a project: clang-tools-extra.
Herald added subscribers: cfe-commits, xazax.hun, mgorny.

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D57353

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationDoubleConversionCheck.cpp
  clang-tidy/abseil/DurationDoubleConversionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-double-conversion.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-double-conversion.cpp

Index: test/clang-tidy/abseil-duration-double-conversion.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-double-conversion.cpp
@@ -0,0 +1,69 @@
+// RUN: %check_clang_tidy %s abseil-duration-double-conversion %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Duration d1, d2;
+
+  // Floating point
+  d2 = absl::Hours(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Minutes(absl::ToDoubleMinutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Seconds(absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Milliseconds(absl::ToDoubleMilliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Microseconds(absl::ToDoubleMicroseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Nanoseconds(absl::ToDoubleNanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+
+  // Integer point
+  d2 = absl::Hours(absl::ToInt64Hours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Minutes(absl::ToInt64Minutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Seconds(absl::ToInt64Seconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Milliseconds(absl::ToInt64Milliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Microseconds(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+  d2 = absl::Nanoseconds(absl::ToInt64Nanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: d1
+
+  // As macro argument
+#define PLUS_FIVE_S(x) x + absl::Seconds(5)
+  d2 = PLUS_FIVE_S(absl::Seconds(absl::ToInt64Seconds(d1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: remove double conversion of absl::Duration [abseil-duration-double-conversion]
+  // CHECK-FIXES: PLUS_FIVE_S(d1)
+#undef PLUS_FIVE_S
+
+  // Split by macro: should not change
+#define TOSECONDS(x) absl::Seconds(x)
+  d2 = TOSECONDS(absl::ToInt64Seconds(d1));
+#undef TOSECONDS
+
+  // Don't change something inside a macro definition
+#define VALUE(x) absl::Hours(absl::ToInt64Hours(x));
+  d2 = VALUE(d1);
+#undef VALUE
+
+  // These should not match
+  d2 = absl::Seconds(absl::ToDoubleMilliseconds(d1));
+  d2 = absl::Seconds(4);
+  int i = absl::ToInt64Milliseconds(d1);
+}
Index: test/clang-tidy/Inputs/absl/time/time.h
===
--- test/clang-tidy/Inputs/absl/time/time.h
+++ test/clang-tidy/Inputs/absl/time/time.h
@@ -14,6 +14,8 @@
   Duration /=(float r);
   Duration /=(double r);
   template  Duration /=(T r);
+
+  Duration +(Duration d);
 };
 
 template  Duration operator*(Duration lhs, T rhs);
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -8,6 +8,7 @@
abseil-duration-comparison
abseil-duration-conversion-cast
abseil-duration-division
+   abseil-duration-double-conversion

[PATCH] D57185: [clang-tidy] Add the abseil-duration-addition check

2019-01-28 Thread Hyrum Wright via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL352362: [clang-tidy] Add the abseil-duration-addition check 
(authored by hwright, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D57185?vs=183583=183840#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57185/new/

https://reviews.llvm.org/D57185

Files:
  clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt
  clang-tools-extra/trunk/clang-tidy/abseil/DurationAdditionCheck.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/DurationAdditionCheck.h
  clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.h
  clang-tools-extra/trunk/docs/ReleaseNotes.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-duration-addition.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
  clang-tools-extra/trunk/test/clang-tidy/Inputs/absl/time/time.h
  clang-tools-extra/trunk/test/clang-tidy/abseil-duration-addition.cpp

Index: clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
===
--- clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
+++ clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
@@ -103,6 +103,25 @@
   llvm_unreachable("unknown scaling factor");
 }
 
+/// Returns the Time factory function name for a given `Scale`.
+llvm::StringRef getTimeFactoryForScale(DurationScale scale) {
+  switch (scale) {
+  case DurationScale::Hours:
+return "absl::ToUnixHours";
+  case DurationScale::Minutes:
+return "absl::ToUnixMinutes";
+  case DurationScale::Seconds:
+return "absl::ToUnixSeconds";
+  case DurationScale::Milliseconds:
+return "absl::ToUnixMillis";
+  case DurationScale::Microseconds:
+return "absl::ToUnixMicros";
+  case DurationScale::Nanoseconds:
+return "absl::ToUnixNanos";
+  }
+  llvm_unreachable("unknown scaling factor");
+}
+
 /// Returns `true` if `Node` is a value which evaluates to a literal `0`.
 bool IsLiteralZero(const MatchFinder::MatchResult , const Expr ) {
   auto ZeroMatcher =
@@ -197,6 +216,22 @@
   return ScaleIter->second;
 }
 
+llvm::Optional getScaleForTimeInverse(llvm::StringRef Name) {
+  static const llvm::StringMap ScaleMap(
+  {{"ToUnixHours", DurationScale::Hours},
+   {"ToUnixMinutes", DurationScale::Minutes},
+   {"ToUnixSeconds", DurationScale::Seconds},
+   {"ToUnixMillis", DurationScale::Milliseconds},
+   {"ToUnixMicros", DurationScale::Microseconds},
+   {"ToUnixNanos", DurationScale::Nanoseconds}});
+
+  auto ScaleIter = ScaleMap.find(std::string(Name));
+  if (ScaleIter == ScaleMap.end())
+return llvm::None;
+
+  return ScaleIter->second;
+}
+
 std::string rewriteExprFromNumberToDuration(
 const ast_matchers::MatchFinder::MatchResult , DurationScale Scale,
 const Expr *Node) {
Index: clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
===
--- clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
+++ clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
@@ -9,6 +9,7 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "DurationAdditionCheck.h"
 #include "DurationComparisonCheck.h"
 #include "DurationConversionCastCheck.h"
 #include "DurationDivisionCheck.h"
@@ -30,6 +31,8 @@
 class AbseilModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories ) override {
+CheckFactories.registerCheck(
+"abseil-duration-addition");
 CheckFactories.registerCheck(
 "abseil-duration-comparison");
 CheckFactories.registerCheck(
Index: clang-tools-extra/trunk/clang-tidy/abseil/DurationAdditionCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/abseil/DurationAdditionCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/abseil/DurationAdditionCheck.cpp
@@ -0,0 +1,73 @@
+//===--- DurationAdditionCheck.cpp - clang-tidy===//
+//
+// 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 "DurationAdditionCheck.h"
+#include "DurationRewriter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+void DurationAdditionCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  

[PATCH] D57185: [clang-tidy] Add the abseil-duration-addition check

2019-01-25 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 183583.
hwright marked an inline comment as done.
hwright added a comment.

Add another test


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57185/new/

https://reviews.llvm.org/D57185

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationAdditionCheck.cpp
  clang-tidy/abseil/DurationAdditionCheck.h
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-addition.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-addition.cpp

Index: test/clang-tidy/abseil-duration-addition.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-addition.cpp
@@ -0,0 +1,98 @@
+// RUN: %check_clang_tidy %s abseil-duration-addition %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Time t;
+  int i;
+
+  i = absl::ToUnixHours(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixHours(t + absl::Hours(5))
+  i = absl::ToUnixMinutes(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMinutes(t + absl::Minutes(5))
+  i = absl::ToUnixSeconds(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5))
+  i = absl::ToUnixMillis(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMillis(t + absl::Milliseconds(5))
+  i = absl::ToUnixMicros(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(t + absl::Microseconds(5))
+  i = absl::ToUnixNanos(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixNanos(t + absl::Nanoseconds(5))
+
+  i = 3 + absl::ToUnixHours(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixHours(absl::Hours(3) + t)
+  i = 3 + absl::ToUnixMinutes(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMinutes(absl::Minutes(3) + t)
+  i = 3 + absl::ToUnixSeconds(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(absl::Seconds(3) + t)
+  i = 3 + absl::ToUnixMillis(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMillis(absl::Milliseconds(3) + t)
+  i = 3 + absl::ToUnixMicros(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(absl::Microseconds(3) + t)
+  i = 3 + absl::ToUnixNanos(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixNanos(absl::Nanoseconds(3) + t)
+
+  // Undoing inverse conversions
+  i = absl::ToUnixMicros(t) + absl::ToInt64Microseconds(absl::Seconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(t + absl::Seconds(1))
+
+  // Parens
+  i = 3 + (absl::ToUnixHours(t));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixHours(absl::Hours(3) + t)
+
+  // Float folding
+  i = absl::ToUnixSeconds(t) + 5.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5))
+
+  // We can rewrite the argument of the duration conversion
+#define THIRTY absl::FromUnixSeconds(30)
+  i = absl::ToUnixSeconds(THIRTY) + 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(THIRTY + absl::Seconds(1))
+#undef THIRTY
+
+  // Some other contexts
+  if (absl::ToUnixSeconds(t) + 1.0 > 10) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(1))
+
+  // These should not match
+  i = 5 + 6;
+  i = absl::ToUnixSeconds(t) - 1.0;
+  i = absl::ToUnixSeconds(t) * 1.0;
+  i = 

[PATCH] D57185: [clang-tidy] Add the abseil-duration-addition check

2019-01-25 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked 2 inline comments as done.
hwright added inline comments.



Comment at: test/clang-tidy/abseil-duration-addition.cpp:84
+#undef PLUS_FIVE
+}

JonasToth wrote:
> a view template test-cases would be good to have.
I'm not sure I know that terminology; do you have an example?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57185/new/

https://reviews.llvm.org/D57185



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57185: [clang-tidy] Add the abseil-duration-addition check

2019-01-25 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationAdditionCheck.cpp:22
+void DurationAdditionCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  binaryOperator(hasOperatorName("+"),

JonasToth wrote:
> This whole file is structurally similar to the `DurationSubtractionCheck.cpp` 
> equivalent (which is expected :)), maybe some parts could be refactored out?
> Will there be a check for duration scaling or the like?
I think that most of it already has been factored out (e.g., 
`rewriteExprFromNumberToDuration` and `getScaleForTimeInverse`, etc) . The 
actual meat here is pretty light: the matcher, and then the diagnostic 
generation.

A scaling change may also follow.  Our experience has been that scaling isn't 
quite straight forward, as the scaling factor may have semantic meaning which 
changes the result, but which isn't captured by the type system.  Probably not 
a design discussion to have here, but suffice it to say that I don't know if 
this is yet settled.



Comment at: clang-tidy/abseil/DurationAdditionCheck.cpp:50
+diag(Binop->getBeginLoc(), "perform addition in the duration domain")
+<< FixItHint::CreateReplacement(
+   Binop->getSourceRange(),

JonasToth wrote:
> The only difference between the two `diag` seems to be the `FixItHint`. I 
> would rather refactor the diag out of the `if`.
This doesn't really de-dupe very much, since the bulk of the work here is 
creating the `FixItHint`.  Done.



Comment at: clang-tidy/abseil/DurationAdditionCheck.cpp:60
+  } else {
+assert(Call == Binop->getRHS()->IgnoreImpCast() && "Call should be found 
on the RHS");
+diag(Binop->getBeginLoc(), "perform addition in the duration domain")

JonasToth wrote:
> What happens with paren-casts, are they ignored as well? (See one comment in 
> the test-cases)
Now they are.



Comment at: test/clang-tidy/abseil-duration-addition.cpp:28
+
+  i = 3 + absl::ToUnixHours(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration 
domain [abseil-duration-addition]

JonasToth wrote:
> Call is on the right side, what happens for `3 + (abs::ToUnixHours(t));`
Added this test, and updated to ignore paren casts.



Comment at: test/clang-tidy/abseil-duration-addition.cpp:48
+  // Undoing inverse conversions
+  i = absl::ToUnixMicros(t) + absl::ToInt64Microseconds(absl::Seconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration 
domain [abseil-duration-addition]

JonasToth wrote:
> Is something like this
> ```
> i += absl::ToInt64MicroSeconds(absl::Seconds(1));
> ```
> possible (syntactically and semantically)?
> The compound operators are currently not covered by this (and the 
> subtraction-check), but in this case it looks like a possible use-case.
Semantically, this is possible, but wouldn't fall under this transform, since 
it would require changing the type of `i`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57185/new/

https://reviews.llvm.org/D57185



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57185: [clang-tidy] Add the abseil-duration-addition check

2019-01-25 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 183539.
hwright marked 11 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57185/new/

https://reviews.llvm.org/D57185

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationAdditionCheck.cpp
  clang-tidy/abseil/DurationAdditionCheck.h
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-addition.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-addition.cpp

Index: test/clang-tidy/abseil-duration-addition.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-addition.cpp
@@ -0,0 +1,84 @@
+// RUN: %check_clang_tidy %s abseil-duration-addition %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Time t;
+  int i;
+
+  i = absl::ToUnixHours(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixHours(t + absl::Hours(5))
+  i = absl::ToUnixMinutes(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMinutes(t + absl::Minutes(5))
+  i = absl::ToUnixSeconds(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5))
+  i = absl::ToUnixMillis(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMillis(t + absl::Milliseconds(5))
+  i = absl::ToUnixMicros(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(t + absl::Microseconds(5))
+  i = absl::ToUnixNanos(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixNanos(t + absl::Nanoseconds(5))
+
+  i = 3 + absl::ToUnixHours(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixHours(absl::Hours(3) + t)
+  i = 3 + absl::ToUnixMinutes(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMinutes(absl::Minutes(3) + t)
+  i = 3 + absl::ToUnixSeconds(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(absl::Seconds(3) + t)
+  i = 3 + absl::ToUnixMillis(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMillis(absl::Milliseconds(3) + t)
+  i = 3 + absl::ToUnixMicros(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(absl::Microseconds(3) + t)
+  i = 3 + absl::ToUnixNanos(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixNanos(absl::Nanoseconds(3) + t)
+
+  // Undoing inverse conversions
+  i = absl::ToUnixMicros(t) + absl::ToInt64Microseconds(absl::Seconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(t + absl::Seconds(1))
+
+  // Parens
+  i = 3 + (absl::ToUnixHours(t));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixHours(absl::Hours(3) + t)
+
+  // Float folding
+  i = absl::ToUnixSeconds(t) + 5.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5))
+
+  // We can rewrite the argument of the duration conversion
+#define THIRTY absl::FromUnixSeconds(30)
+  i = absl::ToUnixSeconds(THIRTY) + 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(THIRTY + absl::Seconds(1))
+#undef THIRTY
+
+  // Some other contexts
+  if (absl::ToUnixSeconds(t) + 1.0 > 10) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(1))
+
+  // These should not match
+  i = 5 + 6;
+  i = absl::ToUnixSeconds(t) - 1.0;
+  i = absl::ToUnixSeconds(t) * 1.0;
+  i = absl::ToUnixSeconds(t) / 1.0;
+  i += 

[PATCH] D57185: [clang-tidy] Add the abseil-duration-addition check

2019-01-25 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 183531.
hwright added a comment.

Sort release notes


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57185/new/

https://reviews.llvm.org/D57185

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationAdditionCheck.cpp
  clang-tidy/abseil/DurationAdditionCheck.h
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-addition.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-addition.cpp

Index: test/clang-tidy/abseil-duration-addition.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-addition.cpp
@@ -0,0 +1,78 @@
+// RUN: %check_clang_tidy %s abseil-duration-addition %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Time t;
+  int i;
+
+  i = absl::ToUnixHours(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixHours(t + absl::Hours(5))
+  i = absl::ToUnixMinutes(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMinutes(t + absl::Minutes(5))
+  i = absl::ToUnixSeconds(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5))
+  i = absl::ToUnixMillis(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMillis(t + absl::Milliseconds(5))
+  i = absl::ToUnixMicros(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(t + absl::Microseconds(5))
+  i = absl::ToUnixNanos(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixNanos(t + absl::Nanoseconds(5))
+
+  i = 3 + absl::ToUnixHours(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixHours(absl::Hours(3) + t)
+  i = 3 + absl::ToUnixMinutes(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMinutes(absl::Minutes(3) + t)
+  i = 3 + absl::ToUnixSeconds(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(absl::Seconds(3) + t)
+  i = 3 + absl::ToUnixMillis(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMillis(absl::Milliseconds(3) + t)
+  i = 3 + absl::ToUnixMicros(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(absl::Microseconds(3) + t)
+  i = 3 + absl::ToUnixNanos(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixNanos(absl::Nanoseconds(3) + t)
+
+  // Undoing inverse conversions
+  i = absl::ToUnixMicros(t) + absl::ToInt64Microseconds(absl::Seconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(t + absl::Seconds(1))
+
+  // Float folding
+  i = absl::ToUnixSeconds(t) + 5.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5))
+
+  // We can rewrite the argument of the duration conversion
+#define THIRTY absl::FromUnixSeconds(30)
+  i = absl::ToUnixSeconds(THIRTY) + 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(THIRTY + absl::Seconds(1))
+#undef THIRTY
+
+  // Some other contexts
+  if (absl::ToUnixSeconds(t) + 1.0 > 10) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(1))
+
+  // These should not match
+  i = 5 + 6;
+  i = absl::ToUnixSeconds(t) - 1.0;
+  i = absl::ToUnixSeconds(t) * 1.0;
+  i = absl::ToUnixSeconds(t) / 1.0;
+
+#define PLUS_FIVE(z) absl::ToUnixSeconds(z) + 5
+  i = PLUS_FIVE(t);
+#undef PLUS_FIVE
+}
Index: test/clang-tidy/Inputs/absl/time/time.h
===
--- 

[PATCH] D57185: [clang-tidy] Add the abseil-duration-addition check

2019-01-24 Thread Hyrum Wright via Phabricator via cfe-commits
hwright created this revision.
hwright added reviewers: hokein, aaron.ballman, JonasToth.
hwright added a project: clang-tools-extra.
Herald added subscribers: cfe-commits, xazax.hun, mgorny.

This is an analog to the existing `abseil-duration-subtraction` check.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D57185

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationAdditionCheck.cpp
  clang-tidy/abseil/DurationAdditionCheck.h
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-addition.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-addition.cpp

Index: test/clang-tidy/abseil-duration-addition.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-addition.cpp
@@ -0,0 +1,78 @@
+// RUN: %check_clang_tidy %s abseil-duration-addition %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Time t;
+  int i;
+
+  i = absl::ToUnixHours(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixHours(t + absl::Hours(5))
+  i = absl::ToUnixMinutes(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMinutes(t + absl::Minutes(5))
+  i = absl::ToUnixSeconds(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5))
+  i = absl::ToUnixMillis(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMillis(t + absl::Milliseconds(5))
+  i = absl::ToUnixMicros(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(t + absl::Microseconds(5))
+  i = absl::ToUnixNanos(t) + 5;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixNanos(t + absl::Nanoseconds(5))
+
+  i = 3 + absl::ToUnixHours(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixHours(absl::Hours(3) + t)
+  i = 3 + absl::ToUnixMinutes(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMinutes(absl::Minutes(3) + t)
+  i = 3 + absl::ToUnixSeconds(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(absl::Seconds(3) + t)
+  i = 3 + absl::ToUnixMillis(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMillis(absl::Milliseconds(3) + t)
+  i = 3 + absl::ToUnixMicros(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(absl::Microseconds(3) + t)
+  i = 3 + absl::ToUnixNanos(t);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixNanos(absl::Nanoseconds(3) + t)
+
+  // Undoing inverse conversions
+  i = absl::ToUnixMicros(t) + absl::ToInt64Microseconds(absl::Seconds(1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixMicros(t + absl::Seconds(1))
+
+  // Float folding
+  i = absl::ToUnixSeconds(t) + 5.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(5))
+
+  // We can rewrite the argument of the duration conversion
+#define THIRTY absl::FromUnixSeconds(30)
+  i = absl::ToUnixSeconds(THIRTY) + 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(THIRTY + absl::Seconds(1))
+#undef THIRTY
+
+  // Some other contexts
+  if (absl::ToUnixSeconds(t) + 1.0 > 10) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform addition in the duration domain [abseil-duration-addition]
+  // CHECK-FIXES: absl::ToUnixSeconds(t + absl::Seconds(1))
+
+  // These should not match
+  i = 5 + 6;
+  i = absl::ToUnixSeconds(t) - 1.0;
+  i = absl::ToUnixSeconds(t) * 1.0;
+  i = absl::ToUnixSeconds(t) / 1.0;
+
+#define PLUS_FIVE(z) absl::ToUnixSeconds(z) + 5
+  i = PLUS_FIVE(t);
+#undef 

[PATCH] D56532: [clang-tidy] Add the abseil-duration-conversion-cast check

2019-01-17 Thread Hyrum Wright via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL351473: [clang-tidy] Add abseil-duration-conversion-cast 
check (authored by hwright, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D56532?vs=182043=182374#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56532/new/

https://reviews.llvm.org/D56532

Files:
  clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt
  clang-tools-extra/trunk/clang-tidy/abseil/DurationConversionCastCheck.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/DurationConversionCastCheck.h
  clang-tools-extra/trunk/docs/ReleaseNotes.rst
  
clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-duration-conversion-cast.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
  clang-tools-extra/trunk/test/clang-tidy/abseil-duration-conversion-cast.cpp

Index: clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
===
--- clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
+++ clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "DurationComparisonCheck.h"
+#include "DurationConversionCastCheck.h"
 #include "DurationDivisionCheck.h"
 #include "DurationFactoryFloatCheck.h"
 #include "DurationFactoryScaleCheck.h"
@@ -32,6 +33,8 @@
   void addCheckFactories(ClangTidyCheckFactories ) override {
 CheckFactories.registerCheck(
 "abseil-duration-comparison");
+CheckFactories.registerCheck(
+"abseil-duration-conversion-cast");
 CheckFactories.registerCheck(
 "abseil-duration-division");
 CheckFactories.registerCheck(
Index: clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt
===
--- clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt
+++ clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt
@@ -3,6 +3,7 @@
 add_clang_library(clangTidyAbseilModule
   AbseilTidyModule.cpp
   DurationComparisonCheck.cpp
+  DurationConversionCastCheck.cpp
   DurationDivisionCheck.cpp
   DurationFactoryFloatCheck.cpp
   DurationFactoryScaleCheck.cpp
Index: clang-tools-extra/trunk/clang-tidy/abseil/DurationConversionCastCheck.h
===
--- clang-tools-extra/trunk/clang-tidy/abseil/DurationConversionCastCheck.h
+++ clang-tools-extra/trunk/clang-tidy/abseil/DurationConversionCastCheck.h
@@ -0,0 +1,36 @@
+//===--- DurationConversionCastCheck.h - clang-tidy -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_DURATIONCONVERSIONCASTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_DURATIONCONVERSIONCASTCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Checks for casts of ``absl::Duration`` conversion functions, and recommends
+/// the right conversion function instead.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-duration-conversion-cast.html
+class DurationConversionCastCheck : public ClangTidyCheck {
+public:
+  DurationConversionCastCheck(StringRef Name, ClangTidyContext *Context)
+  : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult ) override;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_DURATIONCONVERSIONCASTCHECK_H
Index: clang-tools-extra/trunk/clang-tidy/abseil/DurationConversionCastCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/abseil/DurationConversionCastCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/abseil/DurationConversionCastCheck.cpp
@@ -0,0 +1,85 @@
+//===--- DurationConversionCastCheck.cpp - clang-tidy -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "DurationConversionCastCheck.h"
+#include "DurationRewriter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {

[PATCH] D56532: [clang-tidy] Add the abseil-duration-conversion-cast check

2019-01-16 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 182043.
hwright marked 6 inline comments as done.
hwright added a comment.

Address reviewer comments


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56532/new/

https://reviews.llvm.org/D56532

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationConversionCastCheck.cpp
  clang-tidy/abseil/DurationConversionCastCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-conversion-cast.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-conversion-cast.cpp

Index: test/clang-tidy/abseil-duration-conversion-cast.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-conversion-cast.cpp
@@ -0,0 +1,95 @@
+// RUN: %check_clang_tidy %s abseil-duration-conversion-cast %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Duration d1;
+  double x;
+  int i;
+
+  i = static_cast(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Hours(d1);
+  x = static_cast(absl::ToInt64Hours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleHours(d1);
+  i = static_cast(absl::ToDoubleMinutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Minutes(d1);
+  x = static_cast(absl::ToInt64Minutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMinutes(d1);
+  i = static_cast(absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Seconds(d1);
+  x = static_cast(absl::ToInt64Seconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d1);
+  i = static_cast(absl::ToDoubleMilliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Milliseconds(d1);
+  x = static_cast(absl::ToInt64Milliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMilliseconds(d1);
+  i = static_cast(absl::ToDoubleMicroseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Microseconds(d1);
+  x = static_cast(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+  i = static_cast(absl::ToDoubleNanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Nanoseconds(d1);
+  x = static_cast(absl::ToInt64Nanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleNanoseconds(d1);
+
+  // Functional-style casts
+  i = int(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Hours(d1);
+  x = float(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to a floating-piont number rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+
+  // C-style casts
+  i = (int) absl::ToDoubleHours(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: duration should be converted directly to an integer rather than through a type cast [abseil-duration-conversion-cast]
+  // CHECK-FIXES: 

[PATCH] D56532: [clang-tidy] Add the abseil-duration-conversion-cast check

2019-01-16 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationComparisonCheck.cpp:47-48
   // if nothing needs to be done.
-  if (!IsValidMacro(Result, Binop->getLHS()) ||
-  !IsValidMacro(Result, Binop->getRHS()))
+  if (!isNotInMacro(Result, Binop->getLHS()) ||
+  !isNotInMacro(Result, Binop->getRHS()))
 return;

aaron.ballman wrote:
> I think this change (and the related removal) should be landed separately as 
> a NFC commit once this one lands, as it's logically separate from the new 
> check.
I've gone ahead and done the change separately, which should clean this up.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56532/new/

https://reviews.llvm.org/D56532



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56532: [clang-tidy] Add the abseil-duration-conversion-cast check

2019-01-14 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

Ping.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56532/new/

https://reviews.llvm.org/D56532



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56532: [clang-tidy] Add the abseil-duration-conversion-cast check

2019-01-10 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 181204.
hwright marked an inline comment as done.
hwright added a comment.

Run `clang-format`


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56532/new/

https://reviews.llvm.org/D56532

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationConversionCastCheck.cpp
  clang-tidy/abseil/DurationConversionCastCheck.h
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-conversion-cast.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-conversion-cast.cpp

Index: test/clang-tidy/abseil-duration-conversion-cast.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-conversion-cast.cpp
@@ -0,0 +1,84 @@
+// RUN: %check_clang_tidy %s abseil-duration-conversion-cast %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Duration d1;
+  double x;
+  int i;
+
+  i = static_cast(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Hours(d1);
+  x = static_cast(absl::ToInt64Hours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleHours(d1);
+  i = static_cast(absl::ToDoubleMinutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Minutes(d1);
+  x = static_cast(absl::ToInt64Minutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMinutes(d1);
+  i = static_cast(absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Seconds(d1);
+  x = static_cast(absl::ToInt64Seconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d1);
+  i = static_cast(absl::ToDoubleMilliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Milliseconds(d1);
+  x = static_cast(absl::ToInt64Milliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMilliseconds(d1);
+  i = static_cast(absl::ToDoubleMicroseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Microseconds(d1);
+  x = static_cast(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+  i = static_cast(absl::ToDoubleNanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Nanoseconds(d1);
+  x = static_cast(absl::ToInt64Nanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleNanoseconds(d1);
+
+  // Functional-style casts
+  i = int(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Hours(d1);
+  x = float(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+
+  // C-style casts
+  i = (int) absl::ToDoubleHours(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Hours(d1);
+  x = (float) absl::ToInt64Microseconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+
+  // Macro handling
+  // We want to transform things in macro arguments
+#define EXTERNAL(x) (x) + 5
+  i = EXTERNAL(static_cast(absl::ToDoubleSeconds(d1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: EXTERNAL(absl::ToInt64Seconds(d1));
+#undef EXTERNAL
+
+  // We don't want to transform this which get split across macro boundaries
+#define SPLIT(x) 

[PATCH] D56532: [clang-tidy] Add the abseil-duration-conversion-cast check

2019-01-10 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 181125.
hwright marked 5 inline comments as done.
hwright added a comment.

Update documentation line wrapping.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56532/new/

https://reviews.llvm.org/D56532

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationConversionCastCheck.cpp
  clang-tidy/abseil/DurationConversionCastCheck.h
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-conversion-cast.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-conversion-cast.cpp

Index: test/clang-tidy/abseil-duration-conversion-cast.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-conversion-cast.cpp
@@ -0,0 +1,84 @@
+// RUN: %check_clang_tidy %s abseil-duration-conversion-cast %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Duration d1;
+  double x;
+  int i;
+
+  i = static_cast(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Hours(d1);
+  x = static_cast(absl::ToInt64Hours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleHours(d1);
+  i = static_cast(absl::ToDoubleMinutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Minutes(d1);
+  x = static_cast(absl::ToInt64Minutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMinutes(d1);
+  i = static_cast(absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Seconds(d1);
+  x = static_cast(absl::ToInt64Seconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d1);
+  i = static_cast(absl::ToDoubleMilliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Milliseconds(d1);
+  x = static_cast(absl::ToInt64Milliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMilliseconds(d1);
+  i = static_cast(absl::ToDoubleMicroseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Microseconds(d1);
+  x = static_cast(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+  i = static_cast(absl::ToDoubleNanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Nanoseconds(d1);
+  x = static_cast(absl::ToInt64Nanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleNanoseconds(d1);
+
+  // Functional-style casts
+  i = int(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Hours(d1);
+  x = float(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+
+  // C-style casts
+  i = (int) absl::ToDoubleHours(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Hours(d1);
+  x = (float) absl::ToInt64Microseconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+
+  // Macro handling
+  // We want to transform things in macro arguments
+#define EXTERNAL(x) (x) + 5
+  i = EXTERNAL(static_cast(absl::ToDoubleSeconds(d1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: EXTERNAL(absl::ToInt64Seconds(d1));
+#undef EXTERNAL
+
+  // We don't want to transform this which get split across macro boundaries
+#define 

[PATCH] D56532: [clang-tidy] Add the abseil-duration-conversion-cast check

2019-01-10 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: docs/clang-tidy/checks/abseil-duration-conversion-cast.rst:20
+
+
+  // Original - Cast from a double to an integer

MyDeveloperDay wrote:
> nit: double blank line
This is intentional (and consistent with other examples in other tools).



Comment at: docs/clang-tidy/checks/abseil-duration-conversion-cast.rst:28
+
+
+Note: In the second example, the suggested fix could yield a different result,

MyDeveloperDay wrote:
> nit: double blank line
This is intentional (and consistent with other documentation).


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56532/new/

https://reviews.llvm.org/D56532



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56532: [clang-tidy] Add the abseil-duration-conversion-cast check

2019-01-09 Thread Hyrum Wright via Phabricator via cfe-commits
hwright created this revision.
hwright added reviewers: hokein, aaron.ballman.
hwright added a project: clang-tools-extra.
Herald added subscribers: cfe-commits, xazax.hun, mgorny.

This suggests simplifying expressions which are casting conversion functions, 
such as `static_cast(absl::ToDoubleSeconds(...))`


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D56532

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationConversionCastCheck.cpp
  clang-tidy/abseil/DurationConversionCastCheck.h
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-conversion-cast.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-conversion-cast.cpp

Index: test/clang-tidy/abseil-duration-conversion-cast.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-conversion-cast.cpp
@@ -0,0 +1,84 @@
+// RUN: %check_clang_tidy %s abseil-duration-conversion-cast %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  absl::Duration d1;
+  double x;
+  int i;
+
+  i = static_cast(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Hours(d1);
+  x = static_cast(absl::ToInt64Hours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleHours(d1);
+  i = static_cast(absl::ToDoubleMinutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Minutes(d1);
+  x = static_cast(absl::ToInt64Minutes(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMinutes(d1);
+  i = static_cast(absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Seconds(d1);
+  x = static_cast(absl::ToInt64Seconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d1);
+  i = static_cast(absl::ToDoubleMilliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Milliseconds(d1);
+  x = static_cast(absl::ToInt64Milliseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMilliseconds(d1);
+  i = static_cast(absl::ToDoubleMicroseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Microseconds(d1);
+  x = static_cast(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+  i = static_cast(absl::ToDoubleNanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Nanoseconds(d1);
+  x = static_cast(absl::ToInt64Nanoseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleNanoseconds(d1);
+
+  // Functional-style casts
+  i = int(absl::ToDoubleHours(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Hours(d1);
+  x = float(absl::ToInt64Microseconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+
+  // C-style casts
+  i = (int) absl::ToDoubleHours(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToInt64Hours(d1);
+  x = (float) absl::ToInt64Microseconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: convert duration directly to double [abseil-duration-conversion-cast]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d1);
+
+  // Macro handling
+  // We want to transform things in macro arguments
+#define EXTERNAL(x) (x) + 5
+  i = EXTERNAL(static_cast(absl::ToDoubleSeconds(d1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: convert duration directly to integer [abseil-duration-conversion-cast]
+  // CHECK-FIXES: 

[PATCH] D56090: Add a matcher for members of an initializer list expression

2019-01-07 Thread Hyrum Wright via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL350523: [clang] Add AST matcher for initializer list members 
(authored by hwright, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D56090?vs=180248=180481#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56090/new/

https://reviews.llvm.org/D56090

Files:
  cfe/trunk/docs/LibASTMatchersReference.html
  cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
  cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
  cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp


Index: cfe/trunk/docs/LibASTMatchersReference.html
===
--- cfe/trunk/docs/LibASTMatchersReference.html
+++ cfe/trunk/docs/LibASTMatchersReference.html
@@ -718,7 +718,7 @@
 
 
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtblockExprMatcherhttps://clang.llvm.org/doxygen/classclang_1_1BlockExpr.html;>BlockExpr...
-MAtches a reference to a 
block.
+Matches a reference to a 
block.
 
 Example: matches "^{}":
   void f() { ^{}(); }
@@ -5866,6 +5866,15 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html;>InitListExprhasInitunsigned N, 
ast_matchers::Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr 
InnerMatcher
+Matches the n'th item of an 
initializer list expression.
+
+Example matches y.
+(matcher = initListExpr(hasInit(0, expr(
+  int x{y}.
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html;>InitListExprhasSyntacticFormMatcherhttps://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr 
InnerMatcher
 Matches the 
syntactic form of init list expressions
 (if expression have it).
Index: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
===
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
@@ -3514,6 +3514,19 @@
   *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
 }
 
+/// Matches the n'th item of an initializer list expression.
+///
+/// Example matches y.
+/// (matcher = initListExpr(hasInit(0, expr(
+/// \code
+///   int x{y}.
+/// \endcode
+AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
+   ast_matchers::internal::Matcher, InnerMatcher) {
+  return N < Node.getNumInits() &&
+  InnerMatcher.matches(*Node.getInit(N), Finder, Builder);
+}
+
 /// Matches declaration statements that contain a specific number of
 /// declarations.
 ///
Index: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -273,6 +273,7 @@
   REGISTER_MATCHER(hasInClassInitializer);
   REGISTER_MATCHER(hasIncrement);
   REGISTER_MATCHER(hasIndex);
+  REGISTER_MATCHER(hasInit);
   REGISTER_MATCHER(hasInitializer);
   REGISTER_MATCHER(hasKeywordSelector);
   REGISTER_MATCHER(hasLHS);
Index: cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2255,6 +2255,18 @@
   notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
 }
 
+TEST(HasInit, Basic) {
+  EXPECT_TRUE(
+matches("int x{0};",
+initListExpr(hasInit(0, expr();
+  EXPECT_FALSE(
+matches("int x{0};",
+initListExpr(hasInit(1, expr();
+  EXPECT_FALSE(
+matches("int x;",
+initListExpr(hasInit(0, expr();
+}
+
 TEST(Matcher, isMain) {
   EXPECT_TRUE(
 matches("int main() {}", functionDecl(isMain(;


Index: cfe/trunk/docs/LibASTMatchersReference.html
===
--- cfe/trunk/docs/LibASTMatchersReference.html
+++ cfe/trunk/docs/LibASTMatchersReference.html
@@ -718,7 +718,7 @@
 
 
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtblockExprMatcherhttps://clang.llvm.org/doxygen/classclang_1_1BlockExpr.html;>BlockExpr...
-MAtches a reference to a block.
+Matches a reference to a block.
 
 Example: matches "^{}":
   void f() { ^{}(); }
@@ -5866,6 +5866,15 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html;>InitListExprhasInitunsigned N, ast_matchers::Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr InnerMatcher
+Matches the n'th item of an initializer list expression.
+
+Example matches y.
+(matcher = initListExpr(hasInit(0, expr(
+  int x{y}.
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html;>InitListExprhasSyntacticFormMatcherhttps://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr InnerMatcher
 Matches 

[PATCH] D56090: Add a matcher for members of an initializer list expression

2019-01-04 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked 4 inline comments as done.
hwright added inline comments.



Comment at: include/clang/ASTMatchers/ASTMatchers.h:3527
+  return N < Node.getNumInits() &&
+  InnerMatcher.matches(*Node.getInit(N)->IgnoreParenImpCasts(), Finder,
+   Builder);

klimek wrote:
> aaron.ballman wrote:
> > hwright wrote:
> > > aaron.ballman wrote:
> > > > I'm not certain we want the `IgnoreParenImpCasts()` here -- what if 
> > > > someone wants to match an initializer that uses one of those properties?
> > > The `hasArg` implementation directly above has the same call to 
> > > `IgnoreParenImpCasts()`.  Is it also in error?  (It would seem that they 
> > > should both be consistent.)
> > Yeah, I noticed that as well. Doing some code archaeology, it seems that 
> > `hasArg()` has had that form since its inception and it was never 
> > explicitly discussed what should happen there.
> > 
> > @klimek -- do you have opinions here, since you wrote the original code for 
> > `hasArg()`? Should we be leaving the paren and implicit cast stripping up 
> > to the caller rather than doing it automatically?
> Sigh, yea, this is one of those hard decisions: in the end, we decided that 
> the downside of surprise of users not seeing what they expected (due to an 
> imp cast) was less bad than basically taking away the ability to match imp 
> casts, so we stopped putting ignoreparenimpcasts everywhere. I'm not entirely 
> sure how to rate consistency with hasArg vs. getting us towards a more 
> explicit world, but my gut would probably go with leaving the 
> ignoreparenimpcasts out and see how bad people find it.
Removed the call to `IgnoreParenImpCasts()`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56090/new/

https://reviews.llvm.org/D56090



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56090: Add a matcher for members of an initializer list expression

2019-01-04 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 180248.
hwright added a comment.

Removed `IgnoreParenImpCasts` call.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56090/new/

https://reviews.llvm.org/D56090

Files:
  docs/LibASTMatchersReference.html
  include/clang/ASTMatchers/ASTMatchers.h
  lib/ASTMatchers/Dynamic/Registry.cpp
  unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp


Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2255,6 +2255,18 @@
   notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
 }
 
+TEST(HasInit, Basic) {
+  EXPECT_TRUE(
+matches("int x{0};",
+initListExpr(hasInit(0, expr();
+  EXPECT_FALSE(
+matches("int x{0};",
+initListExpr(hasInit(1, expr();
+  EXPECT_FALSE(
+matches("int x;",
+initListExpr(hasInit(0, expr();
+}
+
 TEST(Matcher, isMain) {
   EXPECT_TRUE(
 matches("int main() {}", functionDecl(isMain(;
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -273,6 +273,7 @@
   REGISTER_MATCHER(hasInClassInitializer);
   REGISTER_MATCHER(hasIncrement);
   REGISTER_MATCHER(hasIndex);
+  REGISTER_MATCHER(hasInit);
   REGISTER_MATCHER(hasInitializer);
   REGISTER_MATCHER(hasKeywordSelector);
   REGISTER_MATCHER(hasLHS);
Index: include/clang/ASTMatchers/ASTMatchers.h
===
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -3514,6 +3514,19 @@
   *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
 }
 
+/// Matches the n'th item of an initializer list expression.
+///
+/// Example matches y.
+/// (matcher = initListExpr(hasInit(0, expr(
+/// \code
+///   int x{y}.
+/// \endcode
+AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
+   ast_matchers::internal::Matcher, InnerMatcher) {
+  return N < Node.getNumInits() &&
+  InnerMatcher.matches(*Node.getInit(N), Finder, Builder);
+}
+
 /// Matches declaration statements that contain a specific number of
 /// declarations.
 ///
Index: docs/LibASTMatchersReference.html
===
--- docs/LibASTMatchersReference.html
+++ docs/LibASTMatchersReference.html
@@ -718,7 +718,7 @@
 
 
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtblockExprMatcherhttps://clang.llvm.org/doxygen/classclang_1_1BlockExpr.html;>BlockExpr...
-MAtches a reference to a 
block.
+Matches a reference to a 
block.
 
 Example: matches "^{}":
   void f() { ^{}(); }
@@ -5866,6 +5866,15 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html;>InitListExprhasInitunsigned N, 
ast_matchers::Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr 
InnerMatcher
+Matches the n'th item of an 
initializer list expression.
+
+Example matches y.
+(matcher = initListExpr(hasInit(0, expr(
+  int x{y}.
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html;>InitListExprhasSyntacticFormMatcherhttps://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr 
InnerMatcher
 Matches the 
syntactic form of init list expressions
 (if expression have it).


Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2255,6 +2255,18 @@
   notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
 }
 
+TEST(HasInit, Basic) {
+  EXPECT_TRUE(
+matches("int x{0};",
+initListExpr(hasInit(0, expr();
+  EXPECT_FALSE(
+matches("int x{0};",
+initListExpr(hasInit(1, expr();
+  EXPECT_FALSE(
+matches("int x;",
+initListExpr(hasInit(0, expr();
+}
+
 TEST(Matcher, isMain) {
   EXPECT_TRUE(
 matches("int main() {}", functionDecl(isMain(;
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -273,6 +273,7 @@
   REGISTER_MATCHER(hasInClassInitializer);
   REGISTER_MATCHER(hasIncrement);
   REGISTER_MATCHER(hasIndex);
+  REGISTER_MATCHER(hasInit);
   REGISTER_MATCHER(hasInitializer);
   REGISTER_MATCHER(hasKeywordSelector);
   REGISTER_MATCHER(hasLHS);
Index: include/clang/ASTMatchers/ASTMatchers.h
===
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -3514,6 +3514,19 @@
   

[PATCH] D56090: Add a matcher for members of an initializer list expression

2019-01-03 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: include/clang/ASTMatchers/ASTMatchers.h:3527
+  return N < Node.getNumInits() &&
+  InnerMatcher.matches(*Node.getInit(N)->IgnoreParenImpCasts(), Finder,
+   Builder);

aaron.ballman wrote:
> I'm not certain we want the `IgnoreParenImpCasts()` here -- what if someone 
> wants to match an initializer that uses one of those properties?
The `hasArg` implementation directly above has the same call to 
`IgnoreParenImpCasts()`.  Is it also in error?  (It would seem that they should 
both be consistent.)


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56090/new/

https://reviews.llvm.org/D56090



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56090: Add a matcher for members of an initializer list expression

2019-01-03 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 180089.
hwright marked an inline comment as done.
hwright added a comment.

Added tests, update docs.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56090/new/

https://reviews.llvm.org/D56090

Files:
  docs/LibASTMatchersReference.html
  include/clang/ASTMatchers/ASTMatchers.h
  lib/ASTMatchers/Dynamic/Registry.cpp
  unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp


Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2255,6 +2255,18 @@
   notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
 }
 
+TEST(HasInit, Basic) {
+  EXPECT_TRUE(
+matches("int x{0};",
+initListExpr(hasInit(0, expr();
+  EXPECT_FALSE(
+matches("int x{0};",
+initListExpr(hasInit(1, expr();
+  EXPECT_FALSE(
+matches("int x;",
+initListExpr(hasInit(0, expr();
+}
+
 TEST(Matcher, isMain) {
   EXPECT_TRUE(
 matches("int main() {}", functionDecl(isMain(;
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -273,6 +273,7 @@
   REGISTER_MATCHER(hasInClassInitializer);
   REGISTER_MATCHER(hasIncrement);
   REGISTER_MATCHER(hasIndex);
+  REGISTER_MATCHER(hasInit);
   REGISTER_MATCHER(hasInitializer);
   REGISTER_MATCHER(hasKeywordSelector);
   REGISTER_MATCHER(hasLHS);
Index: include/clang/ASTMatchers/ASTMatchers.h
===
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -3514,6 +3514,20 @@
   *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
 }
 
+/// Matches the n'th item of an initializer list expression.
+///
+/// Example matches y.
+/// (matcher = initListExpr(hasInit(0, expr(
+/// \code
+///   int x{y}.
+/// \endcode
+AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
+   ast_matchers::internal::Matcher, InnerMatcher) {
+  return N < Node.getNumInits() &&
+  InnerMatcher.matches(*Node.getInit(N)->IgnoreParenImpCasts(), Finder,
+   Builder);
+}
+
 /// Matches declaration statements that contain a specific number of
 /// declarations.
 ///
Index: docs/LibASTMatchersReference.html
===
--- docs/LibASTMatchersReference.html
+++ docs/LibASTMatchersReference.html
@@ -718,7 +718,7 @@
 
 
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtblockExprMatcherhttps://clang.llvm.org/doxygen/classclang_1_1BlockExpr.html;>BlockExpr...
-MAtches a reference to a 
block.
+Matches a reference to a 
block.
 
 Example: matches "^{}":
   void f() { ^{}(); }
@@ -5866,6 +5866,15 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html;>InitListExprhasInitunsigned N, 
ast_matchers::Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr 
InnerMatcher
+Matches the n'th item of an 
initializer list expression.
+
+Example matches y.
+(matcher = initListExpr(hasInit(0, expr(
+  int x{y}.
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html;>InitListExprhasSyntacticFormMatcherhttps://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr 
InnerMatcher
 Matches the 
syntactic form of init list expressions
 (if expression have it).


Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2255,6 +2255,18 @@
   notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
 }
 
+TEST(HasInit, Basic) {
+  EXPECT_TRUE(
+matches("int x{0};",
+initListExpr(hasInit(0, expr();
+  EXPECT_FALSE(
+matches("int x{0};",
+initListExpr(hasInit(1, expr();
+  EXPECT_FALSE(
+matches("int x;",
+initListExpr(hasInit(0, expr();
+}
+
 TEST(Matcher, isMain) {
   EXPECT_TRUE(
 matches("int main() {}", functionDecl(isMain(;
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -273,6 +273,7 @@
   REGISTER_MATCHER(hasInClassInitializer);
   REGISTER_MATCHER(hasIncrement);
   REGISTER_MATCHER(hasIndex);
+  REGISTER_MATCHER(hasInit);
   REGISTER_MATCHER(hasInitializer);
   REGISTER_MATCHER(hasKeywordSelector);
   REGISTER_MATCHER(hasLHS);
Index: include/clang/ASTMatchers/ASTMatchers.h
===
--- include/clang/ASTMatchers/ASTMatchers.h
+++ 

[PATCH] D56090: Add a matcher for members of an initializer list expression

2018-12-26 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

@lebedev.ri Where do the appropriate tests live?  (I couldn't find an obvious 
subdirectory in `test/`)
Where are the instructions for regenerating the documentation?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56090/new/

https://reviews.llvm.org/D56090



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56090: Add a matcher for members of an initializer list expression

2018-12-26 Thread Hyrum Wright via Phabricator via cfe-commits
hwright created this revision.
hwright added a reviewer: aaron.ballman.
hwright added a project: clang.
Herald added a subscriber: cfe-commits.

Much like `hasArg` for various call expressions, this allows `LibTooling` users 
to match against a member of an initializer list.

This is currently being used as part of the `abseil-duration-scale` clang-tidy 
check.


Repository:
  rC Clang

https://reviews.llvm.org/D56090

Files:
  include/clang/ASTMatchers/ASTMatchers.h


Index: include/clang/ASTMatchers/ASTMatchers.h
===
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -3514,6 +3514,20 @@
   *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
 }
 
+/// Matches the n'th item of an initializer list expression.
+///
+/// Example matches y.
+/// (matcher = initListExpr(hasInit(0, expr(
+/// \code
+///   int x{y}.
+/// \endcode
+AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
+   ast_matchers::internal::Matcher, InnerMatcher) {
+  return N < Node.getNumInits() &&
+  InnerMatcher.matches(*Node.getInit(N)->IgnoreParenImpCasts(), Finder,
+   Builder);
+}
+
 /// Matches declaration statements that contain a specific number of
 /// declarations.
 ///


Index: include/clang/ASTMatchers/ASTMatchers.h
===
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -3514,6 +3514,20 @@
   *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
 }
 
+/// Matches the n'th item of an initializer list expression.
+///
+/// Example matches y.
+/// (matcher = initListExpr(hasInit(0, expr(
+/// \code
+///   int x{y}.
+/// \endcode
+AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
+   ast_matchers::internal::Matcher, InnerMatcher) {
+  return N < Node.getNumInits() &&
+  InnerMatcher.matches(*Node.getInit(N)->IgnoreParenImpCasts(), Finder,
+   Builder);
+}
+
 /// Matches declaration statements that contain a specific number of
 /// declarations.
 ///
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56012: [clang-tidy] Be more liberal about literal zeroes in abseil checks

2018-12-21 Thread Hyrum Wright via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL349953: [clang-tidy] Be more liberal about literal zeroes in 
abseil checks (authored by hwright, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D56012?vs=179335=179341#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56012/new/

https://reviews.llvm.org/D56012

Files:
  clang-tools-extra/trunk/clang-tidy/abseil/DurationFactoryScaleCheck.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
  clang-tools-extra/trunk/test/clang-tidy/abseil-duration-factory-scale.cpp

Index: clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
===
--- clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
+++ clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
@@ -105,14 +105,44 @@
   llvm_unreachable("unknown scaling factor");
 }
 
+/// Matches the n'th item of an initializer list expression.
+///
+/// Example matches y.
+/// (matcher = initListExpr(hasInit(0, expr(
+/// \code
+///   int x{y}.
+/// \endcode
+AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
+   ast_matchers::internal::Matcher, InnerMatcher) {
+  return N < Node.getNumInits() &&
+  InnerMatcher.matches(*Node.getInit(N)->IgnoreParenImpCasts(), Finder,
+   Builder);
+}
+
 /// Returns `true` if `Node` is a value which evaluates to a literal `0`.
 bool IsLiteralZero(const MatchFinder::MatchResult , const Expr ) {
-  return selectFirst(
- "val",
- match(expr(ignoringImpCasts(anyOf(integerLiteral(equals(0)),
-   floatLiteral(equals(0.0)
-   .bind("val"),
-   Node, *Result.Context)) != nullptr;
+  auto ZeroMatcher =
+  anyOf(integerLiteral(equals(0)), floatLiteral(equals(0.0)));
+
+  // Check to see if we're using a zero directly.
+  if (selectFirst(
+  "val", match(expr(ignoringImpCasts(ZeroMatcher)).bind("val"), Node,
+   *Result.Context)) != nullptr)
+return true;
+
+  // Now check to see if we're using a functional cast with a scalar
+  // initializer expression, e.g. `int{0}`.
+  if (selectFirst(
+  "val",
+  match(cxxFunctionalCastExpr(
+hasDestinationType(
+anyOf(isInteger(), realFloatingPointType())),
+hasSourceExpression(initListExpr(hasInit(0, ZeroMatcher
+.bind("val"),
+Node, *Result.Context)) != nullptr)
+return true;
+
+  return false;
 }
 
 llvm::Optional
Index: clang-tools-extra/trunk/clang-tidy/abseil/DurationFactoryScaleCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/abseil/DurationFactoryScaleCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/abseil/DurationFactoryScaleCheck.cpp
@@ -123,6 +123,10 @@
   hasArgument(
   0,
   ignoringImpCasts(anyOf(
+  cxxFunctionalCastExpr(
+  hasDestinationType(
+  anyOf(isInteger(), realFloatingPointType())),
+  hasSourceExpression(initListExpr())),
   integerLiteral(equals(0)), floatLiteral(equals(0.0)),
   binaryOperator(hasOperatorName("*"),
  hasEitherOperand(ignoringImpCasts(
Index: clang-tools-extra/trunk/test/clang-tidy/abseil-duration-factory-scale.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/abseil-duration-factory-scale.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/abseil-duration-factory-scale.cpp
@@ -2,6 +2,9 @@
 
 #include "absl/time/time.h"
 
+namespace std { typedef long long int64_t; }
+using int64_t = std::int64_t;
+
 void ScaleTest() {
   absl::Duration d;
 
@@ -30,6 +33,15 @@
   d = absl::Seconds(0x0.01p-126f);
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
   // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(int{0});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(int64_t{0});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(float{0});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
 
   // Fold seconds into minutes
   d = absl::Seconds(30 * 60);
@@ -83,6 +95,8 @@
 
   // None of 

[PATCH] D56012: [clang-tidy] Be more liberal about literal zeroes in abseil checks

2018-12-21 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

btw, I think `hasInit` should probably be moved into the core set of matchers 
at some point.




Comment at: clang-tidy/abseil/DurationRewriter.cpp:110
+   ast_matchers::internal::Matcher, InnerMatcher) {
+  return (N < Node.getNumInits() &&
+  InnerMatcher.matches(*Node.getInit(N)->IgnoreParenImpCasts(), Finder,

aaron.ballman wrote:
> Spurious parens can be removed.
Done.  (Though there are similar parens in the implementation of `hasArgument`. 
:)



Comment at: test/clang-tidy/abseil-duration-factory-scale.cpp:34
   // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(int{0});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for 
zero-length time intervals [abseil-duration-factory-scale]

aaron.ballman wrote:
> Do you also have users doing something like: `absl::Seconds(int{});`?
I have not yet seen that.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56012/new/

https://reviews.llvm.org/D56012



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56012: [clang-tidy] Be more liberal about literal zeroes in abseil checks

2018-12-21 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 179335.
hwright marked 6 inline comments as done.
hwright added a comment.

Add documentation, adjust test.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56012/new/

https://reviews.llvm.org/D56012

Files:
  clang-tidy/abseil/DurationFactoryScaleCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  test/clang-tidy/abseil-duration-factory-scale.cpp

Index: test/clang-tidy/abseil-duration-factory-scale.cpp
===
--- test/clang-tidy/abseil-duration-factory-scale.cpp
+++ test/clang-tidy/abseil-duration-factory-scale.cpp
@@ -2,6 +2,9 @@
 
 #include "absl/time/time.h"
 
+namespace std { typedef long long int64_t; }
+using int64_t = std::int64_t;
+
 void ScaleTest() {
   absl::Duration d;
 
@@ -30,6 +33,15 @@
   d = absl::Seconds(0x0.01p-126f);
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
   // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(int{0});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(int64_t{0});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(float{0});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
 
   // Fold seconds into minutes
   d = absl::Seconds(30 * 60);
@@ -83,6 +95,8 @@
 
   // None of these should trigger the check
   d = absl::Seconds(60);
+  d = absl::Seconds(int{60});
+  d = absl::Seconds(float{60});
   d = absl::Seconds(60 + 30);
   d = absl::Seconds(60 - 30);
   d = absl::Seconds(50 * 30);
Index: clang-tidy/abseil/DurationRewriter.cpp
===
--- clang-tidy/abseil/DurationRewriter.cpp
+++ clang-tidy/abseil/DurationRewriter.cpp
@@ -105,14 +105,44 @@
   llvm_unreachable("unknown scaling factor");
 }
 
+/// Matches the n'th item of an initializer list expression.
+///
+/// Example matches y.
+/// (matcher = initListExpr(hasInit(0, expr(
+/// \code
+///   int x{y}.
+/// \endcode
+AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
+   ast_matchers::internal::Matcher, InnerMatcher) {
+  return N < Node.getNumInits() &&
+  InnerMatcher.matches(*Node.getInit(N)->IgnoreParenImpCasts(), Finder,
+   Builder);
+}
+
 /// Returns `true` if `Node` is a value which evaluates to a literal `0`.
 bool IsLiteralZero(const MatchFinder::MatchResult , const Expr ) {
-  return selectFirst(
- "val",
- match(expr(ignoringImpCasts(anyOf(integerLiteral(equals(0)),
-   floatLiteral(equals(0.0)
-   .bind("val"),
-   Node, *Result.Context)) != nullptr;
+  auto ZeroMatcher =
+  anyOf(integerLiteral(equals(0)), floatLiteral(equals(0.0)));
+
+  // Check to see if we're using a zero directly.
+  if (selectFirst(
+  "val", match(expr(ignoringImpCasts(ZeroMatcher)).bind("val"), Node,
+   *Result.Context)) != nullptr)
+return true;
+
+  // Now check to see if we're using a functional cast with a scalar
+  // initializer expression, e.g. `int{0}`.
+  if (selectFirst(
+  "val",
+  match(cxxFunctionalCastExpr(
+hasDestinationType(
+anyOf(isInteger(), realFloatingPointType())),
+hasSourceExpression(initListExpr(hasInit(0, ZeroMatcher
+.bind("val"),
+Node, *Result.Context)) != nullptr)
+return true;
+
+  return false;
 }
 
 llvm::Optional
Index: clang-tidy/abseil/DurationFactoryScaleCheck.cpp
===
--- clang-tidy/abseil/DurationFactoryScaleCheck.cpp
+++ clang-tidy/abseil/DurationFactoryScaleCheck.cpp
@@ -123,6 +123,10 @@
   hasArgument(
   0,
   ignoringImpCasts(anyOf(
+  cxxFunctionalCastExpr(
+  hasDestinationType(
+  anyOf(isInteger(), realFloatingPointType())),
+  hasSourceExpression(initListExpr())),
   integerLiteral(equals(0)), floatLiteral(equals(0.0)),
   binaryOperator(hasOperatorName("*"),
  hasEitherOperand(ignoringImpCasts(
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56012: Be more liberal about literal zeroes in abseil checks

2018-12-21 Thread Hyrum Wright via Phabricator via cfe-commits
hwright created this revision.
hwright added reviewers: aaron.ballman, JonasToth, alexfh, hokein.
hwright added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Previously, we'd only match on literal floating or integral zeroes, but I've 
now also learned that some users spell that value as `int{0}` or `float{0}`, 
which also need to be matched.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D56012

Files:
  clang-tidy/abseil/DurationFactoryScaleCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  test/clang-tidy/abseil-duration-factory-scale.cpp


Index: test/clang-tidy/abseil-duration-factory-scale.cpp
===
--- test/clang-tidy/abseil-duration-factory-scale.cpp
+++ test/clang-tidy/abseil-duration-factory-scale.cpp
@@ -1,5 +1,6 @@
 // RUN: %check_clang_tidy %s abseil-duration-factory-scale %t -- -- -I%S/Inputs
 
+#include 
 #include "absl/time/time.h"
 
 void ScaleTest() {
@@ -30,6 +31,15 @@
   d = absl::Seconds(0x0.01p-126f);
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for 
zero-length time intervals [abseil-duration-factory-scale]
   // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(int{0});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for 
zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(int64_t{0});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for 
zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(float{0});
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for 
zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
 
   // Fold seconds into minutes
   d = absl::Seconds(30 * 60);
@@ -83,6 +93,8 @@
 
   // None of these should trigger the check
   d = absl::Seconds(60);
+  d = absl::Seconds(int{60});
+  d = absl::Seconds(float{60});
   d = absl::Seconds(60 + 30);
   d = absl::Seconds(60 - 30);
   d = absl::Seconds(50 * 30);
Index: clang-tidy/abseil/DurationRewriter.cpp
===
--- clang-tidy/abseil/DurationRewriter.cpp
+++ clang-tidy/abseil/DurationRewriter.cpp
@@ -105,14 +105,37 @@
   llvm_unreachable("unknown scaling factor");
 }
 
+AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
+   ast_matchers::internal::Matcher, InnerMatcher) {
+  return (N < Node.getNumInits() &&
+  InnerMatcher.matches(*Node.getInit(N)->IgnoreParenImpCasts(), Finder,
+   Builder));
+}
+
 /// Returns `true` if `Node` is a value which evaluates to a literal `0`.
 bool IsLiteralZero(const MatchFinder::MatchResult , const Expr ) {
-  return selectFirst(
- "val",
- match(expr(ignoringImpCasts(anyOf(integerLiteral(equals(0)),
-   floatLiteral(equals(0.0)
-   .bind("val"),
-   Node, *Result.Context)) != nullptr;
+  auto ZeroMatcher =
+  anyOf(integerLiteral(equals(0)), floatLiteral(equals(0.0)));
+
+  // Check to see if we're using a zero directly.
+  if (selectFirst(
+  "val", match(expr(ignoringImpCasts(ZeroMatcher)).bind("val"), Node,
+   *Result.Context)) != nullptr)
+return true;
+
+  // Now check to see if we're using a functional cast with a scalar
+  // initializer expression, e.g. `int{0}`.
+  if (selectFirst(
+  "val",
+  match(cxxFunctionalCastExpr(
+hasDestinationType(
+anyOf(isInteger(), realFloatingPointType())),
+hasSourceExpression(initListExpr(hasInit(0, ZeroMatcher
+.bind("val"),
+Node, *Result.Context)) != nullptr)
+return true;
+
+  return false;
 }
 
 llvm::Optional
Index: clang-tidy/abseil/DurationFactoryScaleCheck.cpp
===
--- clang-tidy/abseil/DurationFactoryScaleCheck.cpp
+++ clang-tidy/abseil/DurationFactoryScaleCheck.cpp
@@ -123,6 +123,10 @@
   hasArgument(
   0,
   ignoringImpCasts(anyOf(
+  cxxFunctionalCastExpr(
+  hasDestinationType(
+  anyOf(isInteger(), realFloatingPointType())),
+  hasSourceExpression(initListExpr())),
   integerLiteral(equals(0)), floatLiteral(equals(0.0)),
   binaryOperator(hasOperatorName("*"),
  hasEitherOperand(ignoringImpCasts(


Index: test/clang-tidy/abseil-duration-factory-scale.cpp
===
--- test/clang-tidy/abseil-duration-factory-scale.cpp
+++ test/clang-tidy/abseil-duration-factory-scale.cpp
@@ -1,5 +1,6 @@
 // RUN: 

[PATCH] D55784: [clang-tidy] Update abseil-duration-comparison to handle macro arguments

2018-12-19 Thread Hyrum Wright via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
hwright marked an inline comment as done.
Closed by commit rL349636: [clang-tidy] Diagnose abseil-duration-comparison on 
macro arguments (authored by hwright, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D55784?vs=178733=178891#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55784/new/

https://reviews.llvm.org/D55784

Files:
  clang-tools-extra/trunk/clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.h
  clang-tools-extra/trunk/clang-tidy/abseil/DurationSubtractionCheck.cpp
  clang-tools-extra/trunk/test/clang-tidy/abseil-duration-comparison.cpp

Index: clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.h
===
--- clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.h
+++ clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.h
@@ -65,7 +65,7 @@
 
 /// Assuming `Node` has type `double` or `int` representing a time interval of
 /// `Scale`, return the expression to make it a suitable `Duration`.
-llvm::Optional rewriteExprFromNumberToDuration(
+std::string rewriteExprFromNumberToDuration(
 const ast_matchers::MatchFinder::MatchResult , DurationScale Scale,
 const Expr *Node);
 
Index: clang-tools-extra/trunk/clang-tidy/abseil/DurationComparisonCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/abseil/DurationComparisonCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/abseil/DurationComparisonCheck.cpp
@@ -19,6 +19,26 @@
 namespace tidy {
 namespace abseil {
 
+/// Return `true` if `E` is a either: not a macro at all; or an argument to
+/// one. In the latter case, we should still transform it.
+static bool IsValidMacro(const MatchFinder::MatchResult ,
+ const Expr *E) {
+  if (!E->getBeginLoc().isMacroID())
+return true;
+
+  SourceLocation Loc = E->getBeginLoc();
+  // We want to get closer towards the initial macro typed into the source only
+  // if the location is being expanded as a macro argument.
+  while (Result.SourceManager->isMacroArgExpansion(Loc)) {
+// We are calling getImmediateMacroCallerLoc, but note it is essentially
+// equivalent to calling getImmediateSpellingLoc in this context according
+// to Clang implementation. We are not calling getImmediateSpellingLoc
+// because Clang comment says it "should not generally be used by clients."
+Loc = Result.SourceManager->getImmediateMacroCallerLoc(Loc);
+  }
+  return !Loc.isMacroID();
+}
+
 void DurationComparisonCheck::registerMatchers(MatchFinder *Finder) {
   auto Matcher =
   binaryOperator(anyOf(hasOperatorName(">"), hasOperatorName(">="),
@@ -35,10 +55,6 @@
 void DurationComparisonCheck::check(const MatchFinder::MatchResult ) {
   const auto *Binop = Result.Nodes.getNodeAs("binop");
 
-  // Don't try to replace things inside of macro definitions.
-  if (Binop->getExprLoc().isMacroID())
-return;
-
   llvm::Optional Scale = getScaleForInverse(
   Result.Nodes.getNodeAs("function_decl")->getName());
   if (!Scale)
@@ -48,19 +64,19 @@
   // want to handle the case of rewriting both sides. This is much simpler if
   // we unconditionally try and rewrite both, and let the rewriter determine
   // if nothing needs to be done.
-  llvm::Optional LhsReplacement =
+  if (!IsValidMacro(Result, Binop->getLHS()) ||
+  !IsValidMacro(Result, Binop->getRHS()))
+return;
+  std::string LhsReplacement =
   rewriteExprFromNumberToDuration(Result, *Scale, Binop->getLHS());
-  llvm::Optional RhsReplacement =
+  std::string RhsReplacement =
   rewriteExprFromNumberToDuration(Result, *Scale, Binop->getRHS());
 
-  if (!(LhsReplacement && RhsReplacement))
-return;
-
   diag(Binop->getBeginLoc(), "perform comparison in the duration domain")
   << FixItHint::CreateReplacement(Binop->getSourceRange(),
-  (llvm::Twine(*LhsReplacement) + " " +
+  (llvm::Twine(LhsReplacement) + " " +
Binop->getOpcodeStr() + " " +
-   *RhsReplacement)
+   RhsReplacement)
   .str());
 }
 
Index: clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
===
--- clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
+++ clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
@@ -183,14 +183,11 @@
   return ScaleIter->second;
 }
 
-llvm::Optional rewriteExprFromNumberToDuration(
+std::string rewriteExprFromNumberToDuration(
 const 

[PATCH] D55784: [clang-tidy] Update abseil-duration-comparison to handle macro arguments

2018-12-19 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked 2 inline comments as done.
hwright added inline comments.



Comment at: test/clang-tidy/abseil-duration-comparison.cpp:146
+#define VALUE_IF_2(e) (e)
+#define VALUE_IF(v, e, type) (v ? VALUE_IF_2(absl::To##type##Seconds(e)) : 0)
+  int a3 = VALUE_IF(1, d1, Double);

aaron.ballman wrote:
> hwright wrote:
> > aaron.ballman wrote:
> > > What if this is changed to:
> > > ```
> > > #define VALUE_IF(v, e, type) (v ? (5 > 
> > > VALUE_IF_2(absl::To##type##Seconds(e))) : 0)
> > > ```
> > This also doesn't transform.
> Fantastic, thank you! I wouldn't expect a fix-it there due to the macro 
> shenanigans, but I'm surprised it does not diagnose given that it expands to 
> basically the same thing as `a` and `a2` above: https://godbolt.org/z/D1MvGX 
> (ignore the errors but look at the macro expansion from the diagnostics).
> 
> Granted, this situation is uncommon enough, so feel free to add a FIXME 
> comment to the `a4` test case to say that it probably should be diagnosed 
> without a fix-it hint (assuming you agree).
I actually prefer not to diagnose here, mostly because I'm not sure what value 
we'd actually give without a fix-it hint.  "You are holding it wrong, but we 
can't tell you how to hold it right."

Ultimately, though, I think you are right that the number of cases this occurs 
are vanishingly small, and I'd expect folks doing these kinds of craziness to 
know what they are doing (and take responsibility thereof).  Perhaps that's 
optimistic.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55784/new/

https://reviews.llvm.org/D55784



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55784: [clang-tidy] Update abseil-duration-comparison to handle macro arguments

2018-12-18 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

@aaron.ballman I am both grateful and sad that I don't possess the same macro 
creativity as you do. :)

(I'm also sad that the various clang APIs aren't as well documented as I hoped. 
 The current solution works well, but it took a while and a bit of consultation 
with some other llvm'ers to get it right.)




Comment at: test/clang-tidy/abseil-duration-comparison.cpp:146
+#define VALUE_IF_2(e) (e)
+#define VALUE_IF(v, e, type) (v ? VALUE_IF_2(absl::To##type##Seconds(e)) : 0)
+  int a3 = VALUE_IF(1, d1, Double);

aaron.ballman wrote:
> What if this is changed to:
> ```
> #define VALUE_IF(v, e, type) (v ? (5 > 
> VALUE_IF_2(absl::To##type##Seconds(e))) : 0)
> ```
This also doesn't transform.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55784/new/

https://reviews.llvm.org/D55784



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55784: [clang-tidy] Update abseil-duration-comparison to handle macro arguments

2018-12-18 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 178733.
hwright marked 3 inline comments as done.
hwright added a comment.

Another test.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55784/new/

https://reviews.llvm.org/D55784

Files:
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/DurationSubtractionCheck.cpp
  test/clang-tidy/abseil-duration-comparison.cpp

Index: test/clang-tidy/abseil-duration-comparison.cpp
===
--- test/clang-tidy/abseil-duration-comparison.cpp
+++ test/clang-tidy/abseil-duration-comparison.cpp
@@ -127,6 +127,33 @@
   // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
   // CHECK-FIXES: absl::Milliseconds((y + 5) * 10) > d1;
 
+  // We should still transform the expression inside this macro invocation
+#define VALUE_IF(v, e) v ? (e) : 0
+  int a = VALUE_IF(1, 5 > absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: VALUE_IF(1, absl::Seconds(5) > d1);
+#undef VALUE_IF
+
+#define VALUE_IF_2(e) (e)
+#define VALUE_IF(v, e) v ? VALUE_IF_2(e) : VALUE_IF_2(0)
+  int a2 = VALUE_IF(1, 5 > absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: VALUE_IF(1, absl::Seconds(5) > d1);
+#undef VALUE_IF
+#undef VALUE_IF_2
+
+#define VALUE_IF_2(e) (e)
+#define VALUE_IF(v, e, type) (v ? VALUE_IF_2(absl::To##type##Seconds(e)) : 0)
+  int a3 = VALUE_IF(1, d1, Double);
+#undef VALUE_IF
+#undef VALUE_IF_2
+
+#define VALUE_IF_2(e) (e)
+#define VALUE_IF(v, e, type) (v ? (5 > VALUE_IF_2(absl::To##type##Seconds(e))) : 0)
+  int a4 = VALUE_IF(1, d1, Double);
+#undef VALUE_IF
+#undef VALUE_IF_2
+
   // These should not match
   b = 6 < 4;
 
Index: clang-tidy/abseil/DurationSubtractionCheck.cpp
===
--- clang-tidy/abseil/DurationSubtractionCheck.cpp
+++ clang-tidy/abseil/DurationSubtractionCheck.cpp
@@ -42,10 +42,8 @@
   if (!Scale)
 return;
 
-  llvm::Optional RhsReplacement =
+  std::string RhsReplacement =
   rewriteExprFromNumberToDuration(Result, *Scale, Binop->getRHS());
-  if (!RhsReplacement)
-return;
 
   const Expr *LhsArg = Result.Nodes.getNodeAs("lhs_arg");
 
@@ -54,7 +52,7 @@
  Binop->getSourceRange(),
  (llvm::Twine("absl::") + FuncDecl->getName() + "(" +
   tooling::fixit::getText(*LhsArg, *Result.Context) + " - " +
-  *RhsReplacement + ")")
+  RhsReplacement + ")")
  .str());
 }
 
Index: clang-tidy/abseil/DurationRewriter.h
===
--- clang-tidy/abseil/DurationRewriter.h
+++ clang-tidy/abseil/DurationRewriter.h
@@ -65,7 +65,7 @@
 
 /// Assuming `Node` has type `double` or `int` representing a time interval of
 /// `Scale`, return the expression to make it a suitable `Duration`.
-llvm::Optional rewriteExprFromNumberToDuration(
+std::string rewriteExprFromNumberToDuration(
 const ast_matchers::MatchFinder::MatchResult , DurationScale Scale,
 const Expr *Node);
 
Index: clang-tidy/abseil/DurationRewriter.cpp
===
--- clang-tidy/abseil/DurationRewriter.cpp
+++ clang-tidy/abseil/DurationRewriter.cpp
@@ -183,14 +183,11 @@
   return ScaleIter->second;
 }
 
-llvm::Optional rewriteExprFromNumberToDuration(
+std::string rewriteExprFromNumberToDuration(
 const ast_matchers::MatchFinder::MatchResult , DurationScale Scale,
 const Expr *Node) {
   const Expr  = *Node->IgnoreParenImpCasts();
 
-  if (RootNode.getBeginLoc().isMacroID())
-return llvm::None;
-
   // First check to see if we can undo a complimentary function call.
   if (llvm::Optional MaybeRewrite =
   rewriteInverseDurationCall(Result, Scale, RootNode))
Index: clang-tidy/abseil/DurationComparisonCheck.cpp
===
--- clang-tidy/abseil/DurationComparisonCheck.cpp
+++ clang-tidy/abseil/DurationComparisonCheck.cpp
@@ -19,6 +19,26 @@
 namespace tidy {
 namespace abseil {
 
+/// Return `true` if `E` is a either: not a macro at all; or an argument to
+/// one. In the latter case, we should still transform it.
+static bool IsValidMacro(const MatchFinder::MatchResult ,
+ const Expr *E) {
+  if (!E->getBeginLoc().isMacroID())
+return true;
+
+  SourceLocation Loc = E->getBeginLoc();
+  // We want to get closer towards the initial macro typed into the source only
+  // if the location is being expanded as a macro argument.
+  while (Result.SourceManager->isMacroArgExpansion(Loc)) {
+// We are calling getImmediateMacroCallerLoc, 

[PATCH] D55784: [clang-tidy] Update abseil-duration-comparison to handle macro arguments

2018-12-18 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: test/clang-tidy/abseil-duration-comparison.cpp:131
+  // We should still transform the expression inside this macro invocation
+#define VALUE_IF(v, e) v ? (e) : 0
+  int a = VALUE_IF(1, 5 > absl::ToDoubleSeconds(d1));

aaron.ballman wrote:
> Can you add another example that has one more level of macro arg expansion? 
> e.g.,
> ```
> #define VALUE_IF_2(e) (e)
> #define VALUE_IF(v, e) v ? VALUE_IF_2(e) : VALUE_IF_2(0)
> int a = VALUE_IF(1, 5 > absl::ToDoubleSeconds(d1));
> ```
> Which makes me wonder -- is this transformation valid in all cases? For 
> instance, how do the fixes look with this abomination?
> ```
> #define VALUE_IF_2(e) (e)
> #define VALUE_IF(v, e, type) (v ? VALUE_IF_2(absl::To##type##Seconds(e)) : 0)
> int a = VALUE_IF(1, d1, Double);
> ```
> I would expect these shenanigans to be vanishingly rare, so if this turns out 
> to be a bad FIXIT you may want to document it as a known deficiency if you 
> don't feel like handling such a case.
I've added both these as test cases.

The first one works as expected, and I'm pleasantly surprised to see that the 
second one does as well (which is to say that it doesn't transform).


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55784/new/

https://reviews.llvm.org/D55784



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55784: [clang-tidy] Update abseil-duration-comparison to handle macro arguments

2018-12-18 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 178680.
hwright marked 4 inline comments as done.
hwright added a comment.

Update tests


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55784/new/

https://reviews.llvm.org/D55784

Files:
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/DurationSubtractionCheck.cpp
  test/clang-tidy/abseil-duration-comparison.cpp

Index: test/clang-tidy/abseil-duration-comparison.cpp
===
--- test/clang-tidy/abseil-duration-comparison.cpp
+++ test/clang-tidy/abseil-duration-comparison.cpp
@@ -127,6 +127,27 @@
   // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
   // CHECK-FIXES: absl::Milliseconds((y + 5) * 10) > d1;
 
+  // We should still transform the expression inside this macro invocation
+#define VALUE_IF(v, e) v ? (e) : 0
+  int a = VALUE_IF(1, 5 > absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: VALUE_IF(1, absl::Seconds(5) > d1);
+#undef VALUE_IF
+
+#define VALUE_IF_2(e) (e)
+#define VALUE_IF(v, e) v ? VALUE_IF_2(e) : VALUE_IF_2(0)
+  int a2 = VALUE_IF(1, 5 > absl::ToDoubleSeconds(d1));
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: VALUE_IF(1, absl::Seconds(5) > d1);
+#undef VALUE_IF
+#undef VALUE_IF_2
+
+#define VALUE_IF_2(e) (e)
+#define VALUE_IF(v, e, type) (v ? VALUE_IF_2(absl::To##type##Seconds(e)) : 0)
+  int a3 = VALUE_IF(1, d1, Double);
+#undef VALUE_IF
+#undef VALUE_IF_2
+
   // These should not match
   b = 6 < 4;
 
Index: clang-tidy/abseil/DurationSubtractionCheck.cpp
===
--- clang-tidy/abseil/DurationSubtractionCheck.cpp
+++ clang-tidy/abseil/DurationSubtractionCheck.cpp
@@ -42,10 +42,8 @@
   if (!Scale)
 return;
 
-  llvm::Optional RhsReplacement =
+  std::string RhsReplacement =
   rewriteExprFromNumberToDuration(Result, *Scale, Binop->getRHS());
-  if (!RhsReplacement)
-return;
 
   const Expr *LhsArg = Result.Nodes.getNodeAs("lhs_arg");
 
@@ -54,7 +52,7 @@
  Binop->getSourceRange(),
  (llvm::Twine("absl::") + FuncDecl->getName() + "(" +
   tooling::fixit::getText(*LhsArg, *Result.Context) + " - " +
-  *RhsReplacement + ")")
+  RhsReplacement + ")")
  .str());
 }
 
Index: clang-tidy/abseil/DurationRewriter.h
===
--- clang-tidy/abseil/DurationRewriter.h
+++ clang-tidy/abseil/DurationRewriter.h
@@ -65,7 +65,7 @@
 
 /// Assuming `Node` has type `double` or `int` representing a time interval of
 /// `Scale`, return the expression to make it a suitable `Duration`.
-llvm::Optional rewriteExprFromNumberToDuration(
+std::string rewriteExprFromNumberToDuration(
 const ast_matchers::MatchFinder::MatchResult , DurationScale Scale,
 const Expr *Node);
 
Index: clang-tidy/abseil/DurationRewriter.cpp
===
--- clang-tidy/abseil/DurationRewriter.cpp
+++ clang-tidy/abseil/DurationRewriter.cpp
@@ -183,14 +183,11 @@
   return ScaleIter->second;
 }
 
-llvm::Optional rewriteExprFromNumberToDuration(
+std::string rewriteExprFromNumberToDuration(
 const ast_matchers::MatchFinder::MatchResult , DurationScale Scale,
 const Expr *Node) {
   const Expr  = *Node->IgnoreParenImpCasts();
 
-  if (RootNode.getBeginLoc().isMacroID())
-return llvm::None;
-
   // First check to see if we can undo a complimentary function call.
   if (llvm::Optional MaybeRewrite =
   rewriteInverseDurationCall(Result, Scale, RootNode))
Index: clang-tidy/abseil/DurationComparisonCheck.cpp
===
--- clang-tidy/abseil/DurationComparisonCheck.cpp
+++ clang-tidy/abseil/DurationComparisonCheck.cpp
@@ -19,6 +19,26 @@
 namespace tidy {
 namespace abseil {
 
+/// Return `true` if `E` is a either: not a macro at all; or an argument to
+/// one. In the latter case, we should still transform it.
+static bool IsValidMacro(const MatchFinder::MatchResult ,
+ const Expr *E) {
+  if (!E->getBeginLoc().isMacroID())
+return true;
+
+  SourceLocation Loc = E->getBeginLoc();
+  // We want to get closer towards the initial macro typed into the source only
+  // if the location is being expanded as a macro argument.
+  while (Result.SourceManager->isMacroArgExpansion(Loc)) {
+// We are calling getImmediateMacroCallerLoc, but note it is essentially
+// equivalent to calling getImmediateSpellingLoc in this context according
+// to Clang implementation. We are not calling getImmediateSpellingLoc
+

[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-13 Thread Hyrum Wright via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL349073: [clang-tidy] Add the abseil-duration-subtraction 
check (authored by hwright, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D55245?vs=178039=178101#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245

Files:
  clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt
  clang-tools-extra/trunk/clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.h
  clang-tools-extra/trunk/clang-tidy/abseil/DurationSubtractionCheck.cpp
  clang-tools-extra/trunk/clang-tidy/abseil/DurationSubtractionCheck.h
  clang-tools-extra/trunk/docs/ReleaseNotes.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-duration-subtraction.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
  clang-tools-extra/trunk/test/clang-tidy/abseil-duration-subtraction.cpp

Index: clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-duration-subtraction.rst
===
--- clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-duration-subtraction.rst
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-duration-subtraction.rst
@@ -0,0 +1,36 @@
+.. title:: clang-tidy - abseil-duration-subtraction
+
+abseil-duration-subtraction
+===
+
+Checks for cases where subtraction should be performed in the
+``absl::Duration`` domain. When subtracting two values, and the first one is
+known to be a conversion from ``absl::Duration``, we can infer that the second
+should also be interpreted as an ``absl::Duration``, and make that inference
+explicit.
+
+Examples:
+
+.. code-block:: c++
+
+  // Original - Subtraction in the double domain
+  double x;
+  absl::Duration d;
+  double result = absl::ToDoubleSeconds(d) - x;
+
+  // Suggestion - Subtraction in the absl::Duration domain instead
+  double result = absl::ToDoubleSeconds(d - absl::Seconds(x));
+
+
+  // Original - Subtraction of two Durations in the double domain
+  absl::Duration d1, d2;
+  double result = absl::ToDoubleSeconds(d1) - absl::ToDoubleSeconds(d2);
+
+  // Suggestion - Subtraction in the absl::Duration domain instead
+  double result = absl::ToDoubleSeconds(d1 - d2);
+
+Note: As with other ``clang-tidy`` checks, it is possible that multiple fixes
+may overlap (as in the case of nested expressions), so not all occurences can
+be transformed in one run. In particular, this may occur for nested subtraction
+expressions. Running ``clang-tidy`` multiple times will find and fix these
+overlaps.
Index: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
@@ -8,6 +8,7 @@
abseil-duration-division
abseil-duration-factory-float
abseil-duration-factory-scale
+   abseil-duration-subtraction
abseil-faster-strsplit-delimiter
abseil-no-internal-dependencies
abseil-no-namespace
Index: clang-tools-extra/trunk/docs/ReleaseNotes.rst
===
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst
@@ -93,6 +93,12 @@
   Checks for cases where arguments to ``absl::Duration`` factory functions are
   scaled internally and could be changed to a different factory function.
 
+- New :doc:`abseil-duration-subtraction
+  ` check.
+
+  Checks for cases where subtraction should be performed in the
+  ``absl::Duration`` domain.
+
 - New :doc:`abseil-faster-strsplit-delimiter
   ` check.
 
Index: clang-tools-extra/trunk/test/clang-tidy/abseil-duration-subtraction.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/abseil-duration-subtraction.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/abseil-duration-subtraction.cpp
@@ -0,0 +1,64 @@
+// RUN: %check_clang_tidy %s abseil-duration-subtraction %t -- -- -I %S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  double x;
+  absl::Duration d, d1, d2;
+
+  x = absl::ToDoubleSeconds(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(1))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - d1);
+  x = absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 

[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-13 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

Thanks for reviewing, I'll go ahead and commit.

I've also removed the hash specialization, since we moved to `llvm::IndexedMap` 
instead of `std::unordered_map` inside of `getInverseForScale`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-13 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked an inline comment as done.
hwright added a comment.

I've updated the documentation, and the rebased to `master`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-13 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 178039.
hwright marked an inline comment as done.
hwright added a comment.

Rebase and update documentation


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/DurationSubtractionCheck.cpp
  clang-tidy/abseil/DurationSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-subtraction.cpp

Index: test/clang-tidy/abseil-duration-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-subtraction.cpp
@@ -0,0 +1,64 @@
+// RUN: %check_clang_tidy %s abseil-duration-subtraction %t -- -- -I %S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  double x;
+  absl::Duration d, d1, d2;
+
+  x = absl::ToDoubleSeconds(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(1))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - d1);
+  x = absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(6.5)) - 8.0;
+  x = absl::ToDoubleHours(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleHours(d - absl::Hours(1))
+  x = absl::ToDoubleMinutes(d) - 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMinutes(d - absl::Minutes(1))
+  x = absl::ToDoubleMilliseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMilliseconds(d - absl::Milliseconds(9))
+  x = absl::ToDoubleMicroseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d - absl::Microseconds(9))
+  x = absl::ToDoubleNanoseconds(d) - 42;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleNanoseconds(d - absl::Nanoseconds(42))
+
+  // We can rewrite the argument of the duration conversion
+#define THIRTY absl::Seconds(30)
+  x = absl::ToDoubleSeconds(THIRTY) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(THIRTY - absl::Seconds(1))
+#undef THIRTY
+
+  // Some other contexts
+  if (absl::ToDoubleSeconds(d) - 1.0 > 10) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: if (absl::ToDoubleSeconds(d - absl::Seconds(1)) > 10) {}
+
+  // A nested occurance
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(absl::Seconds(5));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(5))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(absl::Seconds(absl::ToDoubleSeconds(d1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(absl::ToDoubleSeconds(d1)))
+
+  // These should not match
+  x = 5 - 6;
+  x = 4 - absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  x = absl::ToDoubleSeconds(d) + 1.0;
+  x = absl::ToDoubleSeconds(d) * 1.0;
+  x = absl::ToDoubleSeconds(d) / 1.0;
+
+#define MINUS_FIVE(z) absl::ToDoubleSeconds(z) - 5
+  x = MINUS_FIVE(d);
+#undef MINUS_FIVE
+}
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -8,6 +8,7 @@
abseil-duration-division
abseil-duration-factory-float
abseil-duration-factory-scale
+   abseil-duration-subtraction
abseil-faster-strsplit-delimiter
abseil-no-internal-dependencies
abseil-no-namespace
Index: docs/clang-tidy/checks/abseil-duration-subtraction.rst
===
--- /dev/null
+++ 

[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-12 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked 2 inline comments as done.
hwright added inline comments.



Comment at: test/clang-tidy/abseil-duration-subtraction.cpp:12
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(1))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the 
duration domain [abseil-duration-subtraction]

JonasToth wrote:
> hwright wrote:
> > JonasToth wrote:
> > > hwright wrote:
> > > > JonasToth wrote:
> > > > > From this example starting:
> > > > > 
> > > > > - The RHS should be a nested expression with function calls, as the 
> > > > > RHS is transformed to create the adversary example i mean in the 
> > > > > transformation function above.
> > > > > 
> > > > > ```
> > > > > absl::ToDoubleSeconds(d) - 
> > > > > absl::ToDoubleSeconds(absl::ToDoubleSeconds(d) - 
> > > > > absl::ToDoubleSeconds(d1));
> > > > > ```
> > > > > I think you need the proper conversion function, as the result of the 
> > > > > expression is `double` and you need a `Duration`, right?
> > > > > 
> > > > > But in principle starting from this idea the transformation might 
> > > > > break.
> > > > I think there may be some confusion here (and that's entirely my fault. 
> > > > :) )
> > > > 
> > > > We should never get this expression as input to the check, since it 
> > > > doesn't compile (as you point out):
> > > > ```
> > > > absl::ToDoubleSeconds(d) - 
> > > > absl::ToDoubleSeconds(absl::ToDoubleSeconds(d) - 
> > > > absl::ToDoubleSeconds(d1));
> > > > ```
> > > > 
> > > > Since `absl::ToDoubleSeconds` requires that its argument is an 
> > > > `absl::Duration`, but the expression `absl::ToDoubleSeconds(d) - 
> > > > absl::ToDoubleSeconds(d1)` results in a `double`, we can't get this as 
> > > > input.
> > > > 
> > > > There may be other expressions which could be input, but in practice 
> > > > they don't really happen.  I've added a contrived example to the tests, 
> > > > but at some point the tests get too complex and confuse the fix 
> > > > matching infrastructure.
> > > Your last sentence is the thing ;) Murphies Law will hit this check, too. 
> > > In my opinion wrong transformations are very unfortunate and should be 
> > > avoided if possible (in this case possible).
> > > You can simply require that the expression of type double does not 
> > > contain any duration subtraction calls.
> > > 
> > > This is even possible in the matcher-part of the check.
> > I've written a test (which the testing infrastructure fails to handle well, 
> > so I haven't included it in the diff), and it produces these results:
> > 
> > ```
> >//
> >//
> > -  x = absl::ToDoubleSeconds(d) - (absl::ToDoubleSeconds(d1) - 5);
> > +  x = absl::ToDoubleSeconds(d - absl::Seconds(absl::ToDoubleSeconds(d1) - 
> > 5));
> >//
> >//
> > -  x = absl::ToDoubleSeconds(d - absl::Seconds(absl::ToDoubleSeconds(d1) - 
> > 5));
> > +  x = absl::ToDoubleSeconds(d - absl::Seconds(absl::ToDoubleSeconds(d1 - 
> > absl::Seconds(5;
> > ```
> > 
> > Those results are correct.  There is a cosmetic issue of round tripping 
> > through the `double` conversion in the 
> > `absl::Seconds(absl::ToDoubleSeconds(...))` phrase, but untangling that is 
> > 1) difficult (because of order of operations issues) and thus; 2) probably 
> > the subject of a separate check.
> > 
> > This is still such a rare case (as in, we've not encountered it in Google's 
> > codebase), that I'm not really concerned.  But if it's worth it to 
> > explicitly exclude it from the traversal matcher, I can do that.
> Can you say what the direct issue is? I would bet its the overlapping?
> A note in the documentation would be ok from my side. When the conflicting 
> transformations are tried to be applied clang-tidy does not crash but print a 
> nice diagnostic and continue its life?
Another example I've verified:
```
-  x = absl::ToDoubleSeconds(d) - 
absl::ToDoubleSeconds(absl::Seconds(absl::ToDoubleSeconds(d1) - 5));
+  x = absl::ToDoubleSeconds(d - absl::Seconds(absl::ToDoubleSeconds(d1) - 5));
```

This a nested case, and while `clang-tidy` finds both of them, it only applies 
the outer most one (presumably the one it finds first in its AST traversal):
```
note: this fix will not be applied because it overlaps with another fix
```

The new code can then be checked again to fix the internal instance.

It's not possible to express this case in a test because testing infrastructure 
uses regular expressions, and the repeated strings in the test expectation 
cause it to get a bit confused.

Given all the of the above, I'm unsure what content would go in the 
documentation which is specific to this check.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-11 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 177749.
hwright marked 6 inline comments as done.
hwright added a comment.

Rebase


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/DurationSubtractionCheck.cpp
  clang-tidy/abseil/DurationSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-subtraction.cpp

Index: test/clang-tidy/abseil-duration-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-subtraction.cpp
@@ -0,0 +1,64 @@
+// RUN: %check_clang_tidy %s abseil-duration-subtraction %t -- -- -I %S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  double x;
+  absl::Duration d, d1, d2;
+
+  x = absl::ToDoubleSeconds(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(1))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - d1);
+  x = absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(6.5)) - 8.0;
+  x = absl::ToDoubleHours(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleHours(d - absl::Hours(1))
+  x = absl::ToDoubleMinutes(d) - 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMinutes(d - absl::Minutes(1))
+  x = absl::ToDoubleMilliseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMilliseconds(d - absl::Milliseconds(9))
+  x = absl::ToDoubleMicroseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d - absl::Microseconds(9))
+  x = absl::ToDoubleNanoseconds(d) - 42;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleNanoseconds(d - absl::Nanoseconds(42))
+
+  // We can rewrite the argument of the duration conversion
+#define THIRTY absl::Seconds(30)
+  x = absl::ToDoubleSeconds(THIRTY) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(THIRTY - absl::Seconds(1))
+#undef THIRTY
+
+  // Some other contexts
+  if (absl::ToDoubleSeconds(d) - 1.0 > 10) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: if (absl::ToDoubleSeconds(d - absl::Seconds(1)) > 10) {}
+
+  // A nested occurance
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(absl::Seconds(5));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(5))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(absl::Seconds(absl::ToDoubleSeconds(d1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(absl::ToDoubleSeconds(d1)))
+
+  // These should not match
+  x = 5 - 6;
+  x = 4 - absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  x = absl::ToDoubleSeconds(d) + 1.0;
+  x = absl::ToDoubleSeconds(d) * 1.0;
+  x = absl::ToDoubleSeconds(d) / 1.0;
+
+#define MINUS_FIVE(z) absl::ToDoubleSeconds(z) - 5
+  x = MINUS_FIVE(d);
+#undef MINUS_FIVE
+}
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -8,6 +8,7 @@
abseil-duration-division
abseil-duration-factory-float
abseil-duration-factory-scale
+   abseil-duration-subtraction
abseil-faster-strsplit-delimiter
abseil-no-internal-dependencies
abseil-no-namespace
Index: docs/clang-tidy/checks/abseil-duration-subtraction.rst
===
--- /dev/null
+++ 

[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-11 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: test/clang-tidy/abseil-duration-subtraction.cpp:12
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(1))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the 
duration domain [abseil-duration-subtraction]

JonasToth wrote:
> hwright wrote:
> > JonasToth wrote:
> > > From this example starting:
> > > 
> > > - The RHS should be a nested expression with function calls, as the RHS 
> > > is transformed to create the adversary example i mean in the 
> > > transformation function above.
> > > 
> > > ```
> > > absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(absl::ToDoubleSeconds(d) 
> > > - absl::ToDoubleSeconds(d1));
> > > ```
> > > I think you need the proper conversion function, as the result of the 
> > > expression is `double` and you need a `Duration`, right?
> > > 
> > > But in principle starting from this idea the transformation might break.
> > I think there may be some confusion here (and that's entirely my fault. :) )
> > 
> > We should never get this expression as input to the check, since it doesn't 
> > compile (as you point out):
> > ```
> > absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(absl::ToDoubleSeconds(d) - 
> > absl::ToDoubleSeconds(d1));
> > ```
> > 
> > Since `absl::ToDoubleSeconds` requires that its argument is an 
> > `absl::Duration`, but the expression `absl::ToDoubleSeconds(d) - 
> > absl::ToDoubleSeconds(d1)` results in a `double`, we can't get this as 
> > input.
> > 
> > There may be other expressions which could be input, but in practice they 
> > don't really happen.  I've added a contrived example to the tests, but at 
> > some point the tests get too complex and confuse the fix matching 
> > infrastructure.
> Your last sentence is the thing ;) Murphies Law will hit this check, too. In 
> my opinion wrong transformations are very unfortunate and should be avoided 
> if possible (in this case possible).
> You can simply require that the expression of type double does not contain 
> any duration subtraction calls.
> 
> This is even possible in the matcher-part of the check.
I've written a test (which the testing infrastructure fails to handle well, so 
I haven't included it in the diff), and it produces these results:

```
   //
   //
-  x = absl::ToDoubleSeconds(d) - (absl::ToDoubleSeconds(d1) - 5);
+  x = absl::ToDoubleSeconds(d - absl::Seconds(absl::ToDoubleSeconds(d1) - 5));
   //
   //
-  x = absl::ToDoubleSeconds(d - absl::Seconds(absl::ToDoubleSeconds(d1) - 5));
+  x = absl::ToDoubleSeconds(d - absl::Seconds(absl::ToDoubleSeconds(d1 - 
absl::Seconds(5;
```

Those results are correct.  There is a cosmetic issue of round tripping through 
the `double` conversion in the `absl::Seconds(absl::ToDoubleSeconds(...))` 
phrase, but untangling that is 1) difficult (because of order of operations 
issues) and thus; 2) probably the subject of a separate check.

This is still such a rare case (as in, we've not encountered it in Google's 
codebase), that I'm not really concerned.  But if it's worth it to explicitly 
exclude it from the traversal matcher, I can do that.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-10 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 177590.
hwright marked 9 inline comments as done.
hwright added a comment.

Add tests


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/DurationSubtractionCheck.cpp
  clang-tidy/abseil/DurationSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-comparison.cpp
  test/clang-tidy/abseil-duration-factory-float.cpp
  test/clang-tidy/abseil-duration-factory-scale.cpp
  test/clang-tidy/abseil-duration-subtraction.cpp

Index: test/clang-tidy/abseil-duration-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-subtraction.cpp
@@ -0,0 +1,64 @@
+// RUN: %check_clang_tidy %s abseil-duration-subtraction %t -- -- -I %S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  double x;
+  absl::Duration d, d1, d2;
+
+  x = absl::ToDoubleSeconds(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(1))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - d1);
+  x = absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(6.5)) - 8.0;
+  x = absl::ToDoubleHours(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleHours(d - absl::Hours(1))
+  x = absl::ToDoubleMinutes(d) - 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMinutes(d - absl::Minutes(1))
+  x = absl::ToDoubleMilliseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMilliseconds(d - absl::Milliseconds(9))
+  x = absl::ToDoubleMicroseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d - absl::Microseconds(9))
+  x = absl::ToDoubleNanoseconds(d) - 42;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleNanoseconds(d - absl::Nanoseconds(42))
+
+  // We can rewrite the argument of the duration conversion
+#define THIRTY absl::Seconds(30)
+  x = absl::ToDoubleSeconds(THIRTY) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(THIRTY - absl::Seconds(1))
+#undef THIRTY
+
+  // Some other contexts
+  if (absl::ToDoubleSeconds(d) - 1.0 > 10) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: if (absl::ToDoubleSeconds(d - absl::Seconds(1)) > 10) {}
+
+  // A nested occurance
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(absl::Seconds(5));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(5))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(absl::Seconds(absl::ToDoubleSeconds(d1)));
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(absl::ToDoubleSeconds(d1)))
+
+  // These should not match
+  x = 5 - 6;
+  x = 4 - absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  x = absl::ToDoubleSeconds(d) + 1.0;
+  x = absl::ToDoubleSeconds(d) * 1.0;
+  x = absl::ToDoubleSeconds(d) / 1.0;
+
+#define MINUS_FIVE(z) absl::ToDoubleSeconds(z) - 5
+  x = MINUS_FIVE(d);
+#undef MINUS_FIVE
+}
Index: test/clang-tidy/abseil-duration-factory-scale.cpp
===
--- test/clang-tidy/abseil-duration-factory-scale.cpp
+++ test/clang-tidy/abseil-duration-factory-scale.cpp
@@ -1,32 +1,6 @@
-// RUN: %check_clang_tidy %s abseil-duration-factory-scale %t
+// RUN: %check_clang_tidy %s abseil-duration-factory-scale %t -- -- -I %S/Inputs
 

[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-10 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationRewriter.cpp:21
+struct DurationScale2IndexFunctor {
+  using argument_type = DurationScale;
+  unsigned operator()(DurationScale Scale) const {

JonasToth wrote:
> Are you using `argument_type`? Browser searching did only show one result.
This is required by `IndexedMap`, if I understand correctly.



Comment at: clang-tidy/abseil/DurationRewriter.cpp:23
+  unsigned operator()(DurationScale Scale) const {
+return static_cast(Scale);
+  }

JonasToth wrote:
> Why not `std::uint8_t` as its the underlying type for the `enum`?
This is required by `IndexedMap`, if I understand correctly.



Comment at: clang-tidy/abseil/DurationRewriter.cpp:77
+  getInverseForScale(Scale);
+  if (const auto *MaybeCallArg = selectFirst(
+  "e",

JonasToth wrote:
> In Principle the `Node` could have multiple expressions that are a call if 
> there is nesting. 
> The transformation is correct from what I see right now, but might result in 
> the necessity of multiple passes for the check. (Is the addition version 
> affected from that too?)
> 
> Given the recursive nature of the matcher you could construct a nesting with 
> the inner part being a subtraction, too. The generated fixes would conflict 
> and none of them would be applied. At least thats what I would expect right 
> now. Please take a look at this issue.
There isn't an imminent addition version at this point.

This matcher isn't recursive: it's just looking at the entire node to see if it 
is a call to the inverse function.  If an inverse is embedded as part of a 
deeper expression, it won't see it (e.g., there no `hasDescendant` in this 
matcher).



Comment at: test/clang-tidy/Inputs/absl/time/time.h:1
+// Mimic the implementation of absl::Duration
+namespace absl {

JonasToth wrote:
> I think having the extraction of the common test-stuff into this header as 
> one commit would be better. Would you prepare such a patch? I can commit for 
> you. It probably makes sense if you ask for commit access 
> (https://llvm.org/docs/DeveloperPolicy.html#obtaining-commit-access). Do as 
> you wish.
I can do this, but it might take a bit to get the commit bit turned on.



Comment at: test/clang-tidy/abseil-duration-subtraction.cpp:12
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(1))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the 
duration domain [abseil-duration-subtraction]

JonasToth wrote:
> From this example starting:
> 
> - The RHS should be a nested expression with function calls, as the RHS is 
> transformed to create the adversary example i mean in the transformation 
> function above.
> 
> ```
> absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(absl::ToDoubleSeconds(d) - 
> absl::ToDoubleSeconds(d1));
> ```
> I think you need the proper conversion function, as the result of the 
> expression is `double` and you need a `Duration`, right?
> 
> But in principle starting from this idea the transformation might break.
I think there may be some confusion here (and that's entirely my fault. :) )

We should never get this expression as input to the check, since it doesn't 
compile (as you point out):
```
absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(absl::ToDoubleSeconds(d) - 
absl::ToDoubleSeconds(d1));
```

Since `absl::ToDoubleSeconds` requires that its argument is an 
`absl::Duration`, but the expression `absl::ToDoubleSeconds(d) - 
absl::ToDoubleSeconds(d1)` results in a `double`, we can't get this as input.

There may be other expressions which could be input, but in practice they don't 
really happen.  I've added a contrived example to the tests, but at some point 
the tests get too complex and confuse the fix matching infrastructure.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-10 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationRewriter.cpp:20-39
+struct DurationScale2IndexFunctor {
+  using argument_type = DurationScale;
+  unsigned operator()(DurationScale Scale) const {
+switch (Scale) {
+case DurationScale::Hours:
+  return 0;
+case DurationScale::Minutes:

lebedev.ri wrote:
> You should not need this if you change the `enum` instead.
The function is still required; the switch can be removed with a `static_cast`.



Comment at: clang-tidy/abseil/DurationRewriter.cpp:66-77
+InverseMap[DurationScale::Hours] =
+std::make_pair("::absl::ToDoubleHours", "::absl::ToInt64Hours");
+InverseMap[DurationScale::Minutes] =
+std::make_pair("::absl::ToDoubleMinutes", 
"::absl::ToInt64Minutes");
+InverseMap[DurationScale::Seconds] =
+std::make_pair("::absl::ToDoubleSeconds", 
"::absl::ToInt64Seconds");
+InverseMap[DurationScale::Milliseconds] = std::make_pair(

lebedev.ri wrote:
> I was thinking of more like
> ```
> for(std::pair e : std::initializer_list({
>{DurationScale::Hours, 
> std::make_pair("::absl::ToDoubleHours", "::absl::ToInt64Hours")}.
>}))
>   InverseMap[e.first] = e.second;
> ```
The compilable construction looks something like:
```
for (const auto  : {std::make_pair(DurationScale::Hours,
std::make_pair("::absl::ToDoubleHours",
   "::absl::ToInt64Hours"))})
```
Which is a bit more verbose than just assigning values to the map (and not any 
more efficient), so I've just left this bit as-is.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-10 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 177509.
hwright marked 5 inline comments as done.
hwright added a comment.

Use `static_cast` instead of a `switch` for `IndexedMap` lookup.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/DurationSubtractionCheck.cpp
  clang-tidy/abseil/DurationSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-comparison.cpp
  test/clang-tidy/abseil-duration-factory-float.cpp
  test/clang-tidy/abseil-duration-factory-scale.cpp
  test/clang-tidy/abseil-duration-subtraction.cpp

Index: test/clang-tidy/abseil-duration-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-subtraction.cpp
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s abseil-duration-subtraction %t -- -- -I %S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  double x;
+  absl::Duration d, d1;
+
+  x = absl::ToDoubleSeconds(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(1))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - d1);
+  x = absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(6.5)) - 8.0;
+  x = absl::ToDoubleHours(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleHours(d - absl::Hours(1))
+  x = absl::ToDoubleMinutes(d) - 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMinutes(d - absl::Minutes(1))
+  x = absl::ToDoubleMilliseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMilliseconds(d - absl::Milliseconds(9))
+  x = absl::ToDoubleMicroseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d - absl::Microseconds(9))
+  x = absl::ToDoubleNanoseconds(d) - 42;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleNanoseconds(d - absl::Nanoseconds(42))
+
+  // We can rewrite the argument of the duration conversion
+#define THIRTY absl::Seconds(30)
+  x = absl::ToDoubleSeconds(THIRTY) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(THIRTY - absl::Seconds(1))
+#undef THIRTY
+
+  // Some other contexts
+  if (absl::ToDoubleSeconds(d) - 1.0 > 10) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: if (absl::ToDoubleSeconds(d - absl::Seconds(1)) > 10) {}
+
+  // These should not match
+  x = 5 - 6;
+  x = 4 - absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  x = absl::ToDoubleSeconds(d) + 1.0;
+  x = absl::ToDoubleSeconds(d) * 1.0;
+  x = absl::ToDoubleSeconds(d) / 1.0;
+
+#define MINUS_FIVE(z) absl::ToDoubleSeconds(z) - 5
+  x = MINUS_FIVE(d);
+#undef MINUS_FIVE
+}
Index: test/clang-tidy/abseil-duration-factory-scale.cpp
===
--- test/clang-tidy/abseil-duration-factory-scale.cpp
+++ test/clang-tidy/abseil-duration-factory-scale.cpp
@@ -1,32 +1,6 @@
-// RUN: %check_clang_tidy %s abseil-duration-factory-scale %t
+// RUN: %check_clang_tidy %s abseil-duration-factory-scale %t -- -- -I %S/Inputs
 
-// Mimic the implementation of absl::Duration
-namespace absl {
-
-class Duration {};
-
-Duration Nanoseconds(long long);
-Duration Microseconds(long long);
-Duration Milliseconds(long long);
-Duration Seconds(long long);
-Duration Minutes(long long);
-Duration Hours(long long);
-
-#define GENERATE_DURATION_FACTORY_OVERLOADS(NAME) \
-  Duration NAME(float n); \
-  Duration NAME(double n);\
-  template\
-  Duration NAME(T n);
-

[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-10 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

Reminder: I'll need somebody to submit this for me, since I don't have 
subversion access.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-07 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 177325.
hwright marked 7 inline comments as done.
hwright added a comment.

Use an `IndexedMap` instead of an `std::unordered_map`


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/DurationSubtractionCheck.cpp
  clang-tidy/abseil/DurationSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-comparison.cpp
  test/clang-tidy/abseil-duration-factory-float.cpp
  test/clang-tidy/abseil-duration-factory-scale.cpp
  test/clang-tidy/abseil-duration-subtraction.cpp

Index: test/clang-tidy/abseil-duration-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-subtraction.cpp
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s abseil-duration-subtraction %t -- -- -I %S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  double x;
+  absl::Duration d, d1;
+
+  x = absl::ToDoubleSeconds(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(1))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - d1);
+  x = absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(6.5)) - 8.0;
+  x = absl::ToDoubleHours(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleHours(d - absl::Hours(1))
+  x = absl::ToDoubleMinutes(d) - 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMinutes(d - absl::Minutes(1))
+  x = absl::ToDoubleMilliseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMilliseconds(d - absl::Milliseconds(9))
+  x = absl::ToDoubleMicroseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d - absl::Microseconds(9))
+  x = absl::ToDoubleNanoseconds(d) - 42;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleNanoseconds(d - absl::Nanoseconds(42))
+
+  // We can rewrite the argument of the duration conversion
+#define THIRTY absl::Seconds(30)
+  x = absl::ToDoubleSeconds(THIRTY) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(THIRTY - absl::Seconds(1))
+#undef THIRTY
+
+  // Some other contexts
+  if (absl::ToDoubleSeconds(d) - 1.0 > 10) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: if (absl::ToDoubleSeconds(d - absl::Seconds(1)) > 10) {}
+
+  // These should not match
+  x = 5 - 6;
+  x = 4 - absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  x = absl::ToDoubleSeconds(d) + 1.0;
+  x = absl::ToDoubleSeconds(d) * 1.0;
+  x = absl::ToDoubleSeconds(d) / 1.0;
+
+#define MINUS_FIVE(z) absl::ToDoubleSeconds(z) - 5
+  x = MINUS_FIVE(d);
+#undef MINUS_FIVE
+}
Index: test/clang-tidy/abseil-duration-factory-scale.cpp
===
--- test/clang-tidy/abseil-duration-factory-scale.cpp
+++ test/clang-tidy/abseil-duration-factory-scale.cpp
@@ -1,32 +1,6 @@
-// RUN: %check_clang_tidy %s abseil-duration-factory-scale %t
+// RUN: %check_clang_tidy %s abseil-duration-factory-scale %t -- -- -I %S/Inputs
 
-// Mimic the implementation of absl::Duration
-namespace absl {
-
-class Duration {};
-
-Duration Nanoseconds(long long);
-Duration Microseconds(long long);
-Duration Milliseconds(long long);
-Duration Seconds(long long);
-Duration Minutes(long long);
-Duration Hours(long long);
-
-#define GENERATE_DURATION_FACTORY_OVERLOADS(NAME) \
-  Duration NAME(float n); \
-  Duration NAME(double n);\
-  template\
-  Duration NAME(T n);
-

[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-07 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationRewriter.cpp:35
+getInverseForScale(DurationScale Scale) {
+  static const std::unordered_map>

lebedev.ri wrote:
> hwright wrote:
> > lebedev.ri wrote:
> > > https://llvm.org/docs/ProgrammersManual.html#other-map-like-container-options
> > > > We never use hash_set and unordered_set because they are generally very 
> > > > expensive (each insertion requires a malloc) and very non-portable.
> > > 
> > > Since the key is an enum, [[ 
> > > https://llvm.org/docs/ProgrammersManual.html#llvm-adt-indexedmap-h | 
> > > `llvm/ADT/IndexedMap.h` ]] should be a much better fit.
> > It doesn't look like `IndexedMap` has a constructor which takes an 
> > initializer list.  Without it, this code get a bit more difficult to read, 
> > and I'd prefer to optimize for readability here.
> The manual still 'recommends' not to use them.
> Simple solution: immediately invoked lambda
> Better solution: try to add such constructor to `IndexedMap`.
In hopes of not making this too much of a yak shave, I've gone with the 
immediately invoked lambda.



Comment at: clang-tidy/abseil/DurationRewriter.cpp:74
+ Node, *Result.Context))) {
+return tooling::fixit::getText(*MaybeCallArg, *Result.Context).str();
+  }

lebedev.ri wrote:
> hwright wrote:
> > lebedev.ri wrote:
> > > So you generate fix-it, and then immediately degrade it into a string. 
> > > Weird.
> > This doesn't generate a fix-it, it just fetches the text of the given node 
> > as a `StringRef` but we're returning a `string`, so we need to convert.
> > 
> > Is there a more canonical method I should use to fetch a node's text?
> I don't know the answer, but have you tried looking what 
> `tooling::fixit::getText()` does internally?
I have.  It calls `internal::getText`, which, from the namespace, I'm hesitant 
to call in this context.



Comment at: clang-tidy/abseil/DurationRewriter.cpp:156
+llvm::Optional getScaleForInverse(llvm::StringRef Name) {
+  static const llvm::DenseMap ScaleMap(
+  {{"ToDoubleHours", DurationScale::Hours},

lebedev.ri wrote:
> Are you very sure this shouldn't be [[ 
> https://llvm.org/docs/ProgrammersManual.html#llvm-adt-stringmap-h | 
> `StringMap` ]]?
Nope.  Thanks for the catch!


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-07 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationRewriter.cpp:35
+getInverseForScale(DurationScale Scale) {
+  static const std::unordered_map>

lebedev.ri wrote:
> https://llvm.org/docs/ProgrammersManual.html#other-map-like-container-options
> > We never use hash_set and unordered_set because they are generally very 
> > expensive (each insertion requires a malloc) and very non-portable.
> 
> Since the key is an enum, [[ 
> https://llvm.org/docs/ProgrammersManual.html#llvm-adt-indexedmap-h | 
> `llvm/ADT/IndexedMap.h` ]] should be a much better fit.
It doesn't look like `IndexedMap` has a constructor which takes an initializer 
list.  Without it, this code get a bit more difficult to read, and I'd prefer 
to optimize for readability here.



Comment at: clang-tidy/abseil/DurationRewriter.cpp:68
+  getInverseForScale(Scale);
+  if (const Expr *MaybeCallArg = selectFirst(
+  "e", match(callExpr(callee(functionDecl(

lebedev.ri wrote:
> lebedev.ri wrote:
> > `if (const auto *MaybeCallArg`
> Early return?
I'm not quite sure what you mean by `Early return?`  Are you suggesting that 
the call to `selectFirst` should be pulled out of the `if` conditional, and 
then the inverse checked to return `llvm::None` first? 



Comment at: clang-tidy/abseil/DurationRewriter.cpp:74
+ Node, *Result.Context))) {
+return tooling::fixit::getText(*MaybeCallArg, *Result.Context).str();
+  }

lebedev.ri wrote:
> So you generate fix-it, and then immediately degrade it into a string. Weird.
This doesn't generate a fix-it, it just fetches the text of the given node as a 
`StringRef` but we're returning a `string`, so we need to convert.

Is there a more canonical method I should use to fetch a node's text?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-07 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 177266.
hwright marked 8 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/DurationSubtractionCheck.cpp
  clang-tidy/abseil/DurationSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/Inputs/absl/time/time.h
  test/clang-tidy/abseil-duration-comparison.cpp
  test/clang-tidy/abseil-duration-factory-float.cpp
  test/clang-tidy/abseil-duration-factory-scale.cpp
  test/clang-tidy/abseil-duration-subtraction.cpp

Index: test/clang-tidy/abseil-duration-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-subtraction.cpp
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s abseil-duration-subtraction %t -- -- -I %S/Inputs
+
+#include "absl/time/time.h"
+
+void f() {
+  double x;
+  absl::Duration d, d1;
+
+  x = absl::ToDoubleSeconds(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(1))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - d1);
+  x = absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(6.5)) - 8.0;
+  x = absl::ToDoubleHours(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleHours(d - absl::Hours(1))
+  x = absl::ToDoubleMinutes(d) - 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMinutes(d - absl::Minutes(1))
+  x = absl::ToDoubleMilliseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMilliseconds(d - absl::Milliseconds(9))
+  x = absl::ToDoubleMicroseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d - absl::Microseconds(9))
+  x = absl::ToDoubleNanoseconds(d) - 42;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleNanoseconds(d - absl::Nanoseconds(42))
+
+  // We can rewrite the argument of the duration conversion
+#define THIRTY absl::Seconds(30)
+  x = absl::ToDoubleSeconds(THIRTY) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(THIRTY - absl::Seconds(1))
+#undef THIRTY
+
+  // Some other contexts
+  if (absl::ToDoubleSeconds(d) - 1.0 > 10) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: if (absl::ToDoubleSeconds(d - absl::Seconds(1)) > 10) {}
+
+  // These should not match
+  x = 5 - 6;
+  x = 4 - absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  x = absl::ToDoubleSeconds(d) + 1.0;
+  x = absl::ToDoubleSeconds(d) * 1.0;
+  x = absl::ToDoubleSeconds(d) / 1.0;
+
+#define MINUS_FIVE(z) absl::ToDoubleSeconds(z) - 5
+  x = MINUS_FIVE(d);
+#undef MINUS_FIVE
+}
Index: test/clang-tidy/abseil-duration-factory-scale.cpp
===
--- test/clang-tidy/abseil-duration-factory-scale.cpp
+++ test/clang-tidy/abseil-duration-factory-scale.cpp
@@ -1,32 +1,6 @@
-// RUN: %check_clang_tidy %s abseil-duration-factory-scale %t
+// RUN: %check_clang_tidy %s abseil-duration-factory-scale %t -- -- -I %S/Inputs
 
-// Mimic the implementation of absl::Duration
-namespace absl {
-
-class Duration {};
-
-Duration Nanoseconds(long long);
-Duration Microseconds(long long);
-Duration Milliseconds(long long);
-Duration Seconds(long long);
-Duration Minutes(long long);
-Duration Hours(long long);
-
-#define GENERATE_DURATION_FACTORY_OVERLOADS(NAME) \
-  Duration NAME(float n); \
-  Duration NAME(double n);\
-  template\
-  Duration NAME(T n);
-
-GENERATE_DURATION_FACTORY_OVERLOADS(Nanoseconds);
-GENERATE_DURATION_FACTORY_OVERLOADS(Microseconds);

[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-05 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

Ping.

I assume I've got the right reviewers here, but I've also been sending a bunch 
of stuff your way lately, so if I'm overwhelming review capacity, please let me 
know.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55245: [clang-tidy] Add the abseil-duration-subtraction check

2018-12-04 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 176757.
hwright marked an inline comment as done.
hwright added a comment.

Fix double space.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55245/new/

https://reviews.llvm.org/D55245

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  clang-tidy/abseil/DurationSubtractionCheck.cpp
  clang-tidy/abseil/DurationSubtractionCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-subtraction.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-subtraction.cpp

Index: test/clang-tidy/abseil-duration-subtraction.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-subtraction.cpp
@@ -0,0 +1,112 @@
+// RUN: %check_clang_tidy %s abseil-duration-subtraction %t
+
+// Mimic the implementation of absl::Duration
+namespace absl {
+
+class Duration {};
+class Time{};
+
+Duration Nanoseconds(long long);
+Duration Microseconds(long long);
+Duration Milliseconds(long long);
+Duration Seconds(long long);
+Duration Minutes(long long);
+Duration Hours(long long);
+
+#define GENERATE_DURATION_FACTORY_OVERLOADS(NAME) \
+  Duration NAME(float n); \
+  Duration NAME(double n);\
+  template\
+  Duration NAME(T n);
+
+GENERATE_DURATION_FACTORY_OVERLOADS(Nanoseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Microseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Milliseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Seconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Minutes);
+GENERATE_DURATION_FACTORY_OVERLOADS(Hours);
+#undef GENERATE_DURATION_FACTORY_OVERLOADS
+
+using int64_t = long long int;
+
+double ToDoubleHours(Duration d);
+double ToDoubleMinutes(Duration d);
+double ToDoubleSeconds(Duration d);
+double ToDoubleMilliseconds(Duration d);
+double ToDoubleMicroseconds(Duration d);
+double ToDoubleNanoseconds(Duration d);
+int64_t ToInt64Hours(Duration d);
+int64_t ToInt64Minutes(Duration d);
+int64_t ToInt64Seconds(Duration d);
+int64_t ToInt64Milliseconds(Duration d);
+int64_t ToInt64Microseconds(Duration d);
+int64_t ToInt64Nanoseconds(Duration d);
+
+// Relational Operators
+constexpr bool operator<(Duration lhs, Duration rhs);
+constexpr bool operator>(Duration lhs, Duration rhs);
+constexpr bool operator>=(Duration lhs, Duration rhs);
+constexpr bool operator<=(Duration lhs, Duration rhs);
+constexpr bool operator==(Duration lhs, Duration rhs);
+constexpr bool operator!=(Duration lhs, Duration rhs);
+
+// Additive Operators
+inline Time operator+(Time lhs, Duration rhs);
+inline Time operator+(Duration lhs, Time rhs);
+inline Time operator-(Time lhs, Duration rhs);
+inline Duration operator-(Time lhs, Time rhs);
+
+}  // namespace absl
+
+void f() {
+  double x;
+  absl::Duration d, d1;
+
+  x = absl::ToDoubleSeconds(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(1))
+  x = absl::ToDoubleSeconds(d) - absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - d1);
+  x = absl::ToDoubleSeconds(d) - 6.5 - 8.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleSeconds(d - absl::Seconds(6.5)) - 8.0;
+  x = absl::ToDoubleHours(d) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleHours(d - absl::Hours(1))
+  x = absl::ToDoubleMinutes(d) - 1;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMinutes(d - absl::Minutes(1))
+  x = absl::ToDoubleMilliseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMilliseconds(d - absl::Milliseconds(9))
+  x = absl::ToDoubleMicroseconds(d) - 9;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleMicroseconds(d - absl::Microseconds(9))
+  x = absl::ToDoubleNanoseconds(d) - 42;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the duration domain [abseil-duration-subtraction]
+  // CHECK-FIXES: absl::ToDoubleNanoseconds(d - absl::Nanoseconds(42))
+
+  // We can rewrite the argument of the duration conversion
+#define THIRTY absl::Seconds(30)
+  x = absl::ToDoubleSeconds(THIRTY) - 1.0;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: 

[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-30 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

Oh, and thanks for taking the time to review this. :)


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-30 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

@JonasToth reminder that you (or somebody else) will need to commit this for me.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-30 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 176156.
hwright marked 2 inline comments as done.
hwright added a comment.

Add additional test


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationComparisonCheck.h
  clang-tidy/abseil/DurationFactoryFloatCheck.cpp
  clang-tidy/abseil/DurationFactoryScaleCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-comparison.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-comparison.cpp

Index: test/clang-tidy/abseil-duration-comparison.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-comparison.cpp
@@ -0,0 +1,195 @@
+// RUN: %check_clang_tidy %s abseil-duration-comparison %t
+
+// Mimic the implementation of absl::Duration
+namespace absl {
+
+class Duration {};
+class Time{};
+
+Duration Nanoseconds(long long);
+Duration Microseconds(long long);
+Duration Milliseconds(long long);
+Duration Seconds(long long);
+Duration Minutes(long long);
+Duration Hours(long long);
+
+#define GENERATE_DURATION_FACTORY_OVERLOADS(NAME) \
+  Duration NAME(float n); \
+  Duration NAME(double n);\
+  template\
+  Duration NAME(T n);
+
+GENERATE_DURATION_FACTORY_OVERLOADS(Nanoseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Microseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Milliseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Seconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Minutes);
+GENERATE_DURATION_FACTORY_OVERLOADS(Hours);
+#undef GENERATE_DURATION_FACTORY_OVERLOADS
+
+using int64_t = long long int;
+
+double ToDoubleHours(Duration d);
+double ToDoubleMinutes(Duration d);
+double ToDoubleSeconds(Duration d);
+double ToDoubleMilliseconds(Duration d);
+double ToDoubleMicroseconds(Duration d);
+double ToDoubleNanoseconds(Duration d);
+int64_t ToInt64Hours(Duration d);
+int64_t ToInt64Minutes(Duration d);
+int64_t ToInt64Seconds(Duration d);
+int64_t ToInt64Milliseconds(Duration d);
+int64_t ToInt64Microseconds(Duration d);
+int64_t ToInt64Nanoseconds(Duration d);
+
+// Relational Operators
+constexpr bool operator<(Duration lhs, Duration rhs);
+constexpr bool operator>(Duration lhs, Duration rhs);
+constexpr bool operator>=(Duration lhs, Duration rhs);
+constexpr bool operator<=(Duration lhs, Duration rhs);
+constexpr bool operator==(Duration lhs, Duration rhs);
+constexpr bool operator!=(Duration lhs, Duration rhs);
+
+// Additive Operators
+inline Time operator+(Time lhs, Duration rhs);
+inline Time operator+(Duration lhs, Time rhs);
+inline Time operator-(Time lhs, Duration rhs);
+inline Duration operator-(Time lhs, Time rhs);
+
+}  // namespace absl
+
+void f() {
+  double x;
+  absl::Duration d1, d2;
+  bool b;
+  absl::Time t1, t2;
+
+  // Check against the RHS
+  b = x > absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) > d1;
+  b = x >= absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) >= d1;
+  b = x == absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) == d1;
+  b = x <= absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) <= d1;
+  b = x < absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) < d1;
+  b = x == absl::ToDoubleSeconds(t1 - t2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) == t1 - t2;
+  b = absl::ToDoubleSeconds(d1) > absl::ToDoubleSeconds(d2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 > d2;
+
+  // Check against the LHS
+  b = absl::ToDoubleSeconds(d1) < x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 < absl::Seconds(x);
+  b = absl::ToDoubleSeconds(d1) <= x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 <= absl::Seconds(x);
+  b = absl::ToDoubleSeconds(d1) == x;
+  // 

[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-30 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 176103.
hwright added a comment.

Slightly simplify the fixit text


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationComparisonCheck.h
  clang-tidy/abseil/DurationFactoryFloatCheck.cpp
  clang-tidy/abseil/DurationFactoryScaleCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-comparison.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-comparison.cpp

Index: test/clang-tidy/abseil-duration-comparison.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-comparison.cpp
@@ -0,0 +1,189 @@
+// RUN: %check_clang_tidy %s abseil-duration-comparison %t
+
+// Mimic the implementation of absl::Duration
+namespace absl {
+
+class Duration {};
+class Time{};
+
+Duration Nanoseconds(long long);
+Duration Microseconds(long long);
+Duration Milliseconds(long long);
+Duration Seconds(long long);
+Duration Minutes(long long);
+Duration Hours(long long);
+
+#define GENERATE_DURATION_FACTORY_OVERLOADS(NAME) \
+  Duration NAME(float n); \
+  Duration NAME(double n);\
+  template\
+  Duration NAME(T n);
+
+GENERATE_DURATION_FACTORY_OVERLOADS(Nanoseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Microseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Milliseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Seconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Minutes);
+GENERATE_DURATION_FACTORY_OVERLOADS(Hours);
+#undef GENERATE_DURATION_FACTORY_OVERLOADS
+
+using int64_t = long long int;
+
+double ToDoubleHours(Duration d);
+double ToDoubleMinutes(Duration d);
+double ToDoubleSeconds(Duration d);
+double ToDoubleMilliseconds(Duration d);
+double ToDoubleMicroseconds(Duration d);
+double ToDoubleNanoseconds(Duration d);
+int64_t ToInt64Hours(Duration d);
+int64_t ToInt64Minutes(Duration d);
+int64_t ToInt64Seconds(Duration d);
+int64_t ToInt64Milliseconds(Duration d);
+int64_t ToInt64Microseconds(Duration d);
+int64_t ToInt64Nanoseconds(Duration d);
+
+// Relational Operators
+constexpr bool operator<(Duration lhs, Duration rhs);
+constexpr bool operator>(Duration lhs, Duration rhs);
+constexpr bool operator>=(Duration lhs, Duration rhs);
+constexpr bool operator<=(Duration lhs, Duration rhs);
+constexpr bool operator==(Duration lhs, Duration rhs);
+constexpr bool operator!=(Duration lhs, Duration rhs);
+
+// Additive Operators
+inline Time operator+(Time lhs, Duration rhs);
+inline Time operator+(Duration lhs, Time rhs);
+inline Time operator-(Time lhs, Duration rhs);
+inline Duration operator-(Time lhs, Time rhs);
+
+}  // namespace absl
+
+void f() {
+  double x;
+  absl::Duration d1, d2;
+  bool b;
+  absl::Time t1, t2;
+
+  // Check against the RHS
+  b = x > absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) > d1;
+  b = x >= absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) >= d1;
+  b = x == absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) == d1;
+  b = x <= absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) <= d1;
+  b = x < absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) < d1;
+  b = x == absl::ToDoubleSeconds(t1 - t2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) == t1 - t2;
+  b = absl::ToDoubleSeconds(d1) > absl::ToDoubleSeconds(d2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 > d2;
+
+  // Check against the LHS
+  b = absl::ToDoubleSeconds(d1) < x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 < absl::Seconds(x);
+  b = absl::ToDoubleSeconds(d1) <= x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 <= absl::Seconds(x);
+  b = absl::ToDoubleSeconds(d1) == x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 

[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-29 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked an inline comment as done.
hwright added a comment.

Ping.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-29 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked 4 inline comments as done.
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationFactoryFloatCheck.cpp:61
+
+  if (SimpleArg) {
 diag(MatchedCall->getBeginLoc(),

JonasToth wrote:
> hwright wrote:
> > JonasToth wrote:
> > > hwright wrote:
> > > > JonasToth wrote:
> > > > > The diagnostic is not printed if for some reason the fixit was not 
> > > > > creatable. I think that the warning could still be emitted (`auto 
> > > > > Diag = diag(...); if (Fix) Diag << Fixit::-...`)
> > > > I'm not sure under which conditions you'd expect this to be an issue.  
> > > > Could you give me an example?
> > > > 
> > > > My expectation is that if we don't get a value back in `SimpleArg`, we 
> > > > don't have anything to change, so there wouldn't be a warning to emit.
> > > I don't expect this to fail, failure there would mean a bug i guess. 
> > > Having bugs is somewhat expected :)
> > > And that would be our way to find the bug, because some user reports that 
> > > there is no transformation done, that is my motivation behind that.
> > > 
> > > The warning itself should be correct, otherwise the matcher does not 
> > > work, right? This would just be precaution.
> > I guess what I'm saying is that I'm not sure what kind of warning we'd give 
> > if we weren't able to offer a fix.  The optionality here means that we 
> > found a result which was already as simple as we can make it, so there's no 
> > reason to bother the user.
> Lets say the result comes out of arithmetic and then there is a comparison 
> (would be good test btw :)), the warning is still valueable, even if the 
> transformation fails for some reason. The transformation could fail as well, 
> because macros interfere or so. Past experience tells me, there are enough 
> language constructs to break everything in weird combinations :)
I can buy that, but I'm still having trouble seeing the specifics.  Do you have 
a concrete example?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-28 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked 4 inline comments as done.
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationDivisionCheck.h:23
 // http://clang.llvm.org/extra/clang-tidy/checks/abseil-duration-division.html
 
 class DurationDivisionCheck : public ClangTidyCheck {

JonasToth wrote:
> hwright wrote:
> > JonasToth wrote:
> > > I think that blank line could be removed, and it seems the comment is not 
> > > ///, could you take a look at it too?
> > > Touching this file is probably better to do in another patch anyway.
> > Agreed.  I think this snuck into the patch; I'll remove it.
> > 
> > (It would be good to just `clang-format` everything in this directory in a 
> > separate patch.)
> > 
> > The comment issue with `///` seems to be a common problem; is 
> > `clang-tidy/add_new_check.py` not generating correct code?
> add_new_check does ///, maybe IDE settings or so removed these? Maybe someone 
> created everything manually, dunno.
> 
> Doing the clang-format is ok, doesn't need review either (but plz run the 
> test before committing to master).
I don't think I yet have the commit bit...so somebody else wouldn't need to 
directly commit. :)



Comment at: clang-tidy/abseil/DurationFactoryFloatCheck.cpp:61
+
+  if (SimpleArg) {
 diag(MatchedCall->getBeginLoc(),

JonasToth wrote:
> hwright wrote:
> > JonasToth wrote:
> > > The diagnostic is not printed if for some reason the fixit was not 
> > > creatable. I think that the warning could still be emitted (`auto Diag = 
> > > diag(...); if (Fix) Diag << Fixit::-...`)
> > I'm not sure under which conditions you'd expect this to be an issue.  
> > Could you give me an example?
> > 
> > My expectation is that if we don't get a value back in `SimpleArg`, we 
> > don't have anything to change, so there wouldn't be a warning to emit.
> I don't expect this to fail, failure there would mean a bug i guess. Having 
> bugs is somewhat expected :)
> And that would be our way to find the bug, because some user reports that 
> there is no transformation done, that is my motivation behind that.
> 
> The warning itself should be correct, otherwise the matcher does not work, 
> right? This would just be precaution.
I guess what I'm saying is that I'm not sure what kind of warning we'd give if 
we weren't able to offer a fix.  The optionality here means that we found a 
result which was already as simple as we can make it, so there's no reason to 
bother the user.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-28 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationComparisonCheck.cpp:69
+  // We know our map contains all the Scale values, so we can skip the
+  // nonexistence check.
+  auto InverseIter = InverseMap.find(Scale);

JonasToth wrote:
> non-existence? Not sure about english, but i thought english does it that way
https://www.merriam-webster.com/dictionary/nonexistence tells me the hyphen 
isn't required.



Comment at: clang-tidy/abseil/DurationDivisionCheck.h:23
 // http://clang.llvm.org/extra/clang-tidy/checks/abseil-duration-division.html
 
 class DurationDivisionCheck : public ClangTidyCheck {

JonasToth wrote:
> I think that blank line could be removed, and it seems the comment is not 
> ///, could you take a look at it too?
> Touching this file is probably better to do in another patch anyway.
Agreed.  I think this snuck into the patch; I'll remove it.

(It would be good to just `clang-format` everything in this directory in a 
separate patch.)

The comment issue with `///` seems to be a common problem; is 
`clang-tidy/add_new_check.py` not generating correct code?



Comment at: clang-tidy/abseil/DurationFactoryFloatCheck.cpp:61
+
+  if (SimpleArg) {
 diag(MatchedCall->getBeginLoc(),

JonasToth wrote:
> The diagnostic is not printed if for some reason the fixit was not creatable. 
> I think that the warning could still be emitted (`auto Diag = diag(...); if 
> (Fix) Diag << Fixit::-...`)
I'm not sure under which conditions you'd expect this to be an issue.  Could 
you give me an example?

My expectation is that if we don't get a value back in `SimpleArg`, we don't 
have anything to change, so there wouldn't be a warning to emit.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-28 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 175735.
hwright marked 13 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationComparisonCheck.h
  clang-tidy/abseil/DurationFactoryFloatCheck.cpp
  clang-tidy/abseil/DurationFactoryScaleCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-comparison.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-comparison.cpp

Index: test/clang-tidy/abseil-duration-comparison.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-comparison.cpp
@@ -0,0 +1,189 @@
+// RUN: %check_clang_tidy %s abseil-duration-comparison %t
+
+// Mimic the implementation of absl::Duration
+namespace absl {
+
+class Duration {};
+class Time{};
+
+Duration Nanoseconds(long long);
+Duration Microseconds(long long);
+Duration Milliseconds(long long);
+Duration Seconds(long long);
+Duration Minutes(long long);
+Duration Hours(long long);
+
+#define GENERATE_DURATION_FACTORY_OVERLOADS(NAME) \
+  Duration NAME(float n); \
+  Duration NAME(double n);\
+  template\
+  Duration NAME(T n);
+
+GENERATE_DURATION_FACTORY_OVERLOADS(Nanoseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Microseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Milliseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Seconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Minutes);
+GENERATE_DURATION_FACTORY_OVERLOADS(Hours);
+#undef GENERATE_DURATION_FACTORY_OVERLOADS
+
+using int64_t = long long int;
+
+double ToDoubleHours(Duration d);
+double ToDoubleMinutes(Duration d);
+double ToDoubleSeconds(Duration d);
+double ToDoubleMilliseconds(Duration d);
+double ToDoubleMicroseconds(Duration d);
+double ToDoubleNanoseconds(Duration d);
+int64_t ToInt64Hours(Duration d);
+int64_t ToInt64Minutes(Duration d);
+int64_t ToInt64Seconds(Duration d);
+int64_t ToInt64Milliseconds(Duration d);
+int64_t ToInt64Microseconds(Duration d);
+int64_t ToInt64Nanoseconds(Duration d);
+
+// Relational Operators
+constexpr bool operator<(Duration lhs, Duration rhs);
+constexpr bool operator>(Duration lhs, Duration rhs);
+constexpr bool operator>=(Duration lhs, Duration rhs);
+constexpr bool operator<=(Duration lhs, Duration rhs);
+constexpr bool operator==(Duration lhs, Duration rhs);
+constexpr bool operator!=(Duration lhs, Duration rhs);
+
+// Additive Operators
+inline Time operator+(Time lhs, Duration rhs);
+inline Time operator+(Duration lhs, Time rhs);
+inline Time operator-(Time lhs, Duration rhs);
+inline Duration operator-(Time lhs, Time rhs);
+
+}  // namespace absl
+
+void f() {
+  double x;
+  absl::Duration d1, d2;
+  bool b;
+  absl::Time t1, t2;
+
+  // Check against the RHS
+  b = x > absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) > d1;
+  b = x >= absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) >= d1;
+  b = x == absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) == d1;
+  b = x <= absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) <= d1;
+  b = x < absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) < d1;
+  b = x == absl::ToDoubleSeconds(t1 - t2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) == t1 - t2;
+  b = absl::ToDoubleSeconds(d1) > absl::ToDoubleSeconds(d2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 > d2;
+
+  // Check against the LHS
+  b = absl::ToDoubleSeconds(d1) < x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 < absl::Seconds(x);
+  b = absl::ToDoubleSeconds(d1) <= x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 <= absl::Seconds(x);
+  b = 

[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-28 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked 2 inline comments as done.
hwright added a comment.

Anything else for me here?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-27 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked 12 inline comments as done.
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationComparisonCheck.cpp:25
+static llvm::Optional getScaleForInverse(llvm::StringRef Name) {
+  static const std::unordered_map ScaleMap(
+  {{"ToDoubleHours", DurationScale::Hours},

aaron.ballman wrote:
> sammccall wrote:
> > aaron.ballman wrote:
> > > sammccall wrote:
> > > > aaron.ballman wrote:
> > > > > sammccall wrote:
> > > > > > hwright wrote:
> > > > > > > JonasToth wrote:
> > > > > > > > hwright wrote:
> > > > > > > > > JonasToth wrote:
> > > > > > > > > > I think this could be made a `DenseMap` with just the right 
> > > > > > > > > > amount of dense entries. 12 elements seems not too much to 
> > > > > > > > > > me.
> > > > > > > > > > Does the key-type need to be `std::string`, or could it be 
> > > > > > > > > > `StringRef`(or `StringLiteral` making everything 
> > > > > > > > > > `constexpr` if possible)?
> > > > > > > > > > Is there some strange stuff with dangling pointers or other 
> > > > > > > > > > issues going on?
> > > > > > > > > Conceptually, this could easily be `constexpr`, but my 
> > > > > > > > > compiler doesn't seem to want to build something which is 
> > > > > > > > > called `static constexpr llvm::DenseMap > > > > > > > > DurationScale>`.  It's chief complaint is that such a type 
> > > > > > > > > has a non-trivial destructor. Am I using this correctly?
> > > > > > > > I honestly never tried to make a `constexpr DenseMap<>` but it 
> > > > > > > > makes sense it is not possible, as `DenseMap` is involved with 
> > > > > > > > dynamic memory after all, which is not possible with 
> > > > > > > > `constexpr` (yet). So you were my test-bunny ;)
> > > > > > > > 
> > > > > > > > I did reread the Data-structures section in the LLVM manual, i 
> > > > > > > > totally forgot about `StringMap` that maps strings to values.
> > > > > > > > `DenseMap` is good when mapping small values to each other, as 
> > > > > > > > we do here (`const char* -> int (whatever the enum deduces 
> > > > > > > > too)`), which would fit.
> > > > > > > > `StringMap` does allocations for the strings, which we don't 
> > > > > > > > need.
> > > > > > > > 
> > > > > > > > `constexpr` aside my bet is that `DenseMap` fits this case the 
> > > > > > > > better, because we can lay every thing out and never touch it 
> > > > > > > > again. Maybe someone else has better arguments for the decision 
> > > > > > > > :)
> > > > > > > > 
> > > > > > > > Soo: could you please try `static const 
> > > > > > > > llvm::DenseMap`? :)
> > > > > > > > (should work in theory: https://godbolt.org/z/Qo7Nv4)
> > > > > > > `static const llvm::DenseMap` 
> > > > > > > works here. :)
> > > > > > Sorry for the drive-by...
> > > > > > This has a non-trivial destructor, so violates 
> > > > > > https://llvm.org/docs/CodingStandards.html#do-not-use-static-constructors
> > > > > >  at least in spirit.
> > > > > > 
> > > > > > Best to leak it (`auto  = *new const 
> > > > > > llvm::DenseMap<...>(...)`) to avoid the destructor issues. The 
> > > > > > constructor issues are already handled by making it function-local.
> > > > > I do not think this violates the coding standard -- that's talking 
> > > > > mostly about global objects, not local objects, and is concerned 
> > > > > about startup performance and initialization orders. I don't see any 
> > > > > destructor ordering issues with this, so I do not think any of that 
> > > > > applies here and leaking would be less than ideal.
> > > > There are three main issues with global objects that the coding 
> > > > standard mentions:
> > > >  - performance when unused. Not relevant to function-local statics, 
> > > > only constructed when used
> > > >  - static initialization order fiasco (constructors). Not relevant to 
> > > > function-local statics, constructed in well-defined order
> > > >  - static initialization order fiasco (destructors). Just as relevant 
> > > > to function-local statics as to any other object!
> > > > 
> > > > That's why I say it violates the rule in spirit: the destructor is 
> > > > global. https://isocpp.org/wiki/faq/ctors#construct-on-first-use-v2
> > > > 
> > > > > I don't see any destructor ordering issues with this
> > > > The reason these constructs are disallowed in coding guidelines is that 
> > > > humans can't see the problems, and they manifest in non-local ways :-(
> > > > 
> > > > > leaking would be less than ideal
> > > > Why? The current code will (usually) destroy the object when the 
> > > > program exits. This is a waste of CPU, the OS will free the memory.
> > > > The reason these constructs are disallowed in coding guidelines is that 
> > > > humans can't see the problems, and they manifest in non-local ways :-(
> > > 
> > > Can you explain why you think this would have any non-local impact on 
> > > destruction? The DenseMap is local to the function and a pointer to it 
> > > never escapes 

[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-27 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationComparisonCheck.cpp:25
+static llvm::Optional getScaleForInverse(llvm::StringRef Name) {
+  static const std::unordered_map ScaleMap(
+  {{"ToDoubleHours", DurationScale::Hours},

JonasToth wrote:
> hwright wrote:
> > JonasToth wrote:
> > > I think this could be made a `DenseMap` with just the right amount of 
> > > dense entries. 12 elements seems not too much to me.
> > > Does the key-type need to be `std::string`, or could it be `StringRef`(or 
> > > `StringLiteral` making everything `constexpr` if possible)?
> > > Is there some strange stuff with dangling pointers or other issues going 
> > > on?
> > Conceptually, this could easily be `constexpr`, but my compiler doesn't 
> > seem to want to build something which is called `static constexpr 
> > llvm::DenseMap`.  It's chief complaint is 
> > that such a type has a non-trivial destructor. Am I using this correctly?
> I honestly never tried to make a `constexpr DenseMap<>` but it makes sense it 
> is not possible, as `DenseMap` is involved with dynamic memory after all, 
> which is not possible with `constexpr` (yet). So you were my test-bunny ;)
> 
> I did reread the Data-structures section in the LLVM manual, i totally forgot 
> about `StringMap` that maps strings to values.
> `DenseMap` is good when mapping small values to each other, as we do here 
> (`const char* -> int (whatever the enum deduces too)`), which would fit.
> `StringMap` does allocations for the strings, which we don't need.
> 
> `constexpr` aside my bet is that `DenseMap` fits this case the better, 
> because we can lay every thing out and never touch it again. Maybe someone 
> else has better arguments for the decision :)
> 
> Soo: could you please try `static const llvm::DenseMap DurationScale>`? :)
> (should work in theory: https://godbolt.org/z/Qo7Nv4)
`static const llvm::DenseMap` works here. :)



Comment at: clang-tidy/abseil/DurationComparisonCheck.cpp:50
+  static const std::unordered_map>
+  InverseMap(

hwright wrote:
> JonasToth wrote:
> > This variable is a little hard to read. Could you make a little 
> > wrapper-struct instead of the `tuple` to make clear which element 
> > represents what?
> > Otherwise, why not `std::pair`?
> > 
> > - same `DenseMap` argument
> > - same `StringRef`/`StringLiteral` instead `string` consideration
> `std::pair` works here.
> 
> I'll defer the `DenseMap` and `StringRef`/`StringLiteral` changes until we 
> determine if they are actually possible.
...but using `DenseMap` here doesn't work.  From the mountains of compiler 
output I get when I try, it appears that `DenseMap` adds some constraints on 
the key type, and an `enum class` doesn't meet those constraints.

fwiw, the errors are mostly of this form:
```
/llvm/llvm/include/llvm/ADT/DenseMap.h:1277:45: error: ‘getEmptyKey’ is not a 
member of ‘llvm::DenseMapInfo’
 const KeyT Empty = KeyInfoT::getEmptyKey();
~^~
/llvm/llvm/include/llvm/ADT/DenseMap.h:1278:53: error: ‘getTombstoneKey’ is not 
a member of ‘llvm::DenseMapInfo’
 const KeyT Tombstone = KeyInfoT::getTombstoneKey();
~^~
/llvm/llvm/include/llvm/ADT/DenseMap.h:1280:44: error: ‘isEqual’ is not a 
member of ‘llvm::DenseMapInfo’
 while (Ptr != End && (KeyInfoT::isEqual(Ptr[-1].getFirst(), Empty) ||
   ~^~~
/llvm/llvm/include/llvm/ADT/DenseMap.h:1281:44: error: ‘isEqual’ is not a 
member of ‘llvm::DenseMapInfo’
   KeyInfoT::isEqual(Ptr[-1].getFirst(), Tombstone)))
```



Comment at: clang-tidy/abseil/DurationComparisonCheck.cpp:125
+  hasAnyName(
+  "::absl::ToDoubleHours", "::absl::ToDoubleMinutes",
+  "::absl::ToDoubleSeconds", 
"::absl::ToDoubleMilliseconds",

JonasToth wrote:
> hwright wrote:
> > JonasToth wrote:
> > > the list here is somewhat duplicated with the static members in the 
> > > functions at the top. it would be best to merge them.
> > > Not sure on how much `constexpr` is supported by the llvm-datastructures, 
> > > but a constexpr `DenseMap.keys()` would be nice. Did you try something 
> > > along this line?
> > I haven't tried that exact formulation, but given the above issue with 
> > `DenseMap`, I'm not sure it will work.  Happy to try once we get it ironed 
> > out.
> > 
> > Another thing I've thought about is factoring the `functionDecl` matcher 
> > into a separate function, because I expect it to be reused.  I haven't been 
> > able to deduce what type that function would return.
> the type is probably `clang::ast_matchers::internal::Matcher`. 
> Not sure what the `bind` does with the type though.
> 
> If that is not the case you can make a nice error with `int Bad = 
> 

[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-27 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 175476.
hwright marked 10 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationComparisonCheck.h
  clang-tidy/abseil/DurationDivisionCheck.h
  clang-tidy/abseil/DurationFactoryFloatCheck.cpp
  clang-tidy/abseil/DurationFactoryScaleCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-comparison.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-comparison.cpp

Index: test/clang-tidy/abseil-duration-comparison.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-comparison.cpp
@@ -0,0 +1,189 @@
+// RUN: %check_clang_tidy %s abseil-duration-comparison %t
+
+// Mimic the implementation of absl::Duration
+namespace absl {
+
+class Duration {};
+class Time{};
+
+Duration Nanoseconds(long long);
+Duration Microseconds(long long);
+Duration Milliseconds(long long);
+Duration Seconds(long long);
+Duration Minutes(long long);
+Duration Hours(long long);
+
+#define GENERATE_DURATION_FACTORY_OVERLOADS(NAME) \
+  Duration NAME(float n); \
+  Duration NAME(double n);\
+  template\
+  Duration NAME(T n);
+
+GENERATE_DURATION_FACTORY_OVERLOADS(Nanoseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Microseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Milliseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Seconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Minutes);
+GENERATE_DURATION_FACTORY_OVERLOADS(Hours);
+#undef GENERATE_DURATION_FACTORY_OVERLOADS
+
+using int64_t = long long int;
+
+double ToDoubleHours(Duration d);
+double ToDoubleMinutes(Duration d);
+double ToDoubleSeconds(Duration d);
+double ToDoubleMilliseconds(Duration d);
+double ToDoubleMicroseconds(Duration d);
+double ToDoubleNanoseconds(Duration d);
+int64_t ToInt64Hours(Duration d);
+int64_t ToInt64Minutes(Duration d);
+int64_t ToInt64Seconds(Duration d);
+int64_t ToInt64Milliseconds(Duration d);
+int64_t ToInt64Microseconds(Duration d);
+int64_t ToInt64Nanoseconds(Duration d);
+
+// Relational Operators
+constexpr bool operator<(Duration lhs, Duration rhs);
+constexpr bool operator>(Duration lhs, Duration rhs);
+constexpr bool operator>=(Duration lhs, Duration rhs);
+constexpr bool operator<=(Duration lhs, Duration rhs);
+constexpr bool operator==(Duration lhs, Duration rhs);
+constexpr bool operator!=(Duration lhs, Duration rhs);
+
+// Additive Operators
+inline Time operator+(Time lhs, Duration rhs);
+inline Time operator+(Duration lhs, Time rhs);
+inline Time operator-(Time lhs, Duration rhs);
+inline Duration operator-(Time lhs, Time rhs);
+
+}  // namespace absl
+
+void f() {
+  double x;
+  absl::Duration d1, d2;
+  bool b;
+  absl::Time t1, t2;
+
+  // Check against the RHS
+  b = x > absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) > d1;
+  b = x >= absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) >= d1;
+  b = x == absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) == d1;
+  b = x <= absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) <= d1;
+  b = x < absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) < d1;
+  b = x == absl::ToDoubleSeconds(t1 - t2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) == t1 - t2;
+  b = absl::ToDoubleSeconds(d1) > absl::ToDoubleSeconds(d2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 > d2;
+
+  // Check against the LHS
+  b = absl::ToDoubleSeconds(d1) < x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 < absl::Seconds(x);
+  b = absl::ToDoubleSeconds(d1) <= x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 

[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-26 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

Sorry it's taken so long to get all the feedback addressed!




Comment at: clang-tidy/abseil/DurationComparisonCheck.cpp:25
+static llvm::Optional getScaleForInverse(llvm::StringRef Name) {
+  static const std::unordered_map ScaleMap(
+  {{"ToDoubleHours", DurationScale::Hours},

JonasToth wrote:
> I think this could be made a `DenseMap` with just the right amount of dense 
> entries. 12 elements seems not too much to me.
> Does the key-type need to be `std::string`, or could it be `StringRef`(or 
> `StringLiteral` making everything `constexpr` if possible)?
> Is there some strange stuff with dangling pointers or other issues going on?
Conceptually, this could easily be `constexpr`, but my compiler doesn't seem to 
want to build something which is called `static constexpr 
llvm::DenseMap`.  It's chief complaint is that 
such a type has a non-trivial destructor. Am I using this correctly?



Comment at: clang-tidy/abseil/DurationComparisonCheck.cpp:50
+  static const std::unordered_map>
+  InverseMap(

JonasToth wrote:
> This variable is a little hard to read. Could you make a little 
> wrapper-struct instead of the `tuple` to make clear which element represents 
> what?
> Otherwise, why not `std::pair`?
> 
> - same `DenseMap` argument
> - same `StringRef`/`StringLiteral` instead `string` consideration
`std::pair` works here.

I'll defer the `DenseMap` and `StringRef`/`StringLiteral` changes until we 
determine if they are actually possible.



Comment at: clang-tidy/abseil/DurationComparisonCheck.cpp:68
+
+  // We know our map contains all the Scale values, so we can skip the
+  // nonexistence check.

JonasToth wrote:
> The basis for this "we know" might change in the future if `abs::Duration` 
> does things differently. Is adding stuff allowed in the `absl::` space? (i am 
> not fluent with the guarantees that it gives). You could maybe `assert` that 
> the find is always correct, depending on `absl` guarantees.
`absl::` could add things.  In this case, I'm very confident they won't, but 
I've still added the assert.



Comment at: clang-tidy/abseil/DurationComparisonCheck.cpp:108
+
+  // TODO(hwright): Check for another condition:
+  //  1. duration-factory-scale

JonasToth wrote:
> in LLVM the TODO does not contain a name for the author.
I just removed the TODO (this isn't a required part of the check).



Comment at: clang-tidy/abseil/DurationComparisonCheck.cpp:125
+  hasAnyName(
+  "::absl::ToDoubleHours", "::absl::ToDoubleMinutes",
+  "::absl::ToDoubleSeconds", 
"::absl::ToDoubleMilliseconds",

JonasToth wrote:
> the list here is somewhat duplicated with the static members in the functions 
> at the top. it would be best to merge them.
> Not sure on how much `constexpr` is supported by the llvm-datastructures, but 
> a constexpr `DenseMap.keys()` would be nice. Did you try something along this 
> line?
I haven't tried that exact formulation, but given the above issue with 
`DenseMap`, I'm not sure it will work.  Happy to try once we get it ironed out.

Another thing I've thought about is factoring the `functionDecl` matcher into a 
separate function, because I expect it to be reused.  I haven't been able to 
deduce what type that function would return.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54737: [clang-tidy] Add the abseil-duration-comparison check

2018-11-26 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 175379.
hwright marked 23 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54737/new/

https://reviews.llvm.org/D54737

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationComparisonCheck.cpp
  clang-tidy/abseil/DurationComparisonCheck.h
  clang-tidy/abseil/DurationDivisionCheck.h
  clang-tidy/abseil/DurationFactoryFloatCheck.cpp
  clang-tidy/abseil/DurationFactoryScaleCheck.cpp
  clang-tidy/abseil/DurationRewriter.cpp
  clang-tidy/abseil/DurationRewriter.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-comparison.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-comparison.cpp

Index: test/clang-tidy/abseil-duration-comparison.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-comparison.cpp
@@ -0,0 +1,189 @@
+// RUN: %check_clang_tidy %s abseil-duration-comparison %t
+
+// Mimic the implementation of absl::Duration
+namespace absl {
+
+class Duration {};
+class Time{};
+
+Duration Nanoseconds(long long);
+Duration Microseconds(long long);
+Duration Milliseconds(long long);
+Duration Seconds(long long);
+Duration Minutes(long long);
+Duration Hours(long long);
+
+#define GENERATE_DURATION_FACTORY_OVERLOADS(NAME) \
+  Duration NAME(float n); \
+  Duration NAME(double n);\
+  template\
+  Duration NAME(T n);
+
+GENERATE_DURATION_FACTORY_OVERLOADS(Nanoseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Microseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Milliseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Seconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Minutes);
+GENERATE_DURATION_FACTORY_OVERLOADS(Hours);
+#undef GENERATE_DURATION_FACTORY_OVERLOADS
+
+using int64_t = long long int;
+
+double ToDoubleHours(Duration d);
+double ToDoubleMinutes(Duration d);
+double ToDoubleSeconds(Duration d);
+double ToDoubleMilliseconds(Duration d);
+double ToDoubleMicroseconds(Duration d);
+double ToDoubleNanoseconds(Duration d);
+int64_t ToInt64Hours(Duration d);
+int64_t ToInt64Minutes(Duration d);
+int64_t ToInt64Seconds(Duration d);
+int64_t ToInt64Milliseconds(Duration d);
+int64_t ToInt64Microseconds(Duration d);
+int64_t ToInt64Nanoseconds(Duration d);
+
+// Relational Operators
+constexpr bool operator<(Duration lhs, Duration rhs);
+constexpr bool operator>(Duration lhs, Duration rhs);
+constexpr bool operator>=(Duration lhs, Duration rhs);
+constexpr bool operator<=(Duration lhs, Duration rhs);
+constexpr bool operator==(Duration lhs, Duration rhs);
+constexpr bool operator!=(Duration lhs, Duration rhs);
+
+// Additive Operators
+inline Time operator+(Time lhs, Duration rhs);
+inline Time operator+(Duration lhs, Time rhs);
+inline Time operator-(Time lhs, Duration rhs);
+inline Duration operator-(Time lhs, Time rhs);
+
+}  // namespace absl
+
+void f() {
+  double x;
+  absl::Duration d1, d2;
+  bool b;
+  absl::Time t1, t2;
+
+  // Check against the RHS
+  b = x > absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) > d1;
+  b = x >= absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) >= d1;
+  b = x == absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) == d1;
+  b = x <= absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) <= d1;
+  b = x < absl::ToDoubleSeconds(d1);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) < d1;
+  b = x == absl::ToDoubleSeconds(t1 - t2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: absl::Seconds(x) == t1 - t2;
+  b = absl::ToDoubleSeconds(d1) > absl::ToDoubleSeconds(d2);
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 > d2;
+
+  // Check against the LHS
+  b = absl::ToDoubleSeconds(d1) < x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 < absl::Seconds(x);
+  b = absl::ToDoubleSeconds(d1) <= x;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform duration comparison in the duration domain [abseil-duration-comparison]
+  // CHECK-FIXES: d1 

[PATCH] D54246: [clang-tidy] Add the abseil-duration-factory-scale check

2018-11-16 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

@aaron.ballman I don't actually have the commit bit, can you commit this, or 
are we waiting for further review?


https://reviews.llvm.org/D54246



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54246: [clang-tidy] Add the abseil-duration-factory-scale check

2018-11-16 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added a comment.

I think this is ready to go, please advise on next steps.


https://reviews.llvm.org/D54246



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54246: [clang-tidy] Add the abseil-duration-factory-scale check

2018-11-16 Thread Hyrum Wright via Phabricator via cfe-commits
hwright marked 5 inline comments as done.
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationFactoryScaleCheck.cpp:73
+  case DurationScale::Hours:
+if (Multiplier <= 1.0 / 60.0)
+  return std::make_tuple(DurationScale::Minutes, Multiplier * 60.0);

aaron.ballman wrote:
> This doesn't seem quite right. `1.0/6000.0` is less than `1.0/60.0` but isn't 
> a `Minutes` scaling.
After spending two days chasing this down, it finally occurred to me: we don't 
actually handle this case.  Our (somewhat conservative) matchers only look for 
literal values, not division expressions like `1.0/60.0`.

And for this iteration of the tool, I think I'm fine with that, since I expect 
those kinds of things to be exceedingly rare, and probably tricky to handle, 
anyway.


https://reviews.llvm.org/D54246



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54246: [clang-tidy] Add the abseil-duration-factory-scale check

2018-11-14 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationFactoryScaleCheck.cpp:57-58
+// One and only one of `IntLit` and `FloatLit` should be provided.
+static double GetValue(const IntegerLiteral *IntLit,
+   const FloatingLiteral *FloatLit) {
+  if (IntLit) {

aaron.ballman wrote:
> hwright wrote:
> > aaron.ballman wrote:
> > > I really don't like this interface where you pass two arguments, only one 
> > > of which is ever valid. That is pretty confusing. Given that the result 
> > > of this function is only ever passed to `GetNewMultScale()`, and that 
> > > function only does integral checks, I'd prefer logic more like:
> > > 
> > > * If the literal is integral, get its value and call `GetNewMultScale()`.
> > > * If the literal is float, convert it to an integral and call 
> > > `GetNewMultScale()` only if the conversion is exact (this can be done via 
> > > `APFloat::convertToInteger()`).
> > > * `GetNewMultScale()` can now accept an integer value and removes the 
> > > questions about inexact equality tests from the function.
> > > 
> > > With that logic, I don't see a need for `GetValue()` at all, but if a 
> > > helper function is useful, I'd probably guess this is a better signature: 
> > > `int64_t getIntegralValue(const Expr *Literal, bool );`
> > >  Given that the result of this function is only ever passed to 
> > > `GetNewMultScale()`, and that function only does integral checks, I'd 
> > > prefer logic more like:
> > 
> > That's actually not true: `GetNewMultScale()` does checks against values 
> > like `1e-3` which aren't integers.  Does this change your suggestion?
> Hmm, yeah, I suppose it has to! :-D
I've reworked the bulk of this logic. It still uses doubles, but that doesn't 
trouble our test cases.  Please let me know if there's more to do here.



Comment at: clang-tidy/abseil/DurationFactoryScaleCheck.cpp:63
+  assert(FloatLit != nullptr && "Neither IntLit nor FloatLit set");
+  return FloatLit->getValueAsApproximateDouble();
+}

aaron.ballman wrote:
> hwright wrote:
> > aaron.ballman wrote:
> > > I believe the approximate results here can lead to bugs where the 
> > > floating-point literal is subnormal -- it may return 0.0 for literals 
> > > that are not zero.
> > Do you have an example which I could put in a test?
> `0x0.01p-126f` should get you a new, exciting way to spell `0`.
I've added this as a test, and it resolves as normal.  Was your comment 
intended to indicate that it //should//, or that doing so would be a bug?



Comment at: clang-tidy/abseil/DurationFactoryScaleCheck.cpp:81-84
+if (Multiplier == 60.0)
+  return DurationScale::Minutes;
+if (Multiplier == 1e-3)
+  return DurationScale::Milliseconds;

aaron.ballman wrote:
> hwright wrote:
> > aaron.ballman wrote:
> > > What about scaling with a multiplier of 3600 to go from seconds to hours, 
> > > and other plausible conversions?
> > That's a good point, and part of a broader design discussion: should we 
> > support all multipliers?  (e.g., what about multiplying microseconds by 
> > `1.0/864.0`?)
> > 
> > If we do think it's worth handling all of these cases, we probably want a 
> > different construct than the equivalent of a lookup table to do this 
> > computation.
> > That's a good point, and part of a broader design discussion: should we 
> > support all multipliers?
> 
> That's kind of what I'm leaning towards. It's certainly more explainable to 
> users that all the various scaling operations just work, rather than some 
> particular set.
> 
> However, maybe you know more about the user base than I do and there's a 
> sound reason to not handle all cases?
> 
> > If we do think it's worth handling all of these cases, we probably want a 
> > different construct than the equivalent of a lookup table to do this 
> > computation.
> 
> There's a part of me that wonders if we can use `std::ratio` to describe the 
> scaling operations, but I freely admit I've not thought about implementation 
> strategies all that hard.
`std::ratio` didn't look like it made much sense here (though I don't have much 
first-hand experience using it), but we do now handle multiple scaling steps.


https://reviews.llvm.org/D54246



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D54246: [clang-tidy] Add the abseil-duration-factory-scale check

2018-11-14 Thread Hyrum Wright via Phabricator via cfe-commits
hwright updated this revision to Diff 174039.
hwright marked 11 inline comments as done.
hwright added a comment.

Combined multiplication and division logic, and also now handles scaling of 
multiple steps (e.g., Seconds * 3600).


https://reviews.llvm.org/D54246

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/DurationFactoryScaleCheck.cpp
  clang-tidy/abseil/DurationFactoryScaleCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-duration-factory-scale.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-duration-factory-scale.cpp

Index: test/clang-tidy/abseil-duration-factory-scale.cpp
===
--- /dev/null
+++ test/clang-tidy/abseil-duration-factory-scale.cpp
@@ -0,0 +1,130 @@
+// RUN: %check_clang_tidy %s abseil-duration-factory-scale %t
+
+// Mimic the implementation of absl::Duration
+namespace absl {
+
+class Duration {};
+
+Duration Nanoseconds(long long);
+Duration Microseconds(long long);
+Duration Milliseconds(long long);
+Duration Seconds(long long);
+Duration Minutes(long long);
+Duration Hours(long long);
+
+#define GENERATE_DURATION_FACTORY_OVERLOADS(NAME) \
+  Duration NAME(float n); \
+  Duration NAME(double n);\
+  template\
+  Duration NAME(T n);
+
+GENERATE_DURATION_FACTORY_OVERLOADS(Nanoseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Microseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Milliseconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Seconds);
+GENERATE_DURATION_FACTORY_OVERLOADS(Minutes);
+GENERATE_DURATION_FACTORY_OVERLOADS(Hours);
+#undef GENERATE_DURATION_FACTORY_OVERLOADS
+
+}  // namespace absl
+
+void ScaleTest() {
+  absl::Duration d;
+
+  // Zeroes
+  d = absl::Hours(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Minutes(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Milliseconds(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Microseconds(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Nanoseconds(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(0.0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+  d = absl::Seconds(0x0.01p-126f);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use ZeroDuration() for zero-length time intervals [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::ZeroDuration();
+
+  // Fold seconds into minutes
+  d = absl::Seconds(30 * 60);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: internal duration scaling can be removed [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::Minutes(30);
+  d = absl::Seconds(60 * 30);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: internal duration scaling can be removed [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::Minutes(30);
+
+  // Try a few more exotic multiplications
+  d = absl::Seconds(60 * 30 * 60);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: internal duration scaling can be removed [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::Minutes(60 * 30);
+  d = absl::Seconds(1e-3 * 30);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: internal duration scaling can be removed [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::Milliseconds(30);
+  d = absl::Milliseconds(30 * 1000);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: internal duration scaling can be removed [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::Seconds(30);
+  d = absl::Milliseconds(30 * 0.001);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: internal duration scaling can be removed [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::Microseconds(30);
+
+  // Multiple steps
+  d = absl::Seconds(5 * 3600);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: internal duration scaling can be removed [abseil-duration-factory-scale]
+  // CHECK-FIXES: absl::Hours(5);
+  d = absl::Microseconds(5 * 1e6);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: internal duration scaling can be removed 

[PATCH] D54246: [clang-tidy] Add the abseil-duration-factory-scale check

2018-11-12 Thread Hyrum Wright via Phabricator via cfe-commits
hwright added inline comments.



Comment at: clang-tidy/abseil/DurationFactoryScaleCheck.cpp:57-58
+// One and only one of `IntLit` and `FloatLit` should be provided.
+static double GetValue(const IntegerLiteral *IntLit,
+   const FloatingLiteral *FloatLit) {
+  if (IntLit) {

aaron.ballman wrote:
> I really don't like this interface where you pass two arguments, only one of 
> which is ever valid. That is pretty confusing. Given that the result of this 
> function is only ever passed to `GetNewMultScale()`, and that function only 
> does integral checks, I'd prefer logic more like:
> 
> * If the literal is integral, get its value and call `GetNewMultScale()`.
> * If the literal is float, convert it to an integral and call 
> `GetNewMultScale()` only if the conversion is exact (this can be done via 
> `APFloat::convertToInteger()`).
> * `GetNewMultScale()` can now accept an integer value and removes the 
> questions about inexact equality tests from the function.
> 
> With that logic, I don't see a need for `GetValue()` at all, but if a helper 
> function is useful, I'd probably guess this is a better signature: `int64_t 
> getIntegralValue(const Expr *Literal, bool );`
>  Given that the result of this function is only ever passed to 
> `GetNewMultScale()`, and that function only does integral checks, I'd prefer 
> logic more like:

That's actually not true: `GetNewMultScale()` does checks against values like 
`1e-3` which aren't integers.  Does this change your suggestion?



Comment at: clang-tidy/abseil/DurationFactoryScaleCheck.cpp:63
+  assert(FloatLit != nullptr && "Neither IntLit nor FloatLit set");
+  return FloatLit->getValueAsApproximateDouble();
+}

aaron.ballman wrote:
> I believe the approximate results here can lead to bugs where the 
> floating-point literal is subnormal -- it may return 0.0 for literals that 
> are not zero.
Do you have an example which I could put in a test?



Comment at: clang-tidy/abseil/DurationFactoryScaleCheck.cpp:81-84
+if (Multiplier == 60.0)
+  return DurationScale::Minutes;
+if (Multiplier == 1e-3)
+  return DurationScale::Milliseconds;

aaron.ballman wrote:
> What about scaling with a multiplier of 3600 to go from seconds to hours, and 
> other plausible conversions?
That's a good point, and part of a broader design discussion: should we support 
all multipliers?  (e.g., what about multiplying microseconds by 
`1.0/864.0`?)

If we do think it's worth handling all of these cases, we probably want a 
different construct than the equivalent of a lookup table to do this 
computation.


https://reviews.llvm.org/D54246



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


  1   2   >