Author: mitchell
Date: 2025-12-14T12:31:25+08:00
New Revision: 72574b81956ad8bab51deaae0adab5ff6be40a30

URL: 
https://github.com/llvm/llvm-project/commit/72574b81956ad8bab51deaae0adab5ff6be40a30
DIFF: 
https://github.com/llvm/llvm-project/commit/72574b81956ad8bab51deaae0adab5ff6be40a30.diff

LOG: [clang-tidy] Add `IgnoreMacro` option to `bugprone-chained-comparison` 
(#171975)

Closes #171130

---------

Co-authored-by: Baranov Victor <[email protected]>

Added: 
    
clang-tools-extra/test/clang-tidy/checkers/bugprone/chained-comparison-ignore-macros.cpp

Modified: 
    clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp
    clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.h
    clang-tools-extra/docs/ReleaseNotes.rst
    clang-tools-extra/docs/clang-tidy/checks/bugprone/chained-comparison.rst
    clang-tools-extra/test/clang-tidy/checkers/bugprone/chained-comparison.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp
index 47acc217b2c24..8b1c8aaa48e3e 100644
--- a/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp
@@ -112,6 +112,15 @@ void ChainedComparisonData::extract(const Expr *Op) {
   }
 }
 
+ChainedComparisonCheck::ChainedComparisonCheck(StringRef Name,
+                                               ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IgnoreMacros(Options.get("IgnoreMacros", false)) {}
+
+void ChainedComparisonCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoreMacros", IgnoreMacros);
+}
+
 void ChainedComparisonCheck::registerMatchers(MatchFinder *Finder) {
   const auto OperatorMatcher = expr(anyOf(
       binaryOperator(isComparisonOperator(),
@@ -128,6 +137,9 @@ void ChainedComparisonCheck::registerMatchers(MatchFinder 
*Finder) {
 void ChainedComparisonCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *MatchedOperator = Result.Nodes.getNodeAs<Expr>("op");
 
+  if (IgnoreMacros && MatchedOperator->getBeginLoc().isMacroID())
+    return;
+
   ChainedComparisonData Data(MatchedOperator);
   if (Data.Operands.empty())
     return;

diff  --git a/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.h 
b/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.h
index 7c1022904a3a6..dacfc68a8a42a 100644
--- a/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.h
@@ -20,13 +20,16 @@ namespace clang::tidy::bugprone {
 /// 
https://clang.llvm.org/extra/clang-tidy/checks/bugprone/chained-comparison.html
 class ChainedComparisonCheck : public ClangTidyCheck {
 public:
-  ChainedComparisonCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+  ChainedComparisonCheck(StringRef Name, ClangTidyContext *Context);
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   std::optional<TraversalKind> getCheckTraversalKind() const override {
     return TK_IgnoreUnlessSpelledInSource;
   }
+
+private:
+  const bool IgnoreMacros;
 };
 
 } // namespace clang::tidy::bugprone

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 27467d082ea1e..afd873e4007ac 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -344,6 +344,11 @@ New check aliases
 Changes in existing checks
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+- Improved :doc:`bugprone-chained-comparison
+  <clang-tidy/checks/bugprone/chained-comparison>` check by adding a
+  new option `IgnoreMacros` to suppress warnings within macro
+  expansions.
+
 - Improved :doc:`bugprone-easily-swappable-parameters
   <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by
   correcting a spelling mistake on its option

diff  --git 
a/clang-tools-extra/docs/clang-tidy/checks/bugprone/chained-comparison.rst 
b/clang-tools-extra/docs/clang-tidy/checks/bugprone/chained-comparison.rst
index 45b069a8e29de..d3ad0dfe5adda 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/chained-comparison.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/chained-comparison.rst
@@ -71,3 +71,11 @@ developer's intention more explicit and help avoid 
misunderstanding.
         // This block will be executed
     }
 
+Options
+-------
+
+.. option:: IgnoreMacros
+
+    If `true`, the check will not warn on chained comparisons inside macros.
+    Default is `false`.
+

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/chained-comparison-ignore-macros.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/chained-comparison-ignore-macros.cpp
new file mode 100644
index 0000000000000..7141abd619974
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/chained-comparison-ignore-macros.cpp
@@ -0,0 +1,37 @@
+// RUN: %check_clang_tidy -std=c++98-or-later 
--extra-arg=-Wno-error=parentheses %s bugprone-chained-comparison %t -- 
-config="{CheckOptions: {bugprone-chained-comparison.IgnoreMacros: true}}"
+
+#define CHAINED_COMPARE(a, b, c) (a < b < c)
+
+void macro_test(int x, int y, int z) {
+    bool result = CHAINED_COMPARE(x, y, z);
+}
+
+#define NESTED_LESS(a, b) a < b
+#define NESTED_CHAIN(a, b, c) NESTED_LESS(a, b) < c
+
+void nested_macro_test(int x, int y, int z) {
+    bool result = NESTED_CHAIN(x, y, z);
+}
+
+#define LESS_OP <
+
+void operator_macro_test(int x, int y, int z) {
+    bool result = x LESS_OP y LESS_OP z;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:19: warning: chained comparison 'v0 < v1 < v2' 
may generate unintended results
+
+#define PARTIAL_LESS(a, b) a < b
+
+void mixed_macro_test(int x, int y, int z) {
+    bool result = PARTIAL_LESS(x, y) < z;
+}
+
+void if_macro_test(int x, int y, int z) {
+    if (CHAINED_COMPARE(x, y, z)) {}
+}
+
+#define LONG_CHAIN_MACRO(v) v[0] < v[1] < v[2] < v[3]
+
+void long_chain_macro_test(int v[4]) {
+    bool result = LONG_CHAIN_MACRO(v);
+}

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/chained-comparison.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/chained-comparison.cpp
index 88813f72e37ca..2c32d58c23a31 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/chained-comparison.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/chained-comparison.cpp
@@ -89,3 +89,44 @@ bool mixedBinaryAndCpp(Value a, Value b, bool c) {
     return a < b == c;
 }
 // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: chained comparison 'v0 < v1 == 
v2' may generate unintended results, use parentheses to specify order of 
evaluation or a logical operator to separate comparison expressions 
[bugprone-chained-comparison]
+
+#define CHAINED_COMPARE(a, b, c) (a < b < c)
+
+void macro_test(int x, int y, int z) {
+    bool result = CHAINED_COMPARE(x, y, z);
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:35: warning: chained comparison 'v0 < v1 < v2' 
may generate unintended results, use parentheses to specify order of evaluation 
or a logical operator to separate comparison expressions 
[bugprone-chained-comparison]
+
+#define NESTED_LESS(a, b) a < b
+#define NESTED_CHAIN(a, b, c) NESTED_LESS(a, b) < c
+
+void nested_macro_test(int x, int y, int z) {
+    bool result = NESTED_CHAIN(x, y, z);
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:32: warning: chained comparison 'v0 < v1 < v2' 
may generate unintended results, use parentheses to specify order of evaluation 
or a logical operator to separate comparison expressions 
[bugprone-chained-comparison]
+
+#define LESS_OP <
+
+void operator_macro_test(int x, int y, int z) {
+    bool result = x LESS_OP y LESS_OP z;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:19: warning: chained comparison 'v0 < v1 < v2' 
may generate unintended results, use parentheses to specify order of evaluation 
or a logical operator to separate comparison expressions 
[bugprone-chained-comparison]
+
+#define PARTIAL_LESS(a, b) a < b
+
+void mixed_macro_test(int x, int y, int z) {
+    bool result = PARTIAL_LESS(x, y) < z;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:32: warning: chained comparison 'v0 < v1 < v2' 
may generate unintended results, use parentheses to specify order of evaluation 
or a logical operator to separate comparison expressions 
[bugprone-chained-comparison]
+
+void if_macro_test(int x, int y, int z) {
+    if (CHAINED_COMPARE(x, y, z)) {}
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:25: warning: chained comparison 'v0 < v1 < v2' 
may generate unintended results, use parentheses to specify order of evaluation 
or a logical operator to separate comparison expressions 
[bugprone-chained-comparison]
+
+#define LONG_CHAIN_MACRO(v) v[0] < v[1] < v[2] < v[3]
+
+void long_chain_macro_test(int v[4]) {
+    bool result = LONG_CHAIN_MACRO(v);
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:36: warning: chained comparison 'v0 < v1 < v2 
< v3' may generate unintended results, use parentheses to specify order of 
evaluation or a logical operator to separate comparison expressions 
[bugprone-chained-comparison]


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to