A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://clang.llvm.org/doxygen/MoveChecker_8cpp_source.html below:

clang: lib/StaticAnalyzer/Checkers/MoveChecker.cpp Source File

25#include "llvm/ADT/StringSet.h" 27using namespace clang

;

33 enum Kind

{ Moved, Reported } K;

34

RegionState(Kind InK) : K(InK) {}

37 bool

isReported()

const

{

return

K == Reported; }

38 bool

isMoved()

const

{

return

K == Moved; }

40 static

RegionState getReported() {

return

RegionState(Reported); }

41 static

RegionState getMoved() {

return

RegionState(Moved); }

43 bool operator==

(

const

RegionState &

X

)

const

{

return

K ==

X

.K; }

44 void

Profile(llvm::FoldingSetNodeID &ID)

const

{

ID

.AddInteger(K); }

50

:

public Checker

<check::PreCall, check::PostCall,

51

check::DeadSymbols, check::RegionChanges> {

63 const char

*NL,

const char

*Sep)

const override

;

66 enum

MisuseKind { MK_FunCall, MK_Copy, MK_Move, MK_Dereference };

67 enum

StdObjectKind { SK_NonStd, SK_Unsafe, SK_Safe, SK_SmartPtr };

69 enum

AggressivenessKind {

72

AK_KnownsAndLocals = 1,

77 static bool

misuseCausesCrash(MisuseKind MK) {

78 return

MK == MK_Dereference;

85

StdObjectKind StdKind;

91 const

llvm::StringSet<> StdSmartPtrClasses = {

102 const

llvm::StringSet<> StdSafeClasses = {

116 bool

shouldBeTracked(ObjectKind OK)

const

{

130 return

(Aggressiveness == AK_All) ||

131

(Aggressiveness >= AK_KnownsAndLocals && OK.IsLocal) ||

132

OK.StdKind == SK_Unsafe || OK.StdKind == SK_SmartPtr;

137 bool

shouldWarnAbout(ObjectKind OK, MisuseKind MK)

const

{

140 return

shouldBeTracked(OK) &&

141

((Aggressiveness == AK_All) ||

142

(Aggressiveness >= AK_KnownsAndLocals && OK.IsLocal) ||

143

OK.StdKind != SK_SmartPtr || MK == MK_Dereference);

152 void

explainObject(llvm::raw_ostream &OS,

const MemRegion

*MR,

155 bool

belongsTo(

const CXXRecordDecl

*RD,

const

llvm::StringSet<> &

Set

)

const

;

159

MovedBugVisitor(

const

MoveChecker &Chk,

const MemRegion

*R,

161

: Chk(Chk), Region(R), RD(RD), MK(MK),

Found

(

false

) {}

163 void

Profile(llvm::FoldingSetNodeID &ID)

const override

{

165 ID

.AddPointer(&

X

);

166 ID

.AddPointer(Region);

178 const

MoveChecker &Chk;

188

AggressivenessKind Aggressiveness = AK_KnownsAndLocals;

193

llvm::StringSwitch<AggressivenessKind>(Str)

194

.Case(

"KnownsOnly"

, AK_KnownsOnly)

195

.Case(

"KnownsAndLocals"

, AK_KnownsAndLocals)

196

.Case(

"All"

, AK_All)

197

.Default(AK_Invalid);

199 if

(Aggressiveness == AK_Invalid)

201 "either \"KnownsOnly\", \"KnownsAndLocals\" or \"All\" string value"

);

222 bool

isStateResetMethod(

const CXXMethodDecl

*MethodDec)

const

;

223 bool

isMoveSafeMethod(

const CXXMethodDecl

*MethodDec)

const

;

237 const

RegionState *RS = State->get<TrackedRegionMap>(Region);

238 return

RS && (RS->isMoved() || RS->isReported());

249 for

(

auto

&

E

: State->get<TrackedRegionMap>()) {

250 if

(

E

.first->isSubRegionOf(Region))

251

State = State->remove<TrackedRegionMap>(

E

.first);

258 for

(

auto

&

E

: State->get<TrackedRegionMap>()) {

266 if

(

const auto

*SR = dyn_cast_or_null<SymbolicRegion>(MR)) {

276

MoveChecker::MovedBugVisitor::VisitNode(

const ExplodedNode

*N,

285 const

RegionState *TrackedObject = State->get<TrackedRegionMap>(Region);

286 const

RegionState *TrackedObjectPrev =

287

StatePrev->get<TrackedRegionMap>(Region);

290 if

(TrackedObjectPrev && TrackedObject)

300

llvm::raw_svector_ostream OS(Str);

302

ObjectKind OK = Chk.classifyObject(Region, RD);

303 switch

(OK.StdKind) {

305 if

(MK == MK_Dereference) {

306

OS <<

"Smart pointer"

;

307

Chk.explainObject(OS, Region, RD, MK);

308

OS <<

" is reset to null when moved from"

;

318

Chk.explainObject(OS, Region, RD, MK);

323

Chk.explainObject(OS, Region, RD, MK);

324

OS <<

" is left in a valid but unspecified state after move"

;

331 return

std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(),

true

);

343 if

(!State->get<TrackedRegionMap>(Region))

354

assert(!

C

.isDifferent() &&

"No transitions should have been made by now"

);

355 const

RegionState *RS = State->get<TrackedRegionMap>(Region);

356

ObjectKind OK = classifyObject(Region, RD);

360 if

(MK == MK_Dereference && OK.StdKind != SK_SmartPtr)

363 if

(!RS || !shouldWarnAbout(OK, MK)

364

|| isInMoveSafeContext(

C

.getLocationContext())) {

366 C

.addTransition(State);

374 if

(misuseCausesCrash(MK)) {

375 C

.generateSink(State,

C

.getPredecessor());

377 C

.addTransition(State);

388

State = State->set<TrackedRegionMap>(Region, RegionState::getReported());

389 C

.addTransition(State, N);

395

MisuseKind MK)

const

{

396 if

(

ExplodedNode

*N = misuseCausesCrash(MK) ?

C

.generateErrorNode()

397

:

C

.generateNonFatalErrorNode()) {

400 const ExplodedNode

*MoveNode = getMoveLocation(N, Region,

C

);

408

llvm::raw_svector_ostream OS(Str);

411

OS <<

"Method called on moved-from object"

;

412

explainObject(OS, Region, RD, MK);

415

OS <<

"Moved-from object"

;

416

explainObject(OS, Region, RD, MK);

420

OS <<

"Moved-from object"

;

421

explainObject(OS, Region, RD, MK);

425

OS <<

"Dereference of null smart pointer"

;

426

explainObject(OS, Region, RD, MK);

430 auto

R = std::make_unique<PathSensitiveBugReport>(

431

BT, OS.str(), N, LocUsedForUniqueing,

433

R->addVisitor(std::make_unique<MovedBugVisitor>(*

this

, Region, RD, MK));

434 C

.emitReport(std::move(R));

442 const auto

*AFC = dyn_cast<AnyFunctionCall>(&

Call

);

447 const auto

MethodDecl = dyn_cast_or_null<CXXMethodDecl>(AFC->getDecl());

454 const auto

*ConstructorDecl = dyn_cast<CXXConstructorDecl>(MethodDecl);

455 if

(ConstructorDecl && !ConstructorDecl->isMoveConstructor())

458 if

(!ConstructorDecl && !MethodDecl->isMoveAssignmentOperator())

461 const auto

ArgRegion = AFC->getArgSVal(0).getAsRegion();

466 const auto

*CC = dyn_cast_or_null<CXXConstructorCall>(&

Call

);

467 if

(CC && CC->getCXXThisVal().getAsRegion() == ArgRegion)

470 if

(

const auto

*IC = dyn_cast<CXXInstanceCall>(AFC))

471 if

(IC->getCXXThisVal().getAsRegion() == ArgRegion)

477

AFC->getArgExpr(0)->isPRValue())

481 if

(State->get<TrackedRegionMap>(ArgRegion))

485

ObjectKind OK = classifyObject(ArgRegion, RD);

486 if

(shouldBeTracked(OK)) {

488

State = State->set<TrackedRegionMap>(ArgRegion, RegionState::getMoved());

489 C

.addTransition(State);

492

assert(!

C

.isDifferent() &&

"Should not have made transitions on this path!"

);

495bool

MoveChecker::isMoveSafeMethod(

const CXXMethodDecl

*MethodDec)

const

{

497 if

(

const auto

*ConversionDec =

498

dyn_cast_or_null<CXXConversionDecl>(MethodDec)) {

499 const Type

*Tp = ConversionDec->getConversionType().getTypePtrOrNull();

507

(MethodDec->

getName

().lower() ==

"empty"

||

508

MethodDec->

getName

().lower() ==

"isempty"

));

511bool

MoveChecker::isStateResetMethod(

const CXXMethodDecl

*MethodDec)

const

{

514 if

(MethodDec->

hasAttr

<ReinitializesAttr>())

517

std::string MethodName = MethodDec->

getName

().lower();

520 if

(MethodName ==

"assign"

|| MethodName ==

"clear"

||

521

MethodName ==

"destroy"

|| MethodName ==

"reset"

||

522

MethodName ==

"resize"

|| MethodName ==

"shrink"

)

530bool

MoveChecker::isInMoveSafeContext(

const LocationContext

*LC)

const

{

532 const auto

*CtxDec = LC->

getDecl

();

533 auto

*CtorDec = dyn_cast_or_null<CXXConstructorDecl>(CtxDec);

534 auto

*DtorDec = dyn_cast_or_null<CXXDestructorDecl>(CtxDec);

535 auto

*MethodDec = dyn_cast_or_null<CXXMethodDecl>(CtxDec);

536 if

(DtorDec || (CtorDec && CtorDec->isCopyOrMoveConstructor()) ||

539

isStateResetMethod(MethodDec) || isMoveSafeMethod(MethodDec))

546 const

llvm::StringSet<> &

Set

)

const

{

551

MoveChecker::ObjectKind

552

MoveChecker::classifyObject(

const MemRegion

*MR,

559

isa_and_nonnull<VarRegion, CXXLifetimeExtendedObjectRegion>(MR) &&

563 return

{ IsLocal, SK_NonStd };

565 if

(belongsTo(RD, StdSmartPtrClasses))

566 return

{ IsLocal, SK_SmartPtr };

568 if

(belongsTo(RD, StdSafeClasses))

569 return

{ IsLocal, SK_Safe };

571 return

{ IsLocal, SK_Unsafe };

574void

MoveChecker::explainObject(llvm::raw_ostream &OS,

const MemRegion

*MR,

580 const auto

*RegionDecl = cast<NamedDecl>(DR->getDecl());

581

OS <<

" '"

<< RegionDecl->getDeclName() <<

"'"

;

584

ObjectKind OK = classifyObject(MR, RD);

585 switch

(OK.StdKind) {

590 if

(MK != MK_Dereference)

608 if

(

const auto

*CC = dyn_cast<CXXConstructorCall>(&

Call

)) {

610 auto

CtorDec = CC->getDecl();

612 if

(CtorDec && CtorDec->isCopyOrMoveConstructor()) {

613 const MemRegion

*ArgRegion = CC->getArgSVal(0).getAsRegion();

615

MisuseKind MK = CtorDec->isMoveConstructor() ? MK_Move : MK_Copy;

616

modelUse(State, ArgRegion, RD, MK,

C

);

621 const auto

IC = dyn_cast<CXXInstanceCall>(&

Call

);

625 const MemRegion

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

630 const auto

MethodDecl = dyn_cast_or_null<CXXMethodDecl>(IC->getDecl());

635 if

(isa<CXXDestructorDecl>(MethodDecl))

642 if

(isStateResetMethod(MethodDecl)) {

644 C

.addTransition(State);

648 if

(isMoveSafeMethod(MethodDecl))

654 if

(MethodDecl->isOverloadedOperator()) {

657 if

(OOK == OO_Equal) {

662 if

(MethodDecl->isCopyAssignmentOperator() ||

663

MethodDecl->isMoveAssignmentOperator()) {

664 const MemRegion

*ArgRegion = IC->getArgSVal(0).getAsRegion();

666

MethodDecl->isMoveAssignmentOperator() ? MK_Move : MK_Copy;

667

modelUse(State, ArgRegion, RD, MK,

C

);

670 C

.addTransition(State);

674 if

(OOK == OO_Star || OOK == OO_Arrow) {

675

modelUse(State, ThisRegion, RD, MK_Dereference,

C

);

680

modelUse(State, ThisRegion, RD, MK_FunCall,

C

);

683void

MoveChecker::checkDeadSymbols(

SymbolReaper

&SymReaper,

686

TrackedRegionMapTy TrackedRegions = State->get<TrackedRegionMap>();

687 for

(

auto E

: TrackedRegions) {

693

State = State->remove<TrackedRegionMap>(Region);

696 C

.addTransition(State);

711 if

(

const auto

*IC = dyn_cast<CXXInstanceCall>(

Call

))

712

ThisRegion = IC->getCXXThisVal().getAsRegion();

717 for

(

const auto

*Region : RequestedRegions) {

718 if

(ThisRegion != Region &&

719

llvm::is_contained(InvalidatedRegions, Region))

725 for

(

const auto

*Region : InvalidatedRegions)

733 const char

*NL,

const char

*Sep)

const

{

735

TrackedRegionMapTy RS = State->get<TrackedRegionMap>();

738

Out << Sep <<

"Moved-from objects :"

<< NL;

740

I.first->dumpToStream(Out);

741 if

(I.second.isMoved())

744

Out <<

": moved and reported"

;

751

chk->setAggressiveness(

Defines the clang::Expr interface and subclasses for C++ expressions.

static bool isAnyBaseRegionReported(ProgramStateRef State, const MemRegion *Region)

static ProgramStateRef removeFromState(ProgramStateRef State, const MemRegion *Region)

static const MemRegion * unwrapRValueReferenceIndirection(const MemRegion *MR)

#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)

Declares an immutable map of type NameTy, suitable for placement into the ProgramState.

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

Query an option's string value.

Represents a static or instance method of a struct/union/class.

Represents a C++ struct/union/class.

DeclContext * getParent()

getParent - Returns the containing DeclContext.

bool isStdNamespace() const

DeclContext * getDeclContext()

bool isIdentifier() const

Predicate functions for querying what type of name this is.

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.

One of these records is kept for each identifier that is lexed.

StringRef getName() const

Return the actual identifier string.

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

const Decl * getDecl() const

const LocationContext * getParent() const

It might return null.

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

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.

std::string getQualifiedNameAsString() const

Stmt - This represents one statement.

The base class of the type hierarchy.

bool isBooleanType() const

bool isRValueReferenceType() const

bool isVoidPointerType() const

const SourceManager & getSourceManager() const

BugReporterVisitors are used to add custom diagnostics along a path.

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.

void reportInvalidCheckerOptionValue(const CheckerBase *C, StringRef OptionName, StringRef ExpectedValueDesc) const

Emits an error through a DiagnosticsEngine about an invalid user supplied checker option value.

const ProgramStateRef & getState() const

pred_iterator pred_begin()

const Stmt * getStmtForDiagnostics() const

If the node's program point corresponds to a statement, retrieve that statement.

const LocationContext * getLocationContext() const

ExplodedNode * getFirstPred()

MemRegion - The root abstract class for all memory regions.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace() const

virtual bool isSubRegionOf(const MemRegion *R) const

Check if the region is a subregion of the given region.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const

const RegionTy * getAs() const

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getMostDerivedObjectRegion() const

Recursively retrieve the region of the most derived class instance of regions of C++ base class insta...

static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)

Create a location for the beginning of the declaration.

virtual const MemRegion * getOriginRegion() const

Find the region from which this symbol originates.

virtual QualType getType() const =0

A class responsible for cleaning up unused symbols.

bool isLiveRegion(const MemRegion *region)

const char *const CXXMoveSemantics

bool isMovedFrom(ProgramStateRef State, const MemRegion *Region)

Returns true if the object is known to have been recently std::moved.

llvm::DenseSet< SymbolRef > InvalidatedSymbols

std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef

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

OverloadedOperatorKind

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

bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4