1 //===- BugReporterVisitors.cpp - Helpers for reporting bugs ---------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines a set of BugReporter "visitors" which can be used to
10 // enhance the diagnostics reported for a bug.
12 //===----------------------------------------------------------------------===//
14 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclBase.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprCXX.h"
21 #include "clang/AST/ExprObjC.h"
22 #include "clang/AST/Stmt.h"
23 #include "clang/AST/Type.h"
24 #include "clang/ASTMatchers/ASTMatchFinder.h"
25 #include "clang/Analysis/Analyses/Dominators.h"
26 #include "clang/Analysis/AnalysisDeclContext.h"
27 #include "clang/Analysis/CFG.h"
28 #include "clang/Analysis/CFGStmtMap.h"
29 #include "clang/Analysis/PathDiagnostic.h"
30 #include "clang/Analysis/ProgramPoint.h"
31 #include "clang/Basic/IdentifierTable.h"
32 #include "clang/Basic/LLVM.h"
33 #include "clang/Basic/SourceLocation.h"
34 #include "clang/Basic/SourceManager.h"
35 #include "clang/Lex/Lexer.h"
36 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
37 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
38 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
39 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
40 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
41 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
42 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
43 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
44 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
45 #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h"
46 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
47 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
48 #include "llvm/ADT/ArrayRef.h"
49 #include "llvm/ADT/STLExtras.h"
50 #include "llvm/ADT/SmallPtrSet.h"
51 #include "llvm/ADT/SmallString.h"
52 #include "llvm/ADT/SmallVector.h"
53 #include "llvm/ADT/StringExtras.h"
54 #include "llvm/ADT/StringRef.h"
55 #include "llvm/Support/Casting.h"
56 #include "llvm/Support/ErrorHandling.h"
57 #include "llvm/Support/raw_ostream.h"
66 using namespace clang
;
68 using namespace bugreporter
;
70 //===----------------------------------------------------------------------===//
72 //===----------------------------------------------------------------------===//
74 static const Expr
*peelOffPointerArithmetic(const BinaryOperator
*B
) {
75 if (B
->isAdditiveOp() && B
->getType()->isPointerType()) {
76 if (B
->getLHS()->getType()->isPointerType()) {
78 } else if (B
->getRHS()->getType()->isPointerType()) {
85 /// \return A subexpression of @c Ex which represents the
86 /// expression-of-interest.
87 static const Expr
*peelOffOuterExpr(const Expr
*Ex
, const ExplodedNode
*N
);
89 /// Given that expression S represents a pointer that would be dereferenced,
90 /// try to find a sub-expression from which the pointer came from.
91 /// This is used for tracking down origins of a null or undefined value:
92 /// "this is null because that is null because that is null" etc.
93 /// We wipe away field and element offsets because they merely add offsets.
94 /// We also wipe away all casts except lvalue-to-rvalue casts, because the
95 /// latter represent an actual pointer dereference; however, we remove
96 /// the final lvalue-to-rvalue cast before returning from this function
97 /// because it demonstrates more clearly from where the pointer rvalue was
99 /// x->y.z ==> x (lvalue)
100 /// foo()->y.z ==> foo() (rvalue)
101 const Expr
*bugreporter::getDerefExpr(const Stmt
*S
) {
102 const auto *E
= dyn_cast
<Expr
>(S
);
107 if (const auto *CE
= dyn_cast
<CastExpr
>(E
)) {
108 if (CE
->getCastKind() == CK_LValueToRValue
) {
109 // This cast represents the load we're looking for.
112 E
= CE
->getSubExpr();
113 } else if (const auto *B
= dyn_cast
<BinaryOperator
>(E
)) {
114 // Pointer arithmetic: '*(x + 2)' -> 'x') etc.
115 if (const Expr
*Inner
= peelOffPointerArithmetic(B
)) {
117 } else if (B
->isAssignmentOp()) {
118 // Follow LHS of assignments: '*p = 404' -> 'p'.
121 // Probably more arithmetic can be pattern-matched here,
122 // but for now give up.
125 } else if (const auto *U
= dyn_cast
<UnaryOperator
>(E
)) {
126 if (U
->getOpcode() == UO_Deref
|| U
->getOpcode() == UO_AddrOf
||
127 (U
->isIncrementDecrementOp() && U
->getType()->isPointerType())) {
128 // Operators '*' and '&' don't actually mean anything.
129 // We look at casts instead.
132 // Probably more arithmetic can be pattern-matched here,
133 // but for now give up.
137 // Pattern match for a few useful cases: a[0], p->f, *p etc.
138 else if (const auto *ME
= dyn_cast
<MemberExpr
>(E
)) {
139 // This handles the case when the dereferencing of a member reference
140 // happens. This is needed, because the AST for dereferencing a
141 // member reference looks like the following:
144 // Without this special case the notes would refer to the whole object
145 // (struct, class or union variable) instead of just the relevant member.
147 if (ME
->getMemberDecl()->getType()->isReferenceType())
150 } else if (const auto *IvarRef
= dyn_cast
<ObjCIvarRefExpr
>(E
)) {
151 E
= IvarRef
->getBase();
152 } else if (const auto *AE
= dyn_cast
<ArraySubscriptExpr
>(E
)) {
154 } else if (const auto *PE
= dyn_cast
<ParenExpr
>(E
)) {
155 E
= PE
->getSubExpr();
156 } else if (const auto *FE
= dyn_cast
<FullExpr
>(E
)) {
157 E
= FE
->getSubExpr();
159 // Other arbitrary stuff.
164 // Special case: remove the final lvalue-to-rvalue cast, but do not recurse
165 // deeper into the sub-expression. This way we return the lvalue from which
166 // our pointer rvalue was loaded.
167 if (const auto *CE
= dyn_cast
<ImplicitCastExpr
>(E
))
168 if (CE
->getCastKind() == CK_LValueToRValue
)
169 E
= CE
->getSubExpr();
174 static const VarDecl
*getVarDeclForExpression(const Expr
*E
) {
175 if (const auto *DR
= dyn_cast
<DeclRefExpr
>(E
))
176 return dyn_cast
<VarDecl
>(DR
->getDecl());
180 static const MemRegion
*
181 getLocationRegionIfReference(const Expr
*E
, const ExplodedNode
*N
,
182 bool LookingForReference
= true) {
183 if (const auto *ME
= dyn_cast
<MemberExpr
>(E
)) {
184 // This handles null references from FieldRegions, for example:
185 // struct Wrapper { int &ref; };
186 // Wrapper w = { *(int *)0 };
188 const Expr
*Base
= ME
->getBase();
189 const VarDecl
*VD
= getVarDeclForExpression(Base
);
193 const auto *FD
= dyn_cast
<FieldDecl
>(ME
->getMemberDecl());
197 if (FD
->getType()->isReferenceType()) {
198 SVal StructSVal
= N
->getState()->getLValue(VD
, N
->getLocationContext());
199 return N
->getState()->getLValue(FD
, StructSVal
).getAsRegion();
204 const VarDecl
*VD
= getVarDeclForExpression(E
);
207 if (LookingForReference
&& !VD
->getType()->isReferenceType())
209 return N
->getState()->getLValue(VD
, N
->getLocationContext()).getAsRegion();
212 /// Comparing internal representations of symbolic values (via
213 /// SVal::operator==()) is a valid way to check if the value was updated,
214 /// unless it's a LazyCompoundVal that may have a different internal
215 /// representation every time it is loaded from the state. In this function we
216 /// do an approximate comparison for lazy compound values, checking that they
217 /// are the immediate snapshots of the tracked region's bindings within the
218 /// node's respective states but not really checking that these snapshots
219 /// actually contain the same set of bindings.
220 static bool hasVisibleUpdate(const ExplodedNode
*LeftNode
, SVal LeftVal
,
221 const ExplodedNode
*RightNode
, SVal RightVal
) {
222 if (LeftVal
== RightVal
)
225 const auto LLCV
= LeftVal
.getAs
<nonloc::LazyCompoundVal
>();
229 const auto RLCV
= RightVal
.getAs
<nonloc::LazyCompoundVal
>();
233 return LLCV
->getRegion() == RLCV
->getRegion() &&
234 LLCV
->getStore() == LeftNode
->getState()->getStore() &&
235 RLCV
->getStore() == RightNode
->getState()->getStore();
238 static std::optional
<SVal
> getSValForVar(const Expr
*CondVarExpr
,
239 const ExplodedNode
*N
) {
240 ProgramStateRef State
= N
->getState();
241 const LocationContext
*LCtx
= N
->getLocationContext();
244 CondVarExpr
= CondVarExpr
->IgnoreImpCasts();
246 // The declaration of the value may rely on a pointer so take its l-value.
247 // FIXME: As seen in VisitCommonDeclRefExpr, sometimes DeclRefExpr may
248 // evaluate to a FieldRegion when it refers to a declaration of a lambda
249 // capture variable. We most likely need to duplicate that logic here.
250 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(CondVarExpr
))
251 if (const auto *VD
= dyn_cast
<VarDecl
>(DRE
->getDecl()))
252 return State
->getSVal(State
->getLValue(VD
, LCtx
));
254 if (const auto *ME
= dyn_cast
<MemberExpr
>(CondVarExpr
))
255 if (const auto *FD
= dyn_cast
<FieldDecl
>(ME
->getMemberDecl()))
256 if (auto FieldL
= State
->getSVal(ME
, LCtx
).getAs
<Loc
>())
257 return State
->getRawSVal(*FieldL
, FD
->getType());
262 static std::optional
<const llvm::APSInt
*>
263 getConcreteIntegerValue(const Expr
*CondVarExpr
, const ExplodedNode
*N
) {
265 if (std::optional
<SVal
> V
= getSValForVar(CondVarExpr
, N
))
266 if (auto CI
= V
->getAs
<nonloc::ConcreteInt
>())
267 return CI
->getValue().get();
271 static bool isVarAnInterestingCondition(const Expr
*CondVarExpr
,
272 const ExplodedNode
*N
,
273 const PathSensitiveBugReport
*B
) {
274 // Even if this condition is marked as interesting, it isn't *that*
275 // interesting if it didn't happen in a nested stackframe, the user could just
276 // follow the arrows.
277 if (!B
->getErrorNode()->getStackFrame()->isParentOf(N
->getStackFrame()))
280 if (std::optional
<SVal
> V
= getSValForVar(CondVarExpr
, N
))
281 if (std::optional
<bugreporter::TrackingKind
> K
=
282 B
->getInterestingnessKind(*V
))
283 return *K
== bugreporter::TrackingKind::Condition
;
288 static bool isInterestingExpr(const Expr
*E
, const ExplodedNode
*N
,
289 const PathSensitiveBugReport
*B
) {
290 if (std::optional
<SVal
> V
= getSValForVar(E
, N
))
291 return B
->getInterestingnessKind(*V
).has_value();
295 /// \return name of the macro inside the location \p Loc.
296 static StringRef
getMacroName(SourceLocation Loc
,
297 BugReporterContext
&BRC
) {
298 return Lexer::getImmediateMacroName(
300 BRC
.getSourceManager(),
301 BRC
.getASTContext().getLangOpts());
304 /// \return Whether given spelling location corresponds to an expansion
305 /// of a function-like macro.
306 static bool isFunctionMacroExpansion(SourceLocation Loc
,
307 const SourceManager
&SM
) {
308 if (!Loc
.isMacroID())
310 while (SM
.isMacroArgExpansion(Loc
))
311 Loc
= SM
.getImmediateExpansionRange(Loc
).getBegin();
312 std::pair
<FileID
, unsigned> TLInfo
= SM
.getDecomposedLoc(Loc
);
313 SrcMgr::SLocEntry SE
= SM
.getSLocEntry(TLInfo
.first
);
314 const SrcMgr::ExpansionInfo
&EInfo
= SE
.getExpansion();
315 return EInfo
.isFunctionMacroExpansion();
318 /// \return Whether \c RegionOfInterest was modified at \p N,
319 /// where \p ValueAfter is \c RegionOfInterest's value at the end of the
321 static bool wasRegionOfInterestModifiedAt(const SubRegion
*RegionOfInterest
,
322 const ExplodedNode
*N
,
324 ProgramStateRef State
= N
->getState();
325 ProgramStateManager
&Mgr
= N
->getState()->getStateManager();
327 if (!N
->getLocationAs
<PostStore
>() && !N
->getLocationAs
<PostInitializer
>() &&
328 !N
->getLocationAs
<PostStmt
>())
331 // Writing into region of interest.
332 if (auto PS
= N
->getLocationAs
<PostStmt
>())
333 if (auto *BO
= PS
->getStmtAs
<BinaryOperator
>())
334 if (BO
->isAssignmentOp() && RegionOfInterest
->isSubRegionOf(
335 N
->getSVal(BO
->getLHS()).getAsRegion()))
338 // SVal after the state is possibly different.
339 SVal ValueAtN
= N
->getState()->getSVal(RegionOfInterest
);
340 if (!Mgr
.getSValBuilder()
341 .areEqual(State
, ValueAtN
, ValueAfter
)
342 .isConstrainedTrue() &&
343 (!ValueAtN
.isUndef() || !ValueAfter
.isUndef()))
349 //===----------------------------------------------------------------------===//
350 // Implementation of BugReporterVisitor.
351 //===----------------------------------------------------------------------===//
353 PathDiagnosticPieceRef
BugReporterVisitor::getEndPath(BugReporterContext
&,
354 const ExplodedNode
*,
355 PathSensitiveBugReport
&) {
359 void BugReporterVisitor::finalizeVisitor(BugReporterContext
&,
360 const ExplodedNode
*,
361 PathSensitiveBugReport
&) {}
363 PathDiagnosticPieceRef
364 BugReporterVisitor::getDefaultEndPath(const BugReporterContext
&BRC
,
365 const ExplodedNode
*EndPathNode
,
366 const PathSensitiveBugReport
&BR
) {
367 PathDiagnosticLocation L
= BR
.getLocation();
368 const auto &Ranges
= BR
.getRanges();
370 // Only add the statement itself as a range if we didn't specify any
371 // special ranges for this report.
372 auto P
= std::make_shared
<PathDiagnosticEventPiece
>(
373 L
, BR
.getDescription(), Ranges
.begin() == Ranges
.end());
374 for (SourceRange Range
: Ranges
)
380 //===----------------------------------------------------------------------===//
381 // Implementation of NoStateChangeFuncVisitor.
382 //===----------------------------------------------------------------------===//
384 bool NoStateChangeFuncVisitor::isModifiedInFrame(const ExplodedNode
*N
) {
385 const LocationContext
*Ctx
= N
->getLocationContext();
386 const StackFrameContext
*SCtx
= Ctx
->getStackFrame();
387 if (!FramesModifyingCalculated
.count(SCtx
))
388 findModifyingFrames(N
);
389 return FramesModifying
.count(SCtx
);
392 void NoStateChangeFuncVisitor::markFrameAsModifying(
393 const StackFrameContext
*SCtx
) {
394 while (!SCtx
->inTopFrame()) {
395 auto p
= FramesModifying
.insert(SCtx
);
397 break; // Frame and all its parents already inserted.
399 SCtx
= SCtx
->getParent()->getStackFrame();
403 static const ExplodedNode
*getMatchingCallExitEnd(const ExplodedNode
*N
) {
404 assert(N
->getLocationAs
<CallEnter
>());
405 // The stackframe of the callee is only found in the nodes succeeding
406 // the CallEnter node. CallEnter's stack frame refers to the caller.
407 const StackFrameContext
*OrigSCtx
= N
->getFirstSucc()->getStackFrame();
409 // Similarly, the nodes preceding CallExitEnd refer to the callee's stack
411 auto IsMatchingCallExitEnd
= [OrigSCtx
](const ExplodedNode
*N
) {
412 return N
->getLocationAs
<CallExitEnd
>() &&
413 OrigSCtx
== N
->getFirstPred()->getStackFrame();
415 while (N
&& !IsMatchingCallExitEnd(N
)) {
416 assert(N
->succ_size() <= 1 &&
417 "This function is to be used on the trimmed ExplodedGraph!");
418 N
= N
->getFirstSucc();
423 void NoStateChangeFuncVisitor::findModifyingFrames(
424 const ExplodedNode
*const CallExitBeginN
) {
426 assert(CallExitBeginN
->getLocationAs
<CallExitBegin
>());
428 const StackFrameContext
*const OriginalSCtx
=
429 CallExitBeginN
->getLocationContext()->getStackFrame();
431 const ExplodedNode
*CurrCallExitBeginN
= CallExitBeginN
;
432 const StackFrameContext
*CurrentSCtx
= OriginalSCtx
;
434 for (const ExplodedNode
*CurrN
= CallExitBeginN
; CurrN
;
435 CurrN
= CurrN
->getFirstPred()) {
436 // Found a new inlined call.
437 if (CurrN
->getLocationAs
<CallExitBegin
>()) {
438 CurrCallExitBeginN
= CurrN
;
439 CurrentSCtx
= CurrN
->getStackFrame();
440 FramesModifyingCalculated
.insert(CurrentSCtx
);
441 // We won't see a change in between two identical exploded nodes: skip.
445 if (auto CE
= CurrN
->getLocationAs
<CallEnter
>()) {
446 if (const ExplodedNode
*CallExitEndN
= getMatchingCallExitEnd(CurrN
))
447 if (wasModifiedInFunction(CurrN
, CallExitEndN
))
448 markFrameAsModifying(CurrentSCtx
);
450 // We exited this inlined call, lets actualize the stack frame.
451 CurrentSCtx
= CurrN
->getStackFrame();
453 // Stop calculating at the current function, but always regard it as
454 // modifying, so we can avoid notes like this:
456 // F.field = 0; // note: 0 assigned to 'F.field'
457 // // note: returning without writing to 'F.field'
459 if (CE
->getCalleeContext() == OriginalSCtx
) {
460 markFrameAsModifying(CurrentSCtx
);
465 if (wasModifiedBeforeCallExit(CurrN
, CurrCallExitBeginN
))
466 markFrameAsModifying(CurrentSCtx
);
470 PathDiagnosticPieceRef
NoStateChangeFuncVisitor::VisitNode(
471 const ExplodedNode
*N
, BugReporterContext
&BR
, PathSensitiveBugReport
&R
) {
473 const LocationContext
*Ctx
= N
->getLocationContext();
474 const StackFrameContext
*SCtx
= Ctx
->getStackFrame();
475 ProgramStateRef State
= N
->getState();
476 auto CallExitLoc
= N
->getLocationAs
<CallExitBegin
>();
478 // No diagnostic if region was modified inside the frame.
479 if (!CallExitLoc
|| isModifiedInFrame(N
))
482 CallEventRef
<> Call
=
483 BR
.getStateManager().getCallEventManager().getCaller(SCtx
, State
);
485 // Optimistically suppress uninitialized value bugs that result
486 // from system headers having a chance to initialize the value
487 // but failing to do so. It's too unlikely a system header's fault.
488 // It's much more likely a situation in which the function has a failure
489 // mode that the user decided not to check. If we want to hunt such
490 // omitted checks, we should provide an explicit function-specific note
491 // describing the precondition under which the function isn't supposed to
492 // initialize its out-parameter, and additionally check that such
493 // precondition can actually be fulfilled on the current path.
494 if (Call
->isInSystemHeader()) {
495 // We make an exception for system header functions that have no branches.
496 // Such functions unconditionally fail to initialize the variable.
497 // If they call other functions that have more paths within them,
498 // this suppression would still apply when we visit these inner functions.
499 // One common example of a standard function that doesn't ever initialize
500 // its out parameter is operator placement new; it's up to the follow-up
501 // constructor (if any) to initialize the memory.
502 if (!N
->getStackFrame()->getCFG()->isLinear()) {
504 R
.markInvalid(&i
, nullptr);
509 if (const auto *MC
= dyn_cast
<ObjCMethodCall
>(Call
)) {
510 // If we failed to construct a piece for self, we still want to check
511 // whether the entity of interest is in a parameter.
512 if (PathDiagnosticPieceRef Piece
= maybeEmitNoteForObjCSelf(R
, *MC
, N
))
516 if (const auto *CCall
= dyn_cast
<CXXConstructorCall
>(Call
)) {
517 // Do not generate diagnostics for not modified parameters in
519 return maybeEmitNoteForCXXThis(R
, *CCall
, N
);
522 return maybeEmitNoteForParameters(R
, *Call
, N
);
525 /// \return Whether the method declaration \p Parent
526 /// syntactically has a binary operation writing into the ivar \p Ivar.
527 static bool potentiallyWritesIntoIvar(const Decl
*Parent
,
528 const ObjCIvarDecl
*Ivar
) {
529 using namespace ast_matchers
;
530 const char *IvarBind
= "Ivar";
531 if (!Parent
|| !Parent
->hasBody())
533 StatementMatcher WriteIntoIvarM
= binaryOperator(
534 hasOperatorName("="),
535 hasLHS(ignoringParenImpCasts(
536 objcIvarRefExpr(hasDeclaration(equalsNode(Ivar
))).bind(IvarBind
))));
537 StatementMatcher ParentM
= stmt(hasDescendant(WriteIntoIvarM
));
538 auto Matches
= match(ParentM
, *Parent
->getBody(), Parent
->getASTContext());
539 for (BoundNodes
&Match
: Matches
) {
540 auto IvarRef
= Match
.getNodeAs
<ObjCIvarRefExpr
>(IvarBind
);
541 if (IvarRef
->isFreeIvar())
544 const Expr
*Base
= IvarRef
->getBase();
545 if (const auto *ICE
= dyn_cast
<ImplicitCastExpr
>(Base
))
546 Base
= ICE
->getSubExpr();
548 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(Base
))
549 if (const auto *ID
= dyn_cast
<ImplicitParamDecl
>(DRE
->getDecl()))
550 if (ID
->getParameterKind() == ImplicitParamKind::ObjCSelf
)
558 /// Attempts to find the region of interest in a given CXX decl,
559 /// by either following the base classes or fields.
560 /// Dereferences fields up to a given recursion limit.
561 /// Note that \p Vec is passed by value, leading to quadratic copying cost,
562 /// but it's OK in practice since its length is limited to DEREFERENCE_LIMIT.
563 /// \return A chain fields leading to the region of interest or std::nullopt.
564 const std::optional
<NoStoreFuncVisitor::RegionVector
>
565 NoStoreFuncVisitor::findRegionOfInterestInRecord(
566 const RecordDecl
*RD
, ProgramStateRef State
, const MemRegion
*R
,
567 const NoStoreFuncVisitor::RegionVector
&Vec
/* = {} */,
568 int depth
/* = 0 */) {
570 if (depth
== DEREFERENCE_LIMIT
) // Limit the recursion depth.
573 if (const auto *RDX
= dyn_cast
<CXXRecordDecl
>(RD
))
574 if (!RDX
->hasDefinition())
577 // Recursively examine the base classes.
578 // Note that following base classes does not increase the recursion depth.
579 if (const auto *RDX
= dyn_cast
<CXXRecordDecl
>(RD
))
580 for (const auto &II
: RDX
->bases())
581 if (const RecordDecl
*RRD
= II
.getType()->getAsRecordDecl())
582 if (std::optional
<RegionVector
> Out
=
583 findRegionOfInterestInRecord(RRD
, State
, R
, Vec
, depth
))
586 for (const FieldDecl
*I
: RD
->fields()) {
587 QualType FT
= I
->getType();
588 const FieldRegion
*FR
= MmrMgr
.getFieldRegion(I
, cast
<SubRegion
>(R
));
589 const SVal V
= State
->getSVal(FR
);
590 const MemRegion
*VR
= V
.getAsRegion();
592 RegionVector VecF
= Vec
;
595 if (RegionOfInterest
== VR
)
598 if (const RecordDecl
*RRD
= FT
->getAsRecordDecl())
600 findRegionOfInterestInRecord(RRD
, State
, FR
, VecF
, depth
+ 1))
603 QualType PT
= FT
->getPointeeType();
604 if (PT
.isNull() || PT
->isVoidType() || !VR
)
607 if (const RecordDecl
*RRD
= PT
->getAsRecordDecl())
608 if (std::optional
<RegionVector
> Out
=
609 findRegionOfInterestInRecord(RRD
, State
, VR
, VecF
, depth
+ 1))
616 PathDiagnosticPieceRef
617 NoStoreFuncVisitor::maybeEmitNoteForObjCSelf(PathSensitiveBugReport
&R
,
618 const ObjCMethodCall
&Call
,
619 const ExplodedNode
*N
) {
620 if (const auto *IvarR
= dyn_cast
<ObjCIvarRegion
>(RegionOfInterest
)) {
621 const MemRegion
*SelfRegion
= Call
.getReceiverSVal().getAsRegion();
622 if (RegionOfInterest
->isSubRegionOf(SelfRegion
) &&
623 potentiallyWritesIntoIvar(Call
.getRuntimeDefinition().getDecl(),
625 return maybeEmitNote(R
, Call
, N
, {}, SelfRegion
, "self",
626 /*FirstIsReferenceType=*/false, 1);
631 PathDiagnosticPieceRef
632 NoStoreFuncVisitor::maybeEmitNoteForCXXThis(PathSensitiveBugReport
&R
,
633 const CXXConstructorCall
&Call
,
634 const ExplodedNode
*N
) {
635 const MemRegion
*ThisR
= Call
.getCXXThisVal().getAsRegion();
636 if (RegionOfInterest
->isSubRegionOf(ThisR
) && !Call
.getDecl()->isImplicit())
637 return maybeEmitNote(R
, Call
, N
, {}, ThisR
, "this",
638 /*FirstIsReferenceType=*/false, 1);
640 // Do not generate diagnostics for not modified parameters in
645 /// \return whether \p Ty points to a const type, or is a const reference.
646 static bool isPointerToConst(QualType Ty
) {
647 return !Ty
->getPointeeType().isNull() &&
648 Ty
->getPointeeType().getCanonicalType().isConstQualified();
651 PathDiagnosticPieceRef
NoStoreFuncVisitor::maybeEmitNoteForParameters(
652 PathSensitiveBugReport
&R
, const CallEvent
&Call
, const ExplodedNode
*N
) {
653 ArrayRef
<ParmVarDecl
*> Parameters
= Call
.parameters();
654 for (unsigned I
= 0; I
< Call
.getNumArgs() && I
< Parameters
.size(); ++I
) {
655 const ParmVarDecl
*PVD
= Parameters
[I
];
656 SVal V
= Call
.getArgSVal(I
);
657 bool ParamIsReferenceType
= PVD
->getType()->isReferenceType();
658 std::string ParamName
= PVD
->getNameAsString();
660 unsigned IndirectionLevel
= 1;
661 QualType T
= PVD
->getType();
662 while (const MemRegion
*MR
= V
.getAsRegion()) {
663 if (RegionOfInterest
->isSubRegionOf(MR
) && !isPointerToConst(T
))
664 return maybeEmitNote(R
, Call
, N
, {}, MR
, ParamName
,
665 ParamIsReferenceType
, IndirectionLevel
);
667 QualType PT
= T
->getPointeeType();
668 if (PT
.isNull() || PT
->isVoidType())
671 ProgramStateRef State
= N
->getState();
673 if (const RecordDecl
*RD
= PT
->getAsRecordDecl())
674 if (std::optional
<RegionVector
> P
=
675 findRegionOfInterestInRecord(RD
, State
, MR
))
676 return maybeEmitNote(R
, Call
, N
, *P
, RegionOfInterest
, ParamName
,
677 ParamIsReferenceType
, IndirectionLevel
);
679 V
= State
->getSVal(MR
, PT
);
688 bool NoStoreFuncVisitor::wasModifiedBeforeCallExit(
689 const ExplodedNode
*CurrN
, const ExplodedNode
*CallExitBeginN
) {
690 return ::wasRegionOfInterestModifiedAt(
691 RegionOfInterest
, CurrN
,
692 CallExitBeginN
->getState()->getSVal(RegionOfInterest
));
695 static llvm::StringLiteral WillBeUsedForACondition
=
696 ", which participates in a condition later";
698 PathDiagnosticPieceRef
NoStoreFuncVisitor::maybeEmitNote(
699 PathSensitiveBugReport
&R
, const CallEvent
&Call
, const ExplodedNode
*N
,
700 const RegionVector
&FieldChain
, const MemRegion
*MatchedRegion
,
701 StringRef FirstElement
, bool FirstIsReferenceType
,
702 unsigned IndirectionLevel
) {
704 PathDiagnosticLocation L
=
705 PathDiagnosticLocation::create(N
->getLocation(), SM
);
707 // For now this shouldn't trigger, but once it does (as we add more
708 // functions to the body farm), we'll need to decide if these reports
709 // are worth suppressing as well.
710 if (!L
.hasValidLocation())
713 SmallString
<256> sbuf
;
714 llvm::raw_svector_ostream
os(sbuf
);
715 os
<< "Returning without writing to '";
717 // Do not generate the note if failed to pretty-print.
718 if (!prettyPrintRegionName(FieldChain
, MatchedRegion
, FirstElement
,
719 FirstIsReferenceType
, IndirectionLevel
, os
))
723 if (TKind
== bugreporter::TrackingKind::Condition
)
724 os
<< WillBeUsedForACondition
;
725 return std::make_shared
<PathDiagnosticEventPiece
>(L
, os
.str());
728 bool NoStoreFuncVisitor::prettyPrintRegionName(const RegionVector
&FieldChain
,
729 const MemRegion
*MatchedRegion
,
730 StringRef FirstElement
,
731 bool FirstIsReferenceType
,
732 unsigned IndirectionLevel
,
733 llvm::raw_svector_ostream
&os
) {
735 if (FirstIsReferenceType
)
738 RegionVector RegionSequence
;
740 // Add the regions in the reverse order, then reverse the resulting array.
741 assert(RegionOfInterest
->isSubRegionOf(MatchedRegion
));
742 const MemRegion
*R
= RegionOfInterest
;
743 while (R
!= MatchedRegion
) {
744 RegionSequence
.push_back(R
);
745 R
= cast
<SubRegion
>(R
)->getSuperRegion();
747 std::reverse(RegionSequence
.begin(), RegionSequence
.end());
748 RegionSequence
.append(FieldChain
.begin(), FieldChain
.end());
751 for (const MemRegion
*R
: RegionSequence
) {
753 // Just keep going up to the base region.
754 // Element regions may appear due to casts.
755 if (isa
<CXXBaseObjectRegion
, CXXTempObjectRegion
>(R
))
759 Sep
= prettyPrintFirstElement(FirstElement
,
760 /*MoreItemsExpected=*/true,
761 IndirectionLevel
, os
);
765 // Can only reasonably pretty-print DeclRegions.
766 if (!isa
<DeclRegion
>(R
))
769 const auto *DR
= cast
<DeclRegion
>(R
);
770 Sep
= DR
->getValueType()->isAnyPointerType() ? "->" : ".";
771 DR
->getDecl()->getDeclName().print(os
, PP
);
775 prettyPrintFirstElement(FirstElement
,
776 /*MoreItemsExpected=*/false, IndirectionLevel
, os
);
780 StringRef
NoStoreFuncVisitor::prettyPrintFirstElement(
781 StringRef FirstElement
, bool MoreItemsExpected
, int IndirectionLevel
,
782 llvm::raw_svector_ostream
&os
) {
785 if (IndirectionLevel
> 0 && MoreItemsExpected
) {
790 if (IndirectionLevel
> 0 && MoreItemsExpected
)
793 for (int i
= 0; i
< IndirectionLevel
; i
++)
797 if (IndirectionLevel
> 0 && MoreItemsExpected
)
803 //===----------------------------------------------------------------------===//
804 // Implementation of MacroNullReturnSuppressionVisitor.
805 //===----------------------------------------------------------------------===//
809 /// Suppress null-pointer-dereference bugs where dereferenced null was returned
811 class MacroNullReturnSuppressionVisitor final
: public BugReporterVisitor
{
812 const SubRegion
*RegionOfInterest
;
813 const SVal ValueAtDereference
;
815 // Do not invalidate the reports where the value was modified
816 // after it got assigned to from the macro.
817 bool WasModified
= false;
820 MacroNullReturnSuppressionVisitor(const SubRegion
*R
, const SVal V
)
821 : RegionOfInterest(R
), ValueAtDereference(V
) {}
823 PathDiagnosticPieceRef
VisitNode(const ExplodedNode
*N
,
824 BugReporterContext
&BRC
,
825 PathSensitiveBugReport
&BR
) override
{
829 auto BugPoint
= BR
.getErrorNode()->getLocation().getAs
<StmtPoint
>();
833 const SourceManager
&SMgr
= BRC
.getSourceManager();
834 if (auto Loc
= matchAssignment(N
)) {
835 if (isFunctionMacroExpansion(*Loc
, SMgr
)) {
836 std::string MacroName
= std::string(getMacroName(*Loc
, BRC
));
837 SourceLocation BugLoc
= BugPoint
->getStmt()->getBeginLoc();
838 if (!BugLoc
.isMacroID() || getMacroName(BugLoc
, BRC
) != MacroName
)
839 BR
.markInvalid(getTag(), MacroName
.c_str());
843 if (wasRegionOfInterestModifiedAt(RegionOfInterest
, N
, ValueAtDereference
))
849 static void addMacroVisitorIfNecessary(
850 const ExplodedNode
*N
, const MemRegion
*R
,
851 bool EnableNullFPSuppression
, PathSensitiveBugReport
&BR
,
853 AnalyzerOptions
&Options
= N
->getState()->getAnalysisManager().options
;
854 if (EnableNullFPSuppression
&& Options
.ShouldSuppressNullReturnPaths
&&
856 BR
.addVisitor
<MacroNullReturnSuppressionVisitor
>(R
->getAs
<SubRegion
>(),
860 void* getTag() const {
862 return static_cast<void *>(&Tag
);
865 void Profile(llvm::FoldingSetNodeID
&ID
) const override
{
866 ID
.AddPointer(getTag());
870 /// \return Source location of right hand side of an assignment
871 /// into \c RegionOfInterest, empty optional if none found.
872 std::optional
<SourceLocation
> matchAssignment(const ExplodedNode
*N
) {
873 const Stmt
*S
= N
->getStmtForDiagnostics();
874 ProgramStateRef State
= N
->getState();
875 auto *LCtx
= N
->getLocationContext();
879 if (const auto *DS
= dyn_cast
<DeclStmt
>(S
)) {
880 if (const auto *VD
= dyn_cast
<VarDecl
>(DS
->getSingleDecl()))
881 if (const Expr
*RHS
= VD
->getInit())
882 if (RegionOfInterest
->isSubRegionOf(
883 State
->getLValue(VD
, LCtx
).getAsRegion()))
884 return RHS
->getBeginLoc();
885 } else if (const auto *BO
= dyn_cast
<BinaryOperator
>(S
)) {
886 const MemRegion
*R
= N
->getSVal(BO
->getLHS()).getAsRegion();
887 const Expr
*RHS
= BO
->getRHS();
888 if (BO
->isAssignmentOp() && RegionOfInterest
->isSubRegionOf(R
)) {
889 return RHS
->getBeginLoc();
896 } // end of anonymous namespace
900 /// Emits an extra note at the return statement of an interesting stack frame.
902 /// The returned value is marked as an interesting value, and if it's null,
903 /// adds a visitor to track where it became null.
905 /// This visitor is intended to be used when another visitor discovers that an
906 /// interesting value comes from an inlined function call.
907 class ReturnVisitor
: public TrackingBugReporterVisitor
{
908 const StackFrameContext
*CalleeSFC
;
915 bool EnableNullFPSuppression
;
916 bool ShouldInvalidate
= true;
917 AnalyzerOptions
& Options
;
918 bugreporter::TrackingKind TKind
;
921 ReturnVisitor(TrackerRef ParentTracker
, const StackFrameContext
*Frame
,
922 bool Suppressed
, AnalyzerOptions
&Options
,
923 bugreporter::TrackingKind TKind
)
924 : TrackingBugReporterVisitor(ParentTracker
), CalleeSFC(Frame
),
925 EnableNullFPSuppression(Suppressed
), Options(Options
), TKind(TKind
) {}
927 static void *getTag() {
929 return static_cast<void *>(&Tag
);
932 void Profile(llvm::FoldingSetNodeID
&ID
) const override
{
933 ID
.AddPointer(ReturnVisitor::getTag());
934 ID
.AddPointer(CalleeSFC
);
935 ID
.AddBoolean(EnableNullFPSuppression
);
938 PathDiagnosticPieceRef
visitNodeInitial(const ExplodedNode
*N
,
939 BugReporterContext
&BRC
,
940 PathSensitiveBugReport
&BR
) {
941 // Only print a message at the interesting return statement.
942 if (N
->getLocationContext() != CalleeSFC
)
945 std::optional
<StmtPoint
> SP
= N
->getLocationAs
<StmtPoint
>();
949 const auto *Ret
= dyn_cast
<ReturnStmt
>(SP
->getStmt());
953 // Okay, we're at the right return statement, but do we have the return
955 ProgramStateRef State
= N
->getState();
956 SVal V
= State
->getSVal(Ret
, CalleeSFC
);
957 if (V
.isUnknownOrUndef())
960 // Don't print any more notes after this one.
963 const Expr
*RetE
= Ret
->getRetValue();
964 assert(RetE
&& "Tracking a return value for a void function");
966 // Handle cases where a reference is returned and then immediately used.
967 std::optional
<Loc
> LValue
;
968 if (RetE
->isGLValue()) {
969 if ((LValue
= V
.getAs
<Loc
>())) {
970 SVal RValue
= State
->getRawSVal(*LValue
, RetE
->getType());
971 if (isa
<DefinedSVal
>(RValue
))
976 // Ignore aggregate rvalues.
977 if (isa
<nonloc::LazyCompoundVal
, nonloc::CompoundVal
>(V
))
980 RetE
= RetE
->IgnoreParenCasts();
982 // Let's track the return value.
983 getParentTracker().track(RetE
, N
, {TKind
, EnableNullFPSuppression
});
985 // Build an appropriate message based on the return value.
987 llvm::raw_svector_ostream
Out(Msg
);
989 bool WouldEventBeMeaningless
= false;
991 if (State
->isNull(V
).isConstrainedTrue()) {
994 // If we have counter-suppression enabled, make sure we keep visiting
995 // future nodes. We want to emit a path note as well, in case
996 // the report is resurrected as valid later on.
997 if (EnableNullFPSuppression
&&
998 Options
.ShouldAvoidSuppressingNullArgumentPaths
)
999 Mode
= MaybeUnsuppress
;
1001 if (RetE
->getType()->isObjCObjectPointerType()) {
1002 Out
<< "Returning nil";
1004 Out
<< "Returning null pointer";
1007 Out
<< "Returning zero";
1011 if (auto CI
= V
.getAs
<nonloc::ConcreteInt
>()) {
1012 Out
<< "Returning the value " << CI
->getValue();
1014 // There is nothing interesting about returning a value, when it is
1015 // plain value without any constraints, and the function is guaranteed
1016 // to return that every time. We could use CFG::isLinear() here, but
1017 // constexpr branches are obvious to the compiler, not necesserily to
1019 if (N
->getCFG().size() == 3)
1020 WouldEventBeMeaningless
= true;
1022 Out
<< (isa
<Loc
>(V
) ? "Returning pointer" : "Returning value");
1027 if (const MemRegion
*MR
= LValue
->getAsRegion()) {
1028 if (MR
->canPrintPretty()) {
1029 Out
<< " (reference to ";
1030 MR
->printPretty(Out
);
1035 // FIXME: We should have a more generalized location printing mechanism.
1036 if (const auto *DR
= dyn_cast
<DeclRefExpr
>(RetE
))
1037 if (const auto *DD
= dyn_cast
<DeclaratorDecl
>(DR
->getDecl()))
1038 Out
<< " (loaded from '" << *DD
<< "')";
1041 PathDiagnosticLocation
L(Ret
, BRC
.getSourceManager(), CalleeSFC
);
1042 if (!L
.isValid() || !L
.asLocation().isValid())
1045 if (TKind
== bugreporter::TrackingKind::Condition
)
1046 Out
<< WillBeUsedForACondition
;
1048 auto EventPiece
= std::make_shared
<PathDiagnosticEventPiece
>(L
, Out
.str());
1050 // If we determined that the note is meaningless, make it prunable, and
1051 // don't mark the stackframe interesting.
1052 if (WouldEventBeMeaningless
)
1053 EventPiece
->setPrunable(true);
1055 BR
.markInteresting(CalleeSFC
);
1060 PathDiagnosticPieceRef
visitNodeMaybeUnsuppress(const ExplodedNode
*N
,
1061 BugReporterContext
&BRC
,
1062 PathSensitiveBugReport
&BR
) {
1063 assert(Options
.ShouldAvoidSuppressingNullArgumentPaths
);
1065 // Are we at the entry node for this call?
1066 std::optional
<CallEnter
> CE
= N
->getLocationAs
<CallEnter
>();
1070 if (CE
->getCalleeContext() != CalleeSFC
)
1075 // Don't automatically suppress a report if one of the arguments is
1076 // known to be a null pointer. Instead, start tracking /that/ null
1077 // value back to its origin.
1078 ProgramStateManager
&StateMgr
= BRC
.getStateManager();
1079 CallEventManager
&CallMgr
= StateMgr
.getCallEventManager();
1081 ProgramStateRef State
= N
->getState();
1082 CallEventRef
<> Call
= CallMgr
.getCaller(CalleeSFC
, State
);
1083 for (unsigned I
= 0, E
= Call
->getNumArgs(); I
!= E
; ++I
) {
1084 std::optional
<Loc
> ArgV
= Call
->getArgSVal(I
).getAs
<Loc
>();
1088 const Expr
*ArgE
= Call
->getArgExpr(I
);
1092 // Is it possible for this argument to be non-null?
1093 if (!State
->isNull(*ArgV
).isConstrainedTrue())
1096 if (getParentTracker()
1097 .track(ArgE
, N
, {TKind
, EnableNullFPSuppression
})
1098 .FoundSomethingToTrack
)
1099 ShouldInvalidate
= false;
1101 // If we /can't/ track the null pointer, we should err on the side of
1102 // false negatives, and continue towards marking this report invalid.
1103 // (We will still look at the other arguments, though.)
1109 PathDiagnosticPieceRef
VisitNode(const ExplodedNode
*N
,
1110 BugReporterContext
&BRC
,
1111 PathSensitiveBugReport
&BR
) override
{
1114 return visitNodeInitial(N
, BRC
, BR
);
1115 case MaybeUnsuppress
:
1116 return visitNodeMaybeUnsuppress(N
, BRC
, BR
);
1121 llvm_unreachable("Invalid visit mode!");
1124 void finalizeVisitor(BugReporterContext
&, const ExplodedNode
*,
1125 PathSensitiveBugReport
&BR
) override
{
1126 if (EnableNullFPSuppression
&& ShouldInvalidate
)
1127 BR
.markInvalid(ReturnVisitor::getTag(), CalleeSFC
);
1131 //===----------------------------------------------------------------------===//
1133 //===----------------------------------------------------------------------===//
1135 /// Finds last store into the given region,
1136 /// which is different from a given symbolic value.
1137 class StoreSiteFinder final
: public TrackingBugReporterVisitor
{
1140 bool Satisfied
= false;
1142 TrackingOptions Options
;
1143 const StackFrameContext
*OriginSFC
;
1146 /// \param V We're searching for the store where \c R received this value.
1147 /// \param R The region we're tracking.
1148 /// \param Options Tracking behavior options.
1149 /// \param OriginSFC Only adds notes when the last store happened in a
1150 /// different stackframe to this one. Disregarded if the tracking kind
1152 /// This is useful, because for non-tracked regions, notes about
1153 /// changes to its value in a nested stackframe could be pruned, and
1154 /// this visitor can prevent that without polluting the bugpath too
1156 StoreSiteFinder(bugreporter::TrackerRef ParentTracker
, SVal V
,
1157 const MemRegion
*R
, TrackingOptions Options
,
1158 const StackFrameContext
*OriginSFC
= nullptr)
1159 : TrackingBugReporterVisitor(ParentTracker
), R(R
), V(V
), Options(Options
),
1160 OriginSFC(OriginSFC
) {
1164 void Profile(llvm::FoldingSetNodeID
&ID
) const override
;
1166 PathDiagnosticPieceRef
VisitNode(const ExplodedNode
*N
,
1167 BugReporterContext
&BRC
,
1168 PathSensitiveBugReport
&BR
) override
;
1172 void StoreSiteFinder::Profile(llvm::FoldingSetNodeID
&ID
) const {
1174 ID
.AddPointer(&tag
);
1177 ID
.AddInteger(static_cast<int>(Options
.Kind
));
1178 ID
.AddBoolean(Options
.EnableNullFPSuppression
);
1181 /// Returns true if \p N represents the DeclStmt declaring and initializing
1183 static bool isInitializationOfVar(const ExplodedNode
*N
, const VarRegion
*VR
) {
1184 std::optional
<PostStmt
> P
= N
->getLocationAs
<PostStmt
>();
1188 const DeclStmt
*DS
= P
->getStmtAs
<DeclStmt
>();
1192 if (DS
->getSingleDecl() != VR
->getDecl())
1195 const MemSpaceRegion
*VarSpace
= VR
->getMemorySpace();
1196 const auto *FrameSpace
= dyn_cast
<StackSpaceRegion
>(VarSpace
);
1198 // If we ever directly evaluate global DeclStmts, this assertion will be
1199 // invalid, but this still seems preferable to silently accepting an
1200 // initialization that may be for a path-sensitive variable.
1201 assert(VR
->getDecl()->isStaticLocal() && "non-static stackless VarRegion");
1205 assert(VR
->getDecl()->hasLocalStorage());
1206 const LocationContext
*LCtx
= N
->getLocationContext();
1207 return FrameSpace
->getStackFrame() == LCtx
->getStackFrame();
1210 static bool isObjCPointer(const MemRegion
*R
) {
1211 if (R
->isBoundable())
1212 if (const auto *TR
= dyn_cast
<TypedValueRegion
>(R
))
1213 return TR
->getValueType()->isObjCObjectPointerType();
1218 static bool isObjCPointer(const ValueDecl
*D
) {
1219 return D
->getType()->isObjCObjectPointerType();
1222 /// Show diagnostics for initializing or declaring a region \p R with a bad value.
1223 static void showBRDiagnostics(llvm::raw_svector_ostream
&OS
, StoreInfo SI
) {
1224 const bool HasPrefix
= SI
.Dest
->canPrintPretty();
1227 SI
.Dest
->printPretty(OS
);
1231 const char *Action
= nullptr;
1233 switch (SI
.StoreKind
) {
1234 case StoreInfo::Initialization
:
1235 Action
= HasPrefix
? "initialized to " : "Initializing to ";
1237 case StoreInfo::BlockCapture
:
1238 Action
= HasPrefix
? "captured by block as " : "Captured by block as ";
1241 llvm_unreachable("Unexpected store kind");
1244 if (isa
<loc::ConcreteInt
>(SI
.Value
)) {
1245 OS
<< Action
<< (isObjCPointer(SI
.Dest
) ? "nil" : "a null pointer value");
1247 } else if (auto CVal
= SI
.Value
.getAs
<nonloc::ConcreteInt
>()) {
1248 OS
<< Action
<< CVal
->getValue();
1250 } else if (SI
.Origin
&& SI
.Origin
->canPrintPretty()) {
1251 OS
<< Action
<< "the value of ";
1252 SI
.Origin
->printPretty(OS
);
1254 } else if (SI
.StoreKind
== StoreInfo::Initialization
) {
1255 // We don't need to check here, all these conditions were
1256 // checked by StoreSiteFinder, when it figured out that it is
1259 cast
<DeclStmt
>(SI
.StoreSite
->getLocationAs
<PostStmt
>()->getStmt());
1261 if (SI
.Value
.isUndef()) {
1262 if (isa
<VarRegion
>(SI
.Dest
)) {
1263 const auto *VD
= cast
<VarDecl
>(DS
->getSingleDecl());
1265 if (VD
->getInit()) {
1266 OS
<< (HasPrefix
? "initialized" : "Initializing")
1267 << " to a garbage value";
1269 OS
<< (HasPrefix
? "declared" : "Declaring")
1270 << " without an initial value";
1274 OS
<< (HasPrefix
? "initialized" : "Initialized") << " here";
1279 /// Display diagnostics for passing bad region as a parameter.
1280 static void showBRParamDiagnostics(llvm::raw_svector_ostream
&OS
,
1282 const auto *VR
= cast
<VarRegion
>(SI
.Dest
);
1283 const auto *D
= VR
->getDecl();
1287 if (isa
<loc::ConcreteInt
>(SI
.Value
)) {
1288 OS
<< (isObjCPointer(D
) ? "nil object reference" : "null pointer value");
1290 } else if (SI
.Value
.isUndef()) {
1291 OS
<< "uninitialized value";
1293 } else if (auto CI
= SI
.Value
.getAs
<nonloc::ConcreteInt
>()) {
1294 OS
<< "the value " << CI
->getValue();
1296 } else if (SI
.Origin
&& SI
.Origin
->canPrintPretty()) {
1297 SI
.Origin
->printPretty(OS
);
1303 if (const auto *Param
= dyn_cast
<ParmVarDecl
>(VR
->getDecl())) {
1304 // Printed parameter indexes are 1-based, not 0-based.
1305 unsigned Idx
= Param
->getFunctionScopeIndex() + 1;
1306 OS
<< " via " << Idx
<< llvm::getOrdinalSuffix(Idx
) << " parameter";
1307 if (VR
->canPrintPretty()) {
1309 VR
->printPretty(OS
);
1311 } else if (const auto *ImplParam
= dyn_cast
<ImplicitParamDecl
>(D
)) {
1312 if (ImplParam
->getParameterKind() == ImplicitParamKind::ObjCSelf
) {
1313 OS
<< " via implicit parameter 'self'";
1318 /// Show default diagnostics for storing bad region.
1319 static void showBRDefaultDiagnostics(llvm::raw_svector_ostream
&OS
,
1321 const bool HasSuffix
= SI
.Dest
->canPrintPretty();
1323 if (isa
<loc::ConcreteInt
>(SI
.Value
)) {
1324 OS
<< (isObjCPointer(SI
.Dest
) ? "nil object reference stored"
1325 : (HasSuffix
? "Null pointer value stored"
1326 : "Storing null pointer value"));
1328 } else if (SI
.Value
.isUndef()) {
1329 OS
<< (HasSuffix
? "Uninitialized value stored"
1330 : "Storing uninitialized value");
1332 } else if (auto CV
= SI
.Value
.getAs
<nonloc::ConcreteInt
>()) {
1334 OS
<< "The value " << CV
->getValue() << " is assigned";
1336 OS
<< "Assigning " << CV
->getValue();
1338 } else if (SI
.Origin
&& SI
.Origin
->canPrintPretty()) {
1340 OS
<< "The value of ";
1341 SI
.Origin
->printPretty(OS
);
1342 OS
<< " is assigned";
1344 OS
<< "Assigning the value of ";
1345 SI
.Origin
->printPretty(OS
);
1349 OS
<< (HasSuffix
? "Value assigned" : "Assigning value");
1354 SI
.Dest
->printPretty(OS
);
1358 static bool isTrivialCopyOrMoveCtor(const CXXConstructExpr
*CE
) {
1362 const auto *CtorDecl
= CE
->getConstructor();
1364 return CtorDecl
->isCopyOrMoveConstructor() && CtorDecl
->isTrivial();
1367 static const Expr
*tryExtractInitializerFromList(const InitListExpr
*ILE
,
1368 const MemRegion
*R
) {
1370 const auto *TVR
= dyn_cast_or_null
<TypedValueRegion
>(R
);
1375 const auto ITy
= ILE
->getType().getCanonicalType();
1377 // Push each sub-region onto the stack.
1378 std::stack
<const TypedValueRegion
*> TVRStack
;
1379 while (isa
<FieldRegion
>(TVR
) || isa
<ElementRegion
>(TVR
)) {
1380 // We found a region that matches the type of the init list,
1381 // so we assume this is the outer-most region. This can happen
1382 // if the initializer list is inside a class. If our assumption
1383 // is wrong, we return a nullptr in the end.
1384 if (ITy
== TVR
->getValueType().getCanonicalType())
1388 TVR
= cast
<TypedValueRegion
>(TVR
->getSuperRegion());
1391 // If the type of the outer most region doesn't match the type
1392 // of the ILE, we can't match the ILE and the region.
1393 if (ITy
!= TVR
->getValueType().getCanonicalType())
1396 const Expr
*Init
= ILE
;
1397 while (!TVRStack
.empty()) {
1398 TVR
= TVRStack
.top();
1401 // We hit something that's not an init list before
1402 // running out of regions, so we most likely failed.
1403 if (!isa
<InitListExpr
>(Init
))
1406 ILE
= cast
<InitListExpr
>(Init
);
1407 auto NumInits
= ILE
->getNumInits();
1409 if (const auto *FR
= dyn_cast
<FieldRegion
>(TVR
)) {
1410 const auto *FD
= FR
->getDecl();
1412 if (FD
->getFieldIndex() >= NumInits
)
1415 Init
= ILE
->getInit(FD
->getFieldIndex());
1416 } else if (const auto *ER
= dyn_cast
<ElementRegion
>(TVR
)) {
1417 const auto Ind
= ER
->getIndex();
1419 // If index is symbolic, we can't figure out which expression
1420 // belongs to the region.
1421 if (!Ind
.isConstant())
1424 const auto IndVal
= Ind
.getAsInteger()->getLimitedValue();
1425 if (IndVal
>= NumInits
)
1428 Init
= ILE
->getInit(IndVal
);
1435 PathDiagnosticPieceRef
StoreSiteFinder::VisitNode(const ExplodedNode
*Succ
,
1436 BugReporterContext
&BRC
,
1437 PathSensitiveBugReport
&BR
) {
1441 const ExplodedNode
*StoreSite
= nullptr;
1442 const ExplodedNode
*Pred
= Succ
->getFirstPred();
1443 const Expr
*InitE
= nullptr;
1444 bool IsParam
= false;
1446 // First see if we reached the declaration of the region.
1447 if (const auto *VR
= dyn_cast
<VarRegion
>(R
)) {
1448 if (isInitializationOfVar(Pred
, VR
)) {
1450 InitE
= VR
->getDecl()->getInit();
1454 // If this is a post initializer expression, initializing the region, we
1455 // should track the initializer expression.
1456 if (std::optional
<PostInitializer
> PIP
=
1457 Pred
->getLocationAs
<PostInitializer
>()) {
1458 const MemRegion
*FieldReg
= (const MemRegion
*)PIP
->getLocationValue();
1459 if (FieldReg
== R
) {
1461 InitE
= PIP
->getInitializer()->getInit();
1465 // Otherwise, see if this is the store site:
1466 // (1) Succ has this binding and Pred does not, i.e. this is
1467 // where the binding first occurred.
1468 // (2) Succ has this binding and is a PostStore node for this region, i.e.
1469 // the same binding was re-assigned here.
1471 if (Succ
->getState()->getSVal(R
) != V
)
1474 if (hasVisibleUpdate(Pred
, Pred
->getState()->getSVal(R
), Succ
, V
)) {
1475 std::optional
<PostStore
> PS
= Succ
->getLocationAs
<PostStore
>();
1476 if (!PS
|| PS
->getLocationValue() != R
)
1482 if (std::optional
<PostStmt
> P
= Succ
->getLocationAs
<PostStmt
>()) {
1483 // If this is an assignment expression, we can track the value
1485 if (const BinaryOperator
*BO
= P
->getStmtAs
<BinaryOperator
>()) {
1486 if (BO
->isAssignmentOp())
1487 InitE
= BO
->getRHS();
1489 // If we have a declaration like 'S s{1,2}' that needs special
1490 // handling, we handle it here.
1491 else if (const auto *DS
= P
->getStmtAs
<DeclStmt
>()) {
1492 const auto *Decl
= DS
->getSingleDecl();
1493 if (isa
<VarDecl
>(Decl
)) {
1494 const auto *VD
= cast
<VarDecl
>(Decl
);
1496 // FIXME: Here we only track the inner most region, so we lose
1497 // information, but it's still better than a crash or no information
1500 // E.g.: The region we have is 's.s2.s3.s4.y' and we only track 'y',
1501 // and throw away the rest.
1502 if (const auto *ILE
= dyn_cast
<InitListExpr
>(VD
->getInit()))
1503 InitE
= tryExtractInitializerFromList(ILE
, R
);
1505 } else if (const auto *CE
= P
->getStmtAs
<CXXConstructExpr
>()) {
1507 const auto State
= Succ
->getState();
1509 if (isTrivialCopyOrMoveCtor(CE
) && isa
<SubRegion
>(R
)) {
1510 // Migrate the field regions from the current object to
1511 // the parent object. If we track 'a.y.e' and encounter
1512 // 'S a = b' then we need to track 'b.y.e'.
1514 // Push the regions to a stack, from last to first, so
1515 // considering the example above the stack will look like
1516 // (bottom) 'e' -> 'y' (top).
1518 std::stack
<const SubRegion
*> SRStack
;
1519 const SubRegion
*SR
= cast
<SubRegion
>(R
);
1520 while (isa
<FieldRegion
>(SR
) || isa
<ElementRegion
>(SR
)) {
1522 SR
= cast
<SubRegion
>(SR
->getSuperRegion());
1525 // Get the region for the object we copied/moved from.
1526 const auto *OriginEx
= CE
->getArg(0);
1527 const auto OriginVal
=
1528 State
->getSVal(OriginEx
, Succ
->getLocationContext());
1530 // Pop the stored field regions and apply them to the origin
1531 // object in the same order we had them on the copy.
1532 // OriginField will evolve like 'b' -> 'b.y' -> 'b.y.e'.
1533 SVal OriginField
= OriginVal
;
1534 while (!SRStack
.empty()) {
1535 const auto *TopR
= SRStack
.top();
1538 if (const auto *FR
= dyn_cast
<FieldRegion
>(TopR
)) {
1539 OriginField
= State
->getLValue(FR
->getDecl(), OriginField
);
1540 } else if (const auto *ER
= dyn_cast
<ElementRegion
>(TopR
)) {
1541 OriginField
= State
->getLValue(ER
->getElementType(),
1542 ER
->getIndex(), OriginField
);
1544 // FIXME: handle other region type
1549 getParentTracker().track(V
, OriginField
.getAsRegion(), Options
);
1553 // This branch can occur in cases like `Ctor() : field{ x, y } {}'.
1554 else if (const auto *ILE
= P
->getStmtAs
<InitListExpr
>()) {
1555 // FIXME: Here we only track the top level region, so we lose
1556 // information, but it's still better than a crash or no information
1559 // E.g.: The region we have is 's.s2.s3.s4.y' and we only track 'y', and
1560 // throw away the rest.
1561 InitE
= tryExtractInitializerFromList(ILE
, R
);
1565 // If this is a call entry, the variable should be a parameter.
1566 // FIXME: Handle CXXThisRegion as well. (This is not a priority because
1567 // 'this' should never be NULL, but this visitor isn't just for NULL and
1569 if (std::optional
<CallEnter
> CE
= Succ
->getLocationAs
<CallEnter
>()) {
1570 if (const auto *VR
= dyn_cast
<VarRegion
>(R
)) {
1572 if (const auto *Param
= dyn_cast
<ParmVarDecl
>(VR
->getDecl())) {
1573 ProgramStateManager
&StateMgr
= BRC
.getStateManager();
1574 CallEventManager
&CallMgr
= StateMgr
.getCallEventManager();
1576 CallEventRef
<> Call
= CallMgr
.getCaller(CE
->getCalleeContext(),
1578 InitE
= Call
->getArgExpr(Param
->getFunctionScopeIndex());
1580 // Handle Objective-C 'self'.
1581 assert(isa
<ImplicitParamDecl
>(VR
->getDecl()));
1582 InitE
= cast
<ObjCMessageExpr
>(CE
->getCalleeContext()->getCallSite())
1583 ->getInstanceReceiver()->IgnoreParenCasts();
1589 // If this is a CXXTempObjectRegion, the Expr responsible for its creation
1590 // is wrapped inside of it.
1591 if (const auto *TmpR
= dyn_cast
<CXXTempObjectRegion
>(R
))
1592 InitE
= TmpR
->getExpr();
1600 // If we have an expression that provided the value, try to track where it
1604 InitE
= InitE
->IgnoreParenCasts();
1606 getParentTracker().track(InitE
, StoreSite
, Options
);
1609 // Let's try to find the region where the value came from.
1610 const MemRegion
*OldRegion
= nullptr;
1612 // If we have init expression, it might be simply a reference
1613 // to a variable, so we can use it.
1615 // That region might still be not exactly what we are looking for.
1616 // In situations like `int &ref = val;`, we can't say that
1617 // `ref` is initialized with `val`, rather refers to `val`.
1619 // In order, to mitigate situations like this, we check if the last
1620 // stored value in that region is the value that we track.
1622 // TODO: support other situations better.
1623 if (const MemRegion
*Candidate
=
1624 getLocationRegionIfReference(InitE
, Succ
, false)) {
1625 const StoreManager
&SM
= BRC
.getStateManager().getStoreManager();
1627 // Here we traverse the graph up to find the last node where the
1628 // candidate region is still in the store.
1629 for (const ExplodedNode
*N
= StoreSite
; N
; N
= N
->getFirstPred()) {
1630 if (SM
.includedInBindings(N
->getState()->getStore(), Candidate
)) {
1631 // And if it was bound to the target value, we can use it.
1632 if (N
->getState()->getSVal(Candidate
) == V
) {
1633 OldRegion
= Candidate
;
1641 // Otherwise, if the current region does indeed contain the value
1642 // we are looking for, we can look for a region where this value
1645 // It can be useful for situations like:
1646 // new = identity(old)
1647 // where the analyzer knows that 'identity' returns the value of its
1650 // NOTE: If the region R is not a simple var region, it can contain
1651 // V in one of its subregions.
1652 if (!OldRegion
&& StoreSite
->getState()->getSVal(R
) == V
) {
1653 // Let's go up the graph to find the node where the region is
1655 const ExplodedNode
*NodeWithoutBinding
= StoreSite
->getFirstPred();
1657 NodeWithoutBinding
&& NodeWithoutBinding
->getState()->getSVal(R
) == V
;
1658 NodeWithoutBinding
= NodeWithoutBinding
->getFirstPred()) {
1661 if (NodeWithoutBinding
) {
1662 // Let's try to find a unique binding for the value in that node.
1663 // We want to use this to find unique bindings because of the following
1668 // Telling the user that the value of 'a' is assigned to 'c', while
1669 // correct, can be confusing.
1670 StoreManager::FindUniqueBinding
FB(V
.getAsLocSymbol());
1671 BRC
.getStateManager().iterBindings(NodeWithoutBinding
->getState(), FB
);
1673 OldRegion
= FB
.getRegion();
1677 if (Options
.Kind
== TrackingKind::Condition
&& OriginSFC
&&
1678 !OriginSFC
->isParentOf(StoreSite
->getStackFrame()))
1681 // Okay, we've found the binding. Emit an appropriate message.
1682 SmallString
<256> sbuf
;
1683 llvm::raw_svector_ostream
os(sbuf
);
1685 StoreInfo SI
= {StoreInfo::Assignment
, // default kind
1692 if (std::optional
<PostStmt
> PS
= StoreSite
->getLocationAs
<PostStmt
>()) {
1693 const Stmt
*S
= PS
->getStmt();
1694 const auto *DS
= dyn_cast
<DeclStmt
>(S
);
1695 const auto *VR
= dyn_cast
<VarRegion
>(R
);
1698 SI
.StoreKind
= StoreInfo::Initialization
;
1699 } else if (isa
<BlockExpr
>(S
)) {
1700 SI
.StoreKind
= StoreInfo::BlockCapture
;
1702 // See if we can get the BlockVarRegion.
1703 ProgramStateRef State
= StoreSite
->getState();
1704 SVal V
= StoreSite
->getSVal(S
);
1705 if (const auto *BDR
=
1706 dyn_cast_or_null
<BlockDataRegion
>(V
.getAsRegion())) {
1707 if (const VarRegion
*OriginalR
= BDR
->getOriginalRegion(VR
)) {
1708 getParentTracker().track(State
->getSVal(OriginalR
), OriginalR
,
1709 Options
, OriginSFC
);
1714 } else if (SI
.StoreSite
->getLocation().getAs
<CallEnter
>() &&
1715 isa
<VarRegion
>(SI
.Dest
)) {
1716 SI
.StoreKind
= StoreInfo::CallArgument
;
1719 return getParentTracker().handle(SI
, BRC
, Options
);
1722 //===----------------------------------------------------------------------===//
1723 // Implementation of TrackConstraintBRVisitor.
1724 //===----------------------------------------------------------------------===//
1726 void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID
&ID
) const {
1728 ID
.AddPointer(&tag
);
1729 ID
.AddString(Message
);
1730 ID
.AddBoolean(Assumption
);
1734 /// Return the tag associated with this visitor. This tag will be used
1735 /// to make all PathDiagnosticPieces created by this visitor.
1736 const char *TrackConstraintBRVisitor::getTag() {
1737 return "TrackConstraintBRVisitor";
1740 bool TrackConstraintBRVisitor::isZeroCheck() const {
1741 return !Assumption
&& Constraint
.getAs
<Loc
>();
1744 bool TrackConstraintBRVisitor::isUnderconstrained(const ExplodedNode
*N
) const {
1746 return N
->getState()->isNull(Constraint
).isUnderconstrained();
1747 return (bool)N
->getState()->assume(Constraint
, !Assumption
);
1750 PathDiagnosticPieceRef
TrackConstraintBRVisitor::VisitNode(
1751 const ExplodedNode
*N
, BugReporterContext
&BRC
, PathSensitiveBugReport
&) {
1752 const ExplodedNode
*PrevN
= N
->getFirstPred();
1756 // Start tracking after we see the first state in which the value is
1758 if (!IsTrackingTurnedOn
)
1759 if (!isUnderconstrained(N
))
1760 IsTrackingTurnedOn
= true;
1761 if (!IsTrackingTurnedOn
)
1764 // Check if in the previous state it was feasible for this constraint
1765 // to *not* be true.
1766 if (isUnderconstrained(PrevN
)) {
1769 // At this point, the negation of the constraint should be infeasible. If it
1770 // is feasible, make sure that the negation of the constrainti was
1771 // infeasible in the current state. If it is feasible, we somehow missed
1772 // the transition point.
1773 assert(!isUnderconstrained(N
));
1775 // Construct a new PathDiagnosticPiece.
1776 ProgramPoint P
= N
->getLocation();
1778 // If this node already have a specialized note, it's probably better
1779 // than our generic note.
1780 // FIXME: This only looks for note tags, not for other ways to add a note.
1781 if (isa_and_nonnull
<NoteTag
>(P
.getTag()))
1784 PathDiagnosticLocation L
=
1785 PathDiagnosticLocation::create(P
, BRC
.getSourceManager());
1789 auto X
= std::make_shared
<PathDiagnosticEventPiece
>(L
, Message
);
1790 X
->setTag(getTag());
1791 return std::move(X
);
1797 //===----------------------------------------------------------------------===//
1798 // Implementation of SuppressInlineDefensiveChecksVisitor.
1799 //===----------------------------------------------------------------------===//
1801 SuppressInlineDefensiveChecksVisitor::
1802 SuppressInlineDefensiveChecksVisitor(DefinedSVal Value
, const ExplodedNode
*N
)
1804 // Check if the visitor is disabled.
1805 AnalyzerOptions
&Options
= N
->getState()->getAnalysisManager().options
;
1806 if (!Options
.ShouldSuppressInlinedDefensiveChecks
)
1810 void SuppressInlineDefensiveChecksVisitor::Profile(
1811 llvm::FoldingSetNodeID
&ID
) const {
1817 const char *SuppressInlineDefensiveChecksVisitor::getTag() {
1818 return "IDCVisitor";
1821 PathDiagnosticPieceRef
1822 SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode
*Succ
,
1823 BugReporterContext
&BRC
,
1824 PathSensitiveBugReport
&BR
) {
1825 const ExplodedNode
*Pred
= Succ
->getFirstPred();
1829 // Start tracking after we see the first state in which the value is null.
1830 if (!IsTrackingTurnedOn
)
1831 if (Succ
->getState()->isNull(V
).isConstrainedTrue())
1832 IsTrackingTurnedOn
= true;
1833 if (!IsTrackingTurnedOn
)
1836 // Check if in the previous state it was feasible for this value
1837 // to *not* be null.
1838 if (!Pred
->getState()->isNull(V
).isConstrainedTrue() &&
1839 Succ
->getState()->isNull(V
).isConstrainedTrue()) {
1842 // Check if this is inlined defensive checks.
1843 const LocationContext
*CurLC
= Succ
->getLocationContext();
1844 const LocationContext
*ReportLC
= BR
.getErrorNode()->getLocationContext();
1845 if (CurLC
!= ReportLC
&& !CurLC
->isParentOf(ReportLC
)) {
1846 BR
.markInvalid("Suppress IDC", CurLC
);
1850 // Treat defensive checks in function-like macros as if they were an inlined
1851 // defensive check. If the bug location is not in a macro and the
1852 // terminator for the current location is in a macro then suppress the
1854 auto BugPoint
= BR
.getErrorNode()->getLocation().getAs
<StmtPoint
>();
1859 ProgramPoint CurPoint
= Succ
->getLocation();
1860 const Stmt
*CurTerminatorStmt
= nullptr;
1861 if (auto BE
= CurPoint
.getAs
<BlockEdge
>()) {
1862 CurTerminatorStmt
= BE
->getSrc()->getTerminator().getStmt();
1863 } else if (auto SP
= CurPoint
.getAs
<StmtPoint
>()) {
1864 const Stmt
*CurStmt
= SP
->getStmt();
1865 if (!CurStmt
->getBeginLoc().isMacroID())
1868 CFGStmtMap
*Map
= CurLC
->getAnalysisDeclContext()->getCFGStmtMap();
1869 CurTerminatorStmt
= Map
->getBlock(CurStmt
)->getTerminatorStmt();
1874 if (!CurTerminatorStmt
)
1877 SourceLocation TerminatorLoc
= CurTerminatorStmt
->getBeginLoc();
1878 if (TerminatorLoc
.isMacroID()) {
1879 SourceLocation BugLoc
= BugPoint
->getStmt()->getBeginLoc();
1881 // Suppress reports unless we are in that same macro.
1882 if (!BugLoc
.isMacroID() ||
1883 getMacroName(BugLoc
, BRC
) != getMacroName(TerminatorLoc
, BRC
)) {
1884 BR
.markInvalid("Suppress Macro IDC", CurLC
);
1892 //===----------------------------------------------------------------------===//
1893 // TrackControlDependencyCondBRVisitor.
1894 //===----------------------------------------------------------------------===//
1897 /// Tracks the expressions that are a control dependency of the node that was
1898 /// supplied to the constructor.
1905 /// An error is emitted at line 3. This visitor realizes that the branch
1906 /// on line 2 is a control dependency of line 3, and tracks it's condition via
1907 /// trackExpressionValue().
1908 class TrackControlDependencyCondBRVisitor final
1909 : public TrackingBugReporterVisitor
{
1910 const ExplodedNode
*Origin
;
1911 ControlDependencyCalculator ControlDeps
;
1912 llvm::SmallSet
<const CFGBlock
*, 32> VisitedBlocks
;
1915 TrackControlDependencyCondBRVisitor(TrackerRef ParentTracker
,
1916 const ExplodedNode
*O
)
1917 : TrackingBugReporterVisitor(ParentTracker
), Origin(O
),
1918 ControlDeps(&O
->getCFG()) {}
1920 void Profile(llvm::FoldingSetNodeID
&ID
) const override
{
1925 PathDiagnosticPieceRef
VisitNode(const ExplodedNode
*N
,
1926 BugReporterContext
&BRC
,
1927 PathSensitiveBugReport
&BR
) override
;
1929 } // end of anonymous namespace
1931 static std::shared_ptr
<PathDiagnosticEventPiece
>
1932 constructDebugPieceForTrackedCondition(const Expr
*Cond
,
1933 const ExplodedNode
*N
,
1934 BugReporterContext
&BRC
) {
1936 if (BRC
.getAnalyzerOptions().AnalysisDiagOpt
== PD_NONE
||
1937 !BRC
.getAnalyzerOptions().ShouldTrackConditionsDebug
)
1940 std::string ConditionText
= std::string(Lexer::getSourceText(
1941 CharSourceRange::getTokenRange(Cond
->getSourceRange()),
1942 BRC
.getSourceManager(), BRC
.getASTContext().getLangOpts()));
1944 return std::make_shared
<PathDiagnosticEventPiece
>(
1945 PathDiagnosticLocation::createBegin(
1946 Cond
, BRC
.getSourceManager(), N
->getLocationContext()),
1947 (Twine() + "Tracking condition '" + ConditionText
+ "'").str());
1950 static bool isAssertlikeBlock(const CFGBlock
*B
, ASTContext
&Context
) {
1951 if (B
->succ_size() != 2)
1954 const CFGBlock
*Then
= B
->succ_begin()->getReachableBlock();
1955 const CFGBlock
*Else
= (B
->succ_begin() + 1)->getReachableBlock();
1960 if (Then
->isInevitablySinking() != Else
->isInevitablySinking())
1963 // For the following condition the following CFG would be built:
1967 // [B1] -> [B2] -> [B3] -> [sink]
1968 // assert(A && B || C); \ \
1969 // -----------> [go on with the execution]
1971 // It so happens that CFGBlock::getTerminatorCondition returns 'A' for block
1972 // B1, 'A && B' for B2, and 'A && B || C' for B3. Let's check whether we
1973 // reached the end of the condition!
1974 if (const Stmt
*ElseCond
= Else
->getTerminatorCondition())
1975 if (const auto *BinOp
= dyn_cast
<BinaryOperator
>(ElseCond
))
1976 if (BinOp
->isLogicalOp())
1977 return isAssertlikeBlock(Else
, Context
);
1982 PathDiagnosticPieceRef
1983 TrackControlDependencyCondBRVisitor::VisitNode(const ExplodedNode
*N
,
1984 BugReporterContext
&BRC
,
1985 PathSensitiveBugReport
&BR
) {
1986 // We can only reason about control dependencies within the same stack frame.
1987 if (Origin
->getStackFrame() != N
->getStackFrame())
1990 CFGBlock
*NB
= const_cast<CFGBlock
*>(N
->getCFGBlock());
1992 // Skip if we already inspected this block.
1993 if (!VisitedBlocks
.insert(NB
).second
)
1996 CFGBlock
*OriginB
= const_cast<CFGBlock
*>(Origin
->getCFGBlock());
1998 // TODO: Cache CFGBlocks for each ExplodedNode.
1999 if (!OriginB
|| !NB
)
2002 if (isAssertlikeBlock(NB
, BRC
.getASTContext()))
2005 if (ControlDeps
.isControlDependent(OriginB
, NB
)) {
2006 // We don't really want to explain for range loops. Evidence suggests that
2007 // the only thing that leads to is the addition of calls to operator!=.
2008 if (llvm::isa_and_nonnull
<CXXForRangeStmt
>(NB
->getTerminatorStmt()))
2011 if (const Expr
*Condition
= NB
->getLastCondition()) {
2013 // If we can't retrieve a sensible condition, just bail out.
2014 const Expr
*InnerExpr
= peelOffOuterExpr(Condition
, N
);
2018 // If the condition was a function call, we likely won't gain much from
2019 // tracking it either. Evidence suggests that it will mostly trigger in
2020 // scenarios like this:
2024 // if (alwaysTrue()) // We don't need a whole lot of explanation
2025 // // here, the function name is good enough.
2029 // Its easy to create a counterexample where this heuristic would make us
2030 // lose valuable information, but we've never really seen one in practice.
2031 if (isa
<CallExpr
>(InnerExpr
))
2034 // Keeping track of the already tracked conditions on a visitor level
2035 // isn't sufficient, because a new visitor is created for each tracked
2036 // expression, hence the BugReport level set.
2037 if (BR
.addTrackedCondition(N
)) {
2038 getParentTracker().track(InnerExpr
, N
,
2039 {bugreporter::TrackingKind::Condition
,
2040 /*EnableNullFPSuppression=*/false});
2041 return constructDebugPieceForTrackedCondition(Condition
, N
, BRC
);
2049 //===----------------------------------------------------------------------===//
2050 // Implementation of trackExpressionValue.
2051 //===----------------------------------------------------------------------===//
2053 static const Expr
*peelOffOuterExpr(const Expr
*Ex
, const ExplodedNode
*N
) {
2055 Ex
= Ex
->IgnoreParenCasts();
2056 if (const auto *FE
= dyn_cast
<FullExpr
>(Ex
))
2057 return peelOffOuterExpr(FE
->getSubExpr(), N
);
2058 if (const auto *OVE
= dyn_cast
<OpaqueValueExpr
>(Ex
))
2059 return peelOffOuterExpr(OVE
->getSourceExpr(), N
);
2060 if (const auto *POE
= dyn_cast
<PseudoObjectExpr
>(Ex
)) {
2061 const auto *PropRef
= dyn_cast
<ObjCPropertyRefExpr
>(POE
->getSyntacticForm());
2062 if (PropRef
&& PropRef
->isMessagingGetter()) {
2063 const Expr
*GetterMessageSend
=
2064 POE
->getSemanticExpr(POE
->getNumSemanticExprs() - 1);
2065 assert(isa
<ObjCMessageExpr
>(GetterMessageSend
->IgnoreParenCasts()));
2066 return peelOffOuterExpr(GetterMessageSend
, N
);
2070 // Peel off the ternary operator.
2071 if (const auto *CO
= dyn_cast
<ConditionalOperator
>(Ex
)) {
2072 // Find a node where the branching occurred and find out which branch
2073 // we took (true/false) by looking at the ExplodedGraph.
2074 const ExplodedNode
*NI
= N
;
2076 ProgramPoint ProgPoint
= NI
->getLocation();
2077 if (std::optional
<BlockEdge
> BE
= ProgPoint
.getAs
<BlockEdge
>()) {
2078 const CFGBlock
*srcBlk
= BE
->getSrc();
2079 if (const Stmt
*term
= srcBlk
->getTerminatorStmt()) {
2081 bool TookTrueBranch
= (*(srcBlk
->succ_begin()) == BE
->getDst());
2083 return peelOffOuterExpr(CO
->getTrueExpr(), N
);
2085 return peelOffOuterExpr(CO
->getFalseExpr(), N
);
2089 NI
= NI
->getFirstPred();
2093 if (auto *BO
= dyn_cast
<BinaryOperator
>(Ex
))
2094 if (const Expr
*SubEx
= peelOffPointerArithmetic(BO
))
2095 return peelOffOuterExpr(SubEx
, N
);
2097 if (auto *UO
= dyn_cast
<UnaryOperator
>(Ex
)) {
2098 if (UO
->getOpcode() == UO_LNot
)
2099 return peelOffOuterExpr(UO
->getSubExpr(), N
);
2101 // FIXME: There's a hack in our Store implementation that always computes
2102 // field offsets around null pointers as if they are always equal to 0.
2103 // The idea here is to report accesses to fields as null dereferences
2104 // even though the pointer value that's being dereferenced is actually
2105 // the offset of the field rather than exactly 0.
2106 // See the FIXME in StoreManager's getLValueFieldOrIvar() method.
2107 // This code interacts heavily with this hack; otherwise the value
2108 // would not be null at all for most fields, so we'd be unable to track it.
2109 if (UO
->getOpcode() == UO_AddrOf
&& UO
->getSubExpr()->isLValue())
2110 if (const Expr
*DerefEx
= bugreporter::getDerefExpr(UO
->getSubExpr()))
2111 return peelOffOuterExpr(DerefEx
, N
);
2117 /// Find the ExplodedNode where the lvalue (the value of 'Ex')
2119 static const ExplodedNode
* findNodeForExpression(const ExplodedNode
*N
,
2120 const Expr
*Inner
) {
2122 if (N
->getStmtForDiagnostics() == Inner
)
2124 N
= N
->getFirstPred();
2129 //===----------------------------------------------------------------------===//
2130 // Tracker implementation
2131 //===----------------------------------------------------------------------===//
2133 PathDiagnosticPieceRef
StoreHandler::constructNote(StoreInfo SI
,
2134 BugReporterContext
&BRC
,
2135 StringRef NodeText
) {
2136 // Construct a new PathDiagnosticPiece.
2137 ProgramPoint P
= SI
.StoreSite
->getLocation();
2138 PathDiagnosticLocation L
;
2139 if (P
.getAs
<CallEnter
>() && SI
.SourceOfTheValue
)
2140 L
= PathDiagnosticLocation(SI
.SourceOfTheValue
, BRC
.getSourceManager(),
2141 P
.getLocationContext());
2143 if (!L
.isValid() || !L
.asLocation().isValid())
2144 L
= PathDiagnosticLocation::create(P
, BRC
.getSourceManager());
2146 if (!L
.isValid() || !L
.asLocation().isValid())
2149 return std::make_shared
<PathDiagnosticEventPiece
>(L
, NodeText
);
2153 class DefaultStoreHandler final
: public StoreHandler
{
2155 using StoreHandler::StoreHandler
;
2157 PathDiagnosticPieceRef
handle(StoreInfo SI
, BugReporterContext
&BRC
,
2158 TrackingOptions Opts
) override
{
2159 // Okay, we've found the binding. Emit an appropriate message.
2160 SmallString
<256> Buffer
;
2161 llvm::raw_svector_ostream
OS(Buffer
);
2163 switch (SI
.StoreKind
) {
2164 case StoreInfo::Initialization
:
2165 case StoreInfo::BlockCapture
:
2166 showBRDiagnostics(OS
, SI
);
2168 case StoreInfo::CallArgument
:
2169 showBRParamDiagnostics(OS
, SI
);
2171 case StoreInfo::Assignment
:
2172 showBRDefaultDiagnostics(OS
, SI
);
2176 if (Opts
.Kind
== bugreporter::TrackingKind::Condition
)
2177 OS
<< WillBeUsedForACondition
;
2179 return constructNote(SI
, BRC
, OS
.str());
2183 class ControlDependencyHandler final
: public ExpressionHandler
{
2185 using ExpressionHandler::ExpressionHandler
;
2187 Tracker::Result
handle(const Expr
*Inner
, const ExplodedNode
*InputNode
,
2188 const ExplodedNode
*LVNode
,
2189 TrackingOptions Opts
) override
{
2190 PathSensitiveBugReport
&Report
= getParentTracker().getReport();
2192 // We only track expressions if we believe that they are important. Chances
2193 // are good that control dependencies to the tracking point are also
2194 // important because of this, let's explain why we believe control reached
2196 // TODO: Shouldn't we track control dependencies of every bug location,
2197 // rather than only tracked expressions?
2198 if (LVNode
->getState()
2199 ->getAnalysisManager()
2200 .getAnalyzerOptions()
2201 .ShouldTrackConditions
) {
2202 Report
.addVisitor
<TrackControlDependencyCondBRVisitor
>(
2203 &getParentTracker(), InputNode
);
2204 return {/*FoundSomethingToTrack=*/true};
2211 class NilReceiverHandler final
: public ExpressionHandler
{
2213 using ExpressionHandler::ExpressionHandler
;
2215 Tracker::Result
handle(const Expr
*Inner
, const ExplodedNode
*InputNode
,
2216 const ExplodedNode
*LVNode
,
2217 TrackingOptions Opts
) override
{
2218 // The message send could be nil due to the receiver being nil.
2219 // At this point in the path, the receiver should be live since we are at
2220 // the message send expr. If it is nil, start tracking it.
2221 if (const Expr
*Receiver
=
2222 NilReceiverBRVisitor::getNilReceiver(Inner
, LVNode
))
2223 return getParentTracker().track(Receiver
, LVNode
, Opts
);
2229 class ArrayIndexHandler final
: public ExpressionHandler
{
2231 using ExpressionHandler::ExpressionHandler
;
2233 Tracker::Result
handle(const Expr
*Inner
, const ExplodedNode
*InputNode
,
2234 const ExplodedNode
*LVNode
,
2235 TrackingOptions Opts
) override
{
2236 // Track the index if this is an array subscript.
2237 if (const auto *Arr
= dyn_cast
<ArraySubscriptExpr
>(Inner
))
2238 return getParentTracker().track(
2239 Arr
->getIdx(), LVNode
,
2240 {Opts
.Kind
, /*EnableNullFPSuppression*/ false});
2246 // TODO: extract it into more handlers
2247 class InterestingLValueHandler final
: public ExpressionHandler
{
2249 using ExpressionHandler::ExpressionHandler
;
2251 Tracker::Result
handle(const Expr
*Inner
, const ExplodedNode
*InputNode
,
2252 const ExplodedNode
*LVNode
,
2253 TrackingOptions Opts
) override
{
2254 ProgramStateRef LVState
= LVNode
->getState();
2255 const StackFrameContext
*SFC
= LVNode
->getStackFrame();
2256 PathSensitiveBugReport
&Report
= getParentTracker().getReport();
2257 Tracker::Result Result
;
2259 // See if the expression we're interested refers to a variable.
2260 // If so, we can track both its contents and constraints on its value.
2261 if (ExplodedGraph::isInterestingLValueExpr(Inner
)) {
2262 SVal LVal
= LVNode
->getSVal(Inner
);
2264 const MemRegion
*RR
= getLocationRegionIfReference(Inner
, LVNode
);
2265 bool LVIsNull
= LVState
->isNull(LVal
).isConstrainedTrue();
2267 // If this is a C++ reference to a null pointer, we are tracking the
2268 // pointer. In addition, we should find the store at which the reference
2270 if (RR
&& !LVIsNull
)
2271 Result
.combineWith(getParentTracker().track(LVal
, RR
, Opts
, SFC
));
2273 // In case of C++ references, we want to differentiate between a null
2274 // reference and reference to null pointer.
2275 // If the LVal is null, check if we are dealing with null reference.
2276 // For those, we want to track the location of the reference.
2277 const MemRegion
*R
=
2278 (RR
&& LVIsNull
) ? RR
: LVNode
->getSVal(Inner
).getAsRegion();
2282 // Mark both the variable region and its contents as interesting.
2283 SVal V
= LVState
->getRawSVal(loc::MemRegionVal(R
));
2284 Report
.addVisitor
<NoStoreFuncVisitor
>(cast
<SubRegion
>(R
), Opts
.Kind
);
2286 // When we got here, we do have something to track, and we will
2288 Result
.FoundSomethingToTrack
= true;
2289 Result
.WasInterrupted
= true;
2291 MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
2292 LVNode
, R
, Opts
.EnableNullFPSuppression
, Report
, V
);
2294 Report
.markInteresting(V
, Opts
.Kind
);
2295 Report
.addVisitor
<UndefOrNullArgVisitor
>(R
);
2297 // If the contents are symbolic and null, find out when they became
2299 if (V
.getAsLocSymbol(/*IncludeBaseRegions=*/true))
2300 if (LVState
->isNull(V
).isConstrainedTrue())
2301 Report
.addVisitor
<TrackConstraintBRVisitor
>(
2302 V
.castAs
<DefinedSVal
>(),
2303 /*Assumption=*/false, "Assuming pointer value is null");
2305 // Add visitor, which will suppress inline defensive checks.
2306 if (auto DV
= V
.getAs
<DefinedSVal
>())
2307 if (!DV
->isZeroConstant() && Opts
.EnableNullFPSuppression
)
2308 // Note that LVNode may be too late (i.e., too far from the
2309 // InputNode) because the lvalue may have been computed before the
2310 // inlined call was evaluated. InputNode may as well be too early
2311 // here, because the symbol is already dead; this, however, is fine
2312 // because we can still find the node in which it collapsed to null
2314 Report
.addVisitor
<SuppressInlineDefensiveChecksVisitor
>(*DV
,
2316 getParentTracker().track(V
, R
, Opts
, SFC
);
2324 /// Adds a ReturnVisitor if the given statement represents a call that was
2327 /// This will search back through the ExplodedGraph, starting from the given
2328 /// node, looking for when the given statement was processed. If it turns out
2329 /// the statement is a call that was inlined, we add the visitor to the
2330 /// bug report, so it can print a note later.
2331 class InlinedFunctionCallHandler final
: public ExpressionHandler
{
2332 using ExpressionHandler::ExpressionHandler
;
2334 Tracker::Result
handle(const Expr
*E
, const ExplodedNode
*InputNode
,
2335 const ExplodedNode
*ExprNode
,
2336 TrackingOptions Opts
) override
{
2337 if (!CallEvent::isCallStmt(E
))
2340 // First, find when we processed the statement.
2341 // If we work with a 'CXXNewExpr' that is going to be purged away before
2342 // its call take place. We would catch that purge in the last condition
2343 // as a 'StmtPoint' so we have to bypass it.
2344 const bool BypassCXXNewExprEval
= isa
<CXXNewExpr
>(E
);
2346 // This is moving forward when we enter into another context.
2347 const StackFrameContext
*CurrentSFC
= ExprNode
->getStackFrame();
2350 // If that is satisfied we found our statement as an inlined call.
2351 if (std::optional
<CallExitEnd
> CEE
=
2352 ExprNode
->getLocationAs
<CallExitEnd
>())
2353 if (CEE
->getCalleeContext()->getCallSite() == E
)
2356 // Try to move forward to the end of the call-chain.
2357 ExprNode
= ExprNode
->getFirstPred();
2361 const StackFrameContext
*PredSFC
= ExprNode
->getStackFrame();
2363 // If that is satisfied we found our statement.
2364 // FIXME: This code currently bypasses the call site for the
2365 // conservatively evaluated allocator.
2366 if (!BypassCXXNewExprEval
)
2367 if (std::optional
<StmtPoint
> SP
= ExprNode
->getLocationAs
<StmtPoint
>())
2368 // See if we do not enter into another context.
2369 if (SP
->getStmt() == E
&& CurrentSFC
== PredSFC
)
2372 CurrentSFC
= PredSFC
;
2373 } while (ExprNode
->getStackFrame() == CurrentSFC
);
2375 // Next, step over any post-statement checks.
2376 while (ExprNode
&& ExprNode
->getLocation().getAs
<PostStmt
>())
2377 ExprNode
= ExprNode
->getFirstPred();
2381 // Finally, see if we inlined the call.
2382 std::optional
<CallExitEnd
> CEE
= ExprNode
->getLocationAs
<CallExitEnd
>();
2386 const StackFrameContext
*CalleeContext
= CEE
->getCalleeContext();
2387 if (CalleeContext
->getCallSite() != E
)
2390 // Check the return value.
2391 ProgramStateRef State
= ExprNode
->getState();
2392 SVal RetVal
= ExprNode
->getSVal(E
);
2394 // Handle cases where a reference is returned and then immediately used.
2395 if (cast
<Expr
>(E
)->isGLValue())
2396 if (std::optional
<Loc
> LValue
= RetVal
.getAs
<Loc
>())
2397 RetVal
= State
->getSVal(*LValue
);
2399 // See if the return value is NULL. If so, suppress the report.
2400 AnalyzerOptions
&Options
= State
->getAnalysisManager().options
;
2402 bool EnableNullFPSuppression
= false;
2403 if (Opts
.EnableNullFPSuppression
&& Options
.ShouldSuppressNullReturnPaths
)
2404 if (std::optional
<Loc
> RetLoc
= RetVal
.getAs
<Loc
>())
2405 EnableNullFPSuppression
= State
->isNull(*RetLoc
).isConstrainedTrue();
2407 PathSensitiveBugReport
&Report
= getParentTracker().getReport();
2408 Report
.addVisitor
<ReturnVisitor
>(&getParentTracker(), CalleeContext
,
2409 EnableNullFPSuppression
, Options
,
2415 class DefaultExpressionHandler final
: public ExpressionHandler
{
2417 using ExpressionHandler::ExpressionHandler
;
2419 Tracker::Result
handle(const Expr
*Inner
, const ExplodedNode
*InputNode
,
2420 const ExplodedNode
*LVNode
,
2421 TrackingOptions Opts
) override
{
2422 ProgramStateRef LVState
= LVNode
->getState();
2423 const StackFrameContext
*SFC
= LVNode
->getStackFrame();
2424 PathSensitiveBugReport
&Report
= getParentTracker().getReport();
2425 Tracker::Result Result
;
2427 // If the expression is not an "lvalue expression", we can still
2428 // track the constraints on its contents.
2429 SVal V
= LVState
->getSValAsScalarOrLoc(Inner
, LVNode
->getLocationContext());
2431 // Is it a symbolic value?
2432 if (auto L
= V
.getAs
<loc::MemRegionVal
>()) {
2433 // FIXME: this is a hack for fixing a later crash when attempting to
2434 // dereference a void* pointer.
2435 // We should not try to dereference pointers at all when we don't care
2436 // what is written inside the pointer.
2437 bool CanDereference
= true;
2438 if (const auto *SR
= L
->getRegionAs
<SymbolicRegion
>()) {
2439 if (SR
->getPointeeStaticType()->isVoidType())
2440 CanDereference
= false;
2441 } else if (L
->getRegionAs
<AllocaRegion
>())
2442 CanDereference
= false;
2444 // At this point we are dealing with the region's LValue.
2445 // However, if the rvalue is a symbolic region, we should track it as
2446 // well. Try to use the correct type when looking up the value.
2448 if (ExplodedGraph::isInterestingLValueExpr(Inner
))
2449 RVal
= LVState
->getRawSVal(*L
, Inner
->getType());
2450 else if (CanDereference
)
2451 RVal
= LVState
->getSVal(L
->getRegion());
2453 if (CanDereference
) {
2454 Report
.addVisitor
<UndefOrNullArgVisitor
>(L
->getRegion());
2455 Result
.FoundSomethingToTrack
= true;
2457 if (!RVal
.isUnknown())
2459 getParentTracker().track(RVal
, L
->getRegion(), Opts
, SFC
));
2462 const MemRegion
*RegionRVal
= RVal
.getAsRegion();
2463 if (isa_and_nonnull
<SymbolicRegion
>(RegionRVal
)) {
2464 Report
.markInteresting(RegionRVal
, Opts
.Kind
);
2465 Report
.addVisitor
<TrackConstraintBRVisitor
>(
2466 loc::MemRegionVal(RegionRVal
),
2467 /*Assumption=*/false, "Assuming pointer value is null");
2468 Result
.FoundSomethingToTrack
= true;
2476 /// Attempts to add visitors to track an RValue expression back to its point of
2478 class PRValueHandler final
: public ExpressionHandler
{
2480 using ExpressionHandler::ExpressionHandler
;
2482 Tracker::Result
handle(const Expr
*E
, const ExplodedNode
*InputNode
,
2483 const ExplodedNode
*ExprNode
,
2484 TrackingOptions Opts
) override
{
2485 if (!E
->isPRValue())
2488 const ExplodedNode
*RVNode
= findNodeForExpression(ExprNode
, E
);
2492 Tracker::Result CombinedResult
;
2493 Tracker
&Parent
= getParentTracker();
2495 const auto track
= [&CombinedResult
, &Parent
, ExprNode
,
2496 Opts
](const Expr
*Inner
) {
2497 CombinedResult
.combineWith(Parent
.track(Inner
, ExprNode
, Opts
));
2500 // FIXME: Initializer lists can appear in many different contexts
2501 // and most of them needs a special handling. For now let's handle
2502 // what we can. If the initializer list only has 1 element, we track
2504 // This snippet even handles nesting, e.g.: int *x{{{{{y}}}}};
2505 if (const auto *ILE
= dyn_cast
<InitListExpr
>(E
)) {
2506 if (ILE
->getNumInits() == 1) {
2507 track(ILE
->getInit(0));
2509 return CombinedResult
;
2515 ProgramStateRef RVState
= RVNode
->getState();
2516 SVal V
= RVState
->getSValAsScalarOrLoc(E
, RVNode
->getLocationContext());
2517 const auto *BO
= dyn_cast
<BinaryOperator
>(E
);
2519 if (!BO
|| !BO
->isMultiplicativeOp() || !V
.isZeroConstant())
2522 SVal RHSV
= RVState
->getSVal(BO
->getRHS(), RVNode
->getLocationContext());
2523 SVal LHSV
= RVState
->getSVal(BO
->getLHS(), RVNode
->getLocationContext());
2525 // Track both LHS and RHS of a multiplication.
2526 if (BO
->getOpcode() == BO_Mul
) {
2527 if (LHSV
.isZeroConstant())
2528 track(BO
->getLHS());
2529 if (RHSV
.isZeroConstant())
2530 track(BO
->getRHS());
2531 } else { // Track only the LHS of a division or a modulo.
2532 if (LHSV
.isZeroConstant())
2533 track(BO
->getLHS());
2536 return CombinedResult
;
2541 Tracker::Tracker(PathSensitiveBugReport
&Report
) : Report(Report
) {
2542 // Default expression handlers.
2543 addLowPriorityHandler
<ControlDependencyHandler
>();
2544 addLowPriorityHandler
<NilReceiverHandler
>();
2545 addLowPriorityHandler
<ArrayIndexHandler
>();
2546 addLowPriorityHandler
<InterestingLValueHandler
>();
2547 addLowPriorityHandler
<InlinedFunctionCallHandler
>();
2548 addLowPriorityHandler
<DefaultExpressionHandler
>();
2549 addLowPriorityHandler
<PRValueHandler
>();
2550 // Default store handlers.
2551 addHighPriorityHandler
<DefaultStoreHandler
>();
2554 Tracker::Result
Tracker::track(const Expr
*E
, const ExplodedNode
*N
,
2555 TrackingOptions Opts
) {
2559 const Expr
*Inner
= peelOffOuterExpr(E
, N
);
2560 const ExplodedNode
*LVNode
= findNodeForExpression(N
, Inner
);
2564 Result CombinedResult
;
2565 // Iterate through the handlers in the order according to their priorities.
2566 for (ExpressionHandlerPtr
&Handler
: ExpressionHandlers
) {
2567 CombinedResult
.combineWith(Handler
->handle(Inner
, N
, LVNode
, Opts
));
2568 if (CombinedResult
.WasInterrupted
) {
2569 // There is no need to confuse our users here.
2570 // We got interrupted, but our users don't need to know about it.
2571 CombinedResult
.WasInterrupted
= false;
2576 return CombinedResult
;
2579 Tracker::Result
Tracker::track(SVal V
, const MemRegion
*R
, TrackingOptions Opts
,
2580 const StackFrameContext
*Origin
) {
2581 if (!V
.isUnknown()) {
2582 Report
.addVisitor
<StoreSiteFinder
>(this, V
, R
, Opts
, Origin
);
2588 PathDiagnosticPieceRef
Tracker::handle(StoreInfo SI
, BugReporterContext
&BRC
,
2589 TrackingOptions Opts
) {
2590 // Iterate through the handlers in the order according to their priorities.
2591 for (StoreHandlerPtr
&Handler
: StoreHandlers
) {
2592 if (PathDiagnosticPieceRef Result
= Handler
->handle(SI
, BRC
, Opts
))
2593 // If the handler produced a non-null piece, return it.
2594 // There is no need in asking other handlers.
2600 bool bugreporter::trackExpressionValue(const ExplodedNode
*InputNode
,
2603 PathSensitiveBugReport
&Report
,
2604 TrackingOptions Opts
) {
2605 return Tracker::create(Report
)
2606 ->track(E
, InputNode
, Opts
)
2607 .FoundSomethingToTrack
;
2610 void bugreporter::trackStoredValue(SVal V
, const MemRegion
*R
,
2611 PathSensitiveBugReport
&Report
,
2612 TrackingOptions Opts
,
2613 const StackFrameContext
*Origin
) {
2614 Tracker::create(Report
)->track(V
, R
, Opts
, Origin
);
2617 //===----------------------------------------------------------------------===//
2618 // Implementation of NulReceiverBRVisitor.
2619 //===----------------------------------------------------------------------===//
2621 const Expr
*NilReceiverBRVisitor::getNilReceiver(const Stmt
*S
,
2622 const ExplodedNode
*N
) {
2623 const auto *ME
= dyn_cast
<ObjCMessageExpr
>(S
);
2626 if (const Expr
*Receiver
= ME
->getInstanceReceiver()) {
2627 ProgramStateRef state
= N
->getState();
2628 SVal V
= N
->getSVal(Receiver
);
2629 if (state
->isNull(V
).isConstrainedTrue())
2635 PathDiagnosticPieceRef
2636 NilReceiverBRVisitor::VisitNode(const ExplodedNode
*N
, BugReporterContext
&BRC
,
2637 PathSensitiveBugReport
&BR
) {
2638 std::optional
<PreStmt
> P
= N
->getLocationAs
<PreStmt
>();
2642 const Stmt
*S
= P
->getStmt();
2643 const Expr
*Receiver
= getNilReceiver(S
, N
);
2647 llvm::SmallString
<256> Buf
;
2648 llvm::raw_svector_ostream
OS(Buf
);
2650 if (const auto *ME
= dyn_cast
<ObjCMessageExpr
>(S
)) {
2652 ME
->getSelector().print(OS
);
2653 OS
<< "' not called";
2656 OS
<< "No method is called";
2658 OS
<< " because the receiver is nil";
2660 // The receiver was nil, and hence the method was skipped.
2661 // Register a BugReporterVisitor to issue a message telling us how
2662 // the receiver was null.
2663 bugreporter::trackExpressionValue(N
, Receiver
, BR
,
2664 {bugreporter::TrackingKind::Thorough
,
2665 /*EnableNullFPSuppression*/ false});
2666 // Issue a message saying that the method was skipped.
2667 PathDiagnosticLocation
L(Receiver
, BRC
.getSourceManager(),
2668 N
->getLocationContext());
2669 return std::make_shared
<PathDiagnosticEventPiece
>(L
, OS
.str());
2672 //===----------------------------------------------------------------------===//
2673 // Visitor that tries to report interesting diagnostics from conditions.
2674 //===----------------------------------------------------------------------===//
2676 /// Return the tag associated with this visitor. This tag will be used
2677 /// to make all PathDiagnosticPieces created by this visitor.
2678 const char *ConditionBRVisitor::getTag() { return "ConditionBRVisitor"; }
2680 PathDiagnosticPieceRef
2681 ConditionBRVisitor::VisitNode(const ExplodedNode
*N
, BugReporterContext
&BRC
,
2682 PathSensitiveBugReport
&BR
) {
2683 auto piece
= VisitNodeImpl(N
, BRC
, BR
);
2685 piece
->setTag(getTag());
2686 if (auto *ev
= dyn_cast
<PathDiagnosticEventPiece
>(piece
.get()))
2687 ev
->setPrunable(true, /* override */ false);
2692 PathDiagnosticPieceRef
2693 ConditionBRVisitor::VisitNodeImpl(const ExplodedNode
*N
,
2694 BugReporterContext
&BRC
,
2695 PathSensitiveBugReport
&BR
) {
2696 ProgramPoint ProgPoint
= N
->getLocation();
2697 const std::pair
<const ProgramPointTag
*, const ProgramPointTag
*> &Tags
=
2698 ExprEngine::getEagerlyAssumeBifurcationTags();
2700 // If an assumption was made on a branch, it should be caught
2701 // here by looking at the state transition.
2702 if (std::optional
<BlockEdge
> BE
= ProgPoint
.getAs
<BlockEdge
>()) {
2703 const CFGBlock
*SrcBlock
= BE
->getSrc();
2704 if (const Stmt
*Term
= SrcBlock
->getTerminatorStmt()) {
2705 // If the tag of the previous node is 'Eagerly Assume...' the current
2706 // 'BlockEdge' has the same constraint information. We do not want to
2707 // report the value as it is just an assumption on the predecessor node
2708 // which will be caught in the next VisitNode() iteration as a 'PostStmt'.
2709 const ProgramPointTag
*PreviousNodeTag
=
2710 N
->getFirstPred()->getLocation().getTag();
2711 if (PreviousNodeTag
== Tags
.first
|| PreviousNodeTag
== Tags
.second
)
2714 return VisitTerminator(Term
, N
, SrcBlock
, BE
->getDst(), BR
, BRC
);
2719 if (std::optional
<PostStmt
> PS
= ProgPoint
.getAs
<PostStmt
>()) {
2720 const ProgramPointTag
*CurrentNodeTag
= PS
->getTag();
2721 if (CurrentNodeTag
!= Tags
.first
&& CurrentNodeTag
!= Tags
.second
)
2724 bool TookTrue
= CurrentNodeTag
== Tags
.first
;
2725 return VisitTrueTest(cast
<Expr
>(PS
->getStmt()), BRC
, BR
, N
, TookTrue
);
2731 PathDiagnosticPieceRef
ConditionBRVisitor::VisitTerminator(
2732 const Stmt
*Term
, const ExplodedNode
*N
, const CFGBlock
*srcBlk
,
2733 const CFGBlock
*dstBlk
, PathSensitiveBugReport
&R
,
2734 BugReporterContext
&BRC
) {
2735 const Expr
*Cond
= nullptr;
2737 // In the code below, Term is a CFG terminator and Cond is a branch condition
2738 // expression upon which the decision is made on this terminator.
2740 // For example, in "if (x == 0)", the "if (x == 0)" statement is a terminator,
2741 // and "x == 0" is the respective condition.
2743 // Another example: in "if (x && y)", we've got two terminators and two
2744 // conditions due to short-circuit nature of operator "&&":
2745 // 1. The "if (x && y)" statement is a terminator,
2746 // and "y" is the respective condition.
2747 // 2. Also "x && ..." is another terminator,
2748 // and "x" is its condition.
2750 switch (Term
->getStmtClass()) {
2751 // FIXME: Stmt::SwitchStmtClass is worth handling, however it is a bit
2752 // more tricky because there are more than two branches to account for.
2755 case Stmt::IfStmtClass
:
2756 Cond
= cast
<IfStmt
>(Term
)->getCond();
2758 case Stmt::ConditionalOperatorClass
:
2759 Cond
= cast
<ConditionalOperator
>(Term
)->getCond();
2761 case Stmt::BinaryOperatorClass
:
2762 // When we encounter a logical operator (&& or ||) as a CFG terminator,
2763 // then the condition is actually its LHS; otherwise, we'd encounter
2764 // the parent, such as if-statement, as a terminator.
2765 const auto *BO
= cast
<BinaryOperator
>(Term
);
2766 assert(BO
->isLogicalOp() &&
2767 "CFG terminator is not a short-circuit operator!");
2768 Cond
= BO
->getLHS();
2772 Cond
= Cond
->IgnoreParens();
2774 // However, when we encounter a logical operator as a branch condition,
2775 // then the condition is actually its RHS, because LHS would be
2776 // the condition for the logical operator terminator.
2777 while (const auto *InnerBO
= dyn_cast
<BinaryOperator
>(Cond
)) {
2778 if (!InnerBO
->isLogicalOp())
2780 Cond
= InnerBO
->getRHS()->IgnoreParens();
2784 assert(srcBlk
->succ_size() == 2);
2785 const bool TookTrue
= *(srcBlk
->succ_begin()) == dstBlk
;
2786 return VisitTrueTest(Cond
, BRC
, R
, N
, TookTrue
);
2789 PathDiagnosticPieceRef
2790 ConditionBRVisitor::VisitTrueTest(const Expr
*Cond
, BugReporterContext
&BRC
,
2791 PathSensitiveBugReport
&R
,
2792 const ExplodedNode
*N
, bool TookTrue
) {
2793 ProgramStateRef CurrentState
= N
->getState();
2794 ProgramStateRef PrevState
= N
->getFirstPred()->getState();
2795 const LocationContext
*LCtx
= N
->getLocationContext();
2797 // If the constraint information is changed between the current and the
2798 // previous program state we assuming the newly seen constraint information.
2799 // If we cannot evaluate the condition (and the constraints are the same)
2800 // the analyzer has no information about the value and just assuming it.
2801 // FIXME: This logic is not entirely correct, because e.g. in code like
2802 // void f(unsigned arg) {
2807 // it will say that the "arg >= 0" check is _assuming_ something new because
2808 // the constraint that "$arg >= 0" is 1 was added to the list of known
2809 // constraints. However, the unsigned value is always >= 0 so semantically
2810 // this is not a "real" assumption.
2812 !BRC
.getStateManager().haveEqualConstraints(CurrentState
, PrevState
) ||
2813 CurrentState
->getSVal(Cond
, LCtx
).isUnknownOrUndef();
2815 // These will be modified in code below, but we need to preserve the original
2816 // values in case we want to throw the generic message.
2817 const Expr
*CondTmp
= Cond
;
2818 bool TookTrueTmp
= TookTrue
;
2821 CondTmp
= CondTmp
->IgnoreParenCasts();
2822 switch (CondTmp
->getStmtClass()) {
2825 case Stmt::BinaryOperatorClass
:
2826 if (auto P
= VisitTrueTest(Cond
, cast
<BinaryOperator
>(CondTmp
),
2827 BRC
, R
, N
, TookTrueTmp
, IsAssuming
))
2830 case Stmt::DeclRefExprClass
:
2831 if (auto P
= VisitTrueTest(Cond
, cast
<DeclRefExpr
>(CondTmp
),
2832 BRC
, R
, N
, TookTrueTmp
, IsAssuming
))
2835 case Stmt::MemberExprClass
:
2836 if (auto P
= VisitTrueTest(Cond
, cast
<MemberExpr
>(CondTmp
),
2837 BRC
, R
, N
, TookTrueTmp
, IsAssuming
))
2840 case Stmt::UnaryOperatorClass
: {
2841 const auto *UO
= cast
<UnaryOperator
>(CondTmp
);
2842 if (UO
->getOpcode() == UO_LNot
) {
2843 TookTrueTmp
= !TookTrueTmp
;
2844 CondTmp
= UO
->getSubExpr();
2853 // Condition too complex to explain? Just say something so that the user
2854 // knew we've made some path decision at this point.
2855 // If it is too complex and we know the evaluation of the condition do not
2856 // repeat the note from 'BugReporter.cpp'
2860 PathDiagnosticLocation
Loc(Cond
, BRC
.getSourceManager(), LCtx
);
2861 if (!Loc
.isValid() || !Loc
.asLocation().isValid())
2864 return std::make_shared
<PathDiagnosticEventPiece
>(
2865 Loc
, TookTrue
? GenericTrueMessage
: GenericFalseMessage
);
2868 bool ConditionBRVisitor::patternMatch(const Expr
*Ex
, const Expr
*ParentEx
,
2869 raw_ostream
&Out
, BugReporterContext
&BRC
,
2870 PathSensitiveBugReport
&report
,
2871 const ExplodedNode
*N
,
2872 std::optional
<bool> &prunable
,
2873 bool IsSameFieldName
) {
2874 const Expr
*OriginalExpr
= Ex
;
2875 Ex
= Ex
->IgnoreParenCasts();
2877 if (isa
<GNUNullExpr
, ObjCBoolLiteralExpr
, CXXBoolLiteralExpr
, IntegerLiteral
,
2878 FloatingLiteral
>(Ex
)) {
2879 // Use heuristics to determine if the expression is a macro
2880 // expanding to a literal and if so, use the macro's name.
2881 SourceLocation BeginLoc
= OriginalExpr
->getBeginLoc();
2882 SourceLocation EndLoc
= OriginalExpr
->getEndLoc();
2883 if (BeginLoc
.isMacroID() && EndLoc
.isMacroID()) {
2884 const SourceManager
&SM
= BRC
.getSourceManager();
2885 const LangOptions
&LO
= BRC
.getASTContext().getLangOpts();
2886 if (Lexer::isAtStartOfMacroExpansion(BeginLoc
, SM
, LO
) &&
2887 Lexer::isAtEndOfMacroExpansion(EndLoc
, SM
, LO
)) {
2888 CharSourceRange R
= Lexer::getAsCharRange({BeginLoc
, EndLoc
}, SM
, LO
);
2889 Out
<< Lexer::getSourceText(R
, SM
, LO
);
2895 if (const auto *DR
= dyn_cast
<DeclRefExpr
>(Ex
)) {
2896 const bool quotes
= isa
<VarDecl
>(DR
->getDecl());
2899 const LocationContext
*LCtx
= N
->getLocationContext();
2900 const ProgramState
*state
= N
->getState().get();
2901 if (const MemRegion
*R
= state
->getLValue(cast
<VarDecl
>(DR
->getDecl()),
2902 LCtx
).getAsRegion()) {
2903 if (report
.isInteresting(R
))
2906 const ProgramState
*state
= N
->getState().get();
2907 SVal V
= state
->getSVal(R
);
2908 if (report
.isInteresting(V
))
2913 Out
<< DR
->getDecl()->getDeclName().getAsString();
2919 if (const auto *IL
= dyn_cast
<IntegerLiteral
>(Ex
)) {
2920 QualType OriginalTy
= OriginalExpr
->getType();
2921 if (OriginalTy
->isPointerType()) {
2922 if (IL
->getValue() == 0) {
2927 else if (OriginalTy
->isObjCObjectPointerType()) {
2928 if (IL
->getValue() == 0) {
2934 Out
<< IL
->getValue();
2938 if (const auto *ME
= dyn_cast
<MemberExpr
>(Ex
)) {
2939 if (!IsSameFieldName
)
2940 Out
<< "field '" << ME
->getMemberDecl()->getName() << '\'';
2943 << Lexer::getSourceText(
2944 CharSourceRange::getTokenRange(Ex
->getSourceRange()),
2945 BRC
.getSourceManager(), BRC
.getASTContext().getLangOpts(),
2953 PathDiagnosticPieceRef
ConditionBRVisitor::VisitTrueTest(
2954 const Expr
*Cond
, const BinaryOperator
*BExpr
, BugReporterContext
&BRC
,
2955 PathSensitiveBugReport
&R
, const ExplodedNode
*N
, bool TookTrue
,
2957 bool shouldInvert
= false;
2958 std::optional
<bool> shouldPrune
;
2960 // Check if the field name of the MemberExprs is ambiguous. Example:
2961 // " 'a.d' is equal to 'h.d' " in 'test/Analysis/null-deref-path-notes.cpp'.
2962 bool IsSameFieldName
= false;
2963 const auto *LhsME
= dyn_cast
<MemberExpr
>(BExpr
->getLHS()->IgnoreParenCasts());
2964 const auto *RhsME
= dyn_cast
<MemberExpr
>(BExpr
->getRHS()->IgnoreParenCasts());
2968 LhsME
->getMemberDecl()->getName() == RhsME
->getMemberDecl()->getName();
2970 SmallString
<128> LhsString
, RhsString
;
2972 llvm::raw_svector_ostream
OutLHS(LhsString
), OutRHS(RhsString
);
2973 const bool isVarLHS
= patternMatch(BExpr
->getLHS(), BExpr
, OutLHS
, BRC
, R
,
2974 N
, shouldPrune
, IsSameFieldName
);
2975 const bool isVarRHS
= patternMatch(BExpr
->getRHS(), BExpr
, OutRHS
, BRC
, R
,
2976 N
, shouldPrune
, IsSameFieldName
);
2978 shouldInvert
= !isVarLHS
&& isVarRHS
;
2981 BinaryOperator::Opcode Op
= BExpr
->getOpcode();
2983 if (BinaryOperator::isAssignmentOp(Op
)) {
2984 // For assignment operators, all that we care about is that the LHS
2985 // evaluates to "true" or "false".
2986 return VisitConditionVariable(LhsString
, BExpr
->getLHS(), BRC
, R
, N
,
2990 // For non-assignment operations, we require that we can understand
2991 // both the LHS and RHS.
2992 if (LhsString
.empty() || RhsString
.empty() ||
2993 !BinaryOperator::isComparisonOp(Op
) || Op
== BO_Cmp
)
2996 // Should we invert the strings if the LHS is not a variable name?
2997 SmallString
<256> buf
;
2998 llvm::raw_svector_ostream
Out(buf
);
2999 Out
<< (IsAssuming
? "Assuming " : "")
3000 << (shouldInvert
? RhsString
: LhsString
) << " is ";
3002 // Do we need to invert the opcode?
3006 case BO_LT
: Op
= BO_GT
; break;
3007 case BO_GT
: Op
= BO_LT
; break;
3008 case BO_LE
: Op
= BO_GE
; break;
3009 case BO_GE
: Op
= BO_LE
; break;
3014 case BO_EQ
: Op
= BO_NE
; break;
3015 case BO_NE
: Op
= BO_EQ
; break;
3016 case BO_LT
: Op
= BO_GE
; break;
3017 case BO_GT
: Op
= BO_LE
; break;
3018 case BO_LE
: Op
= BO_GT
; break;
3019 case BO_GE
: Op
= BO_LT
; break;
3029 Out
<< "not equal to ";
3032 Out
<< BinaryOperator::getOpcodeStr(Op
) << ' ';
3036 Out
<< (shouldInvert
? LhsString
: RhsString
);
3037 const LocationContext
*LCtx
= N
->getLocationContext();
3038 const SourceManager
&SM
= BRC
.getSourceManager();
3040 if (isVarAnInterestingCondition(BExpr
->getLHS(), N
, &R
) ||
3041 isVarAnInterestingCondition(BExpr
->getRHS(), N
, &R
))
3042 Out
<< WillBeUsedForACondition
;
3044 // Convert 'field ...' to 'Field ...' if it is a MemberExpr.
3045 std::string Message
= std::string(Out
.str());
3046 Message
[0] = toupper(Message
[0]);
3048 // If we know the value create a pop-up note to the value part of 'BExpr'.
3050 PathDiagnosticLocation Loc
;
3051 if (!shouldInvert
) {
3052 if (LhsME
&& LhsME
->getMemberLoc().isValid())
3053 Loc
= PathDiagnosticLocation(LhsME
->getMemberLoc(), SM
);
3055 Loc
= PathDiagnosticLocation(BExpr
->getLHS(), SM
, LCtx
);
3057 if (RhsME
&& RhsME
->getMemberLoc().isValid())
3058 Loc
= PathDiagnosticLocation(RhsME
->getMemberLoc(), SM
);
3060 Loc
= PathDiagnosticLocation(BExpr
->getRHS(), SM
, LCtx
);
3063 return std::make_shared
<PathDiagnosticPopUpPiece
>(Loc
, Message
);
3066 PathDiagnosticLocation
Loc(Cond
, SM
, LCtx
);
3067 auto event
= std::make_shared
<PathDiagnosticEventPiece
>(Loc
, Message
);
3069 event
->setPrunable(*shouldPrune
);
3073 PathDiagnosticPieceRef
ConditionBRVisitor::VisitConditionVariable(
3074 StringRef LhsString
, const Expr
*CondVarExpr
, BugReporterContext
&BRC
,
3075 PathSensitiveBugReport
&report
, const ExplodedNode
*N
, bool TookTrue
) {
3076 // FIXME: If there's already a constraint tracker for this variable,
3077 // we shouldn't emit anything here (c.f. the double note in
3078 // test/Analysis/inlining/path-notes.c)
3079 SmallString
<256> buf
;
3080 llvm::raw_svector_ostream
Out(buf
);
3081 Out
<< "Assuming " << LhsString
<< " is ";
3083 if (!printValue(CondVarExpr
, Out
, N
, TookTrue
, /*IsAssuming=*/true))
3086 const LocationContext
*LCtx
= N
->getLocationContext();
3087 PathDiagnosticLocation
Loc(CondVarExpr
, BRC
.getSourceManager(), LCtx
);
3089 if (isVarAnInterestingCondition(CondVarExpr
, N
, &report
))
3090 Out
<< WillBeUsedForACondition
;
3092 auto event
= std::make_shared
<PathDiagnosticEventPiece
>(Loc
, Out
.str());
3094 if (isInterestingExpr(CondVarExpr
, N
, &report
))
3095 event
->setPrunable(false);
3100 PathDiagnosticPieceRef
ConditionBRVisitor::VisitTrueTest(
3101 const Expr
*Cond
, const DeclRefExpr
*DRE
, BugReporterContext
&BRC
,
3102 PathSensitiveBugReport
&report
, const ExplodedNode
*N
, bool TookTrue
,
3104 const auto *VD
= dyn_cast
<VarDecl
>(DRE
->getDecl());
3108 SmallString
<256> Buf
;
3109 llvm::raw_svector_ostream
Out(Buf
);
3111 Out
<< (IsAssuming
? "Assuming '" : "'") << VD
->getDeclName() << "' is ";
3113 if (!printValue(DRE
, Out
, N
, TookTrue
, IsAssuming
))
3116 const LocationContext
*LCtx
= N
->getLocationContext();
3118 if (isVarAnInterestingCondition(DRE
, N
, &report
))
3119 Out
<< WillBeUsedForACondition
;
3121 // If we know the value create a pop-up note to the 'DRE'.
3123 PathDiagnosticLocation
Loc(DRE
, BRC
.getSourceManager(), LCtx
);
3124 return std::make_shared
<PathDiagnosticPopUpPiece
>(Loc
, Out
.str());
3127 PathDiagnosticLocation
Loc(Cond
, BRC
.getSourceManager(), LCtx
);
3128 auto event
= std::make_shared
<PathDiagnosticEventPiece
>(Loc
, Out
.str());
3130 if (isInterestingExpr(DRE
, N
, &report
))
3131 event
->setPrunable(false);
3133 return std::move(event
);
3136 PathDiagnosticPieceRef
ConditionBRVisitor::VisitTrueTest(
3137 const Expr
*Cond
, const MemberExpr
*ME
, BugReporterContext
&BRC
,
3138 PathSensitiveBugReport
&report
, const ExplodedNode
*N
, bool TookTrue
,
3140 SmallString
<256> Buf
;
3141 llvm::raw_svector_ostream
Out(Buf
);
3143 Out
<< (IsAssuming
? "Assuming field '" : "Field '")
3144 << ME
->getMemberDecl()->getName() << "' is ";
3146 if (!printValue(ME
, Out
, N
, TookTrue
, IsAssuming
))
3149 const LocationContext
*LCtx
= N
->getLocationContext();
3150 PathDiagnosticLocation Loc
;
3152 // If we know the value create a pop-up note to the member of the MemberExpr.
3153 if (!IsAssuming
&& ME
->getMemberLoc().isValid())
3154 Loc
= PathDiagnosticLocation(ME
->getMemberLoc(), BRC
.getSourceManager());
3156 Loc
= PathDiagnosticLocation(Cond
, BRC
.getSourceManager(), LCtx
);
3158 if (!Loc
.isValid() || !Loc
.asLocation().isValid())
3161 if (isVarAnInterestingCondition(ME
, N
, &report
))
3162 Out
<< WillBeUsedForACondition
;
3164 // If we know the value create a pop-up note.
3166 return std::make_shared
<PathDiagnosticPopUpPiece
>(Loc
, Out
.str());
3168 auto event
= std::make_shared
<PathDiagnosticEventPiece
>(Loc
, Out
.str());
3169 if (isInterestingExpr(ME
, N
, &report
))
3170 event
->setPrunable(false);
3174 bool ConditionBRVisitor::printValue(const Expr
*CondVarExpr
, raw_ostream
&Out
,
3175 const ExplodedNode
*N
, bool TookTrue
,
3177 QualType Ty
= CondVarExpr
->getType();
3179 if (Ty
->isPointerType()) {
3180 Out
<< (TookTrue
? "non-null" : "null");
3184 if (Ty
->isObjCObjectPointerType()) {
3185 Out
<< (TookTrue
? "non-nil" : "nil");
3189 if (!Ty
->isIntegralOrEnumerationType())
3192 std::optional
<const llvm::APSInt
*> IntValue
;
3194 IntValue
= getConcreteIntegerValue(CondVarExpr
, N
);
3196 if (IsAssuming
|| !IntValue
) {
3197 if (Ty
->isBooleanType())
3198 Out
<< (TookTrue
? "true" : "false");
3200 Out
<< (TookTrue
? "not equal to 0" : "0");
3202 if (Ty
->isBooleanType())
3203 Out
<< ((*IntValue
)->getBoolValue() ? "true" : "false");
3211 constexpr llvm::StringLiteral
ConditionBRVisitor::GenericTrueMessage
;
3212 constexpr llvm::StringLiteral
ConditionBRVisitor::GenericFalseMessage
;
3214 bool ConditionBRVisitor::isPieceMessageGeneric(
3215 const PathDiagnosticPiece
*Piece
) {
3216 return Piece
->getString() == GenericTrueMessage
||
3217 Piece
->getString() == GenericFalseMessage
;
3220 //===----------------------------------------------------------------------===//
3221 // Implementation of LikelyFalsePositiveSuppressionBRVisitor.
3222 //===----------------------------------------------------------------------===//
3224 void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
3225 BugReporterContext
&BRC
, const ExplodedNode
*N
,
3226 PathSensitiveBugReport
&BR
) {
3227 // Here we suppress false positives coming from system headers. This list is
3228 // based on known issues.
3229 const AnalyzerOptions
&Options
= BRC
.getAnalyzerOptions();
3230 const Decl
*D
= N
->getLocationContext()->getDecl();
3232 if (AnalysisDeclContext::isInStdNamespace(D
)) {
3233 // Skip reports within the 'std' namespace. Although these can sometimes be
3234 // the user's fault, we currently don't report them very well, and
3235 // Note that this will not help for any other data structure libraries, like
3236 // TR1, Boost, or llvm/ADT.
3237 if (Options
.ShouldSuppressFromCXXStandardLibrary
) {
3238 BR
.markInvalid(getTag(), nullptr);
3241 // If the complete 'std' suppression is not enabled, suppress reports
3242 // from the 'std' namespace that are known to produce false positives.
3244 // The analyzer issues a false use-after-free when std::list::pop_front
3245 // or std::list::pop_back are called multiple times because we cannot
3246 // reason about the internal invariants of the data structure.
3247 if (const auto *MD
= dyn_cast
<CXXMethodDecl
>(D
)) {
3248 const CXXRecordDecl
*CD
= MD
->getParent();
3249 if (CD
->getName() == "list") {
3250 BR
.markInvalid(getTag(), nullptr);
3255 // The analyzer issues a false positive when the constructor of
3256 // std::__independent_bits_engine from algorithms is used.
3257 if (const auto *MD
= dyn_cast
<CXXConstructorDecl
>(D
)) {
3258 const CXXRecordDecl
*CD
= MD
->getParent();
3259 if (CD
->getName() == "__independent_bits_engine") {
3260 BR
.markInvalid(getTag(), nullptr);
3265 for (const LocationContext
*LCtx
= N
->getLocationContext(); LCtx
;
3266 LCtx
= LCtx
->getParent()) {
3267 const auto *MD
= dyn_cast
<CXXMethodDecl
>(LCtx
->getDecl());
3271 const CXXRecordDecl
*CD
= MD
->getParent();
3272 // The analyzer issues a false positive on
3273 // std::basic_string<uint8_t> v; v.push_back(1);
3275 // std::u16string s; s += u'a';
3276 // because we cannot reason about the internal invariants of the
3278 if (CD
->getName() == "basic_string") {
3279 BR
.markInvalid(getTag(), nullptr);
3283 // The analyzer issues a false positive on
3284 // std::shared_ptr<int> p(new int(1)); p = nullptr;
3285 // because it does not reason properly about temporary destructors.
3286 if (CD
->getName() == "shared_ptr") {
3287 BR
.markInvalid(getTag(), nullptr);
3294 // Skip reports within the sys/queue.h macros as we do not have the ability to
3295 // reason about data structure shapes.
3296 const SourceManager
&SM
= BRC
.getSourceManager();
3297 FullSourceLoc Loc
= BR
.getLocation().asLocation();
3298 while (Loc
.isMacroID()) {
3299 Loc
= Loc
.getSpellingLoc();
3300 if (SM
.getFilename(Loc
).ends_with("sys/queue.h")) {
3301 BR
.markInvalid(getTag(), nullptr);
3307 //===----------------------------------------------------------------------===//
3308 // Implementation of UndefOrNullArgVisitor.
3309 //===----------------------------------------------------------------------===//
3311 PathDiagnosticPieceRef
3312 UndefOrNullArgVisitor::VisitNode(const ExplodedNode
*N
, BugReporterContext
&BRC
,
3313 PathSensitiveBugReport
&BR
) {
3314 ProgramStateRef State
= N
->getState();
3315 ProgramPoint ProgLoc
= N
->getLocation();
3317 // We are only interested in visiting CallEnter nodes.
3318 std::optional
<CallEnter
> CEnter
= ProgLoc
.getAs
<CallEnter
>();
3322 // Check if one of the arguments is the region the visitor is tracking.
3323 CallEventManager
&CEMgr
= BRC
.getStateManager().getCallEventManager();
3324 CallEventRef
<> Call
= CEMgr
.getCaller(CEnter
->getCalleeContext(), State
);
3326 ArrayRef
<ParmVarDecl
*> parms
= Call
->parameters();
3328 for (const auto ParamDecl
: parms
) {
3329 const MemRegion
*ArgReg
= Call
->getArgSVal(Idx
).getAsRegion();
3332 // Are we tracking the argument or its subregion?
3333 if ( !ArgReg
|| !R
->isSubRegionOf(ArgReg
->StripCasts()))
3336 // Check the function parameter type.
3337 assert(ParamDecl
&& "Formal parameter has no decl?");
3338 QualType T
= ParamDecl
->getType();
3340 if (!(T
->isAnyPointerType() || T
->isReferenceType())) {
3341 // Function can only change the value passed in by address.
3345 // If it is a const pointer value, the function does not intend to
3346 // change the value.
3347 if (T
->getPointeeType().isConstQualified())
3350 // Mark the call site (LocationContext) as interesting if the value of the
3351 // argument is undefined or '0'/'NULL'.
3352 SVal BoundVal
= State
->getSVal(R
);
3353 if (BoundVal
.isUndef() || BoundVal
.isZeroConstant()) {
3354 BR
.markInteresting(CEnter
->getCalleeContext());
3361 //===----------------------------------------------------------------------===//
3362 // Implementation of TagVisitor.
3363 //===----------------------------------------------------------------------===//
3365 int NoteTag::Kind
= 0;
3367 void TagVisitor::Profile(llvm::FoldingSetNodeID
&ID
) const {
3369 ID
.AddPointer(&Tag
);
3372 PathDiagnosticPieceRef
TagVisitor::VisitNode(const ExplodedNode
*N
,
3373 BugReporterContext
&BRC
,
3374 PathSensitiveBugReport
&R
) {
3375 ProgramPoint PP
= N
->getLocation();
3376 const NoteTag
*T
= dyn_cast_or_null
<NoteTag
>(PP
.getTag());
3380 if (std::optional
<std::string
> Msg
= T
->generateMessage(BRC
, R
)) {
3381 PathDiagnosticLocation Loc
=
3382 PathDiagnosticLocation::create(PP
, BRC
.getSourceManager());
3383 auto Piece
= std::make_shared
<PathDiagnosticEventPiece
>(Loc
, *Msg
);
3384 Piece
->setPrunable(T
->isPrunable());