aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp67
1 files changed, 36 insertions, 31 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 977c2b7f51fd..144f034a9dfe 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -65,6 +65,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Casting.h"
@@ -386,15 +387,19 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
State = finishObjectConstruction(State, MT, LC);
State = State->BindExpr(Result, LC, *V);
return State;
- } else {
+ } else if (const ValueDecl *VD = MT->getExtendingDecl()) {
StorageDuration SD = MT->getStorageDuration();
+ assert(SD != SD_FullExpression);
// If this object is bound to a reference with static storage duration, we
// put it in a different region to prevent "address leakage" warnings.
if (SD == SD_Static || SD == SD_Thread) {
- TR = MRMgr.getCXXStaticTempObjectRegion(Init);
+ TR = MRMgr.getCXXStaticLifetimeExtendedObjectRegion(Init, VD);
} else {
- TR = MRMgr.getCXXTempObjectRegion(Init, LC);
+ TR = MRMgr.getCXXLifetimeExtendedObjectRegion(Init, VD, LC);
}
+ } else {
+ assert(MT->getStorageDuration() == SD_FullExpression);
+ TR = MRMgr.getCXXTempObjectRegion(Init, LC);
}
} else {
TR = MRMgr.getCXXTempObjectRegion(Init, LC);
@@ -1242,7 +1247,7 @@ ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,
const QualType &ElementTy,
const LocationContext *LCtx,
SVal *ElementCountVal) {
- assert(Region != nullptr && "Not-null region expected");
+ assert(Region != nullptr && "Not-null region expected");
QualType Ty = ElementTy.getDesugaredType(getContext());
while (const auto *NTy = dyn_cast<ArrayType>(Ty))
@@ -1313,7 +1318,8 @@ void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,
else {
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
const LocationContext *LCtx = Pred->getLocationContext();
- PostImplicitCall PP(NE->getOperatorNew(), NE->getBeginLoc(), LCtx);
+ PostImplicitCall PP(NE->getOperatorNew(), NE->getBeginLoc(), LCtx,
+ getCFGElementRef());
Bldr.generateNode(PP, Pred->getState(), Pred);
}
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
@@ -1361,7 +1367,8 @@ void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
static SimpleProgramPointTag PT(
"ExprEngine", "Skipping automatic 0 length array destruction, "
"which shouldn't be in the CFG.");
- PostImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx, &PT);
+ PostImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx,
+ getCFGElementRef(), &PT);
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
Bldr.generateSink(PP, Pred->getState(), Pred);
return;
@@ -1378,7 +1385,8 @@ void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
static SimpleProgramPointTag PT("ExprEngine",
"Prepare for object destruction");
- PreImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx, &PT);
+ PreImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx, getCFGElementRef(),
+ &PT);
Pred = Bldr.generateNode(PP, state, Pred);
if (!Pred)
@@ -1406,7 +1414,7 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
const CXXRecordDecl *RD = BTy->getAsCXXRecordDecl();
const CXXDestructorDecl *Dtor = RD->getDestructor();
- PostImplicitCall PP(Dtor, DE->getBeginLoc(), LCtx);
+ PostImplicitCall PP(Dtor, DE->getBeginLoc(), LCtx, getCFGElementRef());
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
Bldr.generateNode(PP, Pred->getState(), Pred);
return;
@@ -1439,7 +1447,8 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
static SimpleProgramPointTag PT(
"ExprEngine", "Skipping 0 length array delete destruction");
- PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx, &PT);
+ PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx,
+ getCFGElementRef(), &PT);
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
Bldr.generateNode(PP, Pred->getState(), Pred);
return;
@@ -1453,7 +1462,8 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
NodeBuilder Bldr(Pred, Dst, getBuilderContext());
static SimpleProgramPointTag PT("ExprEngine",
"Prepare for object destruction");
- PreImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx, &PT);
+ PreImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx,
+ getCFGElementRef(), &PT);
Pred = Bldr.generateNode(PP, State, Pred);
if (!Pred)
@@ -1513,7 +1523,8 @@ void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
static SimpleProgramPointTag PT(
"ExprEngine", "Skipping member 0 length array destruction, which "
"shouldn't be in the CFG.");
- PostImplicitCall PP(DtorDecl, Member->getLocation(), LCtx, &PT);
+ PostImplicitCall PP(DtorDecl, Member->getLocation(), LCtx,
+ getCFGElementRef(), &PT);
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
Bldr.generateSink(PP, Pred->getState(), Pred);
return;
@@ -1529,7 +1540,8 @@ void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
static SimpleProgramPointTag PT("ExprEngine",
"Prepare for object destruction");
- PreImplicitCall PP(DtorDecl, Member->getLocation(), LCtx, &PT);
+ PreImplicitCall PP(DtorDecl, Member->getLocation(), LCtx, getCFGElementRef(),
+ &PT);
Pred = Bldr.generateNode(PP, State, Pred);
if (!Pred)
@@ -1565,7 +1577,7 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
PostImplicitCall PP(D.getDestructorDecl(getContext()),
D.getBindTemporaryExpr()->getBeginLoc(),
- Pred->getLocationContext());
+ Pred->getLocationContext(), getCFGElementRef());
Bldr.generateNode(PP, State, Pred);
return;
}
@@ -2114,7 +2126,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
}
}
}
- // FALLTHROUGH
[[fallthrough]];
}
@@ -2630,9 +2641,7 @@ static const Stmt *ResolveCondition(const Stmt *Condition,
// The invariants are still shifting, but it is possible that the
// last element in a CFGBlock is not a CFGStmt. Look for the last
// CFGStmt as the value of the condition.
- CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
- for (; I != E; ++I) {
- CFGElement Elem = *I;
+ for (CFGElement Elem : llvm::reverse(*B)) {
std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>();
if (!CS)
continue;
@@ -2840,9 +2849,9 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
if (std::optional<loc::GotoLabel> LV = V.getAs<loc::GotoLabel>()) {
const LabelDecl *L = LV->getLabel();
- for (iterator I = builder.begin(), E = builder.end(); I != E; ++I) {
- if (I.getLabel() == L) {
- builder.generateNode(I, state);
+ for (iterator Succ : builder) {
+ if (Succ.getLabel() == L) {
+ builder.generateNode(Succ, state);
return;
}
}
@@ -2861,8 +2870,8 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
// This is really a catch-all. We don't support symbolics yet.
// FIXME: Implement dispatch for symbolic pointers.
- for (iterator I = builder.begin(), E = builder.end(); I != E; ++I)
- builder.generateNode(I, state);
+ for (iterator Succ : builder)
+ builder.generateNode(Succ, state);
}
void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,
@@ -3795,12 +3804,9 @@ struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
BugReporter &BR = static_cast<ExprEngine &>(
N->getState()->getStateManager().getOwningEngine()).getBugReporter();
- const auto EQClasses =
- llvm::make_range(BR.EQClasses_begin(), BR.EQClasses_end());
-
- for (const auto &EQ : EQClasses) {
- for (const auto &I : EQ.getReports()) {
- const auto *PR = dyn_cast<PathSensitiveBugReport>(I.get());
+ for (const auto &Class : BR.equivalenceClasses()) {
+ for (const auto &Report : Class.getReports()) {
+ const auto *PR = dyn_cast<PathSensitiveBugReport>(Report.get());
if (!PR)
continue;
const ExplodedNode *EN = PR->getErrorNode();
@@ -3898,10 +3904,9 @@ std::string ExprEngine::DumpGraph(bool trim, StringRef Filename) {
std::vector<const ExplodedNode *> Src;
// Iterate through the reports and get their nodes.
- for (BugReporter::EQClasses_iterator
- EI = BR.EQClasses_begin(), EE = BR.EQClasses_end(); EI != EE; ++EI) {
+ for (const auto &Class : BR.equivalenceClasses()) {
const auto *R =
- dyn_cast<PathSensitiveBugReport>(EI->getReports()[0].get());
+ dyn_cast<PathSensitiveBugReport>(Class.getReports()[0].get());
if (!R)
continue;
const auto *N = const_cast<ExplodedNode *>(R->getErrorNode());