TempRefPtrChecker.cpp (2266B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "TempRefPtrChecker.h" 6 #include "CustomMatchers.h" 7 8 constexpr const char *kCallExpr = "call-expr"; 9 constexpr const char *kOperatorCallExpr = "operator-call"; 10 11 void TempRefPtrChecker::registerMatchers(MatchFinder *AstMatcher) { 12 AstMatcher->addMatcher( 13 cxxOperatorCallExpr( 14 hasOverloadedOperatorName("->"), 15 hasAnyArgument(implicitCastExpr( 16 hasSourceExpression(materializeTemporaryExpr(anyOf( 17 hasDescendant(callExpr().bind(kCallExpr)), anything()))))), 18 callee(hasDeclContext(classTemplateSpecializationDecl( 19 isSmartPtrToRefCountedDecl(), 20 // ignore any calls on temporary RefPtr<MozPromise<T>>, 21 // since these typically need to be locally ref-counted, 22 // e.g. in Then chains where the promise might be resolved 23 // concurrently 24 unless(hasTemplateArgument( 25 0, refersToType(hasDeclaration( 26 cxxRecordDecl(hasName("mozilla::MozPromise")))))))))) 27 .bind(kOperatorCallExpr), 28 this); 29 } 30 31 void TempRefPtrChecker::check(const MatchFinder::MatchResult &Result) { 32 const auto *OCE = 33 Result.Nodes.getNodeAs<CXXOperatorCallExpr>(kOperatorCallExpr); 34 35 const auto *refPtrDecl = 36 dyn_cast<const CXXRecordDecl>(OCE->getCalleeDecl()->getDeclContext()); 37 38 diag(OCE->getOperatorLoc(), 39 "performance issue: temporary %0 is only dereferenced here once which " 40 "involves short-lived AddRef/Release calls") 41 << refPtrDecl; 42 43 const auto *InnerCE = Result.Nodes.getNodeAs<CallExpr>(kCallExpr); 44 if (InnerCE) { 45 const auto functionName = 46 InnerCE->getCalleeDecl()->getAsFunction()->getQualifiedNameAsString(); 47 48 if (functionName != "mozilla::MakeRefPtr") { 49 diag( 50 OCE->getOperatorLoc(), 51 "consider changing function %0 to return a raw reference instead (be " 52 "sure that the pointee is held alive by someone else though!)", 53 DiagnosticIDs::Note) 54 << functionName; 55 } 56 } 57 }