Skip to content

Commit b2f07a9

Browse files
authored
Revert "[clang analysis] ExprMutationAnalyzer avoid infinite recursion for recursive forwarding reference" (#88765)
Reverts #87954 Broke sanitizer bots, e.g. https://lab.llvm.org/buildbot/#/builders/239/builds/6587/steps/10/logs/stdio
1 parent 4d28d3f commit b2f07a9

File tree

5 files changed

+15
-84
lines changed

5 files changed

+15
-84
lines changed

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,6 @@ Changes in existing checks
221221
<clang-tidy/checks/llvm/header-guard>` check by replacing the local
222222
option `HeaderFileExtensions` by the global option of the same name.
223223

224-
- Improved :doc:`misc-const-correctness
225-
<clang-tidy/checks/misc/const-correctness>` check by avoiding infinite recursion
226-
for recursive forwarding reference.
227-
228224
- Improved :doc:`misc-definitions-in-headers
229225
<clang-tidy/checks/misc/definitions-in-headers>` check by replacing the local
230226
option `HeaderFileExtensions` by the global option of the same name.

clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-templates.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,3 @@ void concatenate3(Args... args)
5858
(..., (stream << args));
5959
}
6060
} // namespace gh70323
61-
62-
namespace gh60895 {
63-
64-
template <class T> void f1(T &&a);
65-
template <class T> void f2(T &&a);
66-
template <class T> void f1(T &&a) { f2<T>(a); }
67-
template <class T> void f2(T &&a) { f1<T>(a); }
68-
void f() {
69-
int x = 0;
70-
// CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'x' of type 'int' can be declared 'const'
71-
// CHECK-FIXES: int const x = 0;
72-
f1(x);
73-
}
74-
75-
} // namespace gh60895

clang/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
99
#define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
1010

11+
#include <type_traits>
12+
1113
#include "clang/AST/AST.h"
1214
#include "clang/ASTMatchers/ASTMatchers.h"
1315
#include "llvm/ADT/DenseMap.h"
14-
#include <variant>
1516

1617
namespace clang {
1718

@@ -21,15 +22,8 @@ class FunctionParmMutationAnalyzer;
2122
/// a given statement.
2223
class ExprMutationAnalyzer {
2324
public:
24-
friend class FunctionParmMutationAnalyzer;
25-
struct Cache {
26-
llvm::SmallDenseMap<const FunctionDecl *,
27-
std::unique_ptr<FunctionParmMutationAnalyzer>>
28-
FuncParmAnalyzer;
29-
};
30-
3125
ExprMutationAnalyzer(const Stmt &Stm, ASTContext &Context)
32-
: ExprMutationAnalyzer(Stm, Context, std::make_shared<Cache>()) {}
26+
: Stm(Stm), Context(Context) {}
3327

3428
bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; }
3529
bool isMutated(const Decl *Dec) { return findMutation(Dec) != nullptr; }
@@ -51,11 +45,6 @@ class ExprMutationAnalyzer {
5145
using MutationFinder = const Stmt *(ExprMutationAnalyzer::*)(const Expr *);
5246
using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>;
5347

54-
ExprMutationAnalyzer(const Stmt &Stm, ASTContext &Context,
55-
std::shared_ptr<Cache> CrossAnalysisCache)
56-
: Stm(Stm), Context(Context),
57-
CrossAnalysisCache(std::move(CrossAnalysisCache)) {}
58-
5948
const Stmt *findMutationMemoized(const Expr *Exp,
6049
llvm::ArrayRef<MutationFinder> Finders,
6150
ResultMap &MemoizedResults);
@@ -80,7 +69,9 @@ class ExprMutationAnalyzer {
8069

8170
const Stmt &Stm;
8271
ASTContext &Context;
83-
std::shared_ptr<Cache> CrossAnalysisCache;
72+
llvm::DenseMap<const FunctionDecl *,
73+
std::unique_ptr<FunctionParmMutationAnalyzer>>
74+
FuncParmAnalyzer;
8475
ResultMap Results;
8576
ResultMap PointeeResults;
8677
};
@@ -89,12 +80,7 @@ class ExprMutationAnalyzer {
8980
// params.
9081
class FunctionParmMutationAnalyzer {
9182
public:
92-
FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context)
93-
: FunctionParmMutationAnalyzer(
94-
Func, Context, std::make_shared<ExprMutationAnalyzer::Cache>()) {}
95-
FunctionParmMutationAnalyzer(
96-
const FunctionDecl &Func, ASTContext &Context,
97-
std::shared_ptr<ExprMutationAnalyzer::Cache> CrossAnalysisCache);
83+
FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context);
9884

9985
bool isMutated(const ParmVarDecl *Parm) {
10086
return findMutation(Parm) != nullptr;

clang/lib/Analysis/ExprMutationAnalyzer.cpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -638,10 +638,9 @@ const Stmt *ExprMutationAnalyzer::findFunctionArgMutation(const Expr *Exp) {
638638
if (!RefType->getPointeeType().getQualifiers() &&
639639
RefType->getPointeeType()->getAs<TemplateTypeParmType>()) {
640640
std::unique_ptr<FunctionParmMutationAnalyzer> &Analyzer =
641-
CrossAnalysisCache->FuncParmAnalyzer[Func];
641+
FuncParmAnalyzer[Func];
642642
if (!Analyzer)
643-
Analyzer.reset(new FunctionParmMutationAnalyzer(*Func, Context,
644-
CrossAnalysisCache));
643+
Analyzer.reset(new FunctionParmMutationAnalyzer(*Func, Context));
645644
if (Analyzer->findMutation(Parm))
646645
return Exp;
647646
continue;
@@ -654,15 +653,13 @@ const Stmt *ExprMutationAnalyzer::findFunctionArgMutation(const Expr *Exp) {
654653
}
655654

656655
FunctionParmMutationAnalyzer::FunctionParmMutationAnalyzer(
657-
const FunctionDecl &Func, ASTContext &Context,
658-
std::shared_ptr<ExprMutationAnalyzer::Cache> CrossAnalysisCache)
659-
: BodyAnalyzer(*Func.getBody(), Context, CrossAnalysisCache) {
656+
const FunctionDecl &Func, ASTContext &Context)
657+
: BodyAnalyzer(*Func.getBody(), Context) {
660658
if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(&Func)) {
661659
// CXXCtorInitializer might also mutate Param but they're not part of
662660
// function body, check them eagerly here since they're typically trivial.
663661
for (const CXXCtorInitializer *Init : Ctor->inits()) {
664-
ExprMutationAnalyzer InitAnalyzer(*Init->getInit(), Context,
665-
CrossAnalysisCache);
662+
ExprMutationAnalyzer InitAnalyzer(*Init->getInit(), Context);
666663
for (const ParmVarDecl *Parm : Ctor->parameters()) {
667664
if (Results.contains(Parm))
668665
continue;
@@ -678,14 +675,11 @@ FunctionParmMutationAnalyzer::findMutation(const ParmVarDecl *Parm) {
678675
const auto Memoized = Results.find(Parm);
679676
if (Memoized != Results.end())
680677
return Memoized->second;
681-
// To handle call A -> call B -> call A. Assume parameters of A is not mutated
682-
// before analyzing parameters of A. Then when analyzing the second "call A",
683-
// FunctionParmMutationAnalyzer can use this memoized value to avoid infinite
684-
// recursion.
685-
Results[Parm] = nullptr;
678+
686679
if (const Stmt *S = BodyAnalyzer.findMutation(Parm))
687680
return Results[Parm] = S;
688-
return Results[Parm];
681+
682+
return Results[Parm] = nullptr;
689683
}
690684

691685
} // namespace clang

clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -977,36 +977,6 @@ TEST(ExprMutationAnalyzerTest, FollowFuncArgModified) {
977977
"void f() { int x; g(x); }");
978978
Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
979979
EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
980-
981-
AST = buildASTFromCode(
982-
StdRemoveReference + StdForward +
983-
"template <class T> void f1(T &&a);"
984-
"template <class T> void f2(T &&a);"
985-
"template <class T> void f1(T &&a) { f2<T>(std::forward<T>(a)); }"
986-
"template <class T> void f2(T &&a) { f1<T>(std::forward<T>(a)); }"
987-
"void f() { int x; f1(x); }");
988-
Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
989-
EXPECT_FALSE(isMutated(Results, AST.get()));
990-
991-
AST = buildASTFromCode(
992-
StdRemoveReference + StdForward +
993-
"template <class T> void f1(T &&a);"
994-
"template <class T> void f2(T &&a);"
995-
"template <class T> void f1(T &&a) { f2<T>(std::forward<T>(a)); }"
996-
"template <class T> void f2(T &&a) { f1<T>(std::forward<T>(a)); a++; }"
997-
"void f() { int x; f1(x); }");
998-
Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
999-
EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("f1(x)"));
1000-
1001-
AST = buildASTFromCode(
1002-
StdRemoveReference + StdForward +
1003-
"template <class T> void f1(T &&a);"
1004-
"template <class T> void f2(T &&a);"
1005-
"template <class T> void f1(T &&a) { f2<T>(std::forward<T>(a)); a++; }"
1006-
"template <class T> void f2(T &&a) { f1<T>(std::forward<T>(a)); }"
1007-
"void f() { int x; f1(x); }");
1008-
Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
1009-
EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("f1(x)"));
1010980
}
1011981

1012982
TEST(ExprMutationAnalyzerTest, FollowFuncArgNotModified) {

0 commit comments

Comments
 (0)