diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index f921d3e7d76..f6df0d0e963 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -476,6 +476,29 @@ static const RecordType *getRecordType(QualType QT) { return nullptr; } +template <typename AttrType> +static bool checkRecordDeclForAttr(const RecordDecl *RD) { + // Check if the record itself has the attribute. + if (RD->hasAttr<AttrType>()) + return true; + + // 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.getAs<RecordType>()->getDecl()->hasAttr<AttrType>(); + }, + BPaths, true)) + return true; + } + return false; +} + static bool checkRecordTypeForCapability(Sema &S, QualType Ty) { const RecordType *RT = getRecordType(Ty); @@ -491,21 +514,7 @@ static bool checkRecordTypeForCapability(Sema &S, QualType Ty) { if (threadSafetyCheckIsSmartPointer(S, RT)) return true; - // Check if the record itself has a capability. - RecordDecl *RD = RT->getDecl(); - if (RD->hasAttr<CapabilityAttr>()) - return true; - - // Else check if any base classes have a capability. - if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) { - CXXBasePaths BPaths(false, false); - if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &) { - const auto *Type = BS->getType()->getAs<RecordType>(); - return Type->getDecl()->hasAttr<CapabilityAttr>(); - }, BPaths)) - return true; - } - return false; + return checkRecordDeclForAttr<CapabilityAttr>(RT->getDecl()); } static bool checkTypedefTypeForCapability(QualType Ty) { @@ -563,8 +572,27 @@ static bool isCapabilityExpr(Sema &S, const Expr *Ex) { static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, const ParsedAttr &AL, SmallVectorImpl<Expr *> &Args, - int Sidx = 0, + unsigned Sidx = 0, bool ParamIdxOk = false) { + if (Sidx == AL.getNumArgs()) { + // If we don't have any capability arguments, the attribute implicitly + // refers to 'this'. So we need to make sure that 'this' exists, i.e. we're + // a non-static method, and that the class is a (scoped) capability. + const auto *MD = dyn_cast<const CXXMethodDecl>(D); + if (MD && !MD->isStatic()) { + const CXXRecordDecl *RD = MD->getParent(); + // FIXME -- need to check this again on template instantiation + if (!checkRecordDeclForAttr<CapabilityAttr>(RD) && + !checkRecordDeclForAttr<ScopedLockableAttr>(RD)) + S.Diag(AL.getLoc(), + diag::warn_thread_attribute_not_on_capability_member) + << AL << MD->getParent(); + } else { + S.Diag(AL.getLoc(), diag::warn_thread_attribute_not_on_non_static_member) + << AL; + } + } + for (unsigned Idx = Sidx; Idx < AL.getNumArgs(); ++Idx) { Expr *ArgExp = AL.getArgAsExpr(Idx); |

