Skip to content

Commit 6e31714

Browse files
authored
[analysis] assume expr is not mutated after analysis to avoid recursive (#90581)
Fixes: #89376.
1 parent fa53545 commit 6e31714

File tree

3 files changed

+30
-5
lines changed

3 files changed

+30
-5
lines changed

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ Changes in existing checks
261261

262262
- Improved :doc:`misc-const-correctness
263263
<clang-tidy/checks/misc/const-correctness>` check by avoiding infinite recursion
264-
for recursive forwarding reference.
264+
for recursive functions with forwarding reference parameters and reference
265+
variables which refer to themselves.
265266

266267
- Improved :doc:`misc-definitions-in-headers
267268
<clang-tidy/checks/misc/definitions-in-headers>` check by replacing the local

clang/lib/Analysis/ExprMutationAnalyzer.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,17 @@ const Stmt *ExprMutationAnalyzer::Analyzer::findMutationMemoized(
235235
if (Memoized != MemoizedResults.end())
236236
return Memoized->second;
237237

238+
// Assume Exp is not mutated before analyzing Exp.
239+
MemoizedResults[Exp] = nullptr;
238240
if (isUnevaluated(Exp))
239-
return MemoizedResults[Exp] = nullptr;
241+
return nullptr;
240242

241243
for (const auto &Finder : Finders) {
242244
if (const Stmt *S = (this->*Finder)(Exp))
243245
return MemoizedResults[Exp] = S;
244246
}
245247

246-
return MemoizedResults[Exp] = nullptr;
248+
return nullptr;
247249
}
248250

249251
const Stmt *

clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
#include "clang/AST/TypeLoc.h"
1111
#include "clang/ASTMatchers/ASTMatchFinder.h"
1212
#include "clang/ASTMatchers/ASTMatchers.h"
13+
#include "clang/Frontend/ASTUnit.h"
1314
#include "clang/Tooling/Tooling.h"
14-
#include "llvm/ADT/SmallString.h"
1515
#include "gmock/gmock.h"
1616
#include "gtest/gtest.h"
1717
#include <cctype>
@@ -43,7 +43,7 @@ std::unique_ptr<ASTUnit> buildASTFromCode(const Twine &Code) {
4343
}
4444

4545
ExprMatcher declRefTo(StringRef Name) {
46-
return declRefExpr(to(namedDecl(hasName(Name))));
46+
return declRefExpr(to(namedDecl(hasName(Name)).bind("decl")));
4747
}
4848

4949
StmtMatcher withEnclosingCompound(ExprMatcher Matcher) {
@@ -57,6 +57,13 @@ bool isMutated(const SmallVectorImpl<BoundNodes> &Results, ASTUnit *AST) {
5757
return ExprMutationAnalyzer(*S, AST->getASTContext()).isMutated(E);
5858
}
5959

60+
bool isDeclMutated(const SmallVectorImpl<BoundNodes> &Results, ASTUnit *AST) {
61+
const auto *const S = selectFirst<Stmt>("stmt", Results);
62+
const auto *const D = selectFirst<Decl>("decl", Results);
63+
TraversalKindScope RAII(AST->getASTContext(), TK_AsIs);
64+
return ExprMutationAnalyzer(*S, AST->getASTContext()).isMutated(D);
65+
}
66+
6067
SmallVector<std::string, 1>
6168
mutatedBy(const SmallVectorImpl<BoundNodes> &Results, ASTUnit *AST) {
6269
const auto *const S = selectFirst<Stmt>("stmt", Results);
@@ -1552,6 +1559,21 @@ TEST(ExprMutationAnalyzerTest, UniquePtr) {
15521559

15531560
// section: complex problems detected on real code
15541561

1562+
TEST(ExprMutationAnalyzerTest, SelfRef) {
1563+
std::unique_ptr<ASTUnit> AST{};
1564+
SmallVector<BoundNodes, 1> Results{};
1565+
1566+
AST = buildASTFromCodeWithArgs("void f() { int &x = x; }",
1567+
{"-Wno-unused-value", "-Wno-uninitialized"});
1568+
Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
1569+
EXPECT_FALSE(isDeclMutated(Results, AST.get()));
1570+
1571+
AST = buildASTFromCodeWithArgs("void f() { int &x = x; x = 1; }",
1572+
{"-Wno-unused-value", "-Wno-uninitialized"});
1573+
Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
1574+
EXPECT_TRUE(isDeclMutated(Results, AST.get()));
1575+
}
1576+
15551577
TEST(ExprMutationAnalyzerTest, UnevaluatedContext) {
15561578
const std::string Example =
15571579
"template <typename T>"

0 commit comments

Comments
 (0)