clang: lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

16

34#include "llvm/ADT/STLExtras.h"

35#include "llvm/Support/ErrorHandling.h"

36#include

37#include

38

39using namespace clang;

40using namespace ento;

41

42namespace {

43

44class SmartPtrModeling

45 : public Checker<eval::Call, check::DeadSymbols, check::RegionChanges,

46 check::LiveSymbols> {

47

48 bool isBoolConversionMethod(const CallEvent &Call) const;

49

50public:

51

52 bool ModelSmartPtrDereference = false;

62 const char *Sep) const override;

64

65private:

72 const MemRegion *ThisRegion) const;

74 const MemRegion *OtherSmartPtrRegion,

81 std::pair<SVal, ProgramStateRef>

85

86 using SmartPtrMethodHandlerFn =

89 {{CDM::CXXMethod, {"reset"}}, &SmartPtrModeling::handleReset},

90 {{CDM::CXXMethod, {"release"}}, &SmartPtrModeling::handleRelease},

91 {{CDM::CXXMethod, {"swap"}, 1}, &SmartPtrModeling::handleSwapMethod},

92 {{CDM::CXXMethod, {"get"}}, &SmartPtrModeling::handleGet}};

93 const CallDescription StdSwapCall{CDM::SimpleFunc, {"std", "swap"}, 2};

95 {CDM::SimpleFunc, {"std", "make_unique"}},

96 {CDM::SimpleFunc, {"std", "make_unique_for_overwrite"}}};

97};

98}

99

101

102

105 if (!RD || !RD->getDeclContext()->isStdNamespace())

106 return false;

107 if (RD->getDeclName().isIdentifier())

108 return llvm::is_contained(Names, RD->getName());

109 return false;

110}

111

112constexpr llvm::StringLiteral STD_PTR_NAMES[] = {"shared_ptr", "unique_ptr",

113 "weak_ptr"};

114

117}

118

121}

122

123

125namespace ento {

126namespace smartptr {

128 const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());

129 if (!MethodDecl || !MethodDecl->getParent())

130 return false;

132}

133

136 return false;

137

139 StringRef Name = RD->getName();

140 return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";

141 }

142 return false;

143}

144

147}

148

150 const auto *InnerPointVal = State->get(ThisRegion);

151 return InnerPointVal &&

153}

154}

155}

156}

157

158

159static TrackedRegionMapTy

161 TrackedRegionMapTy::Factory &RegionMapFactory,

163 if (!Region)

164 return RegionMap;

165 for (const auto &E : RegionMap) {

166 if (E.first->isSubRegionOf(Region))

167 RegionMap = RegionMapFactory.remove(RegionMap, E.first);

168 }

169 return RegionMap;

170}

171

174 const SVal *RegionInnerPointerVal) {

175 if (RegionInnerPointerVal) {

176 State = State->set(Region, *RegionInnerPointerVal);

177 } else {

178 State = State->remove(Region);

179 }

180 return State;

181}

182

185 return {};

186

187 const auto *TSD = dyn_cast(RD);

188 if (!TSD)

189 return {};

190

191 auto TemplateArgs = TSD->getTemplateArgs().asArray();

192 if (TemplateArgs.empty())

193 return {};

194 auto InnerValueType = TemplateArgs[0].getAsType();

195 return C.getASTContext().getPointerType(InnerValueType.getCanonicalType());

196}

197

198

199

200

203 const auto *FD = dyn_cast_or_null(Call.getDecl());

204 if (!FD || !FD->getPrimaryTemplate())

205 return {};

206 const auto &TemplateArgs = FD->getTemplateSpecializationArgs()->asArray();

207 if (TemplateArgs.size() == 0)

208 return {};

209 auto ValueType = TemplateArgs[0].getAsType();

210 return C.getASTContext().getPointerType(ValueType.getCanonicalType());

211}

212

213

214

216 const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());

217 if (!MethodDecl || !MethodDecl->getParent())

218 return {};

219

222}

223

224

228 OS << " ";

230 }

231}

232

