Skip to content

Commit 79d8f06

Browse files
author
tobias.gruber
committed
Trigger checkLocation for RHS of copy construction
1 parent af68927 commit 79d8f06

File tree

1 file changed

+121
-129
lines changed

1 file changed

+121
-129
lines changed

clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Lines changed: 121 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,19 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
6969

7070
assert(ThisRD);
7171
SVal V = Call.getArgSVal(0);
72+
const Expr *VExpr = Call.getArgExpr(0);
7273

7374
// If the value being copied is not unknown, load from its location to get
7475
// an aggregate rvalue.
7576
if (std::optional<Loc> L = V.getAs<Loc>())
7677
V = Pred->getState()->getSVal(*L);
7778
else
7879
assert(V.isUnknownOrUndef());
79-
evalBind(Dst, CallExpr, Pred, ThisVal, V, true);
80+
81+
ExplodedNodeSet Tmp;
82+
evalLocation(Tmp, CallExpr, VExpr, Pred, Pred->getState(), V, true);
83+
for (ExplodedNode *N : Tmp)
84+
evalBind(Dst, CallExpr, N, ThisVal, V, true);
8085

8186
PostStmt PS(CallExpr, LCtx);
8287
for (ExplodedNode *N : Dst) {
@@ -141,10 +146,9 @@ SVal ExprEngine::computeObjectUnderConstruction(
141146
if (Init->isBaseInitializer()) {
142147
const auto *ThisReg = cast<SubRegion>(ThisVal.getAsRegion());
143148
const CXXRecordDecl *BaseClass =
144-
Init->getBaseClass()->getAsCXXRecordDecl();
145-
const auto *BaseReg =
146-
MRMgr.getCXXBaseObjectRegion(BaseClass, ThisReg,
147-
Init->isBaseVirtual());
149+
Init->getBaseClass()->getAsCXXRecordDecl();
150+
const auto *BaseReg = MRMgr.getCXXBaseObjectRegion(
151+
BaseClass, ThisReg, Init->isBaseVirtual());
148152
return SVB.makeLoc(BaseReg);
149153
}
150154
if (Init->isDelegatingInitializer())
@@ -183,7 +187,7 @@ SVal ExprEngine::computeObjectUnderConstruction(
183187

184188
return loc::MemRegionVal(R);
185189
}
186-
return V;
190+
return V;
187191
}
188192
// TODO: Detect when the allocator returns a null pointer.
189193
// Constructor shall not be called in this case.
@@ -405,99 +409,99 @@ ProgramStateRef ExprEngine::updateObjectsUnderConstruction(
405409
case ConstructionContext::SimpleVariableKind: {
406410
const auto *DSCC = cast<VariableConstructionContext>(CC);
407411
return addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, V);
408-
}
409-
case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:
410-
case ConstructionContext::SimpleConstructorInitializerKind: {
411-
const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);
412-
const auto *Init = ICC->getCXXCtorInitializer();
413-
// Base and delegating initializers handled above
414-
assert(Init->isAnyMemberInitializer() &&
415-
"Base and delegating initializers should have been handled by"
416-
"computeObjectUnderConstruction()");
417-
return addObjectUnderConstruction(State, Init, LCtx, V);
418-
}
419-
case ConstructionContext::NewAllocatedObjectKind: {
412+
}
413+
case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:
414+
case ConstructionContext::SimpleConstructorInitializerKind: {
415+
const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);
416+
const auto *Init = ICC->getCXXCtorInitializer();
417+
// Base and delegating initializers handled above
418+
assert(Init->isAnyMemberInitializer() &&
419+
"Base and delegating initializers should have been handled by"
420+
"computeObjectUnderConstruction()");
421+
return addObjectUnderConstruction(State, Init, LCtx, V);
422+
}
423+
case ConstructionContext::NewAllocatedObjectKind: {
424+
return State;
425+
}
426+
case ConstructionContext::SimpleReturnedValueKind:
427+
case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {
428+
const StackFrameContext *SFC = LCtx->getStackFrame();
429+
const LocationContext *CallerLCtx = SFC->getParent();
430+
if (!CallerLCtx) {
431+
// No extra work is necessary in top frame.
420432
return State;
421433
}
422-
case ConstructionContext::SimpleReturnedValueKind:
423-
case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {
424-
const StackFrameContext *SFC = LCtx->getStackFrame();
425-
const LocationContext *CallerLCtx = SFC->getParent();
426-
if (!CallerLCtx) {
427-
// No extra work is necessary in top frame.
428-
return State;
429-
}
430434

431-
auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]
432-
.getAs<CFGCXXRecordTypedCall>();
433-
assert(RTC && "Could not have had a target region without it");
434-
if (isa<BlockInvocationContext>(CallerLCtx)) {
435-
// Unwrap block invocation contexts. They're mostly part of
436-
// the current stack frame.
437-
CallerLCtx = CallerLCtx->getParent();
438-
assert(!isa<BlockInvocationContext>(CallerLCtx));
439-
}
440-
441-
return updateObjectsUnderConstruction(V,
442-
cast<Expr>(SFC->getCallSite()), State, CallerLCtx,
443-
RTC->getConstructionContext(), CallOpts);
444-
}
445-
case ConstructionContext::ElidedTemporaryObjectKind: {
446-
assert(AMgr.getAnalyzerOptions().ShouldElideConstructors);
447-
if (!CallOpts.IsElidableCtorThatHasNotBeenElided) {
448-
const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
449-
State = updateObjectsUnderConstruction(
450-
V, TCC->getConstructorAfterElision(), State, LCtx,
451-
TCC->getConstructionContextAfterElision(), CallOpts);
452-
453-
// Remember that we've elided the constructor.
454-
State = addObjectUnderConstruction(
455-
State, TCC->getConstructorAfterElision(), LCtx, V);
456-
457-
// Remember that we've elided the destructor.
458-
if (const auto *BTE = TCC->getCXXBindTemporaryExpr())
459-
State = elideDestructor(State, BTE, LCtx);
460-
461-
// Instead of materialization, shamelessly return
462-
// the final object destination.
463-
if (const auto *MTE = TCC->getMaterializedTemporaryExpr())
464-
State = addObjectUnderConstruction(State, MTE, LCtx, V);
465-
466-
return State;
467-
}
468-
// If we decided not to elide the constructor, proceed as if
469-
// it's a simple temporary.
470-
[[fallthrough]];
435+
auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]
436+
.getAs<CFGCXXRecordTypedCall>();
437+
assert(RTC && "Could not have had a target region without it");
438+
if (isa<BlockInvocationContext>(CallerLCtx)) {
439+
// Unwrap block invocation contexts. They're mostly part of
440+
// the current stack frame.
441+
CallerLCtx = CallerLCtx->getParent();
442+
assert(!isa<BlockInvocationContext>(CallerLCtx));
471443
}
472-
case ConstructionContext::SimpleTemporaryObjectKind: {
473-
const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);
444+
445+
return updateObjectsUnderConstruction(
446+
V, cast<Expr>(SFC->getCallSite()), State, CallerLCtx,
447+
RTC->getConstructionContext(), CallOpts);
448+
}
449+
case ConstructionContext::ElidedTemporaryObjectKind: {
450+
assert(AMgr.getAnalyzerOptions().ShouldElideConstructors);
451+
if (!CallOpts.IsElidableCtorThatHasNotBeenElided) {
452+
const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
453+
State = updateObjectsUnderConstruction(
454+
V, TCC->getConstructorAfterElision(), State, LCtx,
455+
TCC->getConstructionContextAfterElision(), CallOpts);
456+
457+
// Remember that we've elided the constructor.
458+
State = addObjectUnderConstruction(
459+
State, TCC->getConstructorAfterElision(), LCtx, V);
460+
461+
// Remember that we've elided the destructor.
474462
if (const auto *BTE = TCC->getCXXBindTemporaryExpr())
475-
State = addObjectUnderConstruction(State, BTE, LCtx, V);
463+
State = elideDestructor(State, BTE, LCtx);
476464

465+
// Instead of materialization, shamelessly return
466+
// the final object destination.
477467
if (const auto *MTE = TCC->getMaterializedTemporaryExpr())
478468
State = addObjectUnderConstruction(State, MTE, LCtx, V);
479469

480470
return State;
481471
}
482-
case ConstructionContext::LambdaCaptureKind: {
483-
const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);
472+
// If we decided not to elide the constructor, proceed as if
473+
// it's a simple temporary.
474+
[[fallthrough]];
475+
}
476+
case ConstructionContext::SimpleTemporaryObjectKind: {
477+
const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);
478+
if (const auto *BTE = TCC->getCXXBindTemporaryExpr())
479+
State = addObjectUnderConstruction(State, BTE, LCtx, V);
484480

