aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp21
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp5
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp64
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp17
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp5
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp13
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp45
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h4
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp9
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp7
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp80
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporter.cpp1
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp3
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugSuppression.cpp7
-rw-r--r--clang/lib/StaticAnalyzer/Core/CallEvent.cpp18
-rw-r--r--clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp14
-rw-r--r--clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp7
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp5
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp1
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp56
-rw-r--r--clang/lib/StaticAnalyzer/Core/RegionStore.cpp48
-rw-r--r--clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp11
-rw-r--r--clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp6
-rw-r--r--clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp2
28 files changed, 249 insertions, 210 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
index 3ddd659..2db5310 100644
--- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -115,7 +115,23 @@ class RAIIMutexDescriptor {
return false;
const IdentifierInfo *II =
cast<CXXRecordDecl>(C->getDecl()->getParent())->getIdentifier();
- return II == Guard;
+ if (II != Guard)
+ return false;
+
+ // For unique_lock, check if it's constructed with a ctor that takes the tag
+ // type defer_lock_t. In this case, the lock is not acquired.
+ if constexpr (std::is_same_v<T, CXXConstructorCall>) {
+ if (GuardName == "unique_lock" && C->getNumArgs() >= 2) {
+ const Expr *SecondArg = C->getArgExpr(1);
+ QualType ArgType = SecondArg->getType().getNonReferenceType();
+ if (const auto *RD = ArgType->getAsRecordDecl();
+ RD && RD->getName() == "defer_lock_t" && RD->isInStdNamespace()) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
public:
@@ -270,8 +286,7 @@ REGISTER_LIST_WITH_PROGRAMSTATE(ActiveCritSections, CritSectionMarker)
// TODO: Move these to llvm::ImmutableList when overhauling immutable data
// structures for proper iterator concept support.
template <>
-struct std::iterator_traits<
- typename llvm::ImmutableList<CritSectionMarker>::iterator> {
+struct std::iterator_traits<llvm::ImmutableList<CritSectionMarker>::iterator> {
using iterator_category = std::forward_iterator_tag;
using value_type = CritSectionMarker;
using difference_type = std::ptrdiff_t;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 7cc146e..e71fe47 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -322,13 +322,12 @@ bool CallAndMessageChecker::PreVisitProcessArg(
else {
os << " (e.g., via the field chain: '";
bool first = true;
- for (SmallVectorImpl<const FieldDecl *>::iterator
- DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){
+ for (const FieldDecl *FD : F.FieldChain) {
if (first)
first = false;
else
os << '.';
- os << **DI;
+ os << *FD;
}
os << "')";
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 70baab5..ec7ef23 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -6,41 +6,45 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines a variety of memory management related checkers, such as
+// This file defines checkers that report memory management errors such as
// leak, double free, and use-after-free.
//
-// The following checkers are defined here:
+// The logic for modeling memory allocations is implemented in the checker
+// family which is called 'MallocChecker' for historical reasons. (This name is
+// inaccurate, something like 'DynamicMemory' would be more precise.)
//
-// * MallocChecker
-// Despite its name, it models all sorts of memory allocations and
-// de- or reallocation, including but not limited to malloc, free,
-// relloc, new, delete. It also reports on a variety of memory misuse
-// errors.
-// Many other checkers interact very closely with this checker, in fact,
-// most are merely options to this one. Other checkers may register
-// MallocChecker, but do not enable MallocChecker's reports (more details
-// to follow around its field, ChecksEnabled).
-// It also has a boolean "Optimistic" checker option, which if set to true
-// will cause the checker to model user defined memory management related
-// functions annotated via the attribute ownership_takes, ownership_holds
-// and ownership_returns.
+// The reports produced by this backend are exposed through several frontends:
+// * MallocChecker: reports all misuse of dynamic memory allocated by
+// malloc, related functions (like calloc, realloc etc.) and the functions
+// annotated by ownership_returns. (Here the name "MallocChecker" is
+// reasonably accurate; don't confuse this checker frontend with the whole
+// misnamed family.)
+// * NewDeleteChecker: reports most misuse (anything but memory leaks) of
+// memory managed by the C++ operators new and new[].
+// * NewDeleteLeaksChecker: reports leaks of dynamic memory allocated by
+// the C++ operators new and new[].
+// * MismatchedDeallocatorChecker: reports situations where the allocation
+// and deallocation is mismatched, e.g. memory allocated via malloc is
+// passed to operator delete.
+// * InnerPointerChecker: reports use of pointers to the internal buffer of
+// a std::string instance after operations that invalidate them.
+// * TaintedAllocChecker: reports situations where the size argument of a
+// memory allocation function or array new operator is tainted (i.e. comes
+// from an untrusted source and can be controlled by an attacker).
//
-// * NewDeleteChecker
-// Enables the modeling of new, new[], delete, delete[] in MallocChecker,
-// and checks for related double-free and use-after-free errors.
+// In addition to these frontends this file also defines the registration
+// functions for "unix.DynamicMemoryModeling". This registers the callbacks of
+// the checker family MallocChecker without enabling any of the frontends and
+// and handle two checker options which are attached to this "modeling
+// checker" because they affect multiple checker frontends.
//
-// * NewDeleteLeaksChecker
-// Checks for leaks related to new, new[], delete, delete[].
-// Depends on NewDeleteChecker.
-//
-// * MismatchedDeallocatorChecker
-// Enables checking whether memory is deallocated with the corresponding
-// allocation function in MallocChecker, such as malloc() allocated
-// regions are only freed by free(), new by delete, new[] by delete[].
-//
-// InnerPointerChecker interacts very closely with MallocChecker, but unlike
-// the above checkers, it has it's own file, hence the many InnerPointerChecker
-// related headers and non-static functions.
+// Note that what the users see as the checker "cplusplus.InnerPointer" is a
+// combination of the frontend InnerPointerChecker (within this family) which
+// emits the bug reports and a separate checker class (also named
+// InnerPointerChecker) which is defined in InnerPointerChecker.cpp and does a
+// significant part of the modeling. This cooperation is enabled by several
+// non-static helper functions that are defined within this translation unit
+// and used in InnerPointerChecker.cpp.
//
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
index f5c3407..ba8281b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
@@ -244,11 +244,12 @@ bool isMovedFrom(ProgramStateRef State, const MemRegion *Region) {
// If a region is removed all of the subregions needs to be removed too.
static ProgramStateRef removeFromState(ProgramStateRef State,
- const MemRegion *Region) {
+ const MemRegion *Region,
+ bool Strict = false) {
if (!Region)
return State;
for (auto &E : State->get<TrackedRegionMap>()) {
- if (E.first->isSubRegionOf(Region))
+ if ((!Strict || E.first != Region) && E.first->isSubRegionOf(Region))
State = State->remove<TrackedRegionMap>(E.first);
}
return State;
@@ -709,18 +710,16 @@ ProgramStateRef MoveChecker::checkRegionChanges(
// that are passed directly via non-const pointers or non-const references
// or rvalue references.
// In case of an InstanceCall don't invalidate the this-region since
- // it is fully handled in checkPreCall and checkPostCall.
- const MemRegion *ThisRegion = nullptr;
- if (const auto *IC = dyn_cast<CXXInstanceCall>(Call))
- ThisRegion = IC->getCXXThisVal().getAsRegion();
+ // it is fully handled in checkPreCall and checkPostCall, but do invalidate
+ // its strict subregions, as they are not handled.
// Requested ("explicit") regions are the regions passed into the call
// directly, but not all of them end up being invalidated.
// But when they do, they appear in the InvalidatedRegions array as well.
for (const auto *Region : RequestedRegions) {
- if (ThisRegion != Region &&
- llvm::is_contained(InvalidatedRegions, Region))
- State = removeFromState(State, Region);
+ if (llvm::is_contained(InvalidatedRegions, Region))
+ State = removeFromState(State, Region,
+ /*Strict=*/isa<CXXInstanceCall>(Call));
}
} else {
// For invalidations that aren't caused by calls, assume nothing. In
diff --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index 019e81f..027bf78 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -22,6 +22,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace ento;
@@ -247,6 +248,7 @@ class FindStackRegionsSymbolVisitor final : public SymbolVisitor {
CheckerContext &Ctxt;
const StackFrameContext *PoppedStackFrame;
SmallVectorImpl<const MemRegion *> &EscapingStackRegions;
+ llvm::SmallPtrSet<const MemRegion *, 16> VisitedRegions;
public:
explicit FindStackRegionsSymbolVisitor(
@@ -258,6 +260,9 @@ public:
bool VisitSymbol(SymbolRef sym) override { return true; }
bool VisitMemRegion(const MemRegion *MR) override {
+ if (!VisitedRegions.insert(MR).second)
+ return true;
+
SaveIfEscapes(MR);
if (const BlockDataRegion *BDR = MR->getAs<BlockDataRegion>())
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp
index db8bbee..c5dad61 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdVariantChecker.cpp
@@ -90,6 +90,9 @@ bool isStdVariant(const Type *Type) {
static std::optional<ArrayRef<TemplateArgument>>
getTemplateArgsFromVariant(const Type *VariantType) {
const auto *TempSpecType = VariantType->getAs<TemplateSpecializationType>();
+ while (TempSpecType && TempSpecType->isTypeAlias())
+ TempSpecType =
+ TempSpecType->getAliasedType()->getAs<TemplateSpecializationType>();
if (!TempSpecType)
return {};
@@ -219,10 +222,12 @@ private:
bool handleStdGetCall(const CallEvent &Call, CheckerContext &C) const {
ProgramStateRef State = C.getState();
- const auto &ArgType = Call.getArgSVal(0)
- .getType(C.getASTContext())
- ->getPointeeType()
- .getTypePtr();
+ SVal ArgSVal = Call.getArgSVal(0);
+ if (ArgSVal.isUnknown())
+ return false;
+
+ const auto &ArgType =
+ ArgSVal.getType(C.getASTContext())->getPointeeType().getTypePtr();
// We have to make sure that the argument is an std::variant.
// There is another std::get with std::pair argument
if (!isStdVariant(ArgType))
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index 84adbf3..e46bba7 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -321,6 +321,51 @@ bool isExprToGetCheckedPtrCapableMember(const clang::Expr *E) {
return result && *result;
}
+bool isAllocInit(const Expr *E, const Expr **InnerExpr) {
+ auto *ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(E);
+ if (auto *POE = dyn_cast<PseudoObjectExpr>(E)) {
+ if (unsigned ExprCount = POE->getNumSemanticExprs()) {
+ auto *Expr = POE->getSemanticExpr(ExprCount - 1)->IgnoreParenCasts();
+ ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(Expr);
+ if (InnerExpr)
+ *InnerExpr = ObjCMsgExpr;
+ }
+ }
+ if (!ObjCMsgExpr)
+ return false;
+ auto Selector = ObjCMsgExpr->getSelector();
+ auto NameForFirstSlot = Selector.getNameForSlot(0);
+ if (NameForFirstSlot.starts_with("alloc") ||
+ NameForFirstSlot.starts_with("copy") ||
+ NameForFirstSlot.starts_with("mutableCopy"))
+ return true;
+ if (!NameForFirstSlot.starts_with("init") &&
+ !NameForFirstSlot.starts_with("_init"))
+ return false;
+ if (!ObjCMsgExpr->isInstanceMessage())
+ return false;
+ auto *Receiver = ObjCMsgExpr->getInstanceReceiver();
+ if (!Receiver)
+ return false;
+ Receiver = Receiver->IgnoreParenCasts();
+ if (auto *Inner = dyn_cast<ObjCMessageExpr>(Receiver)) {
+ if (InnerExpr)
+ *InnerExpr = Inner;
+ auto InnerSelector = Inner->getSelector();
+ return InnerSelector.getNameForSlot(0).starts_with("alloc");
+ } else if (auto *CE = dyn_cast<CallExpr>(Receiver)) {
+ if (InnerExpr)
+ *InnerExpr = CE;
+ if (auto *Callee = CE->getDirectCallee()) {
+ if (Callee->getDeclName().isIdentifier()) {
+ auto CalleeName = Callee->getName();
+ return CalleeName.starts_with("alloc");
+ }
+ }
+ }
+ return false;
+}
+
class EnsureFunctionVisitor
: public ConstStmtVisitor<EnsureFunctionVisitor, bool> {
public:
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h
index 9fff456..d0a3e471 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h
@@ -77,6 +77,10 @@ bool isConstOwnerPtrMemberExpr(const clang::Expr *E);
/// supports CheckedPtr.
bool isExprToGetCheckedPtrCapableMember(const clang::Expr *E);
+/// \returns true if \p E is a [[alloc] init] pattern expression.
+/// Sets \p InnerExpr to the inner function call or selector invocation.
+bool isAllocInit(const Expr *E, const Expr **InnerExpr = nullptr);
+
/// \returns true if E is a CXXMemberCallExpr which returns a const smart
/// pointer type.
class EnsureFunctionAnalysis {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index d3d1f13..5cd894a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -578,6 +578,10 @@ public:
return WithCachedResult(CS, [&]() { return VisitChildren(CS); });
}
+ bool VisitCoroutineBodyStmt(const CoroutineBodyStmt *CBS) {
+ return WithCachedResult(CBS, [&]() { return VisitChildren(CBS); });
+ }
+
bool VisitReturnStmt(const ReturnStmt *RS) {
// A return statement is allowed as long as the return value is trivial.
if (auto *RV = RS->getRetValue())
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp
index 791e7099..dcc14a0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp
@@ -177,16 +177,11 @@ public:
if (BR->getSourceManager().isInSystemHeader(E->getExprLoc()))
return;
- auto Selector = E->getSelector();
if (auto *Receiver = E->getInstanceReceiver()) {
std::optional<bool> IsUnsafe = isUnsafePtr(E->getReceiverType());
if (IsUnsafe && *IsUnsafe && !isPtrOriginSafe(Receiver)) {
- if (auto *InnerMsg = dyn_cast<ObjCMessageExpr>(Receiver)) {
- auto InnerSelector = InnerMsg->getSelector();
- if (InnerSelector.getNameForSlot(0) == "alloc" &&
- Selector.getNameForSlot(0).starts_with("init"))
- return;
- }
+ if (isAllocInit(E))
+ return;
reportBugOnReceiver(Receiver, D);
}
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
index f60d193..f3fadea 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
@@ -587,6 +587,8 @@ public:
}
std::optional<bool> isUnsafePtr(QualType QT) const final {
+ if (QT.hasStrongOrWeakObjCLifetime())
+ return false;
return RTC->isUnretained(QT);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp
index c13df479..f2235e7c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp
@@ -433,6 +433,8 @@ public:
RTC = RetainTypeChecker();
}
std::optional<bool> isUnsafePtr(const QualType T) const final {
+ if (T.hasStrongOrWeakObjCLifetime())
+ return false;
return RTC->isUnretained(T);
}
bool isSafePtr(const CXXRecordDecl *Record) const final {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
index ace639c..0e23ae3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
@@ -231,8 +231,11 @@ public:
// "assign" property doesn't retain even under ARC so treat it as unsafe.
bool ignoreARC =
!PD->isReadOnly() && PD->getSetterKind() == ObjCPropertyDecl::Assign;
+ bool IsWeak =
+ PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak;
+ bool HasSafeAttr = PD->isRetaining() || IsWeak;
auto IsUnsafePtr = isUnsafePtr(QT, ignoreARC);
- return {IsUnsafePtr && *IsUnsafePtr && !PD->isRetaining(), PropType};
+ return {IsUnsafePtr && *IsUnsafePtr && !HasSafeAttr, PropType};
}
bool shouldSkipDecl(const RecordDecl *RD) const {
@@ -363,6 +366,8 @@ public:
}
std::optional<bool> isUnsafePtr(QualType QT, bool ignoreARC) const final {
+ if (QT.hasStrongOrWeakObjCLifetime())
+ return false;
return RTC->isUnretained(QT, ignoreARC);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
index 955b8d1..2af9067 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
@@ -355,15 +355,37 @@ public:
void visitBinaryOperator(const BinaryOperator *BO) const {
if (!BO->isAssignmentOp())
return;
- if (!isa<ObjCIvarRefExpr>(BO->getLHS()))
- return;
+ auto *LHS = BO->getLHS();
auto *RHS = BO->getRHS()->IgnoreParenCasts();
- const Expr *Inner = nullptr;
- if (isAllocInit(RHS, &Inner)) {
- CreateOrCopyFnCall.insert(RHS);
- if (Inner)
- CreateOrCopyFnCall.insert(Inner);
+ if (isa<ObjCIvarRefExpr>(LHS)) {
+ const Expr *Inner = nullptr;
+ if (isAllocInit(RHS, &Inner)) {
+ CreateOrCopyFnCall.insert(RHS);
+ if (Inner)
+ CreateOrCopyFnCall.insert(Inner);
+ }
+ return;
}
+ auto *UO = dyn_cast<UnaryOperator>(LHS);
+ if (!UO)
+ return;
+ auto OpCode = UO->getOpcode();
+ if (OpCode != UO_Deref)
+ return;
+ auto *DerefTarget = UO->getSubExpr();
+ if (!DerefTarget)
+ return;
+ DerefTarget = DerefTarget->IgnoreParenCasts();
+ auto *DRE = dyn_cast<DeclRefExpr>(DerefTarget);
+ if (!DRE)
+ return;
+ auto *Decl = DRE->getDecl();
+ if (!Decl)
+ return;
+ if (!isa<ParmVarDecl>(Decl) || !isCreateOrCopy(RHS))
+ return;
+ if (Decl->hasAttr<CFReturnsRetainedAttr>())
+ CreateOrCopyFnCall.insert(RHS);
}
void visitReturnStmt(const ReturnStmt *RS, const Decl *DeclWithIssue) const {
@@ -423,50 +445,6 @@ public:
return std::nullopt;
}
- bool isAllocInit(const Expr *E, const Expr **InnerExpr = nullptr) const {
- auto *ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(E);
- if (auto *POE = dyn_cast<PseudoObjectExpr>(E)) {
- if (unsigned ExprCount = POE->getNumSemanticExprs()) {
- auto *Expr = POE->getSemanticExpr(ExprCount - 1)->IgnoreParenCasts();
- ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(Expr);
- if (InnerExpr)
- *InnerExpr = ObjCMsgExpr;
- }
- }
- if (!ObjCMsgExpr)
- return false;
- auto Selector = ObjCMsgExpr->getSelector();
- auto NameForFirstSlot = Selector.getNameForSlot(0);
- if (NameForFirstSlot == "alloc" || NameForFirstSlot.starts_with("copy") ||
- NameForFirstSlot.starts_with("mutableCopy"))
- return true;
- if (!NameForFirstSlot.starts_with("init") &&
- !NameForFirstSlot.starts_with("_init"))
- return false;
- if (!ObjCMsgExpr->isInstanceMessage())
- return false;
- auto *Receiver = ObjCMsgExpr->getInstanceReceiver();
- if (!Receiver)
- return false;
- Receiver = Receiver->IgnoreParenCasts();
- if (auto *Inner = dyn_cast<ObjCMessageExpr>(Receiver)) {
- if (InnerExpr)
- *InnerExpr = Inner;
- auto InnerSelector = Inner->getSelector();
- return InnerSelector.getNameForSlot(0) == "alloc";
- } else if (auto *CE = dyn_cast<CallExpr>(Receiver)) {
- if (InnerExpr)
- *InnerExpr = CE;
- if (auto *Callee = CE->getDirectCallee()) {
- if (Callee->getDeclName().isIdentifier()) {
- auto CalleeName = Callee->getName();
- return CalleeName.starts_with("alloc");
- }
- }
- }
- return false;
- }
-
bool isCreateOrCopy(const Expr *E) const {
auto *CE = dyn_cast<CallExpr>(E);
if (!CE)
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 5fe64dc..4c06652 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -25,7 +25,6 @@
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
-#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/LLVM.h"
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 63f0d70..0ba3c05 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -3254,9 +3254,6 @@ bool ConditionBRVisitor::printValue(const Expr *CondVarExpr, raw_ostream &Out,
return true;
}
-constexpr llvm::StringLiteral ConditionBRVisitor::GenericTrueMessage;
-constexpr llvm::StringLiteral ConditionBRVisitor::GenericFalseMessage;
-
bool ConditionBRVisitor::isPieceMessageGeneric(
const PathDiagnosticPiece *Piece) {
return Piece->getString() == GenericTrueMessage ||
diff --git a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
index 5b5f9df..a7300b7 100644
--- a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp
@@ -117,7 +117,12 @@ private:
}
}
- CacheInitializer(Ranges &R) : Result(R) {}
+ CacheInitializer(Ranges &R) : Result(R) {
+ ShouldVisitTemplateInstantiations = true;
+ ShouldWalkTypesOfTypeLocs = false;
+ ShouldVisitImplicitCode = false;
+ ShouldVisitLambdaBody = true;
+ }
Ranges &Result;
};
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 62460cc..d04c827 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -230,13 +230,11 @@ static void findPtrToConstParams(llvm::SmallSet<unsigned, 4> &PreserveArgs,
}
ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
- ProgramStateRef Orig) const {
- ProgramStateRef Result = (Orig ? Orig : getState());
-
+ ProgramStateRef State) const {
// Don't invalidate anything if the callee is marked pure/const.
- if (const Decl *callee = getDecl())
- if (callee->hasAttr<PureAttr>() || callee->hasAttr<ConstAttr>())
- return Result;
+ if (const Decl *Callee = getDecl())
+ if (Callee->hasAttr<PureAttr>() || Callee->hasAttr<ConstAttr>())
+ return State;
SmallVector<SVal, 8> ValuesToInvalidate;
RegionAndSymbolInvalidationTraits ETraits;
@@ -278,10 +276,10 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
// Invalidate designated regions using the batch invalidation API.
// NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
// global variables.
- return Result->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),
- BlockCount, getLocationContext(),
- /*CausedByPointerEscape*/ true,
- /*Symbols=*/nullptr, this, &ETraits);
+ return State->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),
+ BlockCount, getLocationContext(),
+ /*CausedByPointerEscape*/ true,
+ /*Symbols=*/nullptr, this, &ETraits);
}
ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
diff --git a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
index 8b40437..29d55ac 100644
--- a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -142,19 +142,25 @@ std::optional<int> tryExpandAsInteger(StringRef Macro, const Preprocessor &PP) {
if (InvalidSpelling)
return std::nullopt;
- llvm::APInt IntValue;
+ llvm::APSInt IntValue(/*BitWidth=*/0, /*isUnsigned=*/true);
constexpr unsigned AutoSenseRadix = 0;
- if (ValueStr.getAsInteger(AutoSenseRadix, IntValue))
+ if (ValueStr.getAsInteger(AutoSenseRadix,
+ static_cast<llvm::APInt &>(IntValue)))
return std::nullopt;
// Parse an optional minus sign.
size_t Size = FilteredTokens.size();
if (Size >= 2) {
- if (FilteredTokens[Size - 2].is(tok::minus))
+ if (FilteredTokens[Size - 2].is(tok::minus)) {
+ // Make sure there's space for a sign bit
+ if (IntValue.isSignBitSet())
+ IntValue = IntValue.extend(IntValue.getBitWidth() + 1);
+ IntValue.setIsUnsigned(false);
IntValue = -IntValue;
+ }
}
- return IntValue.getSExtValue();
+ return IntValue.getExtValue();
}
OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK,
diff --git a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
index 34078db..e5d5e01 100644
--- a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
@@ -128,5 +128,12 @@ ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR,
return State->set<DynamicExtentMap>(MR->StripCasts(), Size);
}
+void markAllDynamicExtentLive(ProgramStateRef State, SymbolReaper &SymReaper) {
+ for (const auto &I : State->get<DynamicExtentMap>())
+ if (SymbolRef Sym = I.second.getAsSymbol())
+ if (SymReaper.isLiveRegion(I.first))
+ SymReaper.markLive(Sym);
+}
+
} // namespace ento
} // namespace clang
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 4e472b7..a759aee 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1079,6 +1079,11 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
getCheckerManager().runCheckersForDeadSymbols(CheckedSet, Pred, SymReaper,
DiagnosticStmt, *this, K);
+ // Extend lifetime of symbols used for dynamic extent while the parent region
+ // is live. In this way size information about memory allocations is not lost
+ // if the region remains live.
+ markAllDynamicExtentLive(CleanedState, SymReaper);
+
// For each node in CheckedSet, generate CleanedNodes that have the
// environment, the store, and the constraints cleaned up but have the
// user-supplied states as the predecessors.
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 4ddf8fd..db27c06 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -560,6 +560,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_VectorSplat:
case CK_HLSLElementwiseCast:
case CK_HLSLAggregateSplatCast:
+ case CK_HLSLMatrixTruncation:
case CK_HLSLVectorTruncation: {
QualType resultType = CastE->getType();
if (CastE->isGLValue())
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 75d7e26..00e3ef8 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -1013,7 +1013,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
// FIXME: Once we figure out how we want allocators to work,
// we should be using the usual pre-/(default-)eval-/post-call checkers
// here.
- State = Call->invalidateRegions(blockCount);
+ State = Call->invalidateRegions(blockCount, State);
if (!State)
return;
diff --git a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
index 01d87b0..5803cbd 100644
--- a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
+++ b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
@@ -23,6 +23,8 @@ using namespace clang;
using namespace ento;
using namespace clang::ast_matchers;
+using ast_matchers::internal::Matcher;
+
static const int MAXIMUM_STEP_UNROLLED = 128;
namespace {
@@ -69,6 +71,11 @@ public:
REGISTER_LIST_WITH_PROGRAMSTATE(LoopStack, LoopState)
namespace clang {
+namespace {
+AST_MATCHER(QualType, isIntegralOrEnumerationType) {
+ return Node->isIntegralOrEnumerationType();
+}
+} // namespace
namespace ento {
static bool isLoopStmt(const Stmt *S) {
@@ -82,22 +89,23 @@ ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State) {
return State;
}
-static internal::Matcher<Stmt> simpleCondition(StringRef BindName,
- StringRef RefName) {
+static Matcher<Stmt> simpleCondition(StringRef BindName, StringRef RefName) {
+ auto LoopVariable = ignoringParenImpCasts(
+ declRefExpr(to(varDecl(hasType(isInteger())).bind(BindName)))
+ .bind(RefName));
+ auto UpperBound = ignoringParenImpCasts(
+ expr(hasType(isIntegralOrEnumerationType())).bind("boundNum"));
+
return binaryOperator(
anyOf(hasOperatorName("<"), hasOperatorName(">"),
hasOperatorName("<="), hasOperatorName(">="),
hasOperatorName("!=")),
- hasEitherOperand(ignoringParenImpCasts(
- declRefExpr(to(varDecl(hasType(isInteger())).bind(BindName)))
- .bind(RefName))),
- hasEitherOperand(
- ignoringParenImpCasts(integerLiteral().bind("boundNum"))))
+ anyOf(binaryOperator(hasLHS(LoopVariable), hasRHS(UpperBound)),
+ binaryOperator(hasRHS(LoopVariable), hasLHS(UpperBound))))
.bind("conditionOperator");
}
-static internal::Matcher<Stmt>
-changeIntBoundNode(internal::Matcher<Decl> VarNodeMatcher) {
+static Matcher<Stmt> changeIntBoundNode(Matcher<Decl> VarNodeMatcher) {
return anyOf(
unaryOperator(anyOf(hasOperatorName("--"), hasOperatorName("++")),
hasUnaryOperand(ignoringParenImpCasts(
@@ -107,15 +115,13 @@ changeIntBoundNode(internal::Matcher<Decl> VarNodeMatcher) {
declRefExpr(to(varDecl(VarNodeMatcher)))))));
}
-static internal::Matcher<Stmt>
-callByRef(internal::Matcher<Decl> VarNodeMatcher) {
+static Matcher<Stmt> callByRef(Matcher<Decl> VarNodeMatcher) {
return callExpr(forEachArgumentWithParam(
declRefExpr(to(varDecl(VarNodeMatcher))),
parmVarDecl(hasType(references(qualType(unless(isConstQualified())))))));
}
-static internal::Matcher<Stmt>
-assignedToRef(internal::Matcher<Decl> VarNodeMatcher) {
+static Matcher<Stmt> assignedToRef(Matcher<Decl> VarNodeMatcher) {
return declStmt(hasDescendant(varDecl(
allOf(hasType(referenceType()),
hasInitializer(anyOf(
@@ -123,14 +129,13 @@ assignedToRef(internal::Matcher<Decl> VarNodeMatcher) {
declRefExpr(to(varDecl(VarNodeMatcher)))))))));
}
-static internal::Matcher<Stmt>
-getAddrTo(internal::Matcher<Decl> VarNodeMatcher) {
+static Matcher<Stmt> getAddrTo(Matcher<Decl> VarNodeMatcher) {
return unaryOperator(
hasOperatorName("&"),
hasUnaryOperand(declRefExpr(hasDeclaration(VarNodeMatcher))));
}
-static internal::Matcher<Stmt> hasSuspiciousStmt(StringRef NodeName) {
+static Matcher<Stmt> hasSuspiciousStmt(StringRef NodeName) {
return hasDescendant(stmt(
anyOf(gotoStmt(), switchStmt(), returnStmt(),
// Escaping and not known mutation of the loop counter is handled
@@ -142,7 +147,7 @@ static internal::Matcher<Stmt> hasSuspiciousStmt(StringRef NodeName) {
assignedToRef(equalsBoundNode(std::string(NodeName))))));
}
-static internal::Matcher<Stmt> forLoopMatcher() {
+static Matcher<Stmt> forLoopMatcher() {
return forStmt(
hasCondition(simpleCondition("initVarName", "initVarRef")),
// Initialization should match the form: 'int i = 6' or 'i = 42'.
@@ -271,23 +276,26 @@ static bool shouldCompletelyUnroll(const Stmt *LoopStmt, ASTContext &ASTCtx,
if (!isLoopStmt(LoopStmt))
return false;
- // TODO: Match the cases where the bound is not a concrete literal but an
- // integer with known value
auto Matches = match(forLoopMatcher(), *LoopStmt, ASTCtx);
if (Matches.empty())
return false;
const auto *CounterVarRef = Matches[0].getNodeAs<DeclRefExpr>("initVarRef");
- llvm::APInt BoundNum =
- Matches[0].getNodeAs<IntegerLiteral>("boundNum")->getValue();
+ const Expr *BoundNumExpr = Matches[0].getNodeAs<Expr>("boundNum");
+
+ Expr::EvalResult BoundNumResult;
+ if (!BoundNumExpr || !BoundNumExpr->EvaluateAsInt(BoundNumResult, ASTCtx,
+ Expr::SE_NoSideEffects)) {
+ return false;
+ }
llvm::APInt InitNum =
Matches[0].getNodeAs<IntegerLiteral>("initNum")->getValue();
auto CondOp = Matches[0].getNodeAs<BinaryOperator>("conditionOperator");
- unsigned MaxWidth = std::max(InitNum.getBitWidth(), BoundNum.getBitWidth());
+ unsigned MaxWidth = std::max(InitNum.getBitWidth(),
+ BoundNumResult.Val.getInt().getBitWidth());
InitNum = InitNum.zext(MaxWidth);
- BoundNum = BoundNum.zext(MaxWidth);
-
+ llvm::APInt BoundNum = BoundNumResult.Val.getInt().zext(MaxWidth);
if (CondOp->getOpcode() == BO_GE || CondOp->getOpcode() == BO_LE)
maxStep = (BoundNum - InitNum + 1).abs().getZExtValue();
else
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 2838533..4f4824a 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -714,11 +714,6 @@ public: // Part of public interface to class.
return getBinding(getRegionBindings(S), L, T);
}
- std::optional<SVal> getUniqueDefaultBinding(RegionBindingsConstRef B,
- const TypedValueRegion *R) const;
- std::optional<SVal>
- getUniqueDefaultBinding(nonloc::LazyCompoundVal LCV) const;
-
std::optional<SVal> getDefaultBinding(Store S, const MemRegion *R) override {
RegionBindingsRef B = getRegionBindings(S);
// Default bindings are always applied over a base region so look up the
@@ -2465,11 +2460,6 @@ SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B,
// behavior doesn't depend on the struct layout.
// This way even an empty struct can carry taint, no matter if creduce drops
// the last field member or not.
-
- // Try to avoid creating a LCV if it would anyways just refer to a single
- // default binding.
- if (std::optional<SVal> Val = getUniqueDefaultBinding(B, R))
- return *Val;
return createLazyBinding(B, R);
}
@@ -2757,50 +2747,12 @@ RegionStoreManager::bindVector(LimitedRegionBindingsConstRef B,
return NewB;
}
-std::optional<SVal>
-RegionStoreManager::getUniqueDefaultBinding(RegionBindingsConstRef B,
- const TypedValueRegion *R) const {
- if (R != R->getBaseRegion())
- return std::nullopt;
-
- const auto *Cluster = B.lookup(R);
- if (!Cluster || !llvm::hasSingleElement(*Cluster))
- return std::nullopt;
-
- const auto [Key, Value] = *Cluster->begin();
- return Key.isDirect() ? std::optional<SVal>{} : Value;
-}
-
-std::optional<SVal>
-RegionStoreManager::getUniqueDefaultBinding(nonloc::LazyCompoundVal LCV) const {
- auto B = getRegionBindings(LCV.getStore());
- return getUniqueDefaultBinding(B, LCV.getRegion());
-}
-
std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
LimitedRegionBindingsConstRef B, const TypedValueRegion *R,
const RecordDecl *RD, nonloc::LazyCompoundVal LCV) {
if (B.hasExhaustedBindingLimit())
return B.withValuesEscaped(LCV);
- // If we try to copy a Conjured value representing the value of the whole
- // struct, don't try to element-wise copy each field.
- // That would unnecessarily bind Derived symbols slicing off the subregion for
- // the field from the whole Conjured symbol.
- //
- // struct Window { int width; int height; };
- // Window getWindow(); <-- opaque fn.
- // Window w = getWindow(); <-- conjures a new Window.
- // Window w2 = w; <-- trivial copy "w", calling "tryBindSmallStruct"
- //
- // We should not end up with a new Store for "w2" like this:
- // Direct [ 0..31]: Derived{Conj{}, w.width}
- // Direct [32..63]: Derived{Conj{}, w.height}
- // Instead, we should just bind that Conjured value instead.
- if (std::optional<SVal> Val = getUniqueDefaultBinding(LCV)) {
- return B.addBinding(BindingKey::Make(R, BindingKey::Default), Val.value());
- }
-
FieldVector Fields;
if (const CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(RD))
diff --git a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
index 6673f2f..c9f5774 100644
--- a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
@@ -202,11 +202,10 @@ SarifDiagnostics::createResult(const PathDiagnostic *Diag,
// Find the HTML report that was generated for this issue, if one exists.
PDFileEntry::ConsumerFiles *Files = FM->getFiles(*Diag);
if (Files) {
- auto HtmlFile =
- std::find_if(Files->cbegin(), Files->cend(), [](auto &File) {
- return File.first == HTML_DIAGNOSTICS_NAME;
- });
- if (HtmlFile != Files->cend()) {
+ auto HtmlFile = llvm::find_if(*Files, [](const auto &File) {
+ return File.first == HTML_DIAGNOSTICS_NAME;
+ });
+ if (HtmlFile != Files->end()) {
SmallString<128> HtmlReportPath =
llvm::sys::path::parent_path(OutputFile);
llvm::sys::path::append(HtmlReportPath, HtmlFile->second);
@@ -219,7 +218,7 @@ SarifDiagnostics::createResult(const PathDiagnostic *Diag,
.setRuleId(CheckName)
.setDiagnosticMessage(Diag->getVerboseDescription())
.setDiagnosticLevel(SarifResultLevel::Warning)
- .setLocations({Range})
+ .addLocations({Range})
.addPartialFingerprint(IssueHashKey, IssueHash)
.setHostedViewerURI(HtmlReportURL)
.setThreadFlows(Flows);
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index e0deec1..827fcaa 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -364,7 +364,7 @@ private:
void storeTopLevelDecls(DeclGroupRef DG);
/// Check if we should skip (not analyze) the given function.
- AnalysisMode getModeForDecl(Decl *D, AnalysisMode Mode);
+ AnalysisMode getModeForDecl(const Decl *D, AnalysisMode Mode) const;
void runAnalysisOnTranslationUnit(ASTContext &C);
/// Print \p S to stderr if \c Opts.AnalyzerDisplayProgress is set.
@@ -677,7 +677,7 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
}
AnalysisConsumer::AnalysisMode
-AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
+AnalysisConsumer::getModeForDecl(const Decl *D, AnalysisMode Mode) const {
if (!Opts.AnalyzeSpecificFunction.empty() &&
AnalysisDeclContext::getFunctionName(D) != Opts.AnalyzeSpecificFunction &&
cross_tu::CrossTranslationUnitContext::getLookupName(D).value_or("") !=
@@ -695,7 +695,7 @@ AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
const SourceManager &SM = Ctx->getSourceManager();
- const SourceLocation Loc = [&SM](Decl *D) -> SourceLocation {
+ const SourceLocation Loc = [&SM](const Decl *D) -> SourceLocation {
const Stmt *Body = D->getBody();
SourceLocation SL = Body ? Body->getBeginLoc() : D->getLocation();
return SM.getExpansionLoc(SL);
diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
index aaf3b67..4c7ce29 100644
--- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
@@ -8,9 +8,9 @@
#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"