The original implementation didn't fire on non-template classes when a
base class was an instantiation of a template with a dependent base.
In that case the base of the base is dependent as seen from the base,
but not from the class we're interested in, which isn't a template.
Also it simplifies the code a lot.
Reviewed By: aaron.ballman
Differential Revision: https://reviews.llvm.org/D98724
// Else check if any base classes have the attribute.
if (const auto *CRD = dyn_cast<CXXRecordDecl>(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<RecordType>()->getDecl()->hasAttr<AttrType>();
- },
- BPaths, true))
+ if (!CRD->forallBases([](const CXXRecordDecl *Base) {
+ return !Base->hasAttr<AttrType>();
+ }))
return true;
}
return false;
// 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<int> {
+ ~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
//------------------------------------------------------