RedDocMD updated this revision to Diff 357031.
RedDocMD added a comment.
Invalidating regions
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D105421/new/
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,46 @@
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)) {
+ const auto StreamVal = Call.getArgSVal(0);
+ const MemRegion *StreamThisRegion = StreamVal.getAsRegion();
+ assert(StreamThisRegion &&
+ "expected to retrieve this pointer of basic_ostream");
+ State =
+ State->invalidateRegions({StreamThisRegion}, Call.getOriginExpr(),
+ C.blockCount(), C.getLocationContext(), false);
+ State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
+ StreamVal);
+ C.addTransition(State);
+ 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);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits