33#include "llvm/ADT/STLExtras.h" 
   34#include "llvm/Support/ErrorHandling.h" 
   43    : 
public Checker<eval::Call, check::DeadSymbols, check::RegionChanges,
 
   46  bool isBoolConversionMethod(
const CallEvent &
Call) 
const;
 
   50  bool ModelSmartPtrDereference = 
false;
 
   51  bool evalCall(
const CallEvent &
Call, CheckerContext &
C) 
const;
 
   52  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &
C) 
const;
 
   56                     ArrayRef<const MemRegion *> ExplicitRegions,
 
   57                     ArrayRef<const MemRegion *> Regions,
 
   58                     const LocationContext *LCtx, 
const CallEvent *
Call) 
const;
 
   59  void printState(raw_ostream &Out, 
ProgramStateRef State, 
const char *NL,
 
   60                  const char *Sep) 
const override;
 
   64  void handleReset(
const CallEvent &
Call, CheckerContext &
C) 
const;
 
   65  void handleRelease(
const CallEvent &
Call, CheckerContext &
C) 
const;
 
   66  void handleSwapMethod(
const CallEvent &
Call, CheckerContext &
C) 
const;
 
   67  void handleGet(
const CallEvent &
Call, CheckerContext &
C) 
const;
 
   68  bool handleAssignOp(
const CallEvent &
Call, CheckerContext &
C) 
const;
 
   69  bool handleMoveCtr(
const CallEvent &
Call, CheckerContext &
C,
 
   70                     const MemRegion *ThisRegion) 
const;
 
   71  bool updateMovedSmartPointers(CheckerContext &
C, 
const MemRegion *ThisRegion,
 
   72                                const MemRegion *OtherSmartPtrRegion,
 
   73                                const CallEvent &
Call) 
const;
 
   74  void handleBoolConversion(
const CallEvent &
Call, CheckerContext &
C) 
const;
 
   75  bool handleComparisionOp(
const CallEvent &
Call, CheckerContext &
C) 
const;
 
   76  bool handleOstreamOperator(
const CallEvent &
Call, CheckerContext &
C) 
const;
 
   78                  CheckerContext &