233bool SmartPtrModeling::isBoolConversionMethod(const CallEvent &Call) const {

234

235

236

237

238 const auto *CD = dyn_cast_or_null(Call.getDecl());

239 return CD && CD->getConversionType()->isBooleanType();

240}

241

243

247}

248

250 return Call.getDecl() && Call.getDecl()->getDeclContext()->isStdNamespace();

251}

252

255 return false;

256 const auto *FC = dyn_cast(&Call);

257 if (!FC)

258 return false;

261 return false;

263 if (OOK != clang::OO_LessLess)

264 return false;

267}

268

271 return false;

274}

275

276bool SmartPtrModeling::evalCall(const CallEvent &Call,

278

280

281

282

284 if (handleComparisionOp(Call, C))

285 return true;

286

288 return handleOstreamOperator(Call, C);

289

290 if (StdSwapCall.matches(Call)) {

291

292 assert(Call.getNumArgs() == 2 && "std::swap should have two arguments");

293 const Expr *FirstArg = Call.getArgExpr(0);

295 return false;

296 return handleSwap(State, Call.getArgSVal(0), Call.getArgSVal(1), C);

297 }

298

299 if (MakeUniqueVariants.contains(Call)) {

300 if (!ModelSmartPtrDereference)

301 return false;

302

303 const std::optional ThisRegionOpt =

304 Call.getReturnValueUnderConstruction();

305 if (!ThisRegionOpt)

306 return false;

307

308 const auto PtrVal = C.getSValBuilder().getConjuredHeapSymbolVal(

309 Call.getOriginExpr(), C.getLocationContext(),

311

312 const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion();

313 State = State->set(ThisRegion, PtrVal);

314 State = State->assume(PtrVal, true);

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332 auto &Engine = State->getStateManager().getOwningEngine();

333 State = Engine.updateObjectsUnderConstruction(

334 *ThisRegionOpt, nullptr, State, C.getLocationContext(),

335 Call.getConstructionContext(), {});

336

337

338

339 C.addTransition(State);

340 return true;

341 }

342

344 return false;

345

346 if (isBoolConversionMethod(Call)) {

348 cast(&Call)->getCXXThisVal().getAsRegion();

349

350 if (ModelSmartPtrDereference) {

351

352

353

354

355 handleBoolConversion(Call, C);

356 return true;

357 } else {

359

360

361 return false;

362 }

363

364

365 C.addTransition(State->BindExpr(

366 Call.getOriginExpr(), C.getLocationContext(),

367 C.getSValBuilder().makeZeroVal(Call.getResultType())));

368

369 return true;

370 }

371 }

372

373 if (!ModelSmartPtrDereference)

374 return false;

375

376 if (const auto *CC = dyn_cast(&Call)) {

377 if (CC->getDecl()->isCopyConstructor())

378 return false;

379

380 const MemRegion *ThisRegion = CC->getCXXThisVal().getAsRegion();

381 if (!ThisRegion)

382 return false;

383

384 QualType ThisType = cast(Call.getDecl())->getThisType();

385

386 if (CC->getDecl()->isMoveConstructor())

387 return handleMoveCtr(Call, C, ThisRegion);

388

389 if (Call.getNumArgs() == 0) {

390 auto NullVal = C.getSValBuilder().makeNullWithType(ThisType);

391 State = State->set(ThisRegion, NullVal);

392

393 C.addTransition(

395 llvm::raw_ostream &OS) {

396 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||

397 !BR.isInteresting(ThisRegion))

398 return;

399 OS << "Default constructed smart pointer";

400 checkAndPrettyPrintRegion(OS, ThisRegion);

401 OS << " is null";

402 }));

403 } else {

404 const auto *TrackingExpr = Call.getArgExpr(0);

405 assert(TrackingExpr->getType()->isPointerType() &&

406 "Adding a non pointer value to TrackedRegionMap");

407 auto ArgVal = Call.getArgSVal(0);

408 State = State->set(ThisRegion, ArgVal);

409

410 C.addTransition(State, C.getNoteTag([ThisRegion, TrackingExpr,

412 llvm::raw_ostream &OS) {

413 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||

414 !BR.isInteresting(ThisRegion))

415 return;

416 bugreporter::trackExpressionValue(BR.getErrorNode(), TrackingExpr, BR);

417 OS << "Smart pointer";

418 checkAndPrettyPrintRegion(OS, ThisRegion);

419 if (ArgVal.isZeroConstant())

420 OS << " is constructed using a null value";

421 else

422 OS << " is constructed";

423 }));

424 }

425 return true;

426 }

427

428 if (handleAssignOp(Call, C))

429 return true;

430

431 const SmartPtrMethodHandlerFn *Handler = SmartPtrMethodHandlers.lookup(Call);

432 if (!Handler)

433 return false;

434 (this->**Handler)(Call, C);

435

436 return C.isDifferent();

437}

438

439std::pair<SVal, ProgramStateRef> SmartPtrModeling::retrieveOrConjureInnerPtrVal(

442 const auto *Ptr = State->get(ThisRegion);

443 if (Ptr)

444 return {*Ptr, State};

445 auto Val = C.getSValBuilder().conjureSymbolVal(E, C.getLocationContext(),

446 Type, C.blockCount());

447 State = State->set(ThisRegion, Val);

448 return {Val, State};

449}

450

451bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,

453 const auto *FC = dyn_cast(&Call);

454 if (!FC)

455 return false;

458 return false;

460 if (!(OOK == OO_EqualEqual || OOK == OO_ExclaimEqual || OOK == OO_Less ||

461 OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual ||

462 OOK == OO_Spaceship))

463 return false;

464

465

466

467

468

469

470

472 SVal S) -> std::pair<SVal, ProgramStateRef> {

473 if (S.isZeroConstant()) {

474 return {S, State};

475 }

476 const MemRegion *Reg = S.getAsRegion();

477 assert(Reg &&

478 "this pointer of std::unique_ptr should be obtainable as MemRegion");

480 return retrieveOrConjureInnerPtrVal(State, Reg, E, Type, C);

481 };

482

484 SVal Second = Call.getArgSVal(1);

485 const auto *FirstExpr = Call.getArgExpr(0);

486 const auto *SecondExpr = Call.getArgExpr(1);

487

488 const auto *ResultExpr = Call.getOriginExpr();

489 const auto *LCtx = C.getLocationContext();

490 auto &Bldr = C.getSValBuilder();

492

493 SVal FirstPtrVal, SecondPtrVal;

494 std::tie(FirstPtrVal, State) = makeSValFor(State, FirstExpr, First);

495 std::tie(SecondPtrVal, State) = makeSValFor(State, SecondExpr, Second);

498 auto RetVal = Bldr.evalBinOp(State, BOK, FirstPtrVal, SecondPtrVal,

499 Call.getResultType());

500

501 if (OOK != OO_Spaceship) {

503 std::tie(TrueState, FalseState) =

505 if (TrueState)

506 C.addTransition(

507 TrueState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(true)));

508 if (FalseState)

509 C.addTransition(

510 FalseState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(false)));

511 } else {

512 C.addTransition(State->BindExpr(ResultExpr, LCtx, RetVal));

513 }

514 return true;

515}

516

517bool SmartPtrModeling::handleOstreamOperator(const CallEvent &Call,

519

520

521

522

523

524

525

526

528 const auto StreamVal = Call.getArgSVal(0);

529 const MemRegion *StreamThisRegion = StreamVal.getAsRegion();

530 if (!StreamThisRegion)

531 return false;

532 State =

533 State->invalidateRegions({StreamThisRegion}, Call.getOriginExpr(),

534 C.blockCount(), C.getLocationContext(), false);

535 State =

536 State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), StreamVal);

537 C.addTransition(State);

538 return true;

539}

540

541void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper,

544

545 TrackedRegionMapTy TrackedRegions = State->get();

546 for (auto E : TrackedRegions) {

548 bool IsRegDead = !SymReaper.isLiveRegion(Region);

549

550 if (IsRegDead)

551 State = State->remove(Region);

552 }

553 C.addTransition(State);

554}

555

556void SmartPtrModeling::printState(raw_ostream &Out, ProgramStateRef State,

557 const char *NL, const char *Sep) const {

558 TrackedRegionMapTy RS = State->get();

559

560 if (!RS.isEmpty()) {

561 Out << Sep << "Smart ptr regions :" << NL;

562 for (auto I : RS) {

563 I.first->dumpToStream(Out);

565 Out << ": Null";

566 else

567 Out << ": Non Null";

568 Out << NL;

569 }

570 }

571}

572

578 TrackedRegionMapTy RegionMap = State->get();

579 TrackedRegionMapTy::Factory &RegionMapFactory =

580 State->get_context();

581 for (const auto *Region : Regions)

584 return State->set(RegionMap);

585}

586

587void SmartPtrModeling::checkLiveSymbols(ProgramStateRef State,

589

590 TrackedRegionMapTy TrackedRegions = State->get();

591 for (SVal Val : llvm::make_second_range(TrackedRegions)) {

594 }

595 }

596}

597

598void SmartPtrModeling::handleReset(const CallEvent &Call,

601 const auto *IC = dyn_cast(&Call);

602 if (!IC)

603 return;

604

605 const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();

606 if (!ThisRegion)

607 return;

608

609 assert(Call.getArgExpr(0)->getType()->isPointerType() &&

610 "Adding a non pointer value to TrackedRegionMap");

611 State = State->set(ThisRegion, Call.getArgSVal(0));

612 const auto *TrackingExpr = Call.getArgExpr(0);

613 C.addTransition(

615 llvm::raw_ostream &OS) {

616 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||

617 !BR.isInteresting(ThisRegion))

618 return;

619 bugreporter::trackExpressionValue(BR.getErrorNode(), TrackingExpr, BR);

620 OS << "Smart pointer";

621 checkAndPrettyPrintRegion(OS, ThisRegion);

622 OS << " reset using a null value";

623 }));

624

625

626}

627

628void SmartPtrModeling::handleRelease(const CallEvent &Call,

631 const auto *IC = dyn_cast(&Call);

632 if (!IC)

633 return;

634

635 const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();

636 if (!ThisRegion)

637 return;

638

639 const auto *InnerPointVal = State->get(ThisRegion);

640

641 if (InnerPointVal) {

642 State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),

643 *InnerPointVal);

644 }

645

646 QualType ThisType = cast(Call.getDecl())->getThisType();

647 auto ValueToUpdate = C.getSValBuilder().makeNullWithType(ThisType);

648 State = State->set(ThisRegion, ValueToUpdate);

649

651 llvm::raw_ostream &OS) {

652 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||

653 !BR.isInteresting(ThisRegion))

654 return;

655

656 OS << "Smart pointer";

657 checkAndPrettyPrintRegion(OS, ThisRegion);

658 OS << " is released and set to null";

659 }));

660

661

662}

663

664void SmartPtrModeling::handleSwapMethod(const CallEvent &Call,

666

667 const auto *IC = dyn_cast(&Call);

668 if (!IC)

669 return;

670

671 auto State = C.getState();

672 handleSwap(State, IC->getCXXThisVal(), Call.getArgSVal(0), C);

673}

674

677 const MemRegion *FirstThisRegion = First.getAsRegion();

678 if (!FirstThisRegion)

679 return false;

681 if (!SecondThisRegion)

682 return false;

683

684 const auto *FirstInnerPtrVal = State->get(FirstThisRegion);

685 const auto *SecondInnerPtrVal =

686 State->get(SecondThisRegion);

687

690

691 C.addTransition(State, C.getNoteTag([FirstThisRegion, SecondThisRegion](

693 llvm::raw_ostream &OS) {

694 if (&BR.getBugType() != smartptr::getNullDereferenceBugType())

695 return;

696 if (BR.isInteresting(FirstThisRegion) &&

697 !BR.isInteresting(SecondThisRegion)) {

698 BR.markInteresting(SecondThisRegion);

699 BR.markNotInteresting(FirstThisRegion);

700 }

703 BR.markInteresting(FirstThisRegion);

704 BR.markNotInteresting(SecondThisRegion);

705 }

706

707 }));

708

709 return true;

710}

711

712void SmartPtrModeling::handleGet(const CallEvent &Call,

715 const auto *IC = dyn_cast(&Call);

716 if (!IC)

717 return;

718

719 const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();

720 if (!ThisRegion)

721 return;

722

723 SVal InnerPointerVal;

724 std::tie(InnerPointerVal, State) = retrieveOrConjureInnerPtrVal(

725 State, ThisRegion, Call.getOriginExpr(), Call.getResultType(), C);

726 State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),

727 InnerPointerVal);

728

729 C.addTransition(State);

730}

731

732bool SmartPtrModeling::handleAssignOp(const CallEvent &Call,

735 const auto *OC = dyn_cast(&Call);

736 if (!OC)

737 return false;

739 if (OOK != OO_Equal)

740 return false;

741 const MemRegion *ThisRegion = OC->getCXXThisVal().getAsRegion();

742 if (!ThisRegion)

743 return false;

744

745 QualType ThisType = cast(Call.getDecl())->getThisType();

746

747 const MemRegion *OtherSmartPtrRegion = OC->getArgSVal(0).getAsRegion();

748

749 if (!OtherSmartPtrRegion) {

750 bool AssignedNull = Call.getArgSVal(0).isZeroConstant();

751 if (!AssignedNull)

752 return false;

753 auto NullVal = C.getSValBuilder().makeNullWithType(ThisType);

754 State = State->set(ThisRegion, NullVal);

756 llvm::raw_ostream &OS) {

757 if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||

758 !BR.isInteresting(ThisRegion))

759 return;

760 OS << "Smart pointer";

761 checkAndPrettyPrintRegion(OS, ThisRegion);

762 OS << " is assigned to null";

763 }));

764 return true;

765 }

766

767 return updateMovedSmartPointers(C, ThisRegion, OtherSmartPtrRegion, Call);

768}

769

771 const MemRegion *ThisRegion) const {

772 const auto *OtherSmartPtrRegion = Call.getArgSVal(0).getAsRegion();

773 if (!OtherSmartPtrRegion)

774 return false;

775

776 return updateMovedSmartPointers(C, ThisRegion, OtherSmartPtrRegion, Call);

777}

778

779bool SmartPtrModeling::updateMovedSmartPointers(

783 QualType ThisType = cast(Call.getDecl())->getThisType();

784 const auto *OtherInnerPtr = State->get(OtherSmartPtrRegion);

785 if (OtherInnerPtr) {

786 State = State->set(ThisRegion, *OtherInnerPtr);

787

788 auto NullVal = C.getSValBuilder().makeNullWithType(ThisType);

789 State = State->set(OtherSmartPtrRegion, NullVal);

790 bool IsArgValNull = OtherInnerPtr->isZeroConstant();

791

792 C.addTransition(

793 State,

794 C.getNoteTag([ThisRegion, OtherSmartPtrRegion, IsArgValNull](

797 return;

799 OS << "Smart pointer";

801 OS << " is null after being moved to";

803 }

804 if (BR.isInteresting(ThisRegion) && IsArgValNull) {

805 OS << "A null pointer value is moved to";

808 }

809 }));

810 return true;

811 } else {

812

813

814

815 auto NullVal = C.getSValBuilder().makeNullWithType(ThisType);

816 State = State->remove(ThisRegion);

817 State = State->set(OtherSmartPtrRegion, NullVal);

818 C.addTransition(State, C.getNoteTag([OtherSmartPtrRegion,

820 llvm::raw_ostream &OS) {

823 return;

824 OS << "Smart pointer";

826 OS << " is null after; previous value moved to";

828 }));

829 return true;

830 }

831 return false;

832}

833

