[PATCH] D146922: [clang-tidy] Fix false positve for defaulted move constructor in performance-noexcept-move-constructor
Piotr Zegar via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 30 00:58:53 PDT 2023
PiotrZSL added a comment.
Looks ok, would be good to run this on some code base.
================
Comment at: clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp:22
+ cxxMethodDecl(anyOf(cxxConstructorDecl(isMoveConstructor()),
+ hasOverloadedOperatorName("=")),
unless(isImplicit()), unless(isDeleted()))
----------------
use isMoveAssignmentOperator instead of hasOverloadedOperatorName
================
Comment at: clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp:23
+ hasOverloadedOperatorName("=")),
unless(isImplicit()), unless(isDeleted()))
.bind("decl"),
----------------
move those 2 to begining...
================
Comment at: clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp:30
const MatchFinder::MatchResult &Result) {
if (const auto *Decl = Result.Nodes.getNodeAs<CXXMethodDecl>("decl")) {
bool IsConstructor = false;
----------------
invert this if to reduce nesting.
```
const auto *Decl = Result.Nodes.getNodeAs<CXXMethodDecl>("decl")
if (!Decl)
return;
```
================
Comment at: clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp:32-36
if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(Decl)) {
- if (!Ctor->isMoveConstructor())
- return;
IsConstructor = true;
} else if (!Decl->isMoveAssignmentOperator()) {
return;
}
----------------
IsConstructor = CXXConstructorDecl::classof(Decl);
================
Comment at: clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp:39
+ if (SpecAnalyzer.analyze(Decl) !=
+ utils::ExceptionSpecAnalyzer::State::Throwing) {
return;
----------------
remove {}, leave just
```
if (SpecAnalyzer.analyze(Decl) != utils::ExceptionSpecAnalyzer::State::Throwing) return;
```
================
Comment at: clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp:45-49
+ const auto *ProtoType = Decl->getType()->castAs<FunctionProtoType>();
+ const Expr *NoexceptExpr = ProtoType->getNoexceptExpr();
+ if (NoexceptExpr) {
+ NoexceptExpr = NoexceptExpr->IgnoreImplicit();
+ if (!isa<CXXBoolLiteralExpr>(NoexceptExpr)) {
----------------
woudn't getExceptionSpecInfo() != EST_NoexceptFalse do a trick here ?
================
Comment at: clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp:32
+ // Check if the function has already been analyzed and reuse that result.
+ if (FunctionCache.count(FuncDecl) == 0) {
+ State = analyzeImpl(FuncDecl);
----------------
use FunctionCache.find to avoid double search in line 32 and 38 (and reuse result)
================
Comment at: clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp:36
+ // Cache the result of the analysis.
+ FunctionCache.insert(std::make_pair(FuncDecl, State));
+ } else
----------------
try_emplace ?
================
Comment at: clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp:44
+ExceptionSpecAnalyzer::State
+ExceptionSpecAnalyzer::analyzeUnresolvedOrDefaulted(
+ const FunctionDecl *FuncDecl) {
----------------
pass FunctionProtoType also to this function
================
Comment at: clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp:50-52
+ const auto *MethodDecl = cast<CXXMethodDecl>(FuncDecl);
+ if (!MethodDecl)
+ return State::Unknown;
----------------
technically you could change this class to operator on CXXMethodDecl since begining
================
Comment at: clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp:76
+
+ // FIXME: There may still be a way to figure out if the field can throw or not
+ return State::Unknown;
----------------
check if this is trivial type, if its trivial type then cannot throw...
FDecl->getType()->isTrivialType(FDecl->getAstContext());
================
Comment at: clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp:95
+ DefaultableMemberKind Kind,
+ SkipMethods SkipMethods) {
+ if (!RecordDecl)
----------------
Can we hit some endless recursion here ?
Maybe so protection against checking Record that we currently checking.
================
Comment at: clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp:108-114
+ BasesToVisit Bases = isConstructor(Kind)
+ ? BasesToVisit::VisitPotentiallyConstructedBases
+ : BasesToVisit::VisitAllBases;
+
+ if (Bases == BasesToVisit::VisitPotentiallyConstructedBases)
+ Bases = RecordDecl->isAbstract() ? BasesToVisit::VisitNonVirtualBases
+ : BasesToVisit::VisitAllBases;
----------------
I'm not sure if we need to be so picky...
In short we could check all bases.
Virtual, Abstract or not...
================
Comment at: clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp:155
+ExceptionSpecAnalyzer::State
+ExceptionSpecAnalyzer::analyzeFunctionEST(const FunctionDecl *FuncDecl) {
+ const auto *FuncProto = FuncDecl->getType()->getAs<FunctionProtoType>();
----------------
pass FunctionProtoType also to this function, to avoid double checking
================
Comment at: clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.h:23
+public:
+ enum class State : std::int8_t {
+ Throwing, ///< This function has been declared as possibly throwing.
----------------
No need for std::int8_t, and if you really want then use std::uint8_t
================
Comment at: clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.h:78
+
+ DefaultableMemberKind getDefaultableMemberKind(const FunctionDecl *FuncDecl);
+
----------------
this also can be static
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D146922/new/
https://reviews.llvm.org/D146922
More information about the cfe-commits
mailing list