diff options
author | Richard Trieu <rtrieu@google.com> | 2018-09-22 01:50:52 +0000 |
---|---|---|
committer | Richard Trieu <rtrieu@google.com> | 2018-09-22 01:50:52 +0000 |
commit | 8d3fa39a0d8deaa99b2615b10f61a2ae85f7f119 (patch) | |
tree | cab017df60d3bb425e49951a22952ae09680f028 /clang/lib/Sema/SemaDeclAttr.cpp | |
parent | b32d40417e25bad79e9b5bc0f0a29d7ba0222ad9 (diff) | |
download | bcm5719-llvm-8d3fa39a0d8deaa99b2615b10f61a2ae85f7f119.tar.gz bcm5719-llvm-8d3fa39a0d8deaa99b2615b10f61a2ae85f7f119.zip |
Update smart pointer detection for thread safety analysis.
Objects are determined to be smart pointers if they have both a star and arrow
operator. Some implementations of smart pointers have these overloaded
operators in a base class, while the check only searched the derived class.
This fix will also look for the operators in the base class.
llvm-svn: 342794
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index f6df0d0e963..ff432a6fba4 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -425,17 +425,36 @@ static bool isIntOrBool(Expr *Exp) { // Check to see if the type is a smart pointer of some kind. We assume // it's a smart pointer if it defines both operator-> and operator*. static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { - DeclContextLookupResult Res1 = RT->getDecl()->lookup( - S.Context.DeclarationNames.getCXXOperatorName(OO_Star)); - if (Res1.empty()) - return false; + auto IsOverloadedOperatorPresent = [&S](const RecordDecl *Record, + OverloadedOperatorKind Op) { + DeclContextLookupResult Result = + Record->lookup(S.Context.DeclarationNames.getCXXOperatorName(Op)); + return !Result.empty(); + }; - DeclContextLookupResult Res2 = RT->getDecl()->lookup( - S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow)); - if (Res2.empty()) + const RecordDecl *Record = RT->getDecl(); + bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star); + bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow); + if (foundStarOperator && foundArrowOperator) + return true; + + const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record); + if (!CXXRecord) return false; - return true; + for (auto BaseSpecifier : CXXRecord->bases()) { + if (!foundStarOperator) + foundStarOperator = IsOverloadedOperatorPresent( + BaseSpecifier.getType()->getAsRecordDecl(), OO_Star); + if (!foundArrowOperator) + foundArrowOperator = IsOverloadedOperatorPresent( + BaseSpecifier.getType()->getAsRecordDecl(), OO_Arrow); + } + + if (foundStarOperator && foundArrowOperator) + return true; + + return false; } /// Check if passed in Decl is a pointer type. |