diff --git a/build/clang-plugin/RefCountedInsideLambdaChecker.cpp b/build/clang-plugin/RefCountedInsideLambdaChecker.cpp index 8a95b761de27..03709bc25879 100644 --- a/build/clang-plugin/RefCountedInsideLambdaChecker.cpp +++ b/build/clang-plugin/RefCountedInsideLambdaChecker.cpp @@ -36,6 +36,18 @@ void RefCountedInsideLambdaChecker::emitDiagnostics(SourceLocation Loc, diag(Loc, "Please consider using a smart pointer", DiagnosticIDs::Note); } +static bool IsKnownLive(const VarDecl *Var) { + const Stmt *Init = Var->getInit(); + if (!Init) { + return false; + } + if (auto *Call = dyn_cast(Init)) { + const FunctionDecl *Callee = Call->getDirectCallee(); + return Callee && Callee->getName() == "MOZ_KnownLive"; + } + return false; +} + void RefCountedInsideLambdaChecker::check( const MatchFinder::MatchResult &Result) { static DenseSet CheckedDecls; @@ -107,11 +119,11 @@ void RefCountedInsideLambdaChecker::check( // pointers. for (const LambdaCapture &Capture : Lambda->captures()) { if (Capture.capturesVariable()) { - QualType Pointee = Capture.getCapturedVar()->getType()->getPointeeType(); - - if (!Pointee.isNull() && isClassRefCounted(Pointee)) { - emitDiagnostics(Capture.getLocation(), - Capture.getCapturedVar()->getName(), Pointee); + const VarDecl *Var = Capture.getCapturedVar(); + QualType Pointee = Var->getType()->getPointeeType(); + if (!Pointee.isNull() && isClassRefCounted(Pointee) && + !IsKnownLive(Var)) { + emitDiagnostics(Capture.getLocation(), Var->getName(), Pointee); return; } } diff --git a/build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp b/build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp index 4b4b814751cc..aedc5af096cd 100644 --- a/build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp +++ b/build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp @@ -1,3 +1,5 @@ +#include + #include #define MOZ_STRONG_REF #define MOZ_IMPLICIT __attribute__((annotate("moz_implicit"))) @@ -667,6 +669,9 @@ R::privateMethod() { privateMethod(); }); + std::function( + [instance = MOZ_KnownLive(this)]() { instance->privateMethod(); }); + // It should be OK to go through `this` if we have captured a reference to it. std::function([this, self]() { this->method(); diff --git a/mfbt/StaticAnalysisFunctions.h b/mfbt/StaticAnalysisFunctions.h index 93e6f678455a..b073055c05fd 100644 --- a/mfbt/StaticAnalysisFunctions.h +++ b/mfbt/StaticAnalysisFunctions.h @@ -13,6 +13,7 @@ # endif # define MOZ_CONSTEXPR #else // __cplusplus +# include "mozilla/Attributes.h" # define MOZ_CONSTEXPR constexpr #endif /*