485-
// If we capture and array, we want to store the super region, not a
486-
// sub-region.
487-
if (const auto *EL = dyn_cast_or_null<ElementRegion>(V.getAsRegion()))
488-
V = loc::MemRegionVal(EL->getSuperRegion());
481+
if (const auto *MTE = TCC->getMaterializedTemporaryExpr())
482+
State = addObjectUnderConstruction(State, MTE, LCtx, V);
489483

490-
return addObjectUnderConstruction(
491-
State, {LCC->getLambdaExpr(), LCC->getIndex()}, LCtx, V);
492-
}
493-
case ConstructionContext::ArgumentKind: {
494-
const auto *ACC = cast<ArgumentConstructionContext>(CC);
495-
if (const auto *BTE = ACC->getCXXBindTemporaryExpr())
496-
State = addObjectUnderConstruction(State, BTE, LCtx, V);
484+
return State;
485+
}
486+
case ConstructionContext::LambdaCaptureKind: {
487+
const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);
497488

498-
return addObjectUnderConstruction(
499-
State, {ACC->getCallLikeExpr(), ACC->getIndex()}, LCtx, V);
500-
}
489+
// If we capture and array, we want to store the super region, not a
490+
// sub-region.
491+
if (const auto *EL = dyn_cast_or_null<ElementRegion>(V.getAsRegion()))
492+
V = loc::MemRegionVal(EL->getSuperRegion());
493+
494+
return addObjectUnderConstruction(
495+
State, {LCC->getLambdaExpr(), LCC->getIndex()}, LCtx, V);
496+
}
497+
case ConstructionContext::ArgumentKind: {
498+
const auto *ACC = cast<ArgumentConstructionContext>(CC);
499+
if (const auto *BTE = ACC->getCXXBindTemporaryExpr())
500+
State = addObjectUnderConstruction(State, BTE, LCtx, V);
501+
502+
return addObjectUnderConstruction(
503+
State, {ACC->getCallLikeExpr(), ACC->getIndex()}, LCtx, V);
504+
}
501505
}
502506
llvm_unreachable("Unhandled construction context!");
503507
}
@@ -526,8 +530,7 @@ bindRequiredArrayElementToEnvironment(ProgramStateRef State,
526530
loc::MemRegionVal(ElementRegion));
527531
}
528532

