@@ -2265,27 +2265,37 @@ static bool neverReturns(const CFGBlock *B) {
22652265 return false ;
22662266}
22672267
2268- void ThreadSafetyAnalyzer::checkMismatchedFunctionAttrs (const NamedDecl *ND) {
2269- auto collectCapabilities = [&](const Decl *D) {
2270- CapExprSet Caps;
2271- for (const auto *A : D->specific_attrs <RequiresCapabilityAttr>()) {
2272- for (const Expr *E : A->args ())
2273- Caps.push_back_nodup (SxBuilder.translateAttrExpr (E, nullptr ));
2274- }
2275- return Caps;
2276- };
2268+ template <typename AttrT>
2269+ static CapExprSet collectAttrArgs (SExprBuilder &SxBuilder, const Decl *D) {
2270+ CapExprSet Caps;
2271+ for (const auto *A : D->specific_attrs <AttrT>()) {
2272+ for (const Expr *E : A->args ())
2273+ Caps.push_back_nodup (SxBuilder.translateAttrExpr (E, nullptr ));
2274+ }
2275+ return Caps;
2276+ }
2277+
2278+ template <typename AttrT>
2279+ static void maybeDiagnoseFunctionAttrs (const NamedDecl *ND,
2280+ SExprBuilder &SxBuilder,
2281+ ThreadSafetyHandler &Handler) {
22772282
2278- CapExprSet NDArgs = collectCapabilities (ND);
2283+ // FIXME: The diagnostic here is suboptimal. It would be better to print
2284+ // what attributes are missing in the first declaration.
2285+ CapExprSet NDArgs = collectAttrArgs<AttrT>(SxBuilder, ND);
22792286 for (const Decl *D = ND->getPreviousDecl (); D; D = D->getPreviousDecl ()) {
2280- CapExprSet DArgs = collectCapabilities ( D);
2287+ CapExprSet DArgs = collectAttrArgs<AttrT>(SxBuilder, D);
22812288
2282- for (const auto &[A, B] : zip_longest (NDArgs, DArgs)) {
2283- if (!A || !B || !A->equals (*B))
2284- Handler.handleAttributeMismatch (ND, cast<NamedDecl>(D));
2285- }
2289+ if (NDArgs.size () != DArgs.size ())
2290+ Handler.handleAttributeMismatch (ND, cast<NamedDecl>(D));
22862291 }
22872292}
22882293
2294+ void ThreadSafetyAnalyzer::checkMismatchedFunctionAttrs (const NamedDecl *ND) {
2295+ maybeDiagnoseFunctionAttrs<RequiresCapabilityAttr>(ND, SxBuilder, Handler);
2296+ maybeDiagnoseFunctionAttrs<ReleaseCapabilityAttr>(ND, SxBuilder, Handler);
2297+ }
2298+
22892299// / Check a function's CFG for thread-safety violations.
22902300// /
22912301// / We traverse the blocks in the CFG, compute the set of mutexes that are held
0 commit comments