summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-02-15 02:32:32 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-02-15 02:32:32 +0000
commit94020268fe9f48a88f06a9739ce7b6025945338c (patch)
treec179fc676a59b0b0a53eccfbdf9bebfa239b4854 /clang/lib/StaticAnalyzer
parente231bd342eacb2fe84af9d563c77ea4be5e1f250 (diff)
downloadbcm5719-llvm-94020268fe9f48a88f06a9739ce7b6025945338c.tar.gz
bcm5719-llvm-94020268fe9f48a88f06a9739ce7b6025945338c.zip
[analyzer] Allow inlining constructors into return values.
This only affects the cfg-temporary-dtors mode - in this mode we begin inlining constructors that are constructing function return values. These constructors have a correct construction context since r324952. Because temporary destructors are not only never inlined, but also don't have the correct target region yet, this change is not entirely safe. But this will be fixed in the subsequent commits, while this stays off behind the cfg-temporary-dtors flag. Lifetime extension for return values is still not modeled correctly. Differential Revision: https://reviews.llvm.org/D42875 llvm-svn: 325202
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp13
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp14
2 files changed, 23 insertions, 4 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 1ff1ea49b7a..5b1d8131583 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -113,6 +113,7 @@ ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE,
EvalCallOptions &CallOpts) {
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
+ MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
// See if we're constructing an existing region by looking at the
// current construction context.
@@ -144,6 +145,17 @@ ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE,
LValue = makeZeroElementRegion(State, LValue, Ty,
CallOpts.IsArrayConstructorOrDestructor);
return LValue.getAsRegion();
+ } else if (auto *RS = dyn_cast<ReturnStmt>(TriggerStmt)) {
+ // TODO: We should construct into a CXXBindTemporaryExpr or a
+ // MaterializeTemporaryExpr around the call-expression on the previous
+ // stack frame. Currently we re-bind the temporary to the correct region
+ // later, but that's not semantically correct. This of course does not
+ // apply when we're in the top frame. But if we are in an inlined
+ // function, we should be able to take the call-site CFG element,
+ // and it should contain (but right now it wouldn't) some sort of
+ // construction context that'd give us the right temporary expression.
+ CallOpts.IsConstructorIntoTemporary = true;
+ return MRMgr.getCXXTempObjectRegion(CE, LCtx);
}
// TODO: Consider other directly initialized elements.
} else if (const CXXCtorInitializer *Init = CC->getTriggerInit()) {
@@ -176,7 +188,6 @@ ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE,
// If we couldn't find an existing region to construct into, assume we're
// constructing a temporary. Notify the caller of our failure.
CallOpts.IsConstructorWithImproperlyModeledTargetRegion = true;
- MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
return MRMgr.getCXXTempObjectRegion(CE, LCtx);
}
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 320fa91a1cc..e022196fe58 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -670,11 +670,19 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors))
return CIP_DisallowedAlways;
- // FIXME: This is a hack. We don't handle temporary destructors
- // right now, so we shouldn't inline their constructors.
- if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete)
+ if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete) {
+ // If we don't handle temporary destructors, we shouldn't inline
+ // their constructors.
+ if (CallOpts.IsConstructorIntoTemporary &&
+ !Opts.includeTemporaryDtorsInCFG())
+ return CIP_DisallowedOnce;
+
+ // If we did not construct the correct this-region, it would be pointless
+ // to inline the constructor. Instead we will simply invalidate
+ // the fake temporary target.
if (CallOpts.IsConstructorWithImproperlyModeledTargetRegion)
return CIP_DisallowedOnce;
+ }
break;
}
OpenPOWER on IntegriCloud