aaronpuchert created this revision. aaronpuchert added a reviewer: aaron.ballman. Herald added a project: clang. Herald added a subscriber: cfe-commits. aaronpuchert requested review of this revision.
Public members are always in scope, protected members in derived classes with sufficient access. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D87194 Files: clang/lib/Analysis/ThreadSafety.cpp clang/test/SemaCXX/warn-thread-safety-negative.cpp
Index: clang/test/SemaCXX/warn-thread-safety-negative.cpp =================================================================== --- clang/test/SemaCXX/warn-thread-safety-negative.cpp +++ clang/test/SemaCXX/warn-thread-safety-negative.cpp @@ -108,6 +108,54 @@ ns::fq(); // expected-warning {{calling function 'fq' requires negative capability '!globalMutex'}} } +class Base { +public: + void nopub() EXCLUSIVE_LOCKS_REQUIRED(!pub); + void noprot() EXCLUSIVE_LOCKS_REQUIRED(!prot); + void nopriv() EXCLUSIVE_LOCKS_REQUIRED(!priv); + + void inClass() { + nopub(); // expected-warning {{calling function 'nopub' requires negative capability '!pub'}} + noprot(); // expected-warning {{calling function 'noprot' requires negative capability '!prot'}} + nopriv(); // expected-warning {{calling function 'nopriv' requires negative capability '!priv'}} + } + + Mutex pub; + +protected: + Mutex prot; + +private: + Mutex priv; +}; + +class Derived : private Base { +public: + void nopubDerived() EXCLUSIVE_LOCKS_REQUIRED(!pub); + void noprotDerived() EXCLUSIVE_LOCKS_REQUIRED(!prot); + + void inDerivedClass() { + nopub(); // expected-warning {{calling function 'nopub' requires negative capability '!pub'}} + noprot(); // expected-warning {{calling function 'noprot' requires negative capability '!prot'}} + nopriv(); + } +}; + +class MoreDerived : public Derived { +public: + void inDerivedClassWithInacessibleBase() { + nopubDerived(); // expected-warning {{calling function 'nopubDerived' requires negative capability '!pub'}} + noprotDerived(); + } +}; + +void outside() { + Base x; + x.nopub(); // expected-warning {{calling function 'nopub' requires negative capability '!x.pub'}} + x.noprot(); + x.nopriv(); +} + } // end namespace ScopeTest namespace DoubleAttribute { Index: clang/lib/Analysis/ThreadSafety.cpp =================================================================== --- clang/lib/Analysis/ThreadSafety.cpp +++ clang/lib/Analysis/ThreadSafety.cpp @@ -16,6 +16,7 @@ #include "clang/Analysis/Analyses/ThreadSafety.h" #include "clang/AST/Attr.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclGroup.h" @@ -1275,10 +1276,28 @@ // Members are in scope from methods of the same class. if (const auto *P = dyn_cast<til::Project>(SExp)) { + const ValueDecl *VD = P->clangDecl(); + // Public members are always accessible. + if (VD->getAccess() == AS_public) + return true; + // We are ignoring friends here. if (!CurrentMethod) return false; - const ValueDecl *VD = P->clangDecl(); - return VD->getDeclContext() == CurrentMethod->getDeclContext(); + const auto *CapRecord = cast<CXXRecordDecl>(VD->getDeclContext()), + *MethodRecord = + cast<CXXRecordDecl>(CurrentMethod->getDeclContext()); + // If we're in the same record, all members are accessible. + if (CapRecord == MethodRecord) + return true; + // Additionally in derived classes, protected members are accessible. + if (VD->getAccess() == AS_protected) { + CXXBasePaths Paths; + if (!MethodRecord->isDerivedFrom(CapRecord, Paths)) + return false; + for (const CXXBasePath &Path : Paths) + if (Path.Access != AS_none) + return true; + } } return false;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits