A RetroSearch Logo

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

Search Query:

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

clang: lib/StaticAnalyzer/Core/BugReporter.cpp Source File

49#include "llvm/ADT/ArrayRef.h" 50#include "llvm/ADT/DenseMap.h" 51#include "llvm/ADT/DenseSet.h" 52#include "llvm/ADT/FoldingSet.h" 53#include "llvm/ADT/STLExtras.h" 54#include "llvm/ADT/SmallPtrSet.h" 55#include "llvm/ADT/SmallString.h" 56#include "llvm/ADT/SmallVector.h" 57#include "llvm/ADT/Statistic.h" 58#include "llvm/ADT/StringExtras.h" 59#include "llvm/ADT/StringRef.h" 60#include "llvm/ADT/iterator_range.h" 61#include "llvm/Support/Casting.h" 62#include "llvm/Support/Compiler.h" 63#include "llvm/Support/ErrorHandling.h" 64#include "llvm/Support/MemoryBuffer.h" 65#include "llvm/Support/raw_ostream.h" 78using namespace clang

;

82#define DEBUG_TYPE "BugReporter" 85 "The maximum number of bug reports in the same equivalence class"

);

87 "The maximum number of bug reports in the same equivalence class " 88 "where at least one report is valid (not suppressed)"

);

90STATISTIC

(NumTimesReportPassesZ3,

"Number of reports passed Z3"

);

91STATISTIC

(NumTimesReportRefuted,

"Number of reports refuted by Z3"

);

93 "Number of times a report equivalence class was aborted by the Z3 " 96 "Number of times all reports of an equivalence class was refuted"

);

100void

BugReporterContext::anchor() {}

110

std::pair<PathDiagnosticCallPiece *, const ExplodedNode *>;

114using

VisitorsDiagnosticsTy =

115

llvm::DenseMap<const ExplodedNode *, std::vector<PathDiagnosticPieceRef>>;

119using

LocationContextMap =

120

llvm::DenseMap<const PathPieces *, const LocationContext *>;

125class

PathDiagnosticConstruct {

134

LocationContextMap LCM;

141

CallWithEntryStack CallStack;

145

std::unique_ptr<PathDiagnostic> PD;

151 const Decl

*AnalysisEntryPoint);

156

assert(CurrentNode &&

"Already reached the root!"

);

164 return

LCM.find(&PD->getActivePath())->getSecond();

167 const ExplodedNode

*getCurrentNode()

const

{

return

CurrentNode; }

171 bool