529-
void ExprEngine::handleConstructor(const Expr *E,
530-
ExplodedNode *Pred,
533+
void ExprEngine::handleConstructor(const Expr *E, ExplodedNode *Pred,
531534
ExplodedNodeSet &destNodes) {
532535
const auto *CE = dyn_cast<CXXConstructExpr>(E);
533536
const auto *CIE = dyn_cast<CXXInheritedCtorInitExpr>(E);
@@ -541,16 +544,16 @@ void ExprEngine::handleConstructor(const Expr *E,
541544
if (CE) {
542545
if (std::optional<SVal> ElidedTarget =
543546
getObjectUnderConstruction(State, CE, LCtx)) {
544-
// We've previously modeled an elidable constructor by pretending that
545-
// it in fact constructs into the correct target. This constructor can
546-
// therefore be skipped.
547-
Target = *ElidedTarget;
548-
StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx);
549-
State = finishObjectConstruction(State, CE, LCtx);
550-
if (auto L = Target.getAs<Loc>())
551-
State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType()));
552-
Bldr.generateNode(CE, Pred, State);
553-
return;
547+
// We've previously modeled an elidable constructor by pretending that
548+
// it in fact constructs into the correct target. This constructor can
549+
// therefore be skipped.
550+
Target = *ElidedTarget;
551+
StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx);
552+
State = finishObjectConstruction(State, CE, LCtx);
553+
if (auto L = Target.getAs<Loc>())
554+
State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType()));
555+
Bldr.generateNode(CE, Pred, State);
556+
return;
554557
}
555558
}
556559

@@ -648,8 +651,7 @@ void ExprEngine::handleConstructor(const Expr *E,
648651
[[fallthrough]];
649652
case CXXConstructionKind::Delegating: {
650653
const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
651-
Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
652-
LCtx->getStackFrame());
654+
Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, LCtx->getStackFrame());
653655
SVal ThisVal = State->getSVal(ThisPtr);
654656

655657
if (CK == CXXConstructionKind::Delegating) {
@@ -718,8 +720,8 @@ void ExprEngine::handleConstructor(const Expr *E,
718720
}
719721

720722
ExplodedNodeSet DstPreCall;
721-
getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized,
722-
*Call, *this);
723+
getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized, *Call,
724+
*this);
723725

724726
ExplodedNodeSet DstEvaluated;
725727

@@ -782,9 +784,8 @@ void ExprEngine::handleConstructor(const Expr *E,
782784
// If there were other constructors called for object-type arguments
783785
// of this constructor, clean them up.
784786
ExplodedNodeSet DstPostCall;
785-
getCheckerManager().runCheckersForPostCall(DstPostCall,
786-
DstPostArgumentCleanup,
787-
*Call, *this);
787+
getCheckerManager().runCheckersForPostCall(
788+
DstPostCall, DstPostArgumentCleanup, *Call, *this);
788789
getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, E, *this);
789790
}
790791

