Index: clang-tools-extra/clang-tidy/utils/Aliasing.cpp =================================================================== --- clang-tools-extra/clang-tidy/utils/Aliasing.cpp +++ clang-tools-extra/clang-tidy/utils/Aliasing.cpp @@ -8,6 +8,7 @@ #include "Aliasing.h" +#include "clang/Analysis/AnyCall.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -57,6 +58,10 @@ // it would have been surrounded with an implicit lvalue-to-rvalue cast. return isAccessForVar(ChildE, Var); }); + } else if (Optional Call = AnyCall::forExpr(S)) { + return llvm::any_of(Call->arguments(), [Var](const Expr *ArgE) { + return isAccessForVar(ArgE, Var); + }); } return false; Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp +++ clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp @@ -591,3 +591,28 @@ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (x) are updated in the loop body [bugprone-infinite-loop] } } + +int &hidden_reference(int &x) { + return x; +} + +void test_hidden_reference() { + int x = 0; + int &y = hidden_reference(x); + for (; x < 10; ++y) { + // No warning. The loop is finite because 'y' is a reference to 'x'. + } +} + +struct HiddenReference { + int &y; + HiddenReference(int &x) : y(x) {} +}; + +void test_HiddenReference() { + int x = 0; + int &y = HiddenReference(x).y; + for (; x < 10; ++y) { + // No warning. The loop is finite because 'y' is a reference to 'x'. + } +} Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.mm =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.mm +++ clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.mm @@ -3,6 +3,7 @@ @interface I -(void) instanceMethod; +(void) classMethod; ++(int &) hiddenReferenceTo: (int &)x; @end void plainCFunction() { @@ -14,6 +15,15 @@ } } +void testHiddenReference() { + int i = 0; + int &j = [I hiddenReferenceTo: i]; + while (i < 10) { + // No warning. 'j' is a reference to 'i'. + j++; + } +} + @implementation I - (void)instanceMethod { int i = 0; @@ -32,4 +42,8 @@ j++; } } + ++(int &) hiddenReferenceTo: (int &) x { + return x; +} @end Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-redundant-branch-condition.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/bugprone-redundant-branch-condition.cpp +++ clang-tools-extra/test/clang-tidy/checkers/bugprone-redundant-branch-condition.cpp @@ -968,12 +968,29 @@ } if (tryToExtinguish(onFire) && onFire) { if (tryToExtinguishByVal(onFire) && onFire) { - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [bugprone-redundant-branch-condition] + // NO-MESSAGE: technically tryToExtinguish() may launch + // a background thread to extinguish the fire while tryToExtinguishByVal() + // may be waiting for that thread to finish. scream(); } } } +bool &hidden_reference(bool &flag) { + return flag; +} + +void test_hidden_reference() { + bool onFire = isBurning(); + bool onFireRef = hidden_reference(onFire); + if (onFire) { + onFireRef = false; + if (onFire) { + // NO-MESSAGE: fire was extinguished by the above assignment + } + } +} + void negative_reassigned() { bool onFire = isBurning(); if (onFire) { @@ -993,11 +1010,9 @@ bool onFire = isBurning(); if (onFire) { if (onFire) { - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [bugprone-redundant-branch-condition] - // CHECK-FIXES: {{^\ *$}} + // FIXME: This should warn. scream(); } - // CHECK-FIXES: {{^\ *$}} tryToExtinguish(onFire); } } @@ -1007,11 +1022,9 @@ if (onFire) { if (someOtherCondition()) { if (onFire) { - // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [bugprone-redundant-branch-condition] - // CHECK-FIXES: {{^\ *$}} + // FIXME: This should warn. scream(); } - // CHECK-FIXES: {{^\ *$}} } tryToExtinguish(onFire); } @@ -1022,11 +1035,9 @@ if (onFire) { if (someOtherCondition()) { if (onFire) { - // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [bugprone-redundant-branch-condition] - // CHECK-FIXES: {{^\ *$}} + // FIXME: This should warn. scream(); } - // CHECK-FIXES: {{^\ *$}} tryToExtinguish(onFire); } } @@ -1036,8 +1047,7 @@ bool onFire = isBurning(); if (onFire) { if (onFire) { - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [bugprone-redundant-branch-condition] - // CHECK-FIXES: {{^\ *$}} + // FIXME: This should warn. tryToExtinguish(onFire); scream(); }