834void SmartPtrModeling::handleBoolConversion(const CallEvent &Call,

836

840 cast(&Call)->getCXXThisVal().getAsRegion();

841

842 QualType ThisType = cast(Call.getDecl())->getThisType();

843

844 SVal InnerPointerVal;

845 if (const auto *InnerValPtr = State->get(ThisRegion)) {

846 InnerPointerVal = *InnerValPtr;

847 } else {

848

849

851 if (InnerPointerType.isNull())

852 return;

853

855 InnerPointerVal = C.getSValBuilder().conjureSymbolVal(

856 CallExpr, LC, InnerPointerType, C.blockCount());

857 State = State->set(ThisRegion, InnerPointerVal);

858 }

859

860 if (State->isNull(InnerPointerVal).isConstrainedTrue()) {

861 State = State->BindExpr(CallExpr, C.getLocationContext(),

862 C.getSValBuilder().makeTruthVal(false));

863

864 C.addTransition(State);

865 return;

866 } else if (State->isNonNull(InnerPointerVal).isConstrainedTrue()) {

867 State = State->BindExpr(CallExpr, C.getLocationContext(),

868 C.getSValBuilder().makeTruthVal(true));

869

870 C.addTransition(State);

871 return;

873 C.addTransition(

874 State->BindExpr(CallExpr, C.getLocationContext(),

875 C.getSValBuilder().makeZeroVal(Call.getResultType())));

876 return;

877 } else {

879 std::tie(NotNullState, NullState) =

881

882 auto NullVal = C.getSValBuilder().makeNullWithType(ThisType);

883

884 NullState = NullState->set(ThisRegion, NullVal);

885

886 NullState = NullState->BindExpr(CallExpr, C.getLocationContext(),

887 C.getSValBuilder().makeTruthVal(false));

888 C.addTransition(NullState, C.getNoteTag(

890 llvm::raw_ostream &OS) {

891 OS << "Assuming smart pointer";

892 checkAndPrettyPrintRegion(OS, ThisRegion);

893 OS << " is null";

894 },

895 true));

896 NotNullState =

897 NotNullState->BindExpr(CallExpr, C.getLocationContext(),

898 C.getSValBuilder().makeTruthVal(true));

899 C.addTransition(

900 NotNullState,

901 C.getNoteTag(

903 OS << "Assuming smart pointer";

904 checkAndPrettyPrintRegion(OS, ThisRegion);

905 OS << " is non-null";

906 },

907 true));

908 return;

909 }

910}

911

912void ento::registerSmartPtrModeling(CheckerManager &Mgr) {

914 Checker->ModelSmartPtrDereference =

916 Checker, "ModelSmartPtrDereference");

917}

918

919bool ento::shouldRegisterSmartPtrModeling(const CheckerManager &mgr) {

921 return LO.CPlusPlus;

922}

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.

bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, bool SearchInParents=false) const

Interprets an option's string value as a boolean.

Represents a C++ struct/union/class.

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

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.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...

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.

The base class of the type hierarchy.

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

const BugType & getBugType() const

An immutable map from CallDescriptions to arbitrary data.

An immutable set of CallDescriptions.

A CallDescription is a pattern that can be used to match calls based on the qualified name and the ar...

Represents an abstract call to a function or method along a particular path.

virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const

See CheckerManager::runCheckersForPrintState.

const AnalyzerOptions & getAnalyzerOptions() const

CHECKER * registerChecker(AT &&... Args)

Used to register checkers.

const LangOptions & getLangOpts() const

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

void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind=bugreporter::TrackingKind::Thorough)

Marks a symbol as interesting.

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

A class responsible for cleaning up unused symbols.

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.

const BugType * getNullDereferenceBugType()

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.

OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, bool IsBinary)

llvm::DenseSet< SymbolRef > InvalidatedSymbols

The JSON file list parser is used to communicate input to InstallAPI.

OverloadedOperatorKind

Enumeration specifying the different kinds of C++ overloaded operators.

if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))

Diagnostic wrappers for TextAPI types for error reporting.