Stephen updated this revision to Diff 338272.
Stephen added a comment.

- Add ability to pass semi-colon separated list of types to ignore, instead of 
assuming only size_type and difference_type.
- Remove ability to avoid warnings on ::size() method, since it's subsumed by 
allowing narrowing conversions of size_t.
- Coalesce on/off option tests into per-option test files.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D99543

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
  clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-equivalentbitwidth-off.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-equivalentbitwidth-on.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-equivalentbitwidth-option.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-ignoreconversionfromtypes-option.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-intemplates-off.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-intemplates-on.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-intemplates-option.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizemethod-off.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizemethod-on.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizetypes-off.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizetypes-on.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizetypes-on.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizetypes-on.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
-// RUN: -config="{CheckOptions: [ \
-// RUN:   {key: "cppcoreguidelines-narrowing-conversions.WarnOnSizeTypeAndDifferenceType", value: 1} \
-// RUN: ]}" \
-// RUN: -- -target x86_64-unknown-linux -fsigned-char
-
-struct vector {
-  typedef long long size_type;
-  typedef long long difference_type;
-};
-
-void narrowing_size_type_is_not_ok() {
-  int i;
-  vector::size_type j;
-  i = j;
-  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'vector::size_type' (aka 'long long') to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
-
-void narrowing_difference_type_is_not_ok() {
-  int i;
-  vector::difference_type j;
-  i = j;
-  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'vector::difference_type' (aka 'long long') to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizetypes-off.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizetypes-off.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
-// RUN: -config="{CheckOptions: [ \
-// RUN:   {key: "cppcoreguidelines-narrowing-conversions.WarnOnSizeTypeAndDifferenceType", value: 0} \
-// RUN: ]}" \
-// RUN: -- -target x86_64-unknown-linux -fsigned-char
-struct vector {
-  typedef long long size_type;
-  typedef long long difference_type;
-};
-void narrowing_size_type_is_ok() {
-  int i;
-  vector::size_type j;
-  i = j;
-  // Warning disabled with WarnOnSizeTypeAndDifferenceType=0.
-}
-void narrowing_difference_type_is_ok() {
-  int i;
-  vector::difference_type j;
-  i = j;
-  // Warning disabled with WarnOnSizeTypeAndDifferenceType=0.
-}
-void most_narrowing_is_not_ok() {
-  int i;
-  long long j;
-  i = j;
-  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizemethod-on.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizemethod-on.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
-// RUN: -config="{CheckOptions: [ \
-// RUN:   {key: "cppcoreguidelines-narrowing-conversions.WarnOnReturnOfSizeMethod", value: 1} \
-// RUN: ]}" \
-// RUN: -- -target x86_64-unknown-linux -fsigned-char
-class vector {
-public:
-  long long size() const { return 0; }
-};
-void narrowing_size_method_is_not_ok() {
-  vector v;
-  int i, j;
-  i = v.size();
-  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-  i = j + v.size();
-  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
-void narrowing_size_method_binary_expr_is_not_ok() {
-  int i, j;
-  vector v;
-  i = j + v.size();
-  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-  i += j + v.size();
-  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
-void narrowing_size_method_binary_op_is_not_ok() {
-  int i = 0;
-  vector v;
-  i += v.size();
-  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizemethod-off.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-sizemethod-off.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
-// RUN: -config="{CheckOptions: [ \
-// RUN:   {key: "cppcoreguidelines-narrowing-conversions.WarnOnReturnOfSizeMethod", value: 0} \
-// RUN: ]}" \
-// RUN: -- -target x86_64-unknown-linux -fsigned-char
-
-class vector {
-public:
-  long long size() const { return 0; }
-};
-
-void narrowing_size_method_is_ok() {
-  vector v;
-  int i, j;
-  i = v.size();
-  // Warning disabled with WarnOnReturnOfSizeMethod=0.
-  i = j + v.size();
-  // Warning disabled with WarnOnReturnOfSizeMethod=0.
-}
-
-void narrowing_size_method_binary_expr_is_ok() {
-  int i;
-  int j;
-  vector v;
-  i = j + v.size();
-  // Warning disabled with WarnOnReturnOfSizeMethod=0.
-}
-
-void narrowing_size_method_binary_op_is_ok() {
-  int i, j;
-  vector v;
-  i += v.size();
-  // Warning disabled with WarnOnReturnOfSizeMethod=0.
-  i += j + v.size();
-  // Warning disabled with WarnOnReturnOfSizeMethod=0.
-}
-
-void most_narrowing_is_not_ok() {
-  int i;
-  long long j;
-  i = j;
-  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-intemplates-option.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-intemplates-option.cpp
@@ -0,0 +1,35 @@
+// RUN: %check_clang_tidy -check-suffix=DEFAULT %s \
+// RUN: cppcoreguidelines-narrowing-conversions %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: ]}'
+
+// RUN: %check_clang_tidy -check-suffix=WARN %s \
+// RUN: cppcoreguidelines-narrowing-conversions %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN:   {key: cppcoreguidelines-narrowing-conversions.WarnWithinTemplateInstantiation, value: 1} \
+// RUN: ]}'
+
+template <typename OrigType>
+void assign_in_template(OrigType jj) {
+  int ii;
+  ii = jj;
+  // DEFAULT: Warning disabled because WarnWithinTemplateInstantiation=0.
+  // CHECK-MESSAGES-WARN: :[[@LINE-2]]:8: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+}
+
+void narrow_inside_template_not_ok() {
+  long long j = 123;
+  assign_in_template(j);
+}
+
+void assign_outside_template(long long jj) {
+  int ii;
+  ii = jj;
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:8: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // CHECK-MESSAGES-WARN: :[[@LINE-2]]:8: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+}
+
+void narrow_outside_template_not_ok() {
+  long long j = 123;
+  assign_outside_template(j);
+}
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-intemplates-on.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-intemplates-on.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
-// RUN: -config="{CheckOptions: [ \
-// RUN:   {key: "cppcoreguidelines-narrowing-conversions.WarnWithinTemplateInstantiation", value: 1} \
-// RUN: ]}" \
-// RUN: -- -target x86_64-unknown-linux -fsigned-char
-
-template <typename OrigType>
-void assign_in_template(OrigType jj) {
-  int ii;
-  ii = jj;
-  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
-
-void narrow_inside_template_not_ok() {
-  long long j = 123;
-  assign_in_template(j);
-}
-
-void assign_outside_template(long long jj) {
-  int ii;
-  ii = jj;
-  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
-
-void narrow_outside_template_not_ok() {
-  long long j = 123;
-  assign_outside_template(j);
-}
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-intemplates-off.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-intemplates-off.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
-// RUN: -config="{CheckOptions: [ \
-// RUN:   {key: "cppcoreguidelines-narrowing-conversions.WarnWithinTemplateInstantiation", value: 0} \
-// RUN: ]}" \
-// RUN: -- -target x86_64-unknown-linux -fsigned-char
-
-template <typename OrigType>
-void assign_in_template(OrigType jj) {
-  int ii;
-  ii = jj;
-}
-
-void narrow_inside_template_is_ok() {
-  long long j = 123;
-  assign_in_template(j);
-  // Warning disabled with WarnWithinTemplateInstantiation=0.
-}
-
-void assign_outside_template(long long jj) {
-  int ii;
-  ii = jj;
-  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
-
-void narrow_outside_template_not_ok() {
-  long long j = 123;
-  assign_outside_template(j);
-}
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-ignoreconversionfromtypes-option.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-ignoreconversionfromtypes-option.cpp
@@ -0,0 +1,84 @@
+// RUN: %check_clang_tidy -check-suffix=DEFAULT %s \
+// RUN: cppcoreguidelines-narrowing-conversions %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: ]}'
+
+// RUN: %check_clang_tidy -check-suffix=IGNORED %s \
+// RUN: cppcoreguidelines-narrowing-conversions %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN:   {key: cppcoreguidelines-narrowing-conversions.IgnoreConversionFromTypes, value: "size_t;ptrdiff_t;size_type;difference_type"} \
+// RUN: ]}'
+
+typedef long long size_t;
+
+struct vector {
+  typedef long long size_type;
+  typedef long long difference_type;
+
+  size_t size() const { return 0; }
+};
+
+void narrowing_size_t() {
+  int i;
+  size_t j;
+  i = j;
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:7: warning: narrowing conversion from 'size_t' (aka 'long long') to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // IGNORED: Warning is disabled with IgnoreConversionFromTypes=size_t.
+}
+
+void narrowing_size_type() {
+  int i;
+  vector::size_type j;
+  i = j;
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:7: warning: narrowing conversion from 'vector::size_type' (aka 'long long') to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // IGNORED: Warning is disabled with IgnoreConversionFromTypes=size_type.
+}
+
+void narrowing_difference_type() {
+  int i;
+  vector::difference_type j;
+  i = j;
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:7: warning: narrowing conversion from 'vector::difference_type' (aka 'long long') to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // IGNORED: Warning is disabled with IgnoreConversionFromTypes=difference_type.
+}
+
+void narrowing_size_method() {
+  vector v;
+  int i, j;
+  i = v.size();
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:7: warning: narrowing conversion from 'size_t' (aka 'long long') to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // IGNORED: Warning is disabled with IgnoreConversionFromTypes=size_t.
+
+  i = j + v.size();
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // IGNORED: Warning is disabled with IgnoreConversionFromTypes=size_t.
+}
+
+void narrowing_size_method_binary_expr() {
+  int i;
+  int j;
+  vector v;
+  i = j + v.size();
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // IGNORED: Warning is disabled with IgnoreConversionFromTypes=size_t.
+}
+
+void narrowing_size_method_binary_op() {
+  int i, j;
+  vector v;
+  i += v.size();
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:8: warning: narrowing conversion from 'size_t' (aka 'long long') to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // IGNORED: Warning is disabled with IgnoreConversionFromTypes=size_t.
+
+  i += j + v.size();
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:8: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // IGNORED: Warning is disabled with IgnoreConversionFromTypes=size_t.
+}
+
+void most_narrowing_is_not_ok() {
+  int i;
+  long long j;
+  i = j;
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+}
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-equivalentbitwidth-option.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-equivalentbitwidth-option.cpp
@@ -0,0 +1,26 @@
+// RUN: %check_clang_tidy -check-suffix=DEFAULT %s \
+// RUN: cppcoreguidelines-narrowing-conversions %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: ]}'
+
+// RUN: %check_clang_tidy -check-suffix=DISABLED %s \
+// RUN: cppcoreguidelines-narrowing-conversions %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN:   {key: cppcoreguidelines-narrowing-conversions.WarnOnEquivalentBitWidth, value: 0} \
+// RUN: ]}'
+
+void narrowing_equivalent_bitwidth() {
+  int i;
+  unsigned int j;
+  i = j;
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // DISABLED: Warning disabled with WarnOnEquivalentBitWidth=0.
+}
+
+void most_narrowing_is_not_ok() {
+  int i;
+  long long j;
+  i = j;
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+  // CHECK-MESSAGES-DISABLED: :[[@LINE-2]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
+}
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-equivalentbitwidth-on.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-equivalentbitwidth-on.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
-// RUN: -config="{CheckOptions: [ \
-// RUN:   {key: "cppcoreguidelines-narrowing-conversions.WarnOnEquivalentBitWidth", value: 1} \
-// RUN: ]}" \
-// RUN: -- -target x86_64-unknown-linux -fsigned-char
-
-void narrowing_equivalent_bitwidth_is_not_ok() {
-  int i;
-  unsigned int j;
-  i = j;
-  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-equivalentbitwidth-off.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions-equivalentbitwidth-off.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
-// RUN: -config="{CheckOptions: [ \
-// RUN:   {key: "cppcoreguidelines-narrowing-conversions.WarnOnEquivalentBitWidth", value: 0} \
-// RUN: ]}" \
-// RUN: -- -target x86_64-unknown-linux -fsigned-char
-
-void narrowing_equivalent_bitwidth_is_ok() {
-  int i;
-  unsigned int j;
-  i = j;
-  // Warning disabled with WarnOnEquivalentBitWidth=0.
-  j = i;
-  // Warning disabled with WarnOnEquivalentBitWidth=0.
-}
-
-void most_narrowing_is_not_ok() {
-  int i;
-  long long j;
-  i = j;
-  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'long long' to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
-}
Index: clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst
+++ clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst
@@ -40,24 +40,21 @@
     When `true`, the check will warn on narrowing conversions within template
     instantations. `false` by default.
 
-.. option:: WarnOnReturnOfSizeMethod
-
-    When `true`, the check will warn on narrowing conversions that arise from
-    casts of the result of a method named 'size' (e.g.
-    `int n = std::vector<T>().size();`). `true` by default.
-
-.. option:: WarnOnSizeTypeAndDifferenceType
-
-    When `true`, the check will warn on narrowing conversions that arise from
-    casts of type names `size_type` and `difference_type`. (e.g.
-    `int n = std::difference(it1, it2);`). `true` by default.
-
 .. option:: WarnOnEquivalentBitWidth
 
     When `true`, the check will warn on narrowing conversions that arise from
     casting between types of equivalent bit width. (e.g.
     `int n = uint(0);` or `long long n = double(0);`) `true` by default.
 
+.. option:: IgnoreConversionFromTypes
+
+   Narrowing conversions from any type in this semicolon separated list will be
+   ignored. This may be useful to weed out commonly occurring, but less commonly
+   problematic assignments such as `int n = std::vector<char>().size();` or
+   `int n = std::difference(it1, it2);`. The default list is empty, but one
+   suggested list for a legacy codebase would be
+   `size_t;ptrdiff_t;size_type;difference_type`.
+
 .. option:: PedanticMode
 
     When `true`, the check will warn on assigning a floating point constant
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h
===================================================================
--- clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h
@@ -95,9 +95,8 @@
 
   const bool WarnOnFloatingPointNarrowingConversion;
   const bool WarnWithinTemplateInstantiation;
-  const bool WarnOnReturnOfSizeMethod;
   const bool WarnOnEquivalentBitWidth;
-  const bool WarnOnSizeTypeAndDifferenceType;
+  const std::string IgnoreConversionFromTypes;
   const bool PedanticMode;
 };
 
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "NarrowingConversionsCheck.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/Type.h"
@@ -23,6 +24,13 @@
 namespace clang {
 namespace tidy {
 namespace cppcoreguidelines {
+namespace {
+auto hasAnyListedName(const std::string &Names) {
+  const std::vector<std::string> NameList =
+      utils::options::parseStringList(Names);
+  return hasAnyName(std::vector<StringRef>(NameList.begin(), NameList.end()));
+}
+} // namespace
 
 NarrowingConversionsCheck::NarrowingConversionsCheck(StringRef Name,
                                                      ClangTidyContext *Context)
@@ -31,10 +39,8 @@
           Options.get("WarnOnFloatingPointNarrowingConversion", true)),
       WarnWithinTemplateInstantiation(
           Options.get("WarnWithinTemplateInstantiation", false)),
-      WarnOnReturnOfSizeMethod(Options.get("WarnOnReturnOfSizeMethod", true)),
       WarnOnEquivalentBitWidth(Options.get("WarnOnEquivalentBitWidth", true)),
-      WarnOnSizeTypeAndDifferenceType(
-          Options.get("WarnOnSizeTypeAndDifferenceType", true)),
+      IgnoreConversionFromTypes(Options.get("IgnoreConversionFromTypes", "")),
       PedanticMode(Options.get("PedanticMode", false)) {}
 
 void NarrowingConversionsCheck::storeOptions(
@@ -43,10 +49,8 @@
                 WarnOnFloatingPointNarrowingConversion);
   Options.store(Opts, "WarnWithinTemplateInstantiation",
                 WarnWithinTemplateInstantiation);
-  Options.store(Opts, "WarnOnReturnOfSizeMethod", WarnOnReturnOfSizeMethod);
   Options.store(Opts, "WarnOnEquivalentBitWidth", WarnOnEquivalentBitWidth);
-  Options.store(Opts, "WarnOnSizeTypeAndDifferenceType",
-                WarnOnSizeTypeAndDifferenceType);
+  Options.store(Opts, "IgnoreConversionFromTypes", IgnoreConversionFromTypes);
   Options.store(Opts, "PedanticMode", PedanticMode);
 }
 
@@ -56,56 +60,43 @@
   const auto IsCeilFloorCallExpr = expr(callExpr(callee(functionDecl(
       hasAnyName("::ceil", "::std::ceil", "::floor", "::std::floor")))));
 
-  // `size()` methods typically return `size_t`, often an unsigned long. Lots of
-  // code uses `int` to iterate over containers and containers rarely have >2B
-  // elements, so we allow an option to ignore narrowings that are the result
-  // of the return value of a `size()` method.
-  // Matches a call to a method named `size()`, such as `std::vector::size`.
-  const auto IsSizeMethodCallExpr =
-      callExpr(callee(cxxMethodDecl(hasName("size"))));
-
-  // `IsSizeMethodCallExpr` only finds narrowing calls to `size()`, not
-  // expressions that are promoted to `int64` due to a call to `size()`. For
-  // example, it will reject: `int narrowed = int_value + container.size()`.
+  // We may want to exclude other types from the checks, such as `size_type`
+  // and `difference_type`. These are often used to count elements, represented
+  // in 64 bits and assigned to `int`. Rarely are people counting >2B elements.
+  const auto IsConversionFromIgnoredType =
+      hasType(namedDecl(hasAnyListedName(IgnoreConversionFromTypes)));
+
+  // `IsConversionFromIgnoredType` will ignore narrowing calls from those types,
+  // but not expressions that are promoted to `int64` due to a binary expression
+  // with one of those types. For example, it will continue to reject:
+  // `int narrowed = int_value + container.size()`.
   // We attempt to address common incidents of compound expressions with
-  // `IsSizeMethodCallBinaryExpr`. It allows binary expressions that have one
-  // `size()` call argument where the other argument results in some integer
-  // type.
-  const auto IsSizeMethodCallBinaryExpr =
-      binaryOperator(hasOperands(IsSizeMethodCallExpr, hasType(isInteger())));
-
-  // Similar to the `size()` method options above, we may want to exclude other
-  // types from the checks, such as `size_type` and `difference_type`. These
-  // are often used to count elements, representented in 64 bits and assigned
-  // to `int`. Rarely are people counting >2B elements.
-  const auto IsSizeTypeOrDifferenceType = hasType(
-      namedDecl(anyOf(hasName("size_type"), hasName("difference_type"))));
+  // `IsIgnoredTypeTwoLevelsDeep`, allowing binary expressions that have one
+  // operand of the ignored types and the other operand of another integer type.
+  const auto IsIgnoredTypeTwoLevelsDeep =
+      anyOf(IsConversionFromIgnoredType,
+            binaryOperator(hasOperands(IsConversionFromIgnoredType,
+                                       hasType(isInteger()))));
 
   // Casts:
   //   i = 0.5;
   //   void f(int); f(0.5);
   Finder->addMatcher(
-      traverse(
-          TK_AsIs,
-          implicitCastExpr(
-              hasImplicitDestinationType(
-                  hasUnqualifiedDesugaredType(builtinType())),
-              hasSourceExpression(
-                  hasType(hasUnqualifiedDesugaredType(builtinType()))),
-              unless(hasSourceExpression(IsCeilFloorCallExpr)),
-              unless(hasParent(castExpr())),
-              WarnWithinTemplateInstantiation
-                  ? stmt()
-                  : stmt(unless(isInTemplateInstantiation())),
-              WarnOnReturnOfSizeMethod
-                  ? castExpr()
-                  : castExpr(unless(hasSourceExpression(anyOf(
-                        IsSizeMethodCallExpr, IsSizeMethodCallBinaryExpr)))),
-              WarnOnSizeTypeAndDifferenceType
-                  ? castExpr()
-                  : castExpr(unless(
-                        hasSourceExpression(IsSizeTypeOrDifferenceType))))
-              .bind("cast")),
+      traverse(TK_AsIs, implicitCastExpr(
+                            hasImplicitDestinationType(
+                                hasUnqualifiedDesugaredType(builtinType())),
+                            hasSourceExpression(hasType(
+                                hasUnqualifiedDesugaredType(builtinType()))),
+                            unless(hasSourceExpression(IsCeilFloorCallExpr)),
+                            unless(hasParent(castExpr())),
+                            WarnWithinTemplateInstantiation
+                                ? stmt()
+                                : stmt(unless(isInTemplateInstantiation())),
+                            IgnoreConversionFromTypes.empty()
+                                ? castExpr()
+                                : castExpr(unless(hasSourceExpression(
+                                      IsIgnoredTypeTwoLevelsDeep))))
+                            .bind("cast")),
       this);
 
   // Binary operators:
@@ -119,13 +110,9 @@
           WarnWithinTemplateInstantiation
               ? binaryOperator()
               : binaryOperator(unless(isInTemplateInstantiation())),
-          WarnOnReturnOfSizeMethod
-              ? binaryOperator()
-              : binaryOperator(unless(hasRHS(
-                    anyOf(IsSizeMethodCallExpr, IsSizeMethodCallBinaryExpr)))),
-          WarnOnSizeTypeAndDifferenceType
+          IgnoreConversionFromTypes.empty()
               ? binaryOperator()
-              : binaryOperator(unless(hasRHS(IsSizeTypeOrDifferenceType))),
+              : binaryOperator(unless(hasRHS(IsIgnoredTypeTwoLevelsDeep))),
           // The `=` case generates an implicit cast
           // which is covered by the previous matcher.
           unless(hasOperatorName("=")))
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to