Skip to content

Commit

Permalink
Revert "[clang analysis] ExprMutationAnalyzer avoid infinite recursio…
Browse files Browse the repository at this point in the history
…n 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
  • Loading branch information
fmayer committed Apr 15, 2024
1 parent 4d28d3f commit b2f07a9
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 84 deletions.
4 changes: 0 additions & 4 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,6 @@ Changes in existing checks
<clang-tidy/checks/llvm/header-guard>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`misc-const-correctness
<clang-tidy/checks/misc/const-correctness>` check by avoiding infinite recursion
for recursive forwarding reference.

- Improved :doc:`misc-definitions-in-headers
<clang-tidy/checks/misc/definitions-in-headers>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,3 @@ void concatenate3(Args... args)
(..., (stream << args));
}
} // namespace gh70323

namespace gh60895 {

template <class T> void f1(T &&a);
template <class T> void f2(T &&a);
template <class T> void f1(T &&a) { f2<T>(a); }
template <class T> void f2(T &&a) { f1<T>(a); }
void f() {
int x = 0;
// CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'x' of type 'int' can be declared 'const'
// CHECK-FIXES: int const x = 0;
f1(x);
}

} // namespace gh60895
28 changes: 7 additions & 21 deletions clang/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H

#include <type_traits>

#include "clang/AST/AST.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "llvm/ADT/DenseMap.h"
#include <variant>

namespace clang {

Expand All @@ -21,15 +22,8 @@ class FunctionParmMutationAnalyzer;
/// a given statement.
class ExprMutationAnalyzer {
public:
friend class FunctionParmMutationAnalyzer;
struct Cache {
llvm::SmallDenseMap<const FunctionDecl *,
std::unique_ptr<FunctionParmMutationAnalyzer>>
FuncParmAnalyzer;
};

ExprMutationAnalyzer(const Stmt &Stm, ASTContext &Context)
: ExprMutationAnalyzer(Stm, Context, std::make_shared<Cache>()) {}
: Stm(Stm), Context(Context) {}

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

ExprMutationAnalyzer(const Stmt &Stm, ASTContext &Context,
std::shared_ptr<Cache> CrossAnalysisCache)
: Stm(Stm), Context(Context),
CrossAnalysisCache(std::move(CrossAnalysisCache)) {}

const Stmt *findMutationMemoized(const Expr *Exp,
llvm::ArrayRef<MutationFinder> Finders,
ResultMap &MemoizedResults);
Expand All @@ -80,7 +69,9 @@ class ExprMutationAnalyzer {

const Stmt &Stm;
ASTContext &Context;
std::shared_ptr<Cache> CrossAnalysisCache;
llvm::DenseMap<const FunctionDecl *,
std::unique_ptr<FunctionParmMutationAnalyzer>>
FuncParmAnalyzer;
ResultMap Results;
ResultMap PointeeResults;
};
Expand All @@ -89,12 +80,7 @@ class ExprMutationAnalyzer {
// params.
class FunctionParmMutationAnalyzer {
public:
FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context)
: FunctionParmMutationAnalyzer(
Func, Context, std::make_shared<ExprMutationAnalyzer::Cache>()) {}
FunctionParmMutationAnalyzer(
const FunctionDecl &Func, ASTContext &Context,
std::shared_ptr<ExprMutationAnalyzer::Cache> CrossAnalysisCache);
FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context);

bool isMutated(const ParmVarDecl *Parm) {
return findMutation(Parm) != nullptr;
Expand Down
22 changes: 8 additions & 14 deletions clang/lib/Analysis/ExprMutationAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -638,10 +638,9 @@ const Stmt *ExprMutationAnalyzer::findFunctionArgMutation(const Expr *Exp) {
if (!RefType->getPointeeType().getQualifiers() &&
RefType->getPointeeType()->getAs<TemplateTypeParmType>()) {
std::unique_ptr<FunctionParmMutationAnalyzer> &Analyzer =
CrossAnalysisCache->FuncParmAnalyzer[Func];
FuncParmAnalyzer[Func];
if (!Analyzer)
Analyzer.reset(new FunctionParmMutationAnalyzer(*Func, Context,
CrossAnalysisCache));
Analyzer.reset(new FunctionParmMutationAnalyzer(*Func, Context));
if (Analyzer->findMutation(Parm))
return Exp;
continue;
Expand All @@ -654,15 +653,13 @@ const Stmt *ExprMutationAnalyzer::findFunctionArgMutation(const Expr *Exp) {
}

FunctionParmMutationAnalyzer::FunctionParmMutationAnalyzer(
const FunctionDecl &Func, ASTContext &Context,
std::shared_ptr<ExprMutationAnalyzer::Cache> CrossAnalysisCache)
: BodyAnalyzer(*Func.getBody(), Context, CrossAnalysisCache) {
const FunctionDecl &Func, ASTContext &Context)
: BodyAnalyzer(*Func.getBody(), Context) {
if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(&Func)) {
// CXXCtorInitializer might also mutate Param but they're not part of
// function body, check them eagerly here since they're typically trivial.
for (const CXXCtorInitializer *Init : Ctor->inits()) {
ExprMutationAnalyzer InitAnalyzer(*Init->getInit(), Context,
CrossAnalysisCache);
ExprMutationAnalyzer InitAnalyzer(*Init->getInit(), Context);
for (const ParmVarDecl *Parm : Ctor->parameters()) {
if (Results.contains(Parm))
continue;
Expand All @@ -678,14 +675,11 @@ FunctionParmMutationAnalyzer::findMutation(const ParmVarDecl *Parm) {
const auto Memoized = Results.find(Parm);
if (Memoized != Results.end())
return Memoized->second;
// To handle call A -> call B -> call A. Assume parameters of A is not mutated
// before analyzing parameters of A. Then when analyzing the second "call A",
// FunctionParmMutationAnalyzer can use this memoized value to avoid infinite
// recursion.
Results[Parm] = nullptr;

if (const Stmt *S = BodyAnalyzer.findMutation(Parm))
return Results[Parm] = S;
return Results[Parm];

return Results[Parm] = nullptr;
}

} // namespace clang
30 changes: 0 additions & 30 deletions clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -977,36 +977,6 @@ TEST(ExprMutationAnalyzerTest, FollowFuncArgModified) {
"void f() { int x; g(x); }");
Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));

AST = buildASTFromCode(
StdRemoveReference + StdForward +
"template <class T> void f1(T &&a);"
"template <class T> void f2(T &&a);"
"template <class T> void f1(T &&a) { f2<T>(std::forward<T>(a)); }"
"template <class T> void f2(T &&a) { f1<T>(std::forward<T>(a)); }"
"void f() { int x; f1(x); }");
Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
EXPECT_FALSE(isMutated(Results, AST.get()));

AST = buildASTFromCode(
StdRemoveReference + StdForward +
"template <class T> void f1(T &&a);"
"template <class T> void f2(T &&a);"
"template <class T> void f1(T &&a) { f2<T>(std::forward<T>(a)); }"
"template <class T> void f2(T &&a) { f1<T>(std::forward<T>(a)); a++; }"
"void f() { int x; f1(x); }");
Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("f1(x)"));

AST = buildASTFromCode(
StdRemoveReference + StdForward +
"template <class T> void f1(T &&a);"
"template <class T> void f2(T &&a);"
"template <class T> void f1(T &&a) { f2<T>(std::forward<T>(a)); a++; }"
"template <class T> void f2(T &&a) { f1<T>(std::forward<T>(a)); }"
"void f() { int x; f1(x); }");
Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("f1(x)"));
}

TEST(ExprMutationAnalyzerTest, FollowFuncArgNotModified) {
Expand Down

0 comments on commit b2f07a9

Please sign in to comment.