diff --git a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp index 40f7e9cede1f1..4cd2f2802f30c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp @@ -147,10 +147,18 @@ using MutexDescriptor = class BlockInCriticalSectionChecker : public Checker { private: const std::array MutexDescriptors{ - MemberMutexDescriptor({/*MatchAs=*/CDM::CXXMethod, - /*QualifiedName=*/{"std", "mutex", "lock"}, - /*RequiredArgs=*/0}, - {CDM::CXXMethod, {"std", "mutex", "unlock"}, 0}), + // NOTE: There are standard library implementations where some methods + // of `std::mutex` are inherited from an implementation detail base + // class, and those aren't matched by the name specification {"std", + // "mutex", "lock"}. + // As a workaround here we omit the class name and only require the + // presence of the name parts "std" and "lock"/"unlock". + // TODO: Ensure that CallDescription understands inherited methods. + MemberMutexDescriptor( + {/*MatchAs=*/CDM::CXXMethod, + /*QualifiedName=*/{"std", /*"mutex",*/ "lock"}, + /*RequiredArgs=*/0}, + {CDM::CXXMethod, {"std", /*"mutex",*/ "unlock"}, 0}), FirstArgMutexDescriptor({CDM::CLibrary, {"pthread_mutex_lock"}, 1}, {CDM::CLibrary, {"pthread_mutex_unlock"}, 1}), FirstArgMutexDescriptor({CDM::CLibrary, {"mtx_lock"}, 1}, diff --git a/clang/test/Analysis/block-in-critical-section-inheritance.cpp b/clang/test/Analysis/block-in-critical-section-inheritance.cpp new file mode 100644 index 0000000000000..db20df8c60a5c --- /dev/null +++ b/clang/test/Analysis/block-in-critical-section-inheritance.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=unix.BlockInCriticalSection \ +// RUN: -std=c++11 \ +// RUN: -analyzer-output text \ +// RUN: -verify %s + +unsigned int sleep(unsigned int seconds) {return 0;} +namespace std { +// There are some standard library implementations where some mutex methods +// come from an implementation detail base class. We need to ensure that these +// are matched correctly. +class __mutex_base { +public: + void lock(); +}; +class mutex : public __mutex_base{ +public: + void unlock(); + bool try_lock(); +}; +} // namespace std + +void gh_99628() { + std::mutex m; + m.lock(); + // expected-note@-1 {{Entering critical section here}} + sleep(10); + // expected-warning@-1 {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-2 {{Call to blocking function 'sleep' inside of critical section}} + m.unlock(); +}