ascendToPrevNode() {

173 return static_cast<bool>

(CurrentNode);

177 return

getCurrLocationContext()->getParentMap();

182 const Stmt

*getParent(

const Stmt

*S)

const

{

183 return

getParentMap().getParent(S);

192

assert(LCM.count(

Path

) &&

193 "Failed to find the context associated with these pieces!"

);

194 return

LCM.find(

Path

)->getSecond();

199 PathPieces

&getActivePath() {

return

PD->getActivePath(); }

200 PathPieces

&getMutablePieces() {

return

PD->getMutablePieces(); }

203 bool

shouldAddControlNotes()

const

{

206 bool

shouldGenerateDiagnostics()

const

{

209 bool

supportsLogicalOpControlFlow()

const

{

220

std::unique_ptr<const ExplodedGraph> BugPath;

231

std::unique_ptr<const VisitorsDiagnosticsTy> VisitorsDiagnostics;

237 static

std::optional<PathDiagnosticBuilder>

241

PathDiagnosticBuilder(

244

std::unique_ptr<VisitorsDiagnosticsTy> VisitorsDiagnostics);

256

std::unique_ptr<PathDiagnostic>

261 const

CallWithEntryStack &CallStack)

const

;

262 void

generatePathDiagnosticsForNode(PathDiagnosticConstruct &

C

,

265 void

generateMinimalDiagForBlockEdge(PathDiagnosticConstruct &

C

,

269

generateDiagForGotoOP(

const

PathDiagnosticConstruct &

C

,

const Stmt

*S,

273

generateDiagForSwitchOP(

const

PathDiagnosticConstruct &

C

,

const CFGBlock

*Dst,

277

generateDiagForBinaryOP(

const

PathDiagnosticConstruct &

C

,

const Stmt

*

T

,

281

ExecutionContinues(

const

PathDiagnosticConstruct &

C

)

const

;

284

ExecutionContinues(llvm::raw_string_ostream &os,

285 const

PathDiagnosticConstruct &

C

)

const

;

307 const auto

*CE = dyn_cast_or_null<CallExpr>(CallSite);

312 for

(

auto

[Idx, ArgExpr] : llvm::enumerate(CE->arguments())) {

324 if

(ArgExpr->getType()->isVoidPointerType())

349 return

(llvm::Twine(Msg) +

" via "

+ std::to_string(ArgIndex) +

350

llvm::getOrdinalSuffix(ArgIndex) +

" parameter"

).str();

370 if

(

X

->getTag() == tagPreferred && Y->

getTag

() == tagLesser)

373 if

(Y->

getTag

() == tagPreferred &&

X

->getTag() == tagLesser)

385 unsigned

N = path.size();

392 for

(

unsigned

i = 0; i < N; ++i) {

393 auto

piece = std::move(path.front());

396 switch

(piece->getKind()) {

407 if

(

auto

*nextEvent =

408

dyn_cast<PathDiagnosticEventPiece>(path.front().get())) {

409 auto

*

event

= cast<PathDiagnosticEventPiece>(piece.get());

413 if

(

auto

*pieceToKeep =

415

piece = std::move(pieceToKeep == event ? piece : path.front());

427

path.push_back(std::move(piece));

437 bool

IsInteresting =

false

) {

438 bool

containsSomethingInteresting = IsInteresting;

439 const unsigned

N = pieces.size();

441 for

(

unsigned

i = 0 ; i < N ; ++i) {

444 auto

piece = std::move(pieces.front());

447 switch

(piece->getKind()) {

449 auto

&call = cast<PathDiagnosticCallPiece>(*piece);

456

containsSomethingInteresting =

true

;

460 auto

&macro = cast<PathDiagnosticMacroPiece>(*piece);

463

containsSomethingInteresting =

true

;

467 auto

&

event

= cast<PathDiagnosticEventPiece>(*piece);

471

containsSomethingInteresting |= !

event

.isPrunable();

480

pieces.push_back(std::move(piece));

483 return

containsSomethingInteresting;

488 for

(

unsigned int

i = 0; i <

Path

.size(); ++i) {

489 auto

Piece = std::move(

Path

.front());

491 if

(!isa<PathDiagnosticPopUpPiece>(*Piece))

492 Path

.push_back(std::move(Piece));

508 for

(

const auto

&I : Pieces) {

509 auto

*

Call

= dyn_cast<PathDiagnosticCallPiece>(I.get());

514 if

(LastCallLocation) {

516 if

(CallerIsImplicit || !

Call

->callEnter.asLocation().isValid())

517 Call

->callEnter = *LastCallLocation;

518 if

(CallerIsImplicit || !

Call

->callReturn.asLocation().isValid())

519 Call

->callReturn = *LastCallLocation;

525 if

(

Call

->callEnterWithin.asLocation().isValid() &&

527

ThisCallLocation = &

Call

->callEnterWithin;

529

ThisCallLocation = &

Call

->callEnter;

531

assert(ThisCallLocation &&

"Outermost call has an invalid location"

);

540 for

(PathPieces::iterator I = Pieces.begin(),

E

= Pieces.end(); I !=

E

;) {

541 if

(

auto

*

C

= dyn_cast<PathDiagnosticCallPiece>(I->get()))

544 if

(

auto

*M = dyn_cast<PathDiagnosticMacroPiece>(I->get()))

547 if

(

auto

*

CF

= dyn_cast<PathDiagnosticControlFlowPiece>(I->get())) {

548 const Stmt

*Start =

CF

->getStartLocation().asStmt();

549 const Stmt

*End =

CF

->getEndLocation().asStmt();

550 if

(isa_and_nonnull<CXXDefaultInitExpr>(Start)) {

553

}

else if

(isa_and_nonnull<CXXDefaultInitExpr>(End)) {

554

PathPieces::iterator Next = std::next(I);

557

dyn_cast<PathDiagnosticControlFlowPiece>(Next->get())) {

558

NextCF->setStartLocation(

CF

->getStartLocation());

574 for

(PathPieces::iterator I = Pieces.begin(),

E

= Pieces.end(); I !=

E

;) {

575 if

(

auto

*

C

= dyn_cast<PathDiagnosticCallPiece>(I->get()))

578 if

(

auto

*M = dyn_cast<PathDiagnosticMacroPiece>(I->get()))

581 if

(!(*I)->getLocation().isValid() ||

582

!(*I)->getLocation().asLocation().isValid()) {

591 const

PathDiagnosticConstruct &

C

)

const

{

592 if

(

const Stmt

*S =

C

.getCurrentNode()->getNextStmtForDiagnostics())

594 C

.getCurrLocationContext());

601

llvm::raw_string_ostream &os,

const

PathDiagnosticConstruct &

C

)

const

{

603 if

(os.str().empty())

609

os <<

"Execution continues on line " 610

<< getSourceManager().getExpansionLineNumber(

Loc

.asLocation())

613

os <<

"Execution jumps to the end of the "

;

614 const Decl

*

D

=

C

.getCurrLocationContext()->getDecl();

615 if

(isa<ObjCMethodDecl>(

D

))

617 else if

(isa<FunctionDecl>(

D

))

620

assert(isa<BlockDecl>(

D

));

621

os <<

"anonymous block"

;

637 switch

(

Parent

->getStmtClass()) {

638 case

Stmt::ForStmtClass:

639 case

Stmt::DoStmtClass:

640 case

Stmt::WhileStmtClass:

641 case

Stmt::ObjCForCollectionStmtClass:

642 case

Stmt::CXXForRangeStmtClass:

653 bool

allowNestedContexts =

false

) {

660 switch

(

Parent

->getStmtClass()) {

661 case

Stmt::BinaryOperatorClass: {

662 const auto

*B = cast<BinaryOperator>(

Parent

);

663 if

(B->isLogicalOp())

667 case

Stmt::CompoundStmtClass:

668 case

Stmt::StmtExprClass:

670 case

Stmt::ChooseExprClass:

673 if

(allowNestedContexts || cast<ChooseExpr>(

Parent

)->getCond() == S)

677 case

Stmt::BinaryConditionalOperatorClass:

678 case

Stmt::ConditionalOperatorClass:

681 if

(allowNestedContexts ||

682

cast<AbstractConditionalOperator>(

Parent

)->getCond() == S)

686 case

Stmt::CXXForRangeStmtClass:

687 if

(cast<CXXForRangeStmt>(

Parent

)->getBody() == S)

690 case

Stmt::DoStmtClass:

692 case

Stmt::ForStmtClass:

693 if

(cast<ForStmt>(

Parent

)->getBody() == S)

696 case

Stmt::IfStmtClass:

697 if

(cast<IfStmt>(

Parent

)->getCond() != S)

700 case

Stmt::ObjCForCollectionStmtClass:

701 if

(cast<ObjCForCollectionStmt>(

Parent

)->getBody() == S)

704 case

Stmt::WhileStmtClass:

705 if

(cast<WhileStmt>(

Parent

)->getCond() != S)

715

assert(S &&

"Cannot have null Stmt for PathDiagnosticLocation"

);

734void

PathDiagnosticBuilder::updateStackPiecesWithMessage(

736 if

(R->hasCallStackHint(

P

))

737 for

(

const auto

&I : CallStack) {

740

std::string stackMsg = R->getCallStackMessage(

P

, N);

754 const

PathDiagnosticConstruct &

C

,

const CFGBlock

*Dst,

760

llvm::raw_string_ostream os(sbuf);

766 switch

(S->getStmtClass()) {

768

os <<

"No cases match in the switch statement. " 769 "Control jumps to line " 770

<< End.asLocation().getExpansionLineNumber();

772 case

Stmt::DefaultStmtClass:

773

os <<

"Control jumps to the 'default' case at line " 774

<< End.asLocation().getExpansionLineNumber();

777 case

Stmt::CaseStmtClass: {

778

os <<

"Control jumps to 'case "

;

779 const auto

*Case = cast<CaseStmt>(S);

783 bool

GetRawInt =

true

;

785 if

(

const auto

*DR = dyn_cast<DeclRefExpr>(LHS)) {

788 const auto

*

D

= dyn_cast<EnumConstantDecl>(DR->getDecl());

799

os <<

":' at line "

<< End.asLocation().getExpansionLineNumber();

804

os <<

"'Default' branch taken. "

;

805

End = ExecutionContinues(os,

C

);

807 return

std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, sbuf);

811 const

PathDiagnosticConstruct &

C

,

const Stmt

*S,

814

llvm::raw_string_ostream os(sbuf);

817

os <<

"Control jumps to line "

<< End.asLocation().getExpansionLineNumber();

818 return

std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, sbuf);

822 const

PathDiagnosticConstruct &

C

,

const Stmt

*

T

,

const CFGBlock

*Src,

827 const auto

*B = cast<BinaryOperator>(

T

);

829

llvm::raw_string_ostream os(sbuf);

830

os <<

"Left side of '"

;

833 if

(B->getOpcode() == BO_LAnd) {

846

End = ExecutionContinues(

C

);

849

assert(B->getOpcode() == BO_LOr);

857

End = ExecutionContinues(

C

);

865 return

std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, sbuf);

868void

PathDiagnosticBuilder::generateMinimalDiagForBlockEdge(

869

PathDiagnosticConstruct &

C

,

BlockEdge

BE)

const

{

879 switch

(

T

->getStmtClass()) {

883 case

Stmt::GotoStmtClass:

884 case

Stmt::IndirectGotoStmtClass: {

885 if

(

const Stmt

*S =

C

.getCurrentNode()->getNextStmtForDiagnostics())

886 C

.getActivePath().push_front(generateDiagForGotoOP(

C

, S, Start));

890 case

Stmt::SwitchStmtClass: {

891 C

.getActivePath().push_front(generateDiagForSwitchOP(

C

, Dst, Start));

895 case

Stmt::BreakStmtClass:

896 case

Stmt::ContinueStmtClass: {

898

llvm::raw_string_ostream os(sbuf);

900 C

.getActivePath().push_front(

901

std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, sbuf));

906 case

Stmt::BinaryConditionalOperatorClass:

907 case

Stmt::ConditionalOperatorClass: {

909

llvm::raw_string_ostream os(sbuf);

910

os <<

"'?' condition is "

;

919 if

(

const Stmt

*S = End.asStmt())

922 C

.getActivePath().push_front(

923

std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, sbuf));

928 case

Stmt::BinaryOperatorClass: {

929 if

(!

C

.supportsLogicalOpControlFlow())

932 C

.getActivePath().push_front(generateDiagForBinaryOP(

C

,

T

, Src, Dst));

936 case

Stmt::DoStmtClass:

939

llvm::raw_string_ostream os(sbuf);

941

os <<

"Loop condition is true. "

;

944 if

(

const Stmt

*S = End.asStmt())

947 C

.getActivePath().push_front(

948

std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, sbuf));

952 if

(

const Stmt

*S = End.asStmt())

955 C

.getActivePath().push_front(

956

std::make_shared<PathDiagnosticControlFlowPiece>(

957

Start, End,

"Loop condition is false. Exiting loop"

));

961 case

Stmt::WhileStmtClass:

962 case

Stmt::ForStmtClass:

965

llvm::raw_string_ostream os(sbuf);

967

os <<

"Loop condition is false. "

;

969 if

(

const Stmt

*S = End.asStmt())

972 C

.getActivePath().push_front(

973

std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, sbuf));

976 if

(

const Stmt

*S = End.asStmt())

979 C

.getActivePath().push_front(

980

std::make_shared<PathDiagnosticControlFlowPiece>(

981

Start, End,

"Loop condition is true. Entering loop body"

));

986 case

Stmt::IfStmtClass: {

989 if

(

const Stmt

*S = End.asStmt())

993 C

.getActivePath().push_front(

994

std::make_shared<PathDiagnosticControlFlowPiece>(

995

Start, End,

"Taking false branch"

));

997 C

.getActivePath().push_front(

998

std::make_shared<PathDiagnosticControlFlowPiece>(

999

Start, End,

"Taking true branch"

));

1012 case

Stmt::ForStmtClass:

1013 case

Stmt::WhileStmtClass:

1014 case

Stmt::ObjCForCollectionStmtClass:

1015 case

Stmt::CXXForRangeStmtClass:

1044 const Stmt

*S = SP->getStmt();

1054 const Stmt

*LoopBody =

nullptr

;

1056 case

Stmt::CXXForRangeStmtClass: {

1057 const auto

*FR = cast<CXXForRangeStmt>(Term);

1062

LoopBody = FR->getBody();

1065 case

Stmt::ForStmtClass: {

1066 const auto

*FS = cast<ForStmt>(Term);

1069

LoopBody = FS->getBody();

1072 case

Stmt::ObjCForCollectionStmtClass: {

1073 const auto

*FC = cast<ObjCForCollectionStmt>(Term);

1074

LoopBody = FC->getBody();

1077 case

Stmt::WhileStmtClass:

1078

LoopBody = cast<WhileStmt>(Term)->getBody();

1108

std::make_shared<PathDiagnosticControlFlowPiece>(NewLoc, PrevLoc));

1116 if

(

const auto

*FS = dyn_cast_or_null<ObjCForCollectionStmt>(S))

1117 return

FS->getElement();

1124 "Loop body skipped when range is empty"

;

1126 "Loop body skipped when collection is empty"

;

1128static

std::unique_ptr<FilesToLineNumsMap>

1131void

PathDiagnosticBuilder::generatePathDiagnosticsForNode(

1142 if

(

C

.shouldAddPathEdges()) {

1158 bool

VisitedEntireCall =

C

.PD->isWithinCall();

1159 C

.PD->popActivePath();

1162 if

(VisitedEntireCall) {

1163 Call

= cast<PathDiagnosticCallPiece>(

C

.getActivePath().front().get());

1167 const Decl

*Caller = CE->getLocationContext()->getDecl();

1169

assert(

C

.getActivePath().size() == 1 &&

1170 C

.getActivePath().front().get() ==

Call

);

1174

assert(

C

.isInLocCtxMap(&

C

.getActivePath()) &&

1175 "When we ascend to a previously unvisited call, the active path's " 1176 "address shouldn't change, but rather should be compacted into " 1177 "a single CallEvent!"

);

1178 C

.updateLocCtxMap(&

C

.getActivePath(),

C

.getCurrLocationContext());

1181

assert(!

C

.isInLocCtxMap(&

Call

->path) &&

1182 "When we ascend to a previously unvisited call, this must be the " 1183 "first time we encounter the caller context!"

);

1184 C

.updateLocCtxMap(&

Call

->path, CE->getCalleeContext());

1186 Call

->setCallee(*CE,

SM

);

1189

PrevLoc =

Call

->getLocation();

1191 if

(!

C

.CallStack.empty()) {

1192

assert(

C

.CallStack.back().first ==

Call

);

1193 C

.CallStack.pop_back();

1198

assert(

C

.getCurrLocationContext() ==

C

.getLocationContextForActivePath() &&

1199 "The current position in the bug path is out of sync with the " 1200 "location context associated with the active path!"

);

1203 if

(std::optional<CallExitEnd> CE =

P

.getAs<

CallExitEnd

>()) {

1209

assert(!

C

.isInLocCtxMap(&

Call

->path) &&

1210 "We just entered a call, this must've been the first time we " 1211 "encounter its context!"

);

1212 C

.updateLocCtxMap(&

Call

->path, CE->getCalleeContext());

1214 if

(

C

.shouldAddPathEdges()) {

1220 auto

*

P

=

Call

.get();

1221 C

.getActivePath().push_front(std::move(

Call

));

1224 C

.PD->pushActivePath(&

P

->path);

1225 C

.CallStack.push_back(CallWithEntry(

P

,

C

.getCurrentNode()));

1229 if

(

auto

PS =

P

.getAs<

PostStmt

>()) {

1230 if

(!

C

.shouldAddPathEdges())

1236 if

(!isa<ObjCForCollectionStmt>(PS->getStmt())) {

1242

}

else if

(

auto

BE =

P

.getAs<

BlockEdge

>()) {

1244 if

(

C

.shouldAddControlNotes()) {

1245

generateMinimalDiagForBlockEdge(

C

, *BE);

1248 if

(!

C

.shouldAddPathEdges()) {

1255 const Stmt

*Body =

nullptr

;

1257 if

(

const auto

*FS = dyn_cast<ForStmt>(

Loop

))

1258

Body = FS->getBody();

1259 else if

(

const auto

*WS = dyn_cast<WhileStmt>(

Loop

))

1260

Body = WS->getBody();

1261 else if

(

const auto

*OFS = dyn_cast<ObjCForCollectionStmt>(

Loop

)) {

1262

Body = OFS->getBody();

1263

}

else if

(

const auto

*FRS = dyn_cast<CXXForRangeStmt>(

Loop

)) {

1264

Body = FRS->getBody();

1268 auto

p = std::make_shared<PathDiagnosticEventPiece>(

1269

L,

"Looping back to the head of the loop"

);

1270

p->setPrunable(

true

);

1274 if

(!

C

.shouldAddControlNotes()) {

1275 C

.getActivePath().push_front(std::move(p));

1278 if

(

const auto

*CS = dyn_cast_or_null<CompoundStmt>(Body)) {

1298 if

(!IsInLoopBody) {

1299 if

(isa<ObjCForCollectionStmt>(Term)) {

1301

}

else if

(isa<CXXForRangeStmt>(Term)) {

1313 C

.getCurrLocationContext());

1314 auto

PE = std::make_shared<PathDiagnosticEventPiece>(L, str);

1315

PE->setPrunable(

true

);

1319 if

(!

C

.shouldAddControlNotes()) {

1320 C

.getActivePath().push_front(std::move(PE));

1323

}

else if

(isa<BreakStmt, ContinueStmt, GotoStmt>(Term)) {

1331static

std::unique_ptr<PathDiagnostic>

1333 const Decl

*AnalysisEntryPoint) {

1335 return

std::make_unique<PathDiagnostic>(

1339

AnalysisEntryPoint, std::make_unique<FilesToLineNumsMap>());

1342static

std::unique_ptr<PathDiagnostic>

1345 const Decl

*AnalysisEntryPoint) {

1347 return

std::make_unique<PathDiagnostic>(

1364 if

(isa<FullExpr, CXXBindTemporaryExpr, SubstNonTypeTemplateParmExpr>(S))

1374 switch

(S->getStmtClass()) {

1375 case

Stmt::BinaryOperatorClass: {

1376 const auto

*BO = cast<BinaryOperator>(S);

1377 if

(!BO->isLogicalOp())

1379 return

BO->getLHS() == Cond || BO->getRHS() == Cond;

1381 case

Stmt::IfStmtClass:

1382 return

cast<IfStmt>(S)->getCond() == Cond;

1383 case

Stmt::ForStmtClass:

1384 return

cast<ForStmt>(S)->getCond() == Cond;

1385 case

Stmt::WhileStmtClass:

1386 return

cast<WhileStmt>(S)->getCond() == Cond;

1387 case

Stmt::DoStmtClass:

1388 return

cast<DoStmt>(S)->getCond() == Cond;

1389 case

Stmt::ChooseExprClass:

1390 return

cast<ChooseExpr>(S)->getCond() == Cond;

1391 case

Stmt::IndirectGotoStmtClass:

1392 return

cast<IndirectGotoStmt>(S)->getTarget() == Cond;

1393 case

Stmt::SwitchStmtClass:

1394 return

cast<SwitchStmt>(S)->getCond() == Cond;

1395 case

Stmt::BinaryConditionalOperatorClass:

1396 return

cast<BinaryConditionalOperator>(S)->getCond() == Cond;

1397 case

Stmt::ConditionalOperatorClass: {

1398 const auto

*CO = cast<ConditionalOperator>(S);

1399 return

CO->getCond() == Cond ||

1400

CO->getLHS() == Cond ||

1401

CO->getRHS() == Cond;

1403 case

Stmt::ObjCForCollectionStmtClass:

1404 return

cast<ObjCForCollectionStmt>(S)->getElement() == Cond;

1405 case

Stmt::CXXForRangeStmtClass: {

1406 const auto

*FRS = cast<CXXForRangeStmt>(S);

1407 return

FRS->getCond() == Cond || FRS->getRangeInit() == Cond;

1415 if

(

const auto

*FS = dyn_cast<ForStmt>(FL))

1416 return

FS->getInc() == S || FS->getInit() == S;

1417 if

(

const auto

*FRS = dyn_cast<CXXForRangeStmt>(FL))

1418 return

FRS->getInc() == S || FRS->getRangeStmt() == S ||

1419

FRS->getLoopVarStmt() || FRS->getRangeInit() == S;

1432

PathPieces::iterator Prev = pieces.end();

1433 for

(PathPieces::iterator I = pieces.begin(),

E

= Prev; I !=

E

;

1435 auto

*Piece = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());

1444 const Stmt

*InnerStmt =

nullptr

;

1445 while

(NextSrcContext.

isValid

() && NextSrcContext.

asStmt

() != InnerStmt) {

1446

SrcContexts.push_back(NextSrcContext);

1447

InnerStmt = NextSrcContext.

asStmt

();

1456 const Stmt

*Dst = Piece->getEndLocation().getStmtOrNull();

1462 if

(!DstContext.

isValid

() || DstContext.

asStmt

() == Dst)

1466 if

(llvm::is_contained(SrcContexts, DstContext))

1470

Piece->setStartLocation(DstContext);

1475 auto

*PrevPiece = dyn_cast<PathDiagnosticControlFlowPiece>(Prev->get());

1478 if

(

const Stmt

*PrevSrc =

1479

PrevPiece->getStartLocation().getStmtOrNull()) {

1481 if

(PrevSrcParent ==

1483

PrevPiece->setEndLocation(DstContext);

1494

std::make_shared<PathDiagnosticControlFlowPiece>(SrcLoc, DstContext);

1496

I = pieces.insert(I, std::move(

P

));

1512 for

(PathPieces::iterator I = pieces.begin(),

E

= pieces.end(); I !=

E

; ++I) {

1513 const auto

*PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());

1518 const Stmt

*s1Start = PieceI->getStartLocation().getStmtOrNull();

1519 const Stmt

*s1End = PieceI->getEndLocation().getStmtOrNull();

1521 if

(!s1Start || !s1End)

1524

PathPieces::iterator NextI = I; ++NextI;

1534 const auto

*EV = dyn_cast<PathDiagnosticEventPiece>(NextI->get());

1536

StringRef S = EV->getString();

1545

PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());

1555 if

(!s2Start || !s2End || s1End != s2Start)

1571

I = pieces.erase(I);

1584 SM

.getExpansionRange(

Range

.getEnd()).getEnd());

1587 if

(FID !=

SM

.getFileID(ExpansionRange.

getEnd

()))

1588 return

std::nullopt;

1590

std::optional<MemoryBufferRef> Buffer =

SM

.getBufferOrNone(FID);

1592 return

std::nullopt;

1594 unsigned

BeginOffset =

SM

.getFileOffset(ExpansionRange.

getBegin

());

1595 unsigned

EndOffset =

SM

.getFileOffset(ExpansionRange.

getEnd

());

1596

StringRef Snippet = Buffer->getBuffer().slice(BeginOffset, EndOffset);

1602 if

(Snippet.find_first_of(

"\r\n"

) != StringRef::npos)

1603 return

std::nullopt;

1606 return

Snippet.size();

1632 for

(PathPieces::iterator I =

Path

.begin(),

E

=

Path

.end(); I !=

E

; ) {

1634 const auto

*PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());

1641 const Stmt

*s1Start = PieceI->getStartLocation().getStmtOrNull();

1642 const Stmt

*s1End = PieceI->getEndLocation().getStmtOrNull();

1644

PathPieces::iterator NextI = I; ++NextI;

1648 const auto

*PieceNextI =

1649

dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());

1652 if

(isa<PathDiagnosticEventPiece>(NextI->get())) {

1656

PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());

1665 const Stmt

*s2Start = PieceNextI->getStartLocation().getStmtOrNull();

1666 const Stmt

*s2End = PieceNextI->getEndLocation().getStmtOrNull();

1668 if

(s1Start && s2Start && s1Start == s2End && s2Start == s1End) {

1669 const size_t

MAX_SHORT_LINE_LENGTH = 80;

1671 if

(s1Length && *s1Length <= MAX_SHORT_LINE_LENGTH) {

1673 if

(s2Length && *s2Length <= MAX_SHORT_LINE_LENGTH) {

1675

I =

Path

.erase(NextI);

1698 bool

erased =

false

;

1700 for

(PathPieces::iterator I = path.begin(),

E

= path.end(); I !=

E

;

1704 const auto

*PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());

1709 const Stmt

*start = PieceI->getStartLocation().getStmtOrNull();

1710 const Stmt

*end = PieceI->getEndLocation().getStmtOrNull();

1725 if

(!

SM

.isWrittenInSameFile(FirstLoc, SecondLoc))

1727 if

(

SM

.isBeforeInTranslationUnit(SecondLoc, FirstLoc))

1728

std::swap(SecondLoc, FirstLoc);

1737 const size_t

MAX_PUNY_EDGE_LENGTH = 2;

1738 if

(*ByteWidth <= MAX_PUNY_EDGE_LENGTH) {

1750 for

(PathPieces::iterator I = path.begin(),

E

= path.end(); I !=

E

; ++I) {

1751 const auto

*PieceI = dyn_cast<PathDiagnosticEventPiece>(I->get());

1756

PathPieces::iterator NextI = I; ++NextI;

1760 const auto

*PieceNextI = dyn_cast<PathDiagnosticEventPiece>(NextI->get());

1766 if

(PieceI->getString() == PieceNextI->getString()) {

1774 bool

hasChanges =

false

;

1780 for

(PathPieces::iterator I = path.begin(),

E

= path.end(); I !=

E

; ) {

1782 if

(

auto

*CallI = dyn_cast<PathDiagnosticCallPiece>(I->get())) {

1785 if

(!OCS.count(CallI)) {

1795 auto

*PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());

1802 const Stmt

*s1Start = PieceI->getStartLocation().getStmtOrNull();

1803 const Stmt

*s1End = PieceI->getEndLocation().getStmtOrNull();

1807

PathPieces::iterator NextI = I; ++NextI;

1811 const auto

*PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());

1818 const Stmt

*s2Start = PieceNextI->getStartLocation().getStmtOrNull();

1819 const Stmt

*s2End = PieceNextI->getEndLocation().getStmtOrNull();

1837 if

(level1 && level1 == level2 && level1 == level3 && level1 == level4) {

1838

PieceI->setEndLocation(PieceNextI->getEndLocation());

1851 if

(s1End && s1End == s2Start && level2) {

1852 bool

removeEdge =

false

;

1864 if

(isa<Expr>(s1End) && PM.

isConsumedExpr

(cast<Expr>(s1End))) {

1878 else if

(s1Start && s2End &&

1891 else if

(s1Start && s2End &&

1893 SourceRange

EdgeRange(PieceI->getEndLocation().asLocation(),

1894

PieceI->getStartLocation().asLocation());

1901

PieceI->setEndLocation(PieceNextI->getEndLocation());

1915 if

(s1End == s2Start) {

1916 const auto

*FS = dyn_cast_or_null<ObjCForCollectionStmt>(level3);

1917 if

(FS && FS->getCollection()->IgnoreParens() == s2Start &&

1918

s2End == FS->getElement()) {

1919

PieceI->setEndLocation(PieceNextI->getEndLocation());

1956 const auto

*FirstEdge =

1957

dyn_cast<PathDiagnosticControlFlowPiece>(

Path

.front().get());

1961 const Decl

*

D

=

C

.getLocationContextFor(&

Path

)->getDecl();

1964 if

(FirstEdge->getStartLocation() != EntryLoc)

1976 for

(

const auto

&

P

: path) {

1979 unsigned

LineNo =

Loc

.getLineNumber();

1981

ExecutedLines[FID].insert(LineNo);

1985

PathDiagnosticConstruct::PathDiagnosticConstruct(

1988

: Consumer(PDC), CurrentNode(ErrorNode),

1989 SM

(CurrentNode->getCodeDecl().getASTContext().getSourceManager()),

1991

AnalysisEntryPoint)) {

1995

PathDiagnosticBuilder::PathDiagnosticBuilder(

1998

std::unique_ptr<VisitorsDiagnosticsTy> VisitorsDiagnostics)

2000

ErrorNode(ErrorNode),

2001

VisitorsDiagnostics(

std

::move(VisitorsDiagnostics)) {}

2003

std::unique_ptr<PathDiagnostic>

2005 const Decl

*EntryPoint = getBugReporter().getAnalysisEntryPoint();

2006

PathDiagnosticConstruct Construct(PDC, ErrorNode, R, EntryPoint);

2015 auto

EndNotes = VisitorsDiagnostics->find(ErrorNode);

2017 if

(EndNotes != VisitorsDiagnostics->end()) {

2018

assert(!EndNotes->second.empty());

2019

LastPiece = EndNotes->second[0];

2024

Construct.PD->setEndOfPath(LastPiece);

2029 while

(Construct.ascendToPrevNode()) {

2030

generatePathDiagnosticsForNode(Construct, PrevLoc);

2032 auto

VisitorNotes = VisitorsDiagnostics->find(Construct.getCurrentNode());

2033 if

(VisitorNotes == VisitorsDiagnostics->end())

2038

std::set<llvm::FoldingSetNodeID> DeduplicationSet;

2042

llvm::FoldingSetNodeID

ID

;

2044 if

(!DeduplicationSet.insert(ID).second)

2049

updateStackPiecesWithMessage(

Note

, Construct.CallStack);

2050

Construct.getActivePath().push_front(

Note

);

2058

Construct.getLocationContextForActivePath()->

getStackFrame

();

2066 if

(!Construct.PD->path.empty()) {

2068 bool

stillHasNotes =

2070

assert(stillHasNotes);

2071

(void)stillHasNotes;

2075 if

(!Opts.ShouldAddPopUpNotes)

2088 while

(

optimizeEdges

(Construct, Construct.getMutablePieces(), OCS)) {

2103 if

(Opts.ShouldDisplayMacroExpansions)

2106 return

std::move(Construct.PD);

2113void

BugType::anchor() {}

2119

LLVM_ATTRIBUTE_USED

static bool 2121 for

(

const

std::pair<StringRef, StringRef> &Pair : Registry.

Dependencies

) {

2122 if

(Pair.second == CheckerName)

2129

StringRef CheckerName) {

2131 if

(

Checker

.FullName == CheckerName)

2135 "Checker name not found in CheckerRegistry -- did you retrieve it " 2136 "correctly from CheckerManager::getCurrentCheckerName?"

);

2140 const BugType

&bt, StringRef shortDesc, StringRef desc,

2142 const Decl

*DeclToUnique)

2143

:

BugReport

(

Kind

::PathSensitive, bt, shortDesc, desc), ErrorNode(errorNode),

2144

ErrorNodeRange(getStmt() ? getStmt()->getSourceRange() :

SourceRange

()),

2145

UniqueingLocation(LocationToUnique), UniqueingDecl(DeclToUnique) {

2147

->getAnalysisManager()

2148

.getCheckerManager()

2149

->getCheckerRegistryData(),

2151 "Some checkers depend on this one! We don't allow dependency " 2152 "checkers to emit warnings, because checkers should depend on " 2153 "*modeling*, not *diagnostics*."

);

2157

->getAnalysisManager()

2158

.getCheckerManager()

2159

->getCheckerRegistryData(),

2161 "Hidden checkers musn't emit diagnostics as they are by definition " 2162 "non-user facing!"

);

2166

std::unique_ptr<BugReporterVisitor> visitor) {

2170

llvm::FoldingSetNodeID ID;

2171

visitor->Profile(ID);

2173 void

*InsertPos =

nullptr

;

2174 if

(

CallbacksSet

.FindNodeOrInsertPos(ID, InsertPos)) {

2178 Callbacks

.push_back(std::move(visitor));

2195

hash.AddInteger(

static_cast<int>

(

getKind

()));

2196

hash.AddPointer(&

BT

);

2202 if

(!range.isValid())

2204

hash.Add(range.getBegin());

2205

hash.Add(range.getEnd());

2210

hash.AddInteger(

static_cast<int>

(

getKind

()));

2211

hash.AddPointer(&

BT

);

2225 if

(!range.isValid())

2227

hash.Add(range.getBegin());

2228

hash.Add(range.getEnd());

2234

llvm::DenseMap<T, bugreporter::TrackingKind> &InterestingnessMap,

T

Val,

2236 auto Result

= InterestingnessMap.insert({Val, TKind});

2256 "BugReport::markInteresting currently can only handle 2 different " 2257 "tracking kinds! Please define what tracking kind should this entitiy" 2258 "have, if it was already marked as interesting with a different kind!"

);

2270 if

(

const auto

*meta = dyn_cast<SymbolMetadata>(sym))

2282 if

(

const auto

*meta = dyn_cast<SymbolMetadata>(sym))

2294 if

(

const auto

*SR = dyn_cast<SymbolicRegion>(R))

2305 if

(

const auto

*SR = dyn_cast<SymbolicRegion>(R))

2321

std::optional<bugreporter::TrackingKind>

2340 "BugReport::getInterestingnessKind currently can only handle 2 different " 2341 "tracking kinds! Please define what tracking kind should we return here " 2342 "when the kind of getAsRegion() and getAsSymbol() is different!"

);

2343 return

std::nullopt;

2346

std::optional<bugreporter::TrackingKind>

2349 return

std::nullopt;

2354 return

std::nullopt;

2355 return

It->getSecond();

2358

std::optional<bugreporter::TrackingKind>

2361 return

std::nullopt;

2366 return

It->getSecond();

2368 if

(

const auto

*SR = dyn_cast<SymbolicRegion>(R))

2370 return

std::nullopt;

2396 const Stmt

*S =

nullptr

;

2400 if

(BE->getBlock() == &Exit)

2443

assert(

ErrorNode

&&

"Cannot create a location with a null node."

);

2468 if

(

const auto

*AS = dyn_cast<AttributedStmt>(S))

2469

S = AS->getSubStmt();

2472 if

(

const auto

*ME = dyn_cast<MemberExpr>(S))

2476 if

(

const auto

*B = dyn_cast<BinaryOperator>(S))

2482 if

(S->getBeginLoc().isValid())

2506

:

D

(

D

), UserSuppressions(

D

.getASTContext()) {}

2510

assert(StrBugTypes.empty() &&

2511 "Destroying BugReporter before diagnostics are emitted!"

);

2514 for

(

const auto

I : EQClassesVector)

2521 for

(

const auto

EQ : EQClassesVector)

2528

StrBugTypes.clear();

2541

std::unique_ptr<ExplodedGraph> BugPath;

2548class

BugPathGetter {

2549

std::unique_ptr<ExplodedGraph> TrimmedGraph;

2551 using

PriorityMapTy = llvm::DenseMap<const ExplodedNode *, unsigned>;

2554

PriorityMapTy PriorityMap;

2558 using

ReportNewNodePair =

2559

std::pair<PathSensitiveBugReport *, const ExplodedNode *>;

2562

BugPathInfo CurrentBugPath;

2565 template

<

bool

Descending>

2566 class

PriorityCompare {

2567 const

PriorityMapTy &PriorityMap;

2570

PriorityCompare(

const

PriorityMapTy &M) : PriorityMap(M) {}

2573

PriorityMapTy::const_iterator LI = PriorityMap.find(LHS);

2574

PriorityMapTy::const_iterator RI = PriorityMap.find(RHS);

2575

PriorityMapTy::const_iterator

E

= PriorityMap.end();

2582 return

Descending ? LI->second > RI->second

2583

: LI->second < RI->second;

2586 bool

operator()(

const

ReportNewNodePair &LHS,

2587 const

ReportNewNodePair &RHS)

const

{

2588 return

(*

this

)(LHS.second, RHS.second);

2596

BugPathInfo *getNextBugPath();

2601

BugPathGetter::BugPathGetter(

const ExplodedGraph

*OriginalGraph,

2604 for

(

const auto

I : bugReports) {

2605

assert(I->isValid() &&

2606 "We only allow BugReporterVisitors and BugReporter itself to " 2607 "invalidate reports!"

);

2608 Nodes

.emplace_back(I->getErrorNode());

2614

TrimmedGraph = OriginalGraph->

trim

(

Nodes

, &ForwardMap);

2624 "Failed to construct a trimmed graph that contains this error " 2626

ReportNodes.emplace_back(

Report

, NewNode);

2627

RemainingNodes.insert(NewNode);

2630

assert(!RemainingNodes.empty() &&

"No error node found in the trimmed graph"

);

2633

std::queue<const ExplodedNode *> WS;

2635

assert(TrimmedGraph->num_roots() == 1);

2636

WS.push(*TrimmedGraph->roots_begin());

2639 while

(!WS.empty()) {

2643

PriorityMapTy::iterator PriorityEntry;

2645

std::tie(PriorityEntry, IsNew) = PriorityMap.insert({

Node

,

Priority

});

2649

assert(PriorityEntry->second <= Priority);

2653 if

(RemainingNodes.erase(

Node

))

2654 if

(RemainingNodes.empty())

2662

llvm::sort(ReportNodes, PriorityCompare<true>(PriorityMap));

2665

BugPathInfo *BugPathGetter::getNextBugPath() {

2666 if

(ReportNodes.empty())

2670

std::tie(CurrentBugPath.Report, OrigN) = ReportNodes.pop_back_val();

2671

assert(PriorityMap.contains(OrigN) &&

"error node not accessible from root"

);

2675 auto

GNew = std::make_unique<ExplodedGraph>();

2691

CurrentBugPath.ErrorNode = NewN;

2697

GNew->addRoot(NewN);

2704

PriorityCompare<false>(PriorityMap));

2707

CurrentBugPath.BugPath = std::move(GNew);

2709 return

&CurrentBugPath;

2716 using

MacroStackTy = std::vector<

2717

std::pair<std::shared_ptr<PathDiagnosticMacroPiece>,

SourceLocation

>>;

2719 using

PiecesTy = std::vector<PathDiagnosticPieceRef>;

2721

MacroStackTy MacroStack;

2724 for

(PathPieces::const_iterator I = path.begin(),

E

= path.end();

2726 const auto

&piece = *I;

2729 if

(

auto

*call = dyn_cast<PathDiagnosticCallPiece>(&*piece)) {

2739 SM

.getExpansionLoc(

Loc

) :

2742 if

(

Loc

.isFileID()) {

2744

Pieces.push_back(piece);

2748

assert(

Loc

.isMacroID());

2751 if

(!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {

2752

MacroStack.back().first->subPieces.push_back(piece);

2758

std::shared_ptr<PathDiagnosticMacroPiece> MacroGroup;

2761 SM

.getExpansionLoc(

Loc

) :

2765 while

(!MacroStack.empty()) {

2766 if

(InstantiationLoc == MacroStack.back().second) {

2767

MacroGroup = MacroStack.back().first;

2771 if

(ParentInstantiationLoc == MacroStack.back().second) {

2772

MacroGroup = MacroStack.back().first;

2776

MacroStack.pop_back();

2779 if

(!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {

2781 auto

NewGroup = std::make_shared<PathDiagnosticMacroPiece>(

2785

MacroGroup->subPieces.push_back(NewGroup);

2787

assert(InstantiationLoc.

isFileID

());

2788

Pieces.push_back(NewGroup);

2791

MacroGroup = NewGroup;

2792

MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));

2796

MacroGroup->subPieces.push_back(piece);

2802

path.insert(path.end(), Pieces.begin(), Pieces.end());

2808static

std::unique_ptr<VisitorsDiagnosticsTy>

2812

std::unique_ptr<VisitorsDiagnosticsTy> Notes =

2813

std::make_unique<VisitorsDiagnosticsTy>();

2826 for

(std::unique_ptr<BugReporterVisitor> &Visitor : R->

visitors

())

2827

visitors.push_back(std::move(Visitor));

2834 for

(

auto

&

V

: visitors) {

2835 V

->finalizeVisitor(BRC, ErrorNode, *R);

2837 if

(

auto

Piece =

V

->getEndPath(BRC, ErrorNode, *R)) {

2838

assert(!LastPiece &&

2839 "There can only be one final piece in a diagnostic."

);

2841 "The final piece must contain a message!"

);

2842

LastPiece = std::move(Piece);

2843

(*Notes)[ErrorNode].push_back(LastPiece);

2849 for

(

auto

&

V

: visitors) {

2850 auto P

=

V

->VisitNode(NextNode, BRC, *R);

2852

(*Notes)[NextNode].push_back(std::move(

P

));

2864

std::optional<PathDiagnosticBuilder> PathDiagnosticBuilder::findValidReport(

2869

BugPathGetter BugGraph(&Reporter.

getGraph

(), bugReports);

2871 while

(BugPathInfo *BugPath = BugGraph.getNextBugPath()) {

2874

assert(R &&

"No original report found for sliced graph."

);

2875

assert(R->

isValid

() &&

"Report selected by trimmed graph marked invalid."

);

2890

std::unique_ptr<VisitorsDiagnosticsTy> visitorNotes =

2905 switch

(Z3Oracle.interpretQueryResult(CrosscheckResult)) {

2907

++NumTimesReportRefuted;

2908

R->

markInvalid

(

"Infeasible constraints"

,

nullptr

);

2911

++NumTimesReportEQClassAborted;

2914

++NumTimesReportPassesZ3;

2920 return

PathDiagnosticBuilder(std::move(BRC), std::move(BugPath->BugPath),

2921

BugPath->Report, BugPath->ErrorNode,

2922

std::move(visitorNotes));

2926

++NumTimesReportEQClassWasExhausted;

2930

std::unique_ptr<DiagnosticForConsumerMapTy>

2934

assert(!bugReports.empty());

2936 auto

Out = std::make_unique<DiagnosticForConsumerMapTy>();

2938

std::optional<PathDiagnosticBuilder> PDB =

2939

PathDiagnosticBuilder::findValidReport(bugReports, *

this

);

2943 if

(std::unique_ptr<PathDiagnostic> PD = PDB->generate(PC)) {

2944

(*Out)[PC] = std::move(PD);

2953 bool

ValidSourceLoc = R->getLocation().isValid();

2954

assert(ValidSourceLoc);

2957 if

(!ValidSourceLoc)

2965

llvm::FoldingSetNodeID ID;

2974

EQClasses.InsertNode(EQ, InsertPos);

2975

EQClassesVector.push_back(EQ);

2977

EQ->AddReport(std::move(R));

2981 if

(

auto

PR = dyn_cast<PathSensitiveBugReport>(R.get()))

2985

assert((

E

->isSink() ||

E

->getLocation().getTag()) &&

2986 "Error node must either be a sink or have a tag"

);

2989 E

->getLocationContext()->getAnalysisDeclContext();

3008struct

FRIEC_WLItem {

3013

: N(n), I(N->succ_begin()),

E

(N->succ_end()) {}

3018BugReport

*PathSensitiveBugReporter::findReportInEquivalenceClass(

3023

assert(

EQ

.getReports().size() > 0);

3024 const BugType

& BT =

EQ

.getReports()[0]->getBugType();

3027 for

(

auto

&J :

EQ

.getReports()) {

3028 if

(

auto

*PR = dyn_cast<PathSensitiveBugReport>(J.get())) {

3030

bugReports.push_back(PR);

3044 for

(

const auto

&I:

EQ

.getReports()) {

3045 auto

*R = dyn_cast<PathSensitiveBugReport>(I.get());

3050 if

(errorNode->

isSink

()) {

3052 "BugType::isSuppressSink() should not be 'true' for sink end nodes"

);

3056

bugReports.push_back(R);

3067 if

(ErrorB->isInevitablySinking())

3072 using

WLItem = FRIEC_WLItem;

3075

llvm::DenseMap<const ExplodedNode *, unsigned>

Visited

;

3078

WL.push_back(errorNode);

3081 while

(!WL.empty()) {

3082

WLItem &WI = WL.back();

3083

assert(!WI.N->succ_empty());

3085 for

(; WI.I != WI.E; ++WI.I) {

3091

bugReports.push_back(R);

3102 unsigned

&mark =

Visited

[Succ];

3112 if

(!WL.empty() && &WL.back() == &WI)

3119 return

exampleReport;

3124 BugReport

*report = findReportInEquivalenceClass(EQ, bugReports);

3129 for

(

const

std::string &CheckerOrPackage :

3136

std::unique_ptr<DiagnosticForConsumerMapTy> Diagnostics =

3139 for

(

auto

&

P

: *Diagnostics) {

3141

std::unique_ptr<PathDiagnostic> &PD =

P

.second;

3145 if

(PD->path.empty()) {

3147 auto

piece = std::make_unique<PathDiagnosticEventPiece>(

3150

piece->addRange(

Range

);

3151

PD->setEndOfPath(std::move(piece));

3158 for

(

const auto

&I : llvm::reverse(report->

getNotes

())) {

3160 auto

ConvertedPiece = std::make_shared<PathDiagnosticEventPiece>(

3162 for

(

const auto

&R: Piece->

getRanges

())

3163

ConvertedPiece->addRange(R);

3165

Pieces.push_front(std::move(ConvertedPiece));

3168 for

(

const auto

&I : llvm::reverse(report->

getNotes

()))

3169

Pieces.push_front(I);

3172 for

(

const auto

&I : report->

getFixits

())

3173

Pieces.back()->addFixit(I);

3181

Pieces.push_front(std::make_shared<PathDiagnosticEventPiece>(

3183 "[debug] analyzing from "

+

3197 if

(

const auto

FD = dyn_cast<FunctionDecl>(Signature)) {

3198

SignatureSourceRange = FD->getSourceRange();

3199

}

else if

(

const auto

OD = dyn_cast<ObjCMethodDecl>(Signature)) {

3200

SignatureSourceRange = OD->getSourceRange();

3206

: SignatureSourceRange.

getEnd

();

3207 if

(!Start.

isValid

() || !End.isValid())

3209 unsigned

StartLine =

SM

.getExpansionLineNumber(Start);

3210 unsigned

EndLine =

SM

.getExpansionLineNumber(End);

3212 FileID

FID =

SM

.getFileID(

SM

.getExpansionLoc(Start));

3213 for

(

unsigned Line

= StartLine;

Line

<= EndLine;

Line

++)

3214

ExecutedLines[FID].insert(

Line

);

3224 FileID

FID =

SM

.getFileID(ExpansionLoc);

3225 unsigned

LineNo =

SM

.getExpansionLineNumber(ExpansionLoc);

3226

ExecutedLines[FID].insert(LineNo);

3231static

std::unique_ptr<FilesToLineNumsMap>

3233 auto

ExecutedLines = std::make_unique<FilesToLineNumsMap>();

3242 const Decl

*

D

= CE->getCalleeContext()->getDecl();

3253 if

(

const auto

*RS = dyn_cast_or_null<ReturnStmt>(

P

)) {

3258 if

(isa_and_nonnull<SwitchCase, LabelStmt>(

P

))

3264 return

ExecutedLines;

3267

std::unique_ptr<DiagnosticForConsumerMapTy>

3271 auto

*basicReport = cast<BasicBugReport>(exampleReport);

3272 auto

Out = std::make_unique<DiagnosticForConsumerMapTy>();

3273 for

(

auto

*Consumer : consumers)

3289 "The call piece should not be in a header file."

);

3301 if

(

auto

*CPInner = dyn_cast<PathDiagnosticCallPiece>(

Path

.back().get()))

3309 if

(PD.

path

.empty())

3318 if

(

auto

*CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {

3325 const auto

*ND = dyn_cast<NamedDecl>(CP->

getCallee

());

3328

llvm::raw_svector_ostream os(buf);

3329

os <<

" (within a call to '"

<< ND->getDeclName() <<

"')"

;

3344

std::unique_ptr<DiagnosticForConsumerMapTy>

3345

PathSensitiveBugReporter::generateDiagnosticForConsumerMap(

3348

std::vector<BasicBugReport *> BasicBugReports;

3349

std::vector<PathSensitiveBugReport *> PathSensitiveBugReports;

3350 if

(isa<BasicBugReport>(exampleReport))

3352

consumers, bugReports);

3358

assert(!bugReports.empty());

3359

MaxBugClassSize.updateMax(bugReports.size());

3366

consumers, convertedArrayOfReports);

3371

MaxValidBugClassSize.updateMax(bugReports.size());

3376 for

(

auto const

&

P

: *Out)

3377 if

(Opts.ShouldReportIssuesInMainSourceFile && !Opts.

AnalyzeAll

)

3385

StringRef

Category

, StringRef Str,

3390 Loc

, Ranges, Fixits);

3395

StringRef name, StringRef category,

3400 BugType

*BT = getBugTypeForName(CheckName, name, category);

3401 auto

R = std::make_unique<BasicBugReport>(*BT, str,

Loc

);

3402

R->setDeclWithIssue(DeclWithIssue);

3403 for

(

const auto

&SR : Ranges)

3405 for

(

const auto

&FH : Fixits)

3411

StringRef name, StringRef category) {

3413

llvm::raw_svector_ostream(fullDesc) << CheckName.

getName

() <<

":"

<< name

3415

std::unique_ptr<BugType> &BT = StrBugTypes[fullDesc];

3417

BT = std::make_unique<BugType>(CheckName, name, category);

BoundNodesTreeBuilder Nodes

This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...

static void dropFunctionEntryEdge(const PathDiagnosticConstruct &C, PathPieces &Path)

Drop the very first edge in a path, which should be a function entry edge.

constexpr llvm::StringLiteral StrLoopRangeEmpty

static PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S, const LocationContext *LC, bool allowNestedContexts=false)

static std::unique_ptr< FilesToLineNumsMap > findExecutedLines(const SourceManager &SM, const ExplodedNode *N)

static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond)

static void updateExecutedLinesWithDiagnosticPieces(PathDiagnostic &PD)

Populate executes lines with lines containing at least one diagnostics.

static void removeRedundantMsgs(PathPieces &path)

An optimization pass over PathPieces that removes redundant diagnostics generated by both ConditionBR...

constexpr llvm::StringLiteral StrLoopCollectionEmpty

static void adjustCallLocations(PathPieces &Pieces, PathDiagnosticLocation *LastCallLocation=nullptr)

Recursively scan through a path and make sure that all call pieces have valid locations.

static void removeIdenticalEvents(PathPieces &path)

static const Stmt * getTerminatorCondition(const CFGBlock *B)

A customized wrapper for CFGBlock::getTerminatorCondition() which returns the element for ObjCForColl...

static std::unique_ptr< VisitorsDiagnosticsTy > generateVisitorsDiagnostics(PathSensitiveBugReport *R, const ExplodedNode *ErrorNode, BugReporterContext &BRC)

Generate notes from all visitors.

static bool removeUnneededCalls(const PathDiagnosticConstruct &C, PathPieces &pieces, const PathSensitiveBugReport *R, bool IsInteresting=false)

Recursively scan through a path and prune out calls and macros pieces that aren't needed.

static const Stmt * findReasonableStmtCloseToFunctionExit(const ExplodedNode *N)

static void populateExecutedLinesWithStmt(const Stmt *S, const SourceManager &SM, FilesToLineNumsMap &ExecutedLines)

static bool isJumpToFalseBranch(const BlockEdge *BE)

static std::optional< size_t > getLengthOnSingleLine(const SourceManager &SM, SourceRange Range)

Returns the number of bytes in the given (character-based) SourceRange.

static bool isLoop(const Stmt *Term)

static bool isContainedByStmt(const ParentMap &PM, const Stmt *S, const Stmt *SubS)

constexpr llvm::StringLiteral StrEnteringLoop

static void addEdgeToPath(PathPieces &path, PathDiagnosticLocation &PrevLoc, PathDiagnosticLocation NewLoc)

Adds a sanitized control-flow diagnostic edge to a path.

static bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL)

static std::unique_ptr< PathDiagnostic > generateEmptyDiagnosticForReport(const PathSensitiveBugReport *R, const SourceManager &SM, const Decl *AnalysisEntryPoint)

static void removeContextCycles(PathPieces &Path, const SourceManager &SM)

Eliminate two-edge cycles created by addContextEdges().

static bool lexicalContains(const ParentMap &PM, const Stmt *X, const Stmt *Y)

Return true if X is contained by Y.

static std::unique_ptr< PathDiagnostic > generateDiagnosticForBasicReport(const BasicBugReport *R, const Decl *AnalysisEntryPoint)

static void removePopUpNotes(PathPieces &Path)

Same logic as above to remove extra pieces.

STATISTIC(MaxBugClassSize, "The maximum number of bug reports in the same equivalence class")

static void insertToInterestingnessMap(llvm::DenseMap< T, bugreporter::TrackingKind > &InterestingnessMap, T Val, bugreporter::TrackingKind TKind)

constexpr llvm::StringLiteral StrLoopBodyZero

static const Stmt * getEnclosingParent(const Stmt *S, const ParentMap &PM)

static void removePunyEdges(PathPieces &path, const SourceManager &SM, const ParentMap &PM)

static const Stmt * getStmtParent(const Stmt *S, const ParentMap &PM)

static bool exitingDestructor(const ExplodedNode *N)

static void CompactMacroExpandedPieces(PathPieces &path, const SourceManager &SM)

CompactMacroExpandedPieces - This function postprocesses a PathDiagnostic object and collapses PathDi...

static void simplifySimpleBranches(PathPieces &pieces)

Move edges from a branch condition to a branch target when the condition is simple.

static void populateExecutedLinesWithFunctionSignature(const Decl *Signature, const SourceManager &SM, FilesToLineNumsMap &ExecutedLines)

Insert all lines participating in the function signature Signature into ExecutedLines.

static void resetDiagnosticLocationToMainFile(PathDiagnostic &PD)

static bool optimizeEdges(const PathDiagnosticConstruct &C, PathPieces &path, OptimizedCallsSet &OCS)

static bool hasImplicitBody(const Decl *D)

Returns true if the given decl has been implicitly given a body, either by the analyzer or by the com...

static PathDiagnosticCallPiece * getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, const SourceManager &SMgr)

llvm::DenseSet< const PathDiagnosticCallPiece * > OptimizedCallsSet

static void addContextEdges(PathPieces &pieces, const LocationContext *LC)

Adds synthetic edges from top-level statements to their subexpressions.

static LLVM_ATTRIBUTE_USED bool isDependency(const CheckerRegistryData &Registry, StringRef CheckerName)

static PathDiagnosticEventPiece * eventsDescribeSameCondition(PathDiagnosticEventPiece *X, PathDiagnosticEventPiece *Y)

static bool isInLoopBody(const ParentMap &PM, const Stmt *S, const Stmt *Term)

static void removeEdgesToDefaultInitializers(PathPieces &Pieces)

Remove edges in and out of C++ default initializer expressions.

static const Stmt * getStmtBeforeCond(const ParentMap &PM, const Stmt *Term, const ExplodedNode *N)

static void removePiecesWithInvalidLocations(PathPieces &Pieces)

Remove all pieces with invalid locations as these cannot be serialized.

static LLVM_ATTRIBUTE_USED bool isHidden(const CheckerRegistryData &Registry, StringRef CheckerName)

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

llvm::DenseSet< const void * > Visited

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Defines the clang::SourceLocation class and associated facilities.

Defines the SourceManager interface.

Defines the Objective-C statement AST node classes.

SourceManager & getSourceManager()

AnalysisDeclContext contains the context data for the function, method or block under analysis.

static std::string getFunctionName(const Decl *D)

bool isBodyAutosynthesized() const

bool isBodyAutosynthesizedFromModelFile() const

Stores options for the analyzer from the command line.

const CFGBlock * getSrc() const

const CFGBlock * getDst() const

Represents a single basic block in a source-level CFG.

succ_iterator succ_begin()

Stmt * getTerminatorStmt()

const Stmt * getLoopTarget() const

Stmt * getTerminatorCondition(bool StripParens=true)

unsigned succ_size() const

CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...

Represents a point when we begin processing an inlined call.

Represents a point when we finish the call exit sequence (for inlined call).

const StackFrameContext * getCalleeContext() const

Decl - This represents one declaration (or definition), e.g.

ASTContext & getASTContext() const LLVM_READONLY

bool isImplicit() const

isImplicit - Indicates whether the declaration was implicitly generated by the implementation.

virtual Stmt * getBody() const

getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...

virtual bool hasBody() const

Returns true if this Decl represents a declaration for a body of code, such as a function or method d...

SourceLocation getLocation() const

This represents one expression.

llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const

EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.

Expr * IgnoreParenImpCasts() LLVM_READONLY

Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...

An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...

ForStmt - This represents a 'for (init;cond;inc)' stmt.

A SourceLocation and its associated SourceManager.

IfStmt - This represents an if/then/else.

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

const Decl * getDecl() const

const ParentMap & getParentMap() const

const StackFrameContext * getStackFrame() const

Represents Objective-C's collection statement.

bool isConsumedExpr(Expr *E) const

Stmt * getParent(Stmt *) const

Stmt * getParentIgnoreParens(Stmt *) const

Represents a point after we ran remove dead bindings AFTER processing the given statement.

Represents a program point just before an implicit call event.

std::optional< T > getAs() const

Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...

const LocationContext * getLocationContext() const

ReturnStmt - This represents a return, optionally of an expression: return; return 4;.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

This class handles loading and caching of source files into memory.

A trivial tuple used to represent a source range.

SourceLocation getEnd() const

SourceLocation getBegin() const

It represents a stack frame of the call stack (based on CallEvent).

const Stmt * getCallSite() const

Stmt - This represents one statement.

StmtClass getStmtClass() const

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

SourceLocation getBeginLoc() const LLVM_READONLY

WhileStmt - This represents a 'while' stmt.

static bool isInCodeFile(SourceLocation SL, const SourceManager &SM)

const Decl * getDeclWithIssue() const override

The smallest declaration that contains the bug location.

PathDiagnosticLocation getUniqueingLocation() const override

Get the location on which the report should be uniqued.

void Profile(llvm::FoldingSetNodeID &hash) const override

Reports are uniqued to ensure that we do not emit multiple diagnostics for each bug.

const Decl * getUniqueingDecl() const override

Get the declaration that corresponds to (usually contains) the uniqueing location.

This class provides an interface through which checkers can create individual bug reports.

llvm::ArrayRef< FixItHint > getFixits() const

void addRange(SourceRange R)

Add a range to a bug report.

SmallVector< SourceRange, 4 > Ranges

virtual PathDiagnosticLocation getLocation() const =0

The primary location of the bug report that points at the undesirable behavior in the code.

ArrayRef< std::shared_ptr< PathDiagnosticNotePiece > > getNotes()

void addFixItHint(const FixItHint &F)

Add a fix-it hint to the bug report.

StringRef getDescription() const

A verbose warning message that is appropriate for displaying next to the source code that introduces ...

const BugType & getBugType() const

StringRef getShortDescription(bool UseFallback=true) const

A short general warning message that is appropriate for displaying in the list of all reported bugs.

virtual ArrayRef< SourceRange > getRanges() const

Get the SourceRanges associated with the report.

static PathDiagnosticPieceRef getDefaultEndPath(const BugReporterContext &BRC, const ExplodedNode *N, const PathSensitiveBugReport &BR)

Generates the default final diagnostic piece.

virtual ~BugReporterVisitor()

virtual std::unique_ptr< DiagnosticForConsumerMapTy > generateDiagnosticForConsumerMap(BugReport *exampleReport, ArrayRef< PathDiagnosticConsumer * > consumers, ArrayRef< BugReport * > bugReports)

Generate the diagnostics for the given bug report.

void FlushReports()

Generate and flush diagnostics for all bug reports.

BugReporter(BugReporterData &d)

const SourceManager & getSourceManager()

const Decl * getAnalysisEntryPoint() const

Get the top-level entry point for the issue to be reported.

const AnalyzerOptions & getAnalyzerOptions()

void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges={}, ArrayRef< FixItHint > Fixits={})

virtual void emitReport(std::unique_ptr< BugReport > R)

Add the given report to the set of reports tracked by BugReporter.

ArrayRef< PathDiagnosticConsumer * > getPathDiagnosticConsumers()

bool isSuppressed(const BugReport &)

Return true if the given bug report was explicitly suppressed by the user.

bool isSuppressOnSink() const

isSuppressOnSink - Returns true if bug reports associated with this bug type should be suppressed if ...

StringRef getCategory() const

StringRef getDescription() const

StringRef getCheckerName() const

CheckerNameRef getCheckerName() const

This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...

StringRef getName() const

Visitor that tries to report interesting diagnostics from conditions.

static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece)

static const char * getTag()

Return the tag associated with this visitor.

bool isValid() const =delete

std::unique_ptr< ExplodedGraph > trim(ArrayRef< const NodeTy * > Nodes, InterExplodedGraphMap *ForwardMap=nullptr, InterExplodedGraphMap *InverseMap=nullptr) const

Creates a trimmed version of the graph that only contains paths leading to the given nodes.

const CFGBlock * getCFGBlock() const

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 Stmt * getPreviousStmtForDiagnostics() const

Find the statement that was executed immediately before this node.

ProgramPoint getLocation() const

getLocation - Returns the edge associated with the given node.

void addPredecessor(ExplodedNode *V, ExplodedGraph &G)

addPredeccessor - Adds a predecessor to the current node, and in tandem add this node as a successor ...

const Stmt * getNextStmtForDiagnostics() const

Find the next statement that was executed on this node's execution path.

const ParentMap & getParentMap() const

SVal getSVal(const Stmt *S) const

Get the value of an arbitrary expression at this node.

const LocationContext * getLocationContext() const

std::optional< T > getLocationAs() const &

const Stmt * getCurrentOrPreviousStmtForDiagnostics() const

Find the statement that was executed at or immediately before this node.

ExplodedNode * getFirstPred()

const ExplodedNode *const * const_succ_iterator

ProgramStateManager & getStateManager()

ExplodedGraph & getGraph()

Suppress reports that might lead to known false positives.

MemRegion - The root abstract class for all memory regions.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const

Prints path notes when a message is sent to a nil receiver.

PathDiagnosticLocation getLocation() const override

PathDiagnosticLocation callEnter

void setCallStackMessage(StringRef st)

bool hasCallStackMessage()

const Decl * getCallee() const

static std::shared_ptr< PathDiagnosticCallPiece > construct(const CallExitEnd &CE, const SourceManager &SM)

const Decl * getCaller() const

PathDiagnosticLocation callEnterWithin

virtual bool supportsLogicalOpControlFlow() const

bool shouldAddPathEdges() const

void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)

bool shouldAddControlNotes() const

bool shouldGenerateDiagnostics() const

PathDiagnosticLocation getStartLocation() const

void setStartLocation(const PathDiagnosticLocation &L)

PathDiagnosticLocation getEndLocation() const

static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, const SourceManager &SM)

For member expressions, return the location of the '.

const Stmt * asStmt() const

void Profile(llvm::FoldingSetNodeID &ID) const

const SourceManager & getManager() const

static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)

Create the location for the operator of the binary expression.

static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)

Create a location for the end of the compound statement.

static SourceLocation getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEndOfStatement=false)

Construct a source location that corresponds to either the beginning or the end of the given statemen...

static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)

Create a location for the end of the statement.

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

Create a location for the beginning of the declaration.

FullSourceLoc asLocation() const

static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, const SourceManager &SM)

Constructs a location for the end of the enclosing declaration body.

const Stmt * getStmtOrNull() const

static PathDiagnosticLocation createSingleLocation(const PathDiagnosticLocation &PDL)

Convert the given location into a single kind location.

ArrayRef< SourceRange > getRanges() const

Return the SourceRanges associated with this PathDiagnosticPiece.

virtual PathDiagnosticLocation getLocation() const =0

void setAsLastInMainSourceFile()

const void * getTag() const

Return the opaque tag (if any) on the PathDiagnosticPiece.

StringRef getString() const

PathDiagnosticLocation getLocation() const override

PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.

void setDeclWithIssue(const Decl *D)

void appendToDesc(StringRef S)

void setLocation(PathDiagnosticLocation NewLoc)

const FilesToLineNumsMap & getExecutedLines() const

PathPieces flatten(bool ShouldFlattenMacros) const

llvm::SmallSet< const LocationContext *, 2 > InterestingLocationContexts

A set of location contexts that correspoind to call sites which should be considered "interesting".

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

Marks a symbol as interesting.

PathDiagnosticLocation getUniqueingLocation() const override

Get the location on which the report should be uniqued.

VisitorList Callbacks

A set of custom visitors which generate "event" diagnostics at interesting points in the path.

const Stmt * getStmt() const

PathDiagnosticLocation getLocation() const override

The primary location of the bug report that points at the undesirable behavior in the code.

const Decl * getDeclWithIssue() const override

The smallest declaration that contains the bug location.

bool shouldPrunePath() const

Indicates whether or not any path pruning should take place when generating a PathDiagnostic from thi...

ArrayRef< SourceRange > getRanges() const override

Get the SourceRanges associated with the report.

llvm::DenseMap< SymbolRef, bugreporter::TrackingKind > InterestingSymbols

Profile to identify equivalent bug reports for error report coalescing.

const Decl * getUniqueingDecl() const override

Get the declaration containing the uniqueing location.

const ExplodedNode * getErrorNode() const

PathSensitiveBugReport(const BugType &bt, StringRef desc, const ExplodedNode *errorNode)

const ExplodedNode * ErrorNode

The ExplodedGraph node against which the report was thrown.

void markInvalid(const void *Tag, const void *Data)

Marks the current report as invalid, meaning that it is probably a false positive and should not be r...

void Profile(llvm::FoldingSetNodeID &hash) const override

Profile to identify equivalent bug reports for error report coalescing.

void clearVisitors()

Remove all visitors attached to this bug report.

void addVisitor(std::unique_ptr< BugReporterVisitor > visitor)

Add custom or predefined bug report visitors to this report.

bool isValid() const

Returns whether or not this report should be considered valid.

std::optional< bugreporter::TrackingKind > getInterestingnessKind(SymbolRef sym) const

void markNotInteresting(SymbolRef sym)

llvm::DenseMap< const MemRegion *, bugreporter::TrackingKind > InterestingRegions

A (stack of) set of regions that are registered with this report as being "interesting",...

bool isInteresting(SymbolRef sym) const

const SourceRange ErrorNodeRange

The range that corresponds to ErrorNode's program point.

llvm::FoldingSet< BugReporterVisitor > CallbacksSet

Used for ensuring the visitors are only added once.

GRBugReporter is used for generating path-sensitive reports.

const ExplodedGraph & getGraph() const

getGraph - Get the exploded graph created by the analysis engine for the analyzed method or function.

std::unique_ptr< DiagnosticForConsumerMapTy > generatePathDiagnostics(ArrayRef< PathDiagnosticConsumer * > consumers, ArrayRef< PathSensitiveBugReport * > &bugReports)

bugReports A set of bug reports within a single equivalence class

void emitReport(std::unique_ptr< BugReport > R) override

Add the given report to the set of reports tracked by BugReporter.

ProgramStateManager & getStateManager() const

getStateManager - Return the state manager used by the analysis engine.

A Range represents the closed range [from, to].

SVal - This represents a symbolic expression, which can be either an L-value or an R-value.

std::optional< T > getAs() const

Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.

SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const

If this SVal is a location and wraps a symbol, return that SymbolRef.

std::string getMessage(const ExplodedNode *N) override

Search the call expression for the symbol Sym and dispatch the 'getMessageForX()' methods to construc...

virtual std::string getMessageForSymbolNotFound()

virtual std::string getMessageForReturn(const CallExpr *CallExpr)

virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex)

Produces the message of the following form: 'Msg via Nth parameter'.

virtual ~StackHintGenerator()=0

The visitor detects NoteTags and displays the event notes they contain.

static const char * getTag()

Return the tag associated with this visitor.

The oracle will decide if a report should be accepted or rejected based on the results of the Z3 solv...

The bug visitor will walk all the nodes in a path and collect all the constraints.

TrackingKind

Specifies the type of tracking for an expression.

@ Thorough

Default tracking kind – specifies that as much information should be gathered about the tracked expre...

@ Condition

Specifies that a more moderate tracking should be used for the expression value.

llvm::DenseMap< const ExplodedNode *, const ExplodedNode * > InterExplodedGraphMap

std::map< FileID, std::set< unsigned > > FilesToLineNumsMap

File IDs mapped to sets of line numbers.

@ CF

Indicates that the tracked object is a CF object.

std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef

bool EQ(InterpState &S, CodePtr OpPC)

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

bool isa(CodeGen::Address addr)

@ Result

The result type of a method or function.

const FunctionProtoType * T

Diagnostic wrappers for TextAPI types for error reporting.

llvm::SmallVector< std::pair< StringRef, StringRef >, 0 > Dependencies


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