mirror of
https://github.com/intel/llvm.git
synced 2026-02-04 03:26:06 +08:00
[analyzer] NFC: Move the code for setting temp object lifetime into method.
Differential Revision: https://reviews.llvm.org/D44129 llvm-svn: 327347
This commit is contained in:
@@ -774,6 +774,14 @@ private:
|
||||
const LocationContext *FromLC,
|
||||
const LocationContext *ToLC);
|
||||
|
||||
/// Adds an initialized temporary and/or a materialization, whichever is
|
||||
/// necessary, by looking at the whole construction context. Handles
|
||||
/// function return values, which need the construction context of the parent
|
||||
/// stack frame, automagically.
|
||||
ProgramStateRef addAllNecessaryTemporaryInfo(
|
||||
ProgramStateRef State, const ConstructionContext *CC,
|
||||
const LocationContext *LC, const MemRegion *R);
|
||||
|
||||
/// Store the region returned by operator new() so that the constructor
|
||||
/// that follows it knew what location to initialize. The value should be
|
||||
/// cleared once the respective CXXNewExpr CFGStmt element is processed.
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Analysis/AnalysisDeclContext.h"
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "clang/Analysis/ConstructionContext.h"
|
||||
#include "clang/Analysis/ProgramPoint.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
@@ -449,6 +450,65 @@ bool ExprEngine::areTemporaryMaterializationsClear(
|
||||
return true;
|
||||
}
|
||||
|
||||
ProgramStateRef ExprEngine::addAllNecessaryTemporaryInfo(
|
||||
ProgramStateRef State, const ConstructionContext *CC,
|
||||
const LocationContext *LC, const MemRegion *R) {
|
||||
const CXXBindTemporaryExpr *BTE = nullptr;
|
||||
const MaterializeTemporaryExpr *MTE = nullptr;
|
||||
const LocationContext *TempLC = LC;
|
||||
|
||||
if (CC) {
|
||||
// In case of temporary object construction, extract data necessary for
|
||||
// destruction and lifetime extension.
|
||||
const auto *TCC = dyn_cast<TemporaryObjectConstructionContext>(CC);
|
||||
|
||||
// If the temporary is being returned from the function, it will be
|
||||
// destroyed or lifetime-extended in the caller stack frame.
|
||||
if (const auto *RCC = dyn_cast<ReturnedValueConstructionContext>(CC)) {
|
||||
const StackFrameContext *SFC = LC->getCurrentStackFrame();
|
||||
assert(SFC);
|
||||
if (SFC->getParent()) {
|
||||
TempLC = SFC->getParent();
|
||||
const CFGElement &CallElem =
|
||||
(*SFC->getCallSiteBlock())[SFC->getIndex()];
|
||||
if (auto RTCElem = CallElem.getAs<CFGCXXRecordTypedCall>()) {
|
||||
TCC = cast<TemporaryObjectConstructionContext>(
|
||||
RTCElem->getConstructionContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (TCC) {
|
||||
if (AMgr.getAnalyzerOptions().includeTemporaryDtorsInCFG()) {
|
||||
BTE = TCC->getCXXBindTemporaryExpr();
|
||||
MTE = TCC->getMaterializedTemporaryExpr();
|
||||
if (!BTE) {
|
||||
// FIXME: Lifetime extension for temporaries without destructors
|
||||
// is not implemented yet.
|
||||
MTE = nullptr;
|
||||
}
|
||||
if (MTE && MTE->getStorageDuration() != SD_FullExpression) {
|
||||
// If the temporary is lifetime-extended, don't save the BTE,
|
||||
// because we don't need a temporary destructor, but an automatic
|
||||
// destructor.
|
||||
BTE = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BTE) {
|
||||
State = addInitializedTemporary(State, BTE, TempLC,
|
||||
cast<CXXTempObjectRegion>(R));
|
||||
}
|
||||
|
||||
if (MTE) {
|
||||
State = addTemporaryMaterialization(State, MTE, TempLC,
|
||||
cast<CXXTempObjectRegion>(R));
|
||||
}
|
||||
}
|
||||
|
||||
return State;
|
||||
}
|
||||
|
||||
ProgramStateRef
|
||||
ExprEngine::setCXXNewAllocatorValue(ProgramStateRef State,
|
||||
const CXXNewExpr *CNE,
|
||||
|
||||
@@ -265,55 +265,9 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
|
||||
assert(C || getCurrentCFGElement().getAs<CFGStmt>());
|
||||
const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr;
|
||||
|
||||
bool IsReturnedIntoParentStackFrame = false;
|
||||
const CXXBindTemporaryExpr *BTE = nullptr;
|
||||
const MaterializeTemporaryExpr *MTE = nullptr;
|
||||
|
||||
switch (CE->getConstructionKind()) {
|
||||
case CXXConstructExpr::CK_Complete: {
|
||||
Target = getRegionForConstructedObject(CE, Pred, CC, CallOpts);
|
||||
|
||||
if (CC) {
|
||||
// In case of temporary object construction, extract data necessary for
|
||||
// destruction and lifetime extension.
|
||||
const auto *TCC = dyn_cast<TemporaryObjectConstructionContext>(CC);
|
||||
|
||||
// If the temporary is being returned from the function, it will be
|
||||
// destroyed or lifetime-extended in the caller stack frame.
|
||||
if (const auto *RCC = dyn_cast<ReturnedValueConstructionContext>(CC)) {
|
||||
const StackFrameContext *SFC = LCtx->getCurrentStackFrame();
|
||||
assert(SFC);
|
||||
if (SFC->getParent()) {
|
||||
IsReturnedIntoParentStackFrame = true;
|
||||
const CFGElement &CallElem =
|
||||
(*SFC->getCallSiteBlock())[SFC->getIndex()];
|
||||
if (auto RTCElem = CallElem.getAs<CFGCXXRecordTypedCall>()) {
|
||||
TCC = cast<TemporaryObjectConstructionContext>(
|
||||
RTCElem->getConstructionContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TCC) {
|
||||
assert(CallOpts.IsTemporaryCtorOrDtor);
|
||||
assert(!CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion);
|
||||
if (AMgr.getAnalyzerOptions().includeTemporaryDtorsInCFG()) {
|
||||
BTE = TCC->getCXXBindTemporaryExpr();
|
||||
MTE = TCC->getMaterializedTemporaryExpr();
|
||||
if (!BTE) {
|
||||
// FIXME: lifetime extension for temporaries without destructors
|
||||
// is not implemented yet.
|
||||
MTE = nullptr;
|
||||
}
|
||||
if (MTE && MTE->getStorageDuration() != SD_FullExpression) {
|
||||
// If the temporary is lifetime-extended, don't save the BTE,
|
||||
// because we don't need a temporary destructor, but an automatic
|
||||
// destructor.
|
||||
BTE = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CXXConstructExpr::CK_VirtualBase:
|
||||
@@ -408,21 +362,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
|
||||
State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal, LCtx);
|
||||
}
|
||||
|
||||
// Set up destruction and lifetime extension information.
|
||||
const LocationContext *TempLCtx =
|
||||
IsReturnedIntoParentStackFrame
|
||||
? LCtx->getCurrentStackFrame()->getParent()
|
||||
: LCtx;
|
||||
|
||||
if (BTE) {
|
||||
State = addInitializedTemporary(State, BTE, TempLCtx,
|
||||
cast<CXXTempObjectRegion>(Target));
|
||||
}
|
||||
|
||||
if (MTE) {
|
||||
State = addTemporaryMaterialization(State, MTE, TempLCtx,
|
||||
cast<CXXTempObjectRegion>(Target));
|
||||
}
|
||||
State = addAllNecessaryTemporaryInfo(State, CC, LCtx, Target);
|
||||
|
||||
Bldr.generateNode(CE, *I, State, /*tag=*/nullptr,
|
||||
ProgramPoint::PreStmtKind);
|
||||
|
||||
Reference in New Issue
Block a user