Skip to content

Commit

Permalink
[analyzer] NFC: Move the code for setting temp object lifetime into m…
Browse files Browse the repository at this point in the history
…ethod.

Differential Revision: https://reviews.llvm.org/D44129

llvm-svn: 327347
  • Loading branch information
haoNoQ committed Mar 12, 2018
1 parent 729d9f8 commit 98a24bf
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 61 deletions.
Expand Up @@ -774,6 +774,14 @@ class ExprEngine : public SubEngine {
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.
Expand Down
60 changes: 60 additions & 0 deletions clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Expand Down
62 changes: 1 addition & 61 deletions clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 98a24bf

Please sign in to comment.