summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2018-09-22 01:50:52 +0000
committerRichard Trieu <rtrieu@google.com>2018-09-22 01:50:52 +0000
commit797bc2cafc595aa8f6909145bad94eb7b37faec9 (patch)
treebd8b2955ae54f792cf0b3f4c2c064ca06b96b87d /lib/Sema/SemaDeclAttr.cpp
parentd05cbec4c2c7fcf52a428d3253ca0c97662d7285 (diff)
downloadclang-797bc2cafc595aa8f6909145bad94eb7b37faec9.tar.gz
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@342794 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclAttr.cpp')
-rw-r--r--lib/Sema/SemaDeclAttr.cpp35
1 files changed, 27 insertions, 8 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index f6df0d0e96..ff432a6fba 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/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.