================ @@ -1915,6 +1936,101 @@ void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D, } } + std::optional<CallExpr::const_arg_range> Args; + if (Exp) { + if (const auto *CE = dyn_cast<CallExpr>(Exp)) + Args = CE->arguments(); + else if (const auto *CE = dyn_cast<CXXConstructExpr>(Exp)) + Args = CE->arguments(); + else + llvm_unreachable("Unknown call kind"); + } + const FunctionDecl *CalledFunction = dyn_cast<FunctionDecl>(D); + if (CalledFunction && Args.has_value()) { + for (auto [Param, Arg] : zip(CalledFunction->parameters(), *Args)) { + CapExprSet DeclaredLocks; + for (const Attr *At : Param->attrs()) { + switch (At->getKind()) { + case attr::AcquireCapability: { + const auto *A = cast<AcquireCapabilityAttr>(At); + Analyzer->getMutexIDs(A->isShared() ? SharedLocksToAdd + : ExclusiveLocksToAdd, + A, Exp, D, Self); + Analyzer->getMutexIDs(DeclaredLocks, A, nullptr, Param); + break; + } + + case attr::ReleaseCapability: { + const auto *A = cast<ReleaseCapabilityAttr>(At); + if (A->isGeneric()) + Analyzer->getMutexIDs(GenericLocksToRemove, A, Exp, D, Self); + else if (A->isShared()) + Analyzer->getMutexIDs(SharedLocksToRemove, A, Exp, D, Self); + else + Analyzer->getMutexIDs(ExclusiveLocksToRemove, A, Exp, D, Self); + Analyzer->getMutexIDs(DeclaredLocks, A, nullptr, Param); + break; + } + + case attr::RequiresCapability: { + const auto *A = cast<RequiresCapabilityAttr>(At); + for (auto *Arg : A->args()) + Analyzer->warnIfMutexNotHeld(FSet, D, Exp, + A->isShared() ? AK_Read : AK_Written, + Arg, POK_FunctionCall, Self, Loc); + Analyzer->getMutexIDs(DeclaredLocks, A, nullptr, Param); + break; + } + + case attr::LocksExcluded: { + const auto *A = cast<LocksExcludedAttr>(At); + for (auto *Arg : A->args()) + Analyzer->warnIfMutexHeld(FSet, D, Exp, Arg, Self, Loc); + Analyzer->getMutexIDs(DeclaredLocks, A, nullptr, Param); + break; + } + + default: + break; + } + } + if (DeclaredLocks.size() == 0) + continue; + CapabilityExpr Cp = Analyzer->SxBuilder.translateAttrExpr(Arg, nullptr); + if (const auto *CBTE = dyn_cast<CXXBindTemporaryExpr>(Arg->IgnoreCasts()); + Cp.isInvalid() && CBTE) { + if (auto Object = Analyzer->ConstructedObjects.find(CBTE->getSubExpr()); + Object != Analyzer->ConstructedObjects.end()) + Cp = CapabilityExpr(Object->second, StringRef(), false); ---------------- aaronpuchert wrote:
This is slightly wrong, but we currently use "mutex" as fallback, see e.g. `ClassifyDiagnostic` in `ThreadSafetyCommon.cpp`. ```suggestion Cp = CapabilityExpr(Object->second, StringRef("mutex"), false); ``` https://github.com/llvm/llvm-project/pull/110523 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits