From 91ca3269a1b544db1303b496101fd9d6fe953277 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Mon, 3 May 2021 14:32:37 -0700 Subject: [PATCH] [clang-tidy] Aliasing: Add support for aggregates with references. When a variable is used in an initializer of an aggregate for its reference-type field this counts as aliasing. Differential Revision: https://reviews.llvm.org/D101791 --- clang-tools-extra/clang-tidy/utils/Aliasing.cpp | 7 ++++++ .../clang-tidy/checkers/bugprone-infinite-loop.cpp | 26 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/clang-tools-extra/clang-tidy/utils/Aliasing.cpp b/clang-tools-extra/clang-tidy/utils/Aliasing.cpp index 12a8ca8..69aea11 100644 --- a/clang-tools-extra/clang-tidy/utils/Aliasing.cpp +++ b/clang-tools-extra/clang-tidy/utils/Aliasing.cpp @@ -50,6 +50,13 @@ static bool isPtrOrReferenceForVar(const Stmt *S, const VarDecl *Var) { } else if (const auto *LE = dyn_cast(S)) { // Treat lambda capture by reference as a form of taking a reference. return capturesByRef(LE->getLambdaClass(), Var); + } else if (const auto *ILE = dyn_cast(S)) { + return llvm::any_of(ILE->inits(), [Var](const Expr *ChildE) { + // If the child expression is a reference to Var, this means that it's + // used as an initializer of a reference-typed field. Otherwise + // it would have been surrounded with an implicit lvalue-to-rvalue cast. + return isAccessForVar(ChildE, Var); + }); } return false; diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp index 5b47713..2765b18 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp @@ -566,3 +566,29 @@ int foo(void) { } return 0; } + +struct AggregateWithReference { + int &y; +}; + +void test_structured_bindings_good() { + int x = 0; + AggregateWithReference ref { x }; + auto &[y] = ref; + for (; x < 10; ++y) { + // No warning. The loop is finite because 'y' is a reference to 'x'. + } +} + +struct AggregateWithValue { + int y; +}; + +void test_structured_bindings_bad() { + int x = 0; + AggregateWithValue val { x }; + auto &[y] = val; + for (; x < 10; ++y) { + // 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] + } +} -- 2.7.4