shuaiwang created this revision.
Herald added a reviewer: george.karpenkov.
Herald added subscribers: cfe-commits, a.sidorin.
This yields better recall as ExprMutationAnalyzer is more accurate.
One common pattern this check is now able to catch is:
void foo(std::vector v) {
for (const auto& elm : v) {
// ...
}
}
Repository:
rCTE Clang Tools Extra
https://reviews.llvm.org/D50102
Files:
clang-tidy/performance/UnnecessaryValueParamCheck.cpp
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -10,6 +10,7 @@
#include "UnnecessaryValueParamCheck.h"
#include "../utils/DeclRefExprUtils.h"
+#include "../utils/ExprMutationAnalyzer.h"
#include "../utils/FixItHintUtils.h"
#include "../utils/Matchers.h"
#include "../utils/TypeTraits.h"
@@ -98,43 +99,52 @@
void UnnecessaryValueParamCheck::check(const MatchFinder::MatchResult )
{
const auto *Param = Result.Nodes.getNodeAs("param");
const auto *Function = Result.Nodes.getNodeAs("functionDecl");
- const size_t Index = std::find(Function->parameters().begin(),
- Function->parameters().end(), Param) -
- Function->parameters().begin();
- bool IsConstQualified =
- Param->getType().getCanonicalType().isConstQualified();
-
- auto AllDeclRefExprs = utils::decl_ref_expr::allDeclRefExprs(
- *Param, *Function, *Result.Context);
- auto ConstDeclRefExprs = utils::decl_ref_expr::constReferenceDeclRefExprs(
- *Param, *Function, *Result.Context);
// Do not trigger on non-const value parameters when they are not only used
as
// const.
- if (!isSubset(AllDeclRefExprs, ConstDeclRefExprs))
+ if (utils::ExprMutationAnalyzer(Function->getBody(), Result.Context)
+ .isMutated(Param))
return;
+ if (const auto *Ctor = dyn_cast(Function)) {
+for (const auto *Init : Ctor->inits()) {
+ if (utils::ExprMutationAnalyzer(Init->getInit(), Result.Context)
+ .isMutated(Param))
+return;
+}
+ }
+
+ const bool IsConstQualified =
+ Param->getType().getCanonicalType().isConstQualified();
// If the parameter is non-const, check if it has a move constructor and is
// only referenced once to copy-construct another object or whether it has a
// move assignment operator and is only referenced once when copy-assigned.
// In this case wrap DeclRefExpr with std::move() to avoid the unnecessary
// copy.
- if (!IsConstQualified && AllDeclRefExprs.size() == 1) {
-auto CanonicalType = Param->getType().getCanonicalType();
-const auto = **AllDeclRefExprs.begin();
-
-if (!hasLoopStmtAncestor(DeclRefExpr, *Function, *Result.Context) &&
-((utils::type_traits::hasNonTrivialMoveConstructor(CanonicalType) &&
- utils::decl_ref_expr::isCopyConstructorArgument(
- DeclRefExpr, *Function, *Result.Context)) ||
- (utils::type_traits::hasNonTrivialMoveAssignment(CanonicalType) &&
- utils::decl_ref_expr::isCopyAssignmentArgument(
- DeclRefExpr, *Function, *Result.Context {
- handleMoveFix(*Param, DeclRefExpr, *Result.Context);
- return;
+ if (!IsConstQualified) {
+auto AllDeclRefExprs = utils::decl_ref_expr::allDeclRefExprs(
+*Param, *Function, *Result.Context);
+if (AllDeclRefExprs.size() == 1) {
+ auto CanonicalType = Param->getType().getCanonicalType();
+ const auto = **AllDeclRefExprs.begin();
+
+ if (!hasLoopStmtAncestor(DeclRefExpr, *Function, *Result.Context) &&
+ ((utils::type_traits::hasNonTrivialMoveConstructor(CanonicalType) &&
+utils::decl_ref_expr::isCopyConstructorArgument(
+DeclRefExpr, *Function, *Result.Context)) ||
+ (utils::type_traits::hasNonTrivialMoveAssignment(CanonicalType) &&
+utils::decl_ref_expr::isCopyAssignmentArgument(
+DeclRefExpr, *Function, *Result.Context {
+handleMoveFix(*Param, DeclRefExpr, *Result.Context);
+return;
+ }
}
}
+ const size_t Index = std::find(Function->parameters().begin(),
+ Function->parameters().end(), Param) -
+ Function->parameters().begin();
+
auto Diag =
diag(Param->getLocation(),
IsConstQualified ? "the const qualified parameter %0 is "
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -10,6 +10,7 @@
#include "UnnecessaryValueParamCheck.h"
#include "../utils/DeclRefExprUtils.h"
+#include "../utils/ExprMutationAnalyzer.h"
#include "../utils/FixItHintUtils.h"
#include