From 186af2de86aea41d7418158e68f96c1f8620e013 Mon Sep 17 00:00:00 2001 From: DeLesley Hutchins Date: Thu, 20 Sep 2012 22:18:02 +0000 Subject: [PATCH] Thread safety analysis: properly canonicalize calls to virtual methods within lock expressions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164324 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ThreadSafety.cpp | 20 +++++++++--- test/SemaCXX/warn-thread-safety-analysis.cpp | 32 ++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp index 036d0b8888..fd59556665 100644 --- a/lib/Analysis/ThreadSafety.cpp +++ b/lib/Analysis/ThreadSafety.cpp @@ -226,8 +226,21 @@ private: return NodeVec.size()-1; } - unsigned makeMCall(unsigned NumArgs, const NamedDecl *D) { - NodeVec.push_back(SExprNode(EOP_MCall, NumArgs, D)); + // Grab the very first declaration of virtual method D + const CXXMethodDecl* getFirstVirtualDecl(const CXXMethodDecl *D) { + while (true) { + D = D->getCanonicalDecl(); + CXXMethodDecl::method_iterator I = D->begin_overridden_methods(), + E = D->end_overridden_methods(); + if (I == E) + return D; // Method does not override anything + D = *I; // FIXME: this does not work with multiple inheritance. + } + return 0; + } + + unsigned makeMCall(unsigned NumArgs, const CXXMethodDecl *D) { + NodeVec.push_back(SExprNode(EOP_MCall, NumArgs, getFirstVirtualDecl(D))); return NodeVec.size()-1; } @@ -328,8 +341,7 @@ private: return buildSExpr(CMCE->getImplicitObjectArgument(), CallCtx, NDeref); } unsigned NumCallArgs = CMCE->getNumArgs(); - unsigned Root = - makeMCall(NumCallArgs, CMCE->getMethodDecl()->getCanonicalDecl()); + unsigned Root = makeMCall(NumCallArgs, CMCE->getMethodDecl()); unsigned Sz = buildSExpr(CMCE->getImplicitObjectArgument(), CallCtx); Expr** CallArgs = CMCE->getArgs(); for (unsigned i = 0; i < NumCallArgs; ++i) { diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 0d6aa4c79b..c45adb6f0c 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -3453,3 +3453,35 @@ void test3() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) { } } // end namespace UnreachableExitTest + + +namespace VirtualMethodCanonicalizationTest { + +class Base { +public: + virtual Mutex* getMutex() = 0; +}; + +class Base2 : public Base { +public: + Mutex* getMutex(); +}; + +class Base3 : public Base2 { +public: + Mutex* getMutex(); +}; + +class Derived : public Base3 { +public: + Mutex* getMutex(); // overrides Base::getMutex() +}; + +void baseFun(Base *b) EXCLUSIVE_LOCKS_REQUIRED(b->getMutex()) { } + +void derivedFun(Derived *d) EXCLUSIVE_LOCKS_REQUIRED(d->getMutex()) { + baseFun(d); +} + +} // end namespace VirtualMethodCanonicalizationTest + -- 2.40.0