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 models the std::make_unique method. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D103750 Files: 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 @@ -40,6 +40,7 @@ check::LiveSymbols> { bool isBoolConversionMethod(const CallEvent &Call) const; + bool isStdMakeUniqueCall(const CallEvent &Call) const; public: // Whether the checker should model for null dereferences of smart pointers. @@ -68,6 +69,7 @@ bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion, const MemRegion *OtherSmartPtrRegion) const; void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const; + void handleMakeUnique(const CallEvent &Call, CheckerContext &C) const; using SmartPtrMethodHandlerFn = void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const; @@ -175,8 +177,31 @@ return CD && CD->getConversionType()->isBooleanType(); } +bool SmartPtrModeling::isStdMakeUniqueCall(const CallEvent &Call) const { + if (Call.getKind() != CallEventKind::CE_Function) + return false; + const auto *D = Call.getDecl(); + if (!D) + return false; + const auto *FTD = llvm::dyn_cast<FunctionDecl>(D); + if (!FTD) + return false; + if (FTD->getDeclName().isIdentifier()) { + StringRef Name = FTD->getName(); + if (Name == "make_unique") + return true; + } + return false; +} + bool SmartPtrModeling::evalCall(const CallEvent &Call, CheckerContext &C) const { + + if (isStdMakeUniqueCall(Call)) { + handleMakeUnique(Call, C); + return true; + } + ProgramStateRef State = C.getState(); if (!smartptr::isStdSmartPtrCall(Call)) return false; @@ -272,6 +297,21 @@ return C.isDifferent(); } +void SmartPtrModeling::handleMakeUnique(const CallEvent &Call, + CheckerContext &C) const { + const auto *OriginExpr = Call.getOriginExpr(); + const auto *LocCtx = C.getLocationContext(); + auto ExprVal = C.getSValBuilder().conjureSymbolVal( + OriginExpr, LocCtx, Call.getResultType(), C.blockCount()); + ProgramStateRef State = C.getState(); + State = State->BindExpr(OriginExpr, LocCtx, ExprVal); + + // With make unique it is not possible to make a null smart pointer. + // So we can set the SVal for Call.getOriginExpr() to be non-null + State = State->assume(ExprVal, true); + C.addTransition(State); +} + void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const { ProgramStateRef State = C.getState();
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -40,6 +40,7 @@ check::LiveSymbols> { bool isBoolConversionMethod(const CallEvent &Call) const; + bool isStdMakeUniqueCall(const CallEvent &Call) const; public: // Whether the checker should model for null dereferences of smart pointers. @@ -68,6 +69,7 @@ bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion, const MemRegion *OtherSmartPtrRegion) const; void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const; + void handleMakeUnique(const CallEvent &Call, CheckerContext &C) const; using SmartPtrMethodHandlerFn = void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const; @@ -175,8 +177,31 @@ return CD && CD->getConversionType()->isBooleanType(); } +bool SmartPtrModeling::isStdMakeUniqueCall(const CallEvent &Call) const { + if (Call.getKind() != CallEventKind::CE_Function) + return false; + const auto *D = Call.getDecl(); + if (!D) + return false; + const auto *FTD = llvm::dyn_cast<FunctionDecl>(D); + if (!FTD) + return false; + if (FTD->getDeclName().isIdentifier()) { + StringRef Name = FTD->getName(); + if (Name == "make_unique") + return true; + } + return false; +} + bool SmartPtrModeling::evalCall(const CallEvent &Call, CheckerContext &C) const { + + if (isStdMakeUniqueCall(Call)) { + handleMakeUnique(Call, C); + return true; + } + ProgramStateRef State = C.getState(); if (!smartptr::isStdSmartPtrCall(Call)) return false; @@ -272,6 +297,21 @@ return C.isDifferent(); } +void SmartPtrModeling::handleMakeUnique(const CallEvent &Call, + CheckerContext &C) const { + const auto *OriginExpr = Call.getOriginExpr(); + const auto *LocCtx = C.getLocationContext(); + auto ExprVal = C.getSValBuilder().conjureSymbolVal( + OriginExpr, LocCtx, Call.getResultType(), C.blockCount()); + ProgramStateRef State = C.getState(); + State = State->BindExpr(OriginExpr, LocCtx, ExprVal); + + // With make unique it is not possible to make a null smart pointer. + // So we can set the SVal for Call.getOriginExpr() to be non-null + State = State->assume(ExprVal, true); + C.addTransition(State); +} + void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const { ProgramStateRef State = C.getState();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits