diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -513,16 +513,9 @@ // Else check if any base classes have the attribute. if (const auto *CRD = dyn_cast(RD)) { - CXXBasePaths BPaths(false, false); - if (CRD->lookupInBases( - [](const CXXBaseSpecifier *BS, CXXBasePath &) { - const auto &Ty = *BS->getType(); - // If it's type-dependent, we assume it could have the attribute. - if (Ty.isDependentType()) - return true; - return Ty.castAs()->getDecl()->hasAttr(); - }, - BPaths, true)) + if (!CRD->forallBases([](const CXXRecordDecl *Base) { + return !Base->hasAttr(); + })) return true; } return false; diff --git a/clang/test/SemaCXX/warn-thread-safety-parsing.cpp b/clang/test/SemaCXX/warn-thread-safety-parsing.cpp --- a/clang/test/SemaCXX/warn-thread-safety-parsing.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -1295,6 +1295,11 @@ // expected-warning{{'unlock_function' attribute without capability arguments refers to 'this', but 'SLDerived2' isn't annotated with 'capability' or 'scoped_lockable' attribute}} }; +struct SLDerived3 : public SLTemplateDerived { + ~SLDerived3() UNLOCK_FUNCTION(); // \ + // expected-warning{{'unlock_function' attribute without capability arguments refers to 'this', but 'SLDerived3' isn't annotated with 'capability' or 'scoped_lockable' attribute}} +}; + //----------------------------------------------------- // Parsing of member variables and function parameters //------------------------------------------------------