Skip to content

Conversation

PiotrZSL
Copy link
Member

Skip checking for references to variable in unevaluated context, like decltype, static_assert and so on.

Closes #85838

…-dec-in-conditions

Skip checking for references to variable in unevaluated context,
like decltype, static_assert and so on.

Closes llvm#85838
@llvmbot
Copy link
Member

llvmbot commented Mar 19, 2024

@llvm/pr-subscribers-clang-tidy

@llvm/pr-subscribers-clang-tools-extra

Author: Piotr Zegar (PiotrZSL)

Changes

Skip checking for references to variable in unevaluated context, like decltype, static_assert and so on.

Closes #85838


Full diff: https://github.com/llvm/llvm-project/pull/85849.diff

3 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp (+6-1)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp (+9)
diff --git a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp
index 16f43128d55e87..c9990cf6d10fd5 100644
--- a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp
@@ -31,6 +31,10 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) {
       anyOf(binaryOperator(anyOf(isComparisonOperator(), isLogicalOperator())),
             cxxOperatorCallExpr(isComparisonOperator())));
 
+  auto IsInUnevaluatedContext =
+      expr(anyOf(hasAncestor(expr(matchers::hasUnevaluatedContext())),
+                 hasAncestor(typeLoc())));
+
   Finder->addMatcher(
       expr(
           OperatorMatcher, unless(isExpansionInSystemHeader()),
@@ -47,7 +51,8 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) {
                             hasDescendant(
                                 expr(unless(equalsBoundNode("operand")),
                                      matchers::isStatementIdenticalToBoundNode(
-                                         "operand"))
+                                         "operand"),
+                                     unless(IsInUnevaluatedContext))
                                     .bind("second")))))
                   .bind("operator"))),
       this);
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 44680f79de6f54..8803be56d4fd1a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -132,6 +132,10 @@ Changes in existing checks
   <clang-tidy/checks/bugprone/assert-side-effect>` check by detecting side
   effect from calling a method with non-const reference parameters.
 
+- Improved :doc:`bugprone-inc-dec-in-conditions
+  <clang-tidy/checks/bugprone/inc-dec-in-conditions>` check to ignore code
+  within unevaluated contexts, such as ``decltype``.
+
 - Improved :doc:`bugprone-non-zero-enum-to-bool-conversion
   <clang-tidy/checks/bugprone/non-zero-enum-to-bool-conversion>` check by
   eliminating false positives resulting from direct usage of bitwise operators
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp
index 82af039973c3bb..a9cb27a47f35b5 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp
@@ -68,3 +68,12 @@ bool doubleCheck(Container<int> x) {
   // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: decrementing and referencing a variable in a complex condition can cause unintended side-effects due to C++'s order of evaluation, consider moving the modification outside of the condition to avoid misunderstandings [bugprone-inc-dec-in-conditions]
   // CHECK-MESSAGES: :[[@LINE-2]]:31: warning: incrementing and referencing a variable in a complex condition can cause unintended side-effects due to C++'s order of evaluation, consider moving the modification outside of the condition to avoid misunderstandings [bugprone-inc-dec-in-conditions]
 }
+
+namespace PR85838 {
+  void test()
+  {
+    auto foo = 0;
+    auto bar = 0;
+    if (++foo < static_cast<decltype(foo)>(bar)) {}
+  }
+}

@PiotrZSL PiotrZSL requested a review from carlosgalvezp March 20, 2024 20:12
Copy link
Contributor

@5chmidti 5chmidti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but the operand node may also be in an unevaluated context, you only guard against the non ++/-- expr being in an unevaluated context here.
Fix: add unless(IsInUnevaluatedContext) to both expr().bind("operand").
Example: if (foo < static_cast<decltype(foo++)>(bar)) {}

@PiotrZSL PiotrZSL requested a review from 5chmidti March 24, 2024 15:43
Copy link

✅ With the latest revision this PR passed the Python code formatter.

Copy link

✅ With the latest revision this PR passed the C/C++ code formatter.

@PiotrZSL PiotrZSL merged commit d4a4585 into llvm:main Mar 24, 2024
@PiotrZSL PiotrZSL deleted the 85838-bugprone-inc-dec-in-conditions-decltype-should-not-count-as-a-variable-reference branch March 24, 2024 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[18.1.1][BUG][clang-tidy][bugprone-inc-dec-in-conditions] decltype should not count as a variable "reference"
3 participants