C) 
const;
 
   79  std::pair<SVal, ProgramStateRef> retrieveOrConjureInnerPtrVal(
 
   83  using SmartPtrMethodHandlerFn =
 
   84      void (SmartPtrModeling::*)(
const CallEvent &
Call, CheckerContext &) 
const;
 
   85  CallDescriptionMap<SmartPtrMethodHandlerFn> SmartPtrMethodHandlers{
 
   86      {{CDM::CXXMethod, {
"reset"}}, &SmartPtrModeling::handleReset},
 
   87      {{CDM::CXXMethod, {
"release"}}, &SmartPtrModeling::handleRelease},
 
   88      {{CDM::CXXMethod, {
"swap"}, 1}, &SmartPtrModeling::handleSwapMethod},
 
   89      {{CDM::CXXMethod, {
"get"}}, &SmartPtrModeling::handleGet}};
 
   90  const CallDescription StdSwapCall{CDM::SimpleFunc, {
"std", 
"swap"}, 2};
 
   91  const CallDescriptionSet MakeUniqueVariants{
 
   92      {CDM::SimpleFunc, {
"std", 
"make_unique"}},
 
   93      {CDM::SimpleFunc, {
"std", 
"make_unique_for_overwrite"}}};
 
  102  if (!RD || !RD->getDeclContext()->isStdNamespace())
 
  104  if (RD->getDeclName().isIdentifier())
 
  105    return llvm::is_contained(Names, RD->getName());
 
 
  125  const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(
Call.getDecl());
 
  126  if (!MethodDecl || !MethodDecl->getParent())
 
 
  136    StringRef Name = RD->
getName();
 
  137    return Name == 
"shared_ptr" || Name == 
"unique_ptr" || Name == 
"weak_ptr";
 
 
  147  const auto *InnerPointVal = State->get<TrackedRegionMap>(ThisRegion);
 
  148  return InnerPointVal &&
 
 
  156static TrackedRegionMapTy
 
  158                        TrackedRegionMapTy::Factory &RegionMapFactory,
 
  162  for (
const auto &E : RegionMap) {
 
  163    if (E.first->isSubRegionOf(Region))
 
  164      RegionMap = RegionMapFactory.remove(RegionMap, E.first);
 
 
  171                                           const SVal *RegionInnerPointerVal) {
 
  172  if (RegionInnerPointerVal) {
 
  173    State = State->set<TrackedRegionMap>(Region, *RegionInnerPointerVal);
 
  175    State = State->remove<TrackedRegionMap>(Region);
 
 
  184  const auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(RD);
 
  188  auto TemplateArgs = TSD->getTemplateArgs().asArray();
 
  189  if (TemplateArgs.empty())
 
  191  auto InnerValueType = TemplateArgs[0].getAsType();
 
  192  return C.getASTContext().getPointerType(InnerValueType.getCanonicalType());
 
 
  200  const auto *FD = dyn_cast_or_null<FunctionDecl>(
Call.getDecl());
 
  201  if (!FD || !FD->getPrimaryTemplate())
 
  203  const auto &TemplateArgs = FD->getTemplateSpecializationArgs()->asArray();
 
  204  if (TemplateArgs.size() == 0)
 
  206  auto ValueType = TemplateArgs[0].getAsType();
 
  207  return C.getASTContext().getPointerType(ValueType.getCanonicalType());
 
 
  213  const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(
Call.getDecl());
 
  214  if (!MethodDecl || !MethodDecl->getParent())
 
 
  230bool SmartPtrModeling::isBoolConversionMethod(
const CallEvent &
Call)
 const {
 
  235  const auto *CD = dyn_cast_or_null<CXXConversionDecl>(
Call.getDecl());
 
  236  return CD && CD->getConversionType()->isBooleanType();
 
  247  return Call.getDecl() && 
Call.getDecl()->getDeclContext()->isStdNamespace();
 
 
  253  const auto *FC = dyn_cast<SimpleFunctionCall>(&
Call);
 
  260  if (OOK != clang::OO_LessLess)
 
 
  273bool SmartPtrModeling::evalCall(
const CallEvent &
Call,
 
  274                                CheckerContext &
C)
 const {
 
  281    if (handleComparisionOp(
Call, 
C))
 
  285    return handleOstreamOperator(
Call, 
C);
 
  289    assert(
Call.getNumArgs() == 2 && 
"std::swap should have two arguments");
 
  290    const Expr *FirstArg = 
Call.getArgExpr(0);
 
  293    return handleSwap(State, 
Call.getArgSVal(0), 
Call.getArgSVal(1), 
C);
 
  297    if (!ModelSmartPtrDereference)
 
  300    const std::optional<SVal> ThisRegionOpt =
 
  301        Call.getReturnValueUnderConstruction();
 
  305    const auto PtrVal = 
C.getSValBuilder().getConjuredHeapSymbolVal(
 
  306        Call.getCFGElementRef(), 
C.getLocationContext(),
 
  309    const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion();
 
  310    State = State->set<TrackedRegionMap>(ThisRegion, PtrVal);
 
  311    State = State->assume(PtrVal, 
true);
 
  329    auto &Engine = State->getStateManager().getOwningEngine();
 
  330    State = Engine.updateObjectsUnderConstruction(
 
  331        *ThisRegionOpt, 
nullptr, State, 
C.getLocationContext(),
 
  332        Call.getConstructionContext(), {});
 
  336    C.addTransition(State);
 
  343  if (isBoolConversionMethod(
Call)) {
 
  344    const MemRegion *ThisR =
 
  347    if (ModelSmartPtrDereference) {
 
  352      handleBoolConversion(
Call, 
C);
 
  362      C.addTransition(State->BindExpr(
 
  363          Call.getOriginExpr(), 
C.getLocationContext(),
 
  364          C.getSValBuilder().makeZeroVal(
Call.getResultType())));
 
  370  if (!ModelSmartPtrDereference)
 
  373  if (
const auto *CC = dyn_cast<CXXConstructorCall>(&
Call)) {
 
  374    if (CC->getDecl()->isCopyConstructor())
 
  377    const MemRegion *ThisRegion = CC->getCXXThisVal().getAsRegion();
 
  383    if (CC->getDecl()->isMoveConstructor())
 
  384      return handleMoveCtr(
Call, 
C, ThisRegion);
 
  386    if (
Call.getNumArgs() == 0) {
 
  387      auto NullVal = 
C.getSValBuilder().makeNullWithType(ThisType);
 
  388      State = State->set<TrackedRegionMap>(ThisRegion, NullVal);
 
  391          State, 
C.getNoteTag([ThisRegion](PathSensitiveBugReport &BR,
 
  392                                           llvm::raw_ostream &
OS) {
 
  393            if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
 
  394                !BR.isInteresting(ThisRegion))
 
  396            OS << 
"Default constructed smart pointer";
 
  397            checkAndPrettyPrintRegion(OS, ThisRegion);
 
  401      const auto *TrackingExpr = 
Call.getArgExpr(0);
 
  402      assert(TrackingExpr->getType()->isPointerType() &&
 
  403             "Adding a non pointer value to TrackedRegionMap");
 
  404      auto ArgVal = 
Call.getArgSVal(0);
 
  405      State = State->set<TrackedRegionMap>(ThisRegion, ArgVal);
 
  407      C.addTransition(State, 
C.getNoteTag([ThisRegion, TrackingExpr,
 
  408                                           ArgVal](PathSensitiveBugReport &BR,
 
  409                                                   llvm::raw_ostream &
OS) {
 
  410        if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
 
  411            !BR.isInteresting(ThisRegion))
 
  413        bugreporter::trackExpressionValue(BR.getErrorNode(), TrackingExpr, BR);
 
  414        OS << 
"Smart pointer";
 
  415        checkAndPrettyPrintRegion(OS, ThisRegion);
 
  416        if (ArgVal.isZeroConstant())
 
  417          OS << 
" is constructed using a null value";
 
  419          OS << 
" is constructed";
 
  425  if (handleAssignOp(
Call, 
C))
 
  428  const SmartPtrMethodHandlerFn *Handler = SmartPtrMethodHandlers.lookup(
Call);
 
  431  (this->**Handler)(
Call, 
C);
 
  433  return C.isDifferent();
 
  436std::pair<SVal, ProgramStateRef> SmartPtrModeling::retrieveOrConjureInnerPtrVal(
 
  438    QualType 
Type, CheckerContext &
C)
 const {
 
  439  const auto *Ptr = State->get<TrackedRegionMap>(ThisRegion);
 
  441    return {*Ptr, State};
 
  442  auto Val = 
C.getSValBuilder().conjureSymbolVal(Elem, 
C.getLocationContext(),
 
  443                                                 Type, 
C.blockCount());
 
  444  State = State->set<TrackedRegionMap>(ThisRegion, Val);
 
  448bool SmartPtrModeling::handleComparisionOp(
const CallEvent &
Call,
 
  449                                           CheckerContext &
C)
 const {
 
  450  const auto *FC = dyn_cast<SimpleFunctionCall>(&
Call);
 
  453  const FunctionDecl *FD = FC->getDecl();
 
  457  if (!(OOK == OO_EqualEqual || OOK == OO_ExclaimEqual || OOK == OO_Less ||
 
  458        OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual ||
 
  459        OOK == OO_Spaceship))
 
  470                                SVal S) -> std::pair<SVal, ProgramStateRef> {
 
  471    if (S.isZeroConstant()) {
 
  474    const MemRegion *Reg = S.getAsRegion();
 
  476           "this pointer of std::unique_ptr should be obtainable as MemRegion");
 
  478    return retrieveOrConjureInnerPtrVal(State, Reg, Elem, 
Type, 
C);
 
  482  SVal Second = 
Call.getArgSVal(1);
 
  483  const auto *FirstExpr = 
Call.getArgExpr(0);
 
  484  const auto *SecondExpr = 
Call.getArgExpr(1);
 
  486  const auto *ResultExpr = 
Call.getOriginExpr();
 
  487  const auto *LCtx = 
C.getLocationContext();
 
  488  auto &Bldr = 
C.getSValBuilder();
 
  491  SVal FirstPtrVal, SecondPtrVal;
 
  492  std::tie(FirstPtrVal, State) =
 
  493      makeSValFor(State, FirstExpr, 
Call.getCFGElementRef(), 
First);
 
  494  std::tie(SecondPtrVal, State) =
 
  495      makeSValFor(State, SecondExpr, 
Call.getCFGElementRef(), Second);
 
  498  auto RetVal = Bldr.evalBinOp(State, BOK, FirstPtrVal, SecondPtrVal,
 
  499                               Call.getResultType());
 
  501  if (OOK != OO_Spaceship) {
 
  503    std::tie(TrueState, FalseState) =
 
  504        State->assume(*RetVal.getAs<DefinedOrUnknownSVal>());
 
  507          TrueState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(
true)));
 
  510          FalseState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(
false)));
 
  512    C.addTransition(State->BindExpr(ResultExpr, LCtx, RetVal));
 
  517bool SmartPtrModeling::handleOstreamOperator(
const CallEvent &
Call,
 
  518                                             CheckerContext &
C)
 const {
 
  528  const auto StreamVal = 
Call.getArgSVal(0);
 
  529  const MemRegion *StreamThisRegion = StreamVal.getAsRegion();
 
  530  if (!StreamThisRegion)
 
  533      State->invalidateRegions({StreamThisRegion}, 
Call.getCFGElementRef(),
 
  534                               C.blockCount(), 
C.getLocationContext(), 
false);
 
  536      State->BindExpr(
Call.getOriginExpr(), 
C.getLocationContext(), StreamVal);
 
  537  C.addTransition(State);
 
  541void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper,
 
  542                                        CheckerContext &
C)
 const {
 
  545  TrackedRegionMapTy TrackedRegions = State->get<TrackedRegionMap>();
 
  546  for (
auto E : TrackedRegions) {
 
  547    const MemRegion *Region = E.first;
 
  551      State = State->remove<TrackedRegionMap>(Region);
 
  553  C.addTransition(State);
 
  556void SmartPtrModeling::printState(raw_ostream &Out, 
ProgramStateRef State,
 
  557                                  const char *NL, 
const char *Sep)
 const {
 
  558  TrackedRegionMapTy RS = State->get<TrackedRegionMap>();
 
  561    Out << Sep << 
"Smart ptr regions :" << NL;
 
  563      I.first->dumpToStream(Out);
 
  575    ArrayRef<const MemRegion *> ExplicitRegions,
 
  576    ArrayRef<const MemRegion *> Regions, 
const LocationContext *LCtx,
 
  577    const CallEvent *
Call)
 const {
 
  578  TrackedRegionMapTy RegionMap = State->get<TrackedRegionMap>();
 
  579  TrackedRegionMapTy::Factory &RegionMapFactory =
 
  580      State->get_context<TrackedRegionMap>();
 
  581  for (
const auto *Region : Regions)
 
  584  return State->set<TrackedRegionMap>(RegionMap);
 
  588                                        SymbolReaper &SR)
 const {
 
  590  TrackedRegionMapTy TrackedRegions = State->get<TrackedRegionMap>();
 
  591  for (SVal Val : llvm::make_second_range(TrackedRegions)) {
 
  598void SmartPtrModeling::handleReset(
const CallEvent &
Call,
 
  599                                   CheckerContext &
C)
 const {
 
  601  const auto *IC = dyn_cast<CXXInstanceCall>(&
Call);
 
  605  const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
 
  609  assert(
Call.getArgExpr(0)->getType()->isPointerType() &&
 
  610         "Adding a non pointer value to TrackedRegionMap");
 
  611  State = State->set<TrackedRegionMap>(ThisRegion, 
Call.getArgSVal(0));
 
  612  const auto *TrackingExpr = 
Call.getArgExpr(0);
 
  614      State, 
C.getNoteTag([ThisRegion, TrackingExpr](PathSensitiveBugReport &BR,
 
  615                                                     llvm::raw_ostream &
OS) {
 
  616        if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
 
  617            !BR.isInteresting(ThisRegion))
 
  619        bugreporter::trackExpressionValue(BR.getErrorNode(), TrackingExpr, BR);
 
  620        OS << 
"Smart pointer";
 
  621        checkAndPrettyPrintRegion(OS, ThisRegion);
 
  622        OS << 
" reset using a null value";
 
  628void SmartPtrModeling::handleRelease(
const CallEvent &
Call,
 
  629                                     CheckerContext &
C)
 const {
 
  631  const auto *IC = dyn_cast<CXXInstanceCall>(&
Call);
 
  635  const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
 
  639  const auto *InnerPointVal = State->get<TrackedRegionMap>(ThisRegion);
 
  642    State = State->BindExpr(
Call.getOriginExpr(), 
C.getLocationContext(),
 
  647  auto ValueToUpdate = 
C.getSValBuilder().makeNullWithType(ThisType);
 
  648  State = State->set<TrackedRegionMap>(ThisRegion, ValueToUpdate);
 
  650  C.addTransition(State, 
C.getNoteTag([ThisRegion](PathSensitiveBugReport &BR,
 
  651                                                   llvm::raw_ostream &
OS) {
 
  652    if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
 
  653        !BR.isInteresting(ThisRegion))
 
  656    OS << 
"Smart pointer";
 
  657    checkAndPrettyPrintRegion(OS, ThisRegion);
 
  658    OS << 
" is released and set to null";
 
  664void SmartPtrModeling::handleSwapMethod(
const CallEvent &
Call,
 
  665                                        CheckerContext &
C)
 const {
 
  667  const auto *IC = dyn_cast<CXXInstanceCall>(&
Call);
 
  671  auto State = 
C.getState();
 
  672  handleSwap(State, IC->getCXXThisVal(), 
Call.getArgSVal(0), 
C);
 
  676                                  SVal Second, CheckerContext &
C)
 const {
 
  677  const MemRegion *FirstThisRegion = 
First.getAsRegion();
 
  678  if (!FirstThisRegion)
 
  680  const MemRegion *SecondThisRegion = Second.
getAsRegion();
 
  681  if (!SecondThisRegion)
 
  684  const auto *FirstInnerPtrVal = State->get<TrackedRegionMap>(FirstThisRegion);
 
  685  const auto *SecondInnerPtrVal =
 
  686      State->get<TrackedRegionMap>(SecondThisRegion);
 
  691  C.addTransition(State, 
C.getNoteTag([FirstThisRegion, SecondThisRegion](
 
  692                                          PathSensitiveBugReport &BR,
 
  693                                          llvm::raw_ostream &
OS) {
 
  694    if (&BR.getBugType() != smartptr::getNullDereferenceBugType())
 
  696    if (BR.isInteresting(FirstThisRegion) &&
 
  697        !BR.isInteresting(SecondThisRegion)) {
 
  698      BR.markInteresting(SecondThisRegion);
 
  699      BR.markNotInteresting(FirstThisRegion);
 
  703      BR.markInteresting(FirstThisRegion);
 
  704      BR.markNotInteresting(SecondThisRegion);
 
  712void SmartPtrModeling::handleGet(
const CallEvent &
Call,
 
  713                                 CheckerContext &
C)
 const {
 
  715  const auto *IC = dyn_cast<CXXInstanceCall>(&
Call);
 
  719  const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
 
  723  SVal InnerPointerVal;
 
  724  std::tie(InnerPointerVal, State) = retrieveOrConjureInnerPtrVal(
 
  725      State, ThisRegion, 
Call.getCFGElementRef(), 
Call.getResultType(), 
C);
 
  726  State = State->BindExpr(
Call.getOriginExpr(), 
C.getLocationContext(),
 
  729  C.addTransition(State);
 
  732bool SmartPtrModeling::handleAssignOp(
const CallEvent &
Call,
 
  733                                      CheckerContext &
C)
 const {
 
  735  const auto *OC = dyn_cast<CXXMemberOperatorCall>(&
Call);
 
  741  const MemRegion *ThisRegion = OC->getCXXThisVal().getAsRegion();
 
  747  const MemRegion *OtherSmartPtrRegion = OC->getArgSVal(0).getAsRegion();
 
  749  if (!OtherSmartPtrRegion) {
 
  750    bool AssignedNull = 
Call.getArgSVal(0).isZeroConstant();
 
  753    auto NullVal = 
C.getSValBuilder().makeNullWithType(ThisType);
 
  754    State = State->set<TrackedRegionMap>(ThisRegion, NullVal);
 
  755    C.addTransition(State, 
C.getNoteTag([ThisRegion](PathSensitiveBugReport &BR,
 
  756                                                     llvm::raw_ostream &
OS) {
 
  757      if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
 
  758          !BR.isInteresting(ThisRegion))
 
  760      OS << 
"Smart pointer";
 
  761      checkAndPrettyPrintRegion(OS, ThisRegion);
 
  762      OS << 
" is assigned to null";
 
  767  return updateMovedSmartPointers(
C, ThisRegion, OtherSmartPtrRegion, 
Call);
 
  770bool SmartPtrModeling::handleMoveCtr(
const CallEvent &
Call, CheckerContext &
C,
 
  771                                     const MemRegion *ThisRegion)
 const {
 
  772  const auto *OtherSmartPtrRegion = 
Call.getArgSVal(0).getAsRegion();
 
  773  if (!OtherSmartPtrRegion)
 
  776  return updateMovedSmartPointers(
C, ThisRegion, OtherSmartPtrRegion, 
Call);
 
  779bool SmartPtrModeling::updateMovedSmartPointers(
 
  780    CheckerContext &
C, 
const MemRegion *ThisRegion,
 
  781    const MemRegion *OtherSmartPtrRegion, 
const CallEvent &
Call)
 const {
 
  784  const auto *OtherInnerPtr = State->get<TrackedRegionMap>(OtherSmartPtrRegion);
 
  786    State = State->set<TrackedRegionMap>(ThisRegion, *OtherInnerPtr);
 
  788    auto NullVal = 
C.getSValBuilder().makeNullWithType(ThisType);
 
  789    State = State->set<TrackedRegionMap>(OtherSmartPtrRegion, NullVal);
 
  790    bool IsArgValNull = OtherInnerPtr->isZeroConstant();
 
  794        C.getNoteTag([ThisRegion, OtherSmartPtrRegion, IsArgValNull](
 
  795                         PathSensitiveBugReport &BR, llvm::raw_ostream &
OS) {
 
  796          if (&BR.getBugType() != smartptr::getNullDereferenceBugType())
 
  798          if (BR.isInteresting(OtherSmartPtrRegion)) {
 
  799            OS << 
"Smart pointer";
 
  800            checkAndPrettyPrintRegion(OS, OtherSmartPtrRegion);
 
  801            OS << 
" is null after being moved to";
 
  802            checkAndPrettyPrintRegion(OS, ThisRegion);
 
  805            OS << 
"A null pointer value is moved to";
 
  806            checkAndPrettyPrintRegion(OS, ThisRegion);
 
  807            BR.markInteresting(OtherSmartPtrRegion);
 
  815    auto NullVal = 
C.getSValBuilder().makeNullWithType(ThisType);
 
  816    State = State->remove<TrackedRegionMap>(ThisRegion);
 
  817    State = State->set<TrackedRegionMap>(OtherSmartPtrRegion, NullVal);
 
  818    C.addTransition(State, 
C.getNoteTag([OtherSmartPtrRegion,
 
  819                                         ThisRegion](PathSensitiveBugReport &BR,
 
  820                                                     llvm::raw_ostream &
OS) {
 
  821      if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
 
  822          !BR.isInteresting(OtherSmartPtrRegion))
 
  824      OS << 
"Smart pointer";
 
  825      checkAndPrettyPrintRegion(OS, OtherSmartPtrRegion);
 
  826      OS << 
" is null after; previous value moved to";
 
  827      checkAndPrettyPrintRegion(OS, ThisRegion);
 
  834void SmartPtrModeling::handleBoolConversion(
const CallEvent &
Call,
 
  835                                            CheckerContext &
C)
 const {
 
  838  const Expr *CallExpr = 
Call.getOriginExpr();
 
  839  const MemRegion *ThisRegion =
 
  844  SVal InnerPointerVal;
 
  845  if (
const auto *InnerValPtr = State->get<TrackedRegionMap>(ThisRegion)) {
 
  846    InnerPointerVal = *InnerValPtr;
 
  851    if (InnerPointerType.isNull())
 
  854    InnerPointerVal = 
C.getSValBuilder().conjureSymbolVal(
 
  855        Call, InnerPointerType, 
C.blockCount());
 
  856    State = State->set<TrackedRegionMap>(ThisRegion, InnerPointerVal);
 
  859  if (State->isNull(InnerPointerVal).isConstrainedTrue()) {
 
  860    State = State->BindExpr(CallExpr, 
C.getLocationContext(),
 
  861                            C.getSValBuilder().makeTruthVal(
false));
 
  863    C.addTransition(State);
 
  865  } 
else if (State->isNonNull(InnerPointerVal).isConstrainedTrue()) {
 
  866    State = State->BindExpr(CallExpr, 
C.getLocationContext(),
 
  867                            C.getSValBuilder().makeTruthVal(
true));
 
  869    C.addTransition(State);
 
  873        State->BindExpr(CallExpr, 
C.getLocationContext(),
 
  874                        C.getSValBuilder().makeZeroVal(
Call.getResultType())));
 
  878    std::tie(NotNullState, NullState) =
 
  879        State->assume(InnerPointerVal.
castAs<DefinedOrUnknownSVal>());
 
  881    auto NullVal = 
C.getSValBuilder().makeNullWithType(ThisType);
 
  883    NullState = NullState->set<TrackedRegionMap>(ThisRegion, NullVal);
 
  885    NullState = NullState->BindExpr(CallExpr, 
C.getLocationContext(),
 
  886                                    C.getSValBuilder().makeTruthVal(
false));
 
  887    C.addTransition(NullState, 
C.getNoteTag(
 
  888                                   [ThisRegion](PathSensitiveBugReport &BR,
 
  889                                                llvm::raw_ostream &
OS) {
 
  890                                     OS << 
"Assuming smart pointer";
 
  891                                     checkAndPrettyPrintRegion(OS, ThisRegion);
 
  896        NotNullState->BindExpr(CallExpr, 
C.getLocationContext(),
 
  897                               C.getSValBuilder().makeTruthVal(
true));
 
  901            [ThisRegion](PathSensitiveBugReport &BR, llvm::raw_ostream &
OS) {
 
  902              OS << 
"Assuming smart pointer";
 
  903              checkAndPrettyPrintRegion(OS, ThisRegion);
 
  904              OS << 
" is non-null";
 
  911void ento::registerSmartPtrModeling(CheckerManager &Mgr) {
 
  913  Checker->ModelSmartPtrDereference =
 
  915          Checker, 
"ModelSmartPtrDereference");
 
  918bool ento::shouldRegisterSmartPtrModeling(
const CheckerManager &mgr) {
 
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
 
Defines the clang::Expr interface and subclasses for C++ expressions.
 
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
 
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
 
static bool isStdFunctionCall(const CallEvent &Call)
 
static bool isStdBasicOstream(const Expr *E)
 
static void checkAndPrettyPrintRegion(llvm::raw_ostream &OS, const MemRegion *Region)
 
static QualType getInnerPointerType(CheckerContext C, const CXXRecordDecl *RD)
 
static ProgramStateRef updateSwappedRegion(ProgramStateRef State, const MemRegion *Region, const SVal *RegionInnerPointerVal)
 
static bool isStdOstreamOperatorCall(const CallEvent &Call)
 
static TrackedRegionMapTy removeTrackedSubregions(TrackedRegionMapTy RegionMap, TrackedRegionMapTy::Factory &RegionMapFactory, const MemRegion *Region)
 
static bool isPotentiallyComparisionOpCall(const CallEvent &Call)
 
static QualType getPointerTypeFromTemplateArg(const CallEvent &Call, CheckerContext &C)
 
static bool hasStdClassWithName(const CXXRecordDecl *RD, ArrayRef< llvm::StringLiteral > Names)
 
static bool isStdSmartPtr(const CXXRecordDecl *RD)
 
constexpr llvm::StringLiteral BASIC_OSTREAM_NAMES[]
 
constexpr llvm::StringLiteral STD_PTR_NAMES[]
 
C Language Family Type Representation.
 
Represents a C++ struct/union/class.
 
DeclContext * getParent()
getParent - Returns the containing DeclContext.
 
bool isStdNamespace() const
 
bool isInStdNamespace() const
 
DeclContext * getDeclContext()
 
bool isIdentifier() const
Predicate functions for querying what type of name this is.
 
This represents one expression.
 
Represents a function declaration or definition.
 
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
 
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
 
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
 
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
 
A (possibly-)qualified type.
 
Represents a struct/union/class.
 
StringLiteral - This represents a string literal expression, e.g.
 
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
 
bool contains(const CallEvent &Call) const
 
bool matches(const CallEvent &Call) const
Returns true if the CallEvent is a call to a function that matches the CallDescription.
 
Represents an abstract call to a function or method along a particular path.
 
const AnalyzerOptions & getAnalyzerOptions() const
 
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
 
const LangOptions & getLangOpts() const
 
Simple checker classes that implement one frontend (i.e.
 
MemRegion - The root abstract class for all memory regions.
 
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
 
virtual void printPretty(raw_ostream &os) const
Print the region for use in diagnostics.
 
virtual bool canPrintPretty() const
Returns true if this region can be printed in a user-friendly way.
 
BinaryOperatorKind GetBinaryOpUnsafe() const
 
bool isInteresting(SymbolRef sym) const
 
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
 
const MemRegion * getAsRegion() const
 
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
 
llvm::iterator_range< symbol_iterator > symbols() const
 
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
 
bool isLiveRegion(const MemRegion *region)
 
bool isMovedFrom(ProgramStateRef State, const MemRegion *Region)
Returns true if the object is known to have been recently std::moved.
 
bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion)
Returns whether the smart pointer is null or not.
 
bool isStdSmartPtr(const CXXRecordDecl *RD)
 
bool isStdSmartPtrCall(const CallEvent &Call)
Returns true if the event call is on smart pointer.
 
llvm::DenseSet< SymbolRef > InvalidatedSymbols
 
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
 
const SymExpr * SymbolRef
 
OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, bool IsBinary)
 
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
 
The JSON file list parser is used to communicate input to InstallAPI.
 
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
 
CFGBlock::ConstCFGElementRef ConstCFGElementRef
 
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
 
@ Type
The name was classified as a type.
 
U cast(CodeGen::Address addr)
 
Diagnostic wrappers for TextAPI types for error reporting.