[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr
Deep Majumder via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 5 01:50:50 PDT 2021
RedDocMD created this revision.
RedDocMD added reviewers: NoQ, vsavchenko, xazax.hun, teemperor.
Herald added subscribers: manas, steakhal, ASDenysPetrov, martong, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware.
RedDocMD requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
This patch handles the `<<` operator defined for `std::unique_ptr` in
the std namespace (ignores custom overloads of the operator).
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D105421
Files:
clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -81,6 +81,20 @@
REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal)
+// Checks if RD has name in Names and is in std namespace
+bool hasStdClassWithName(const CXXRecordDecl *RD,
+ const SmallVectorImpl<StringRef> &Names) {
+ if (!RD || !RD->getDeclContext()->isStdNamespace())
+ return false;
+ if (RD->getDeclName().isIdentifier()) {
+ StringRef Name = RD->getName();
+ return llvm::any_of(Names, [&Name](StringRef GivenName) -> bool {
+ return Name == GivenName;
+ });
+ }
+ return false;
+}
+
// Define the inter-checker API.
namespace clang {
namespace ento {
@@ -89,16 +103,16 @@
const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(Call.getDecl());
if (!MethodDecl || !MethodDecl->getParent())
return false;
+ return isStdSmartPtr(MethodDecl->getParent());
+}
- const auto *RecordDecl = MethodDecl->getParent();
- if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
- return false;
+bool isStdSmartPtr(const CXXRecordDecl *RD) {
+ return hasStdClassWithName(
+ RD, SmallVector<StringRef, 3>{"shared_ptr", "unique_ptr", "weak_ptr"});
+}
- if (RecordDecl->getDeclName().isIdentifier()) {
- StringRef Name = RecordDecl->getName();
- return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
- }
- return false;
+bool isStdSmartPtr(const Expr *E) {
+ return isStdSmartPtr(E->getType()->getAsCXXRecordDecl());
}
bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion) {
@@ -175,9 +189,35 @@
return CD && CD->getConversionType()->isBooleanType();
}
+bool isStdBasicOstream(const Expr *E) {
+ const auto *RD = E->getType()->getAsCXXRecordDecl();
+ return hasStdClassWithName(RD, SmallVector<StringRef, 1>{"basic_ostream"});
+}
+
+bool isStdOstreamOperatorCall(const CallEvent &Call) {
+ if (Call.getNumArgs() != 2 ||
+ !Call.getDecl()->getDeclContext()->isStdNamespace())
+ return false;
+ const auto *FC = dyn_cast<SimpleFunctionCall>(&Call);
+ if (!FC)
+ return false;
+ const FunctionDecl *FD = FC->getDecl();
+ if (!FD->isOverloadedOperator())
+ return false;
+ const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
+ if (OOK != clang::OO_LessLess)
+ return false;
+ return smartptr::isStdSmartPtr(Call.getArgExpr(1)) &&
+ isStdBasicOstream(Call.getArgExpr(0));
+}
+
bool SmartPtrModeling::evalCall(const CallEvent &Call,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
+
+ if (isStdOstreamOperatorCall(Call))
+ return true;
+
if (!smartptr::isStdSmartPtrCall(Call))
return false;
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
@@ -22,6 +22,8 @@
/// Returns true if the event call is on smart pointer.
bool isStdSmartPtrCall(const CallEvent &Call);
+bool isStdSmartPtr(const CXXRecordDecl *RD);
+bool isStdSmartPtr(const Expr *E);
/// Returns whether the smart pointer is null or not.
bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D105421.356449.patch
Type: text/x-patch
Size: 3491 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210705/362e2135/attachment.bin>
More information about the cfe-commits
mailing list