@@ -800,12 +801,9 @@ void ExprEngine::VisitCXXInheritedCtorInitExpr(
800801
handleConstructor(CE, Pred, Dst);
801802
}
802803

803-
void ExprEngine::VisitCXXDestructor(QualType ObjectType,
804-
const MemRegion *Dest,
805-
const Stmt *S,
806-
bool IsBaseDtor,
807-
ExplodedNode *Pred,
808-
ExplodedNodeSet &Dst,
804+
void ExprEngine::VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest,
805+
const Stmt *S, bool IsBaseDtor,
806+
ExplodedNode *Pred, ExplodedNodeSet &Dst,
809807
EvalCallOptions &CallOpts) {
810808
assert(S && "A destructor without a trigger!");
811809
const LocationContext *LCtx = Pred->getLocationContext();
@@ -840,8 +838,8 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType,
840838
} else {
841839
static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor");
842840
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
843-
Bldr.generateSink(Pred->getLocation().withTag(&T),
844-
Pred->getState(), Pred);
841+
Bldr.generateSink(Pred->getLocation().withTag(&T), Pred->getState(),
842+
Pred);
845843
return;
846844
}
847845
}
@@ -855,16 +853,14 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType,
855853
"Error evaluating destructor");
856854

857855
ExplodedNodeSet DstPreCall;
858-
getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
859-
*Call, *this);
856+
getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, *Call, *this);
860857

861858
ExplodedNodeSet DstInvalidated;
862859
StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
863860
for (ExplodedNode *N : DstPreCall)
864861
defaultEvalCall(Bldr, N, *Call, CallOpts);
865862

866-
getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
867-
*Call, *this);
863+
getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, *Call, *this);
868864
}
869865

870866
void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
@@ -880,8 +876,7 @@ void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
880876
CEMgr.getCXXAllocatorCall(CNE, State, LCtx, getCFGElementRef());
881877

882878
ExplodedNodeSet DstPreCall;
883-
getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
884-
*Call, *this);
879+
getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, *Call, *this);
885880

886881
ExplodedNodeSet DstPostCall;
887882
StmtNodeBuilder CallBldr(DstPreCall, DstPostCall, *currBldrCtx);
@@ -940,7 +935,7 @@ void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
940935
}
941936

942937
void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
943-
ExplodedNodeSet &Dst) {
938+
ExplodedNodeSet &Dst) {
944939
// FIXME: Much of this should eventually migrate to CXXAllocatorCall.
945940
// Also, we need to decide how allocators actually work -- they're not
946941
// really part of the CXXNewExpr because they happen BEFORE the
@@ -1112,15 +1107,13 @@ void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,
11121107
}
11131108

11141109
void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
1115-
ExplodedNodeSet &Dst) {
1110+
ExplodedNodeSet &Dst) {
11161111
StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
11171112

11181113
// Get the this object region from StoreManager.
11191114
const LocationContext *LCtx = Pred->getLocationContext();
1120-
const MemRegion *R =
1121-
svalBuilder.getRegionManager().getCXXThisRegion(
1122-
getContext().getCanonicalType(TE->getType()),
1123-
LCtx);
1115+
const MemRegion *R = svalBuilder.getRegionManager().getCXXThisRegion(
1116+
getContext().getCanonicalType(TE->getType()), LCtx);
11241117

11251118
ProgramStateRef state = Pred->getState();
11261119
SVal V = state->getSVal(loc::MemRegionVal(R));
@@ -1132,8 +1125,8 @@ void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
11321125
const LocationContext *LocCtxt = Pred->getLocationContext();
11331126

11341127
// Get the region of the lambda itself.
1135-
const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion(
1136-
LE, LocCtxt);
1128+
const MemRegion *R =
1129+
svalBuilder.getRegionManager().getCXXTempObjectRegion(LE, LocCtxt);
11371130
SVal V = loc::MemRegionVal(R);
11381131

11391132
ProgramStateRef State = Pred->getState();
@@ -1193,9 +1186,8 @@ void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
11931186
ExplodedNodeSet Tmp;
11941187
StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
11951188
// FIXME: is this the right program point kind?
1196-
Bldr.generateNode(LE, Pred,
1197-
State->BindExpr(LE, LocCtxt, LambdaRVal),
1198-
nullptr, ProgramPoint::PostLValueKind);
1189+
Bldr.generateNode(LE, Pred, State->BindExpr(LE, LocCtxt, LambdaRVal), nullptr,
1190+
ProgramPoint::PostLValueKind);
11991191

12001192
// FIXME: Move all post/pre visits to ::Visit().
12011193
getCheckerManager().runCheckersForPostStmt(Dst, Tmp, LE, *this);

0 commit comments

Comments
 (0)