forked from OSchip/llvm-project
[clang-tidy] Make performance-inefficient-vector-operation work on members
Fixes https://llvm.org/PR50157 Adds support for when the container being read from in a range-for is a member of a struct. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D101624
This commit is contained in:
parent
b20719dc7d
commit
0e0b0feff1
|
@ -68,6 +68,10 @@ ast_matchers::internal::Matcher<Expr> supportedContainerTypesMatcher() {
|
|||
"::std::unordered_map", "::std::array", "::std::deque")));
|
||||
}
|
||||
|
||||
AST_MATCHER(Expr, hasSideEffects) {
|
||||
return Node.HasSideEffects(Finder->getASTContext());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
InefficientVectorOperationCheck::InefficientVectorOperationCheck(
|
||||
|
@ -145,7 +149,10 @@ void InefficientVectorOperationCheck::addMatcher(
|
|||
// FIXME: Support more complex range-expressions.
|
||||
Finder->addMatcher(
|
||||
cxxForRangeStmt(
|
||||
hasRangeInit(declRefExpr(supportedContainerTypesMatcher())),
|
||||
hasRangeInit(
|
||||
anyOf(declRefExpr(supportedContainerTypesMatcher()),
|
||||
memberExpr(hasObjectExpression(unless(hasSideEffects())),
|
||||
supportedContainerTypesMatcher()))),
|
||||
HasInterestingLoopBody, InInterestingCompoundStmt)
|
||||
.bind(RangeLoopName),
|
||||
this);
|
||||
|
|
|
@ -127,6 +127,10 @@ New check aliases
|
|||
Changes in existing checks
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Improved :doc:`performance-inefficient-vector-operation
|
||||
<clang-tidy/checks/performance-inefficient-vector-operation>` to work when
|
||||
the vector is a member of a structure.
|
||||
|
||||
- Fixed a false positive in :doc:`readability-non-const-parameter
|
||||
<clang-tidy/checks/readability-non-const-parameter>` when the parameter is referenced by an lvalue
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ class vector {
|
|||
void reserve(size_t n);
|
||||
void resize(size_t n);
|
||||
|
||||
size_t size();
|
||||
size_t size() const;
|
||||
const_reference operator[] (size_type) const;
|
||||
reference operator[] (size_type);
|
||||
|
||||
|
@ -359,3 +359,31 @@ void f(std::vector<int>& t) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct StructWithFieldContainer {
|
||||
std::vector<int> Numbers;
|
||||
std::vector<int> getNumbers() const {
|
||||
std::vector<int> Result;
|
||||
// CHECK-FIXES: Result.reserve(Numbers.size());
|
||||
for (auto Number : Numbers) {
|
||||
Result.push_back(Number);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
};
|
||||
|
||||
StructWithFieldContainer getStructWithField();
|
||||
|
||||
void foo(const StructWithFieldContainer &Src) {
|
||||
std::vector<int> A;
|
||||
// CHECK-FIXES: A.reserve(Src.Numbers.size());
|
||||
for (auto Number : Src.Numbers) {
|
||||
A.push_back(Number);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'push_back' is called
|
||||
}
|
||||
std::vector<int> B;
|
||||
for (auto Number : getStructWithField().Numbers) {
|
||||
B.push_back(Number);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue