[clang-tools-extra] [clang-tidy] performance-unnecessary-copy-initialization: Enhance the check for the scenario with MemberExpr initialization. (PR #151936)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 29 05:01:14 PDT 2025
================
@@ -273,6 +273,18 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(LocalVarCopiedFrom(declRefExpr(
to(varDecl(hasLocalStorage()).bind(OldVarDeclId)))),
this);
+
+ auto DeclRefToConstVar =
+ declRefExpr(to(varDecl(anyOf(hasType(isConstQualified()),
+ hasType(references(isConstQualified()))))
+ .bind(OldVarDeclId)));
+ Finder->addMatcher(
+ LocalVarCopiedFrom(
+ memberExpr(hasObjectExpression(anyOf(hasDescendant(DeclRefToConstVar),
----------------
movie-travel-code wrote:
Hi @vbvictor , the original implementation only consider the `const_var` and `var` in `const_var.xxx.xxx.xxx.var`, If there is a `CXXMemberCallExpr()` in the middle, it will brings a lot of complex analyses and potential bugs, as shown below.
```cpp
struct Name {
std::string str;
};
struct Person {
Name n;
Name& getNameLocalRef() const {
Name localN;
return localN;
}
const Name getNameConst() const {
return n;
}
const Name& getNameConstRef() const {
return n;
}
};
std::string foo(const Person& p) {
// There is a bug here, i.e. use-after-stack, so the fix `const auto& str1 = p.getNameLocalRef().str;` is also incorrect.
auto str1 = p.getNameLocalRef().str;
auto str2 = p.getNameConst().str;
auto str3 = p.getNameConstRef().str;
return str1 + str2 + str3;
}
```
So I filtered all the `MemExpr`s that contain `CXXMemberCallExpr`. Since there are no `CXXMemberCallExpr`s in the middle, the pure `MemberExpr` can guarantee constness of all the chain, I believe.
https://github.com/llvm/llvm-project/pull/151936
More information about the cfe-commits
mailing list