48 const auto IsSmartptr = hasAnyName(SmartPointers);
50 const auto ResetMethod =
51 cxxMethodDecl(hasName(
"reset"), hasOnlyDefaultParameters());
53 const auto TypeWithReset =
55 anyOf(hasMethod(ResetMethod),
56 isDerivedFrom(cxxRecordDecl(hasMethod(ResetMethod))))),
57 classTemplateSpecializationDecl(
58 hasSpecializedTemplate(classTemplateDecl(has(ResetMethod)))));
60 const auto SmartptrWithReset = expr(hasType(hasUnqualifiedDesugaredType(
61 recordType(hasDeclaration(classTemplateSpecializationDecl(
64 0, templateArgument(refersToType(hasUnqualifiedDesugaredType(
65 recordType(hasDeclaration(TypeWithReset))))))))))));
70 unless(hasAnyArgument(expr(unless(cxxDefaultArgExpr())))),
71 anyOf(on(cxxOperatorCallExpr(hasOverloadedOperatorName(
"->"),
72 hasArgument(0, SmartptrWithReset))
74 on(SmartptrWithReset)))
80 const MatchFinder::MatchResult &Result) {
81 const auto *MemberCall =
82 Result.Nodes.getNodeAs<CXXMemberCallExpr>(
"MemberCall");
85 if (
const auto *Arrow =
86 Result.Nodes.getNodeAs<CXXOperatorCallExpr>(
"ArrowOp")) {
87 const CharSourceRange SmartptrSourceRange =
88 Lexer::getAsCharRange(Arrow->getArg(0)->getSourceRange(),
89 *Result.SourceManager, getLangOpts());
91 diag(MemberCall->getBeginLoc(),
92 "ambiguous call to 'reset()' on a pointee of a smart pointer, prefer "
93 "more explicit approach");
95 diag(MemberCall->getBeginLoc(),
96 "consider dereferencing smart pointer to call 'reset' method "
97 "of the pointee here",
99 << FixItHint::CreateInsertion(SmartptrSourceRange.getBegin(),
"(*")
100 << FixItHint::CreateInsertion(SmartptrSourceRange.getEnd(),
")")
101 << FixItHint::CreateReplacement(
102 CharSourceRange::getCharRange(
103 Arrow->getOperatorLoc(),
104 Arrow->getOperatorLoc().getLocWithOffset(2)),
107 const auto *Member = cast<MemberExpr>(MemberCall->getCallee());
110 diag(MemberCall->getBeginLoc(),
111 "ambiguous call to 'reset()' on a smart pointer with pointee that "
112 "also has a 'reset()' method, prefer more explicit approach");
114 diag(MemberCall->getBeginLoc(),
115 "consider assigning the pointer to 'nullptr' here",
117 << FixItHint::CreateReplacement(
118 SourceRange(Member->getOperatorLoc(), Member->getOperatorLoc()),
120 << FixItHint::CreateReplacement(
121 SourceRange(Member->getMemberLoc(), MemberCall->getEndLoc()),