diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/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(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();