summaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-08-02 17:33:11 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-08-02 17:33:11 +0000
commitc7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (patch)
tree27425930fc0c91650a7f3527fcac8e0f92907b90 /lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
parent486754660bb926339aefcf012a3f848592babb8b (diff)
Notes
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineCXX.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp43
1 files changed, 32 insertions, 11 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index dc124fc3ff2d2..4f1766a813c6d 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -221,25 +221,42 @@ std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction(
// and construct directly into the final object. This call
// also sets the CallOpts flags for us.
SVal V;
+ // If the elided copy/move constructor is not supported, there's still
+ // benefit in trying to model the non-elided constructor.
+ // Stash our state before trying to elide, as it'll get overwritten.
+ ProgramStateRef PreElideState = State;
+ EvalCallOptions PreElideCallOpts = CallOpts;
+
std::tie(State, V) = prepareForObjectConstruction(
CE, State, LCtx, TCC->getConstructionContextAfterElision(), CallOpts);
- // Remember that we've elided the constructor.
- State = addObjectUnderConstruction(State, CE, LCtx, V);
+ // FIXME: This definition of "copy elision has not failed" is unreliable.
+ // It doesn't indicate that the constructor will actually be inlined
+ // later; it is still up to evalCall() to decide.
+ if (!CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion) {
+ // Remember that we've elided the constructor.
+ State = addObjectUnderConstruction(State, CE, LCtx, V);
- // Remember that we've elided the destructor.
- if (BTE)
- State = elideDestructor(State, BTE, LCtx);
+ // Remember that we've elided the destructor.
+ if (BTE)
+ State = elideDestructor(State, BTE, LCtx);
- // Instead of materialization, shamelessly return
- // the final object destination.
- if (MTE)
- State = addObjectUnderConstruction(State, MTE, LCtx, V);
+ // Instead of materialization, shamelessly return
+ // the final object destination.
+ if (MTE)
+ State = addObjectUnderConstruction(State, MTE, LCtx, V);
- return std::make_pair(State, V);
+ return std::make_pair(State, V);
+ } else {
+ // Copy elision failed. Revert the changes and proceed as if we have
+ // a simple temporary.
+ State = PreElideState;
+ CallOpts = PreElideCallOpts;
+ }
+ LLVM_FALLTHROUGH;
}
case ConstructionContext::SimpleTemporaryObjectKind: {
- const auto *TCC = cast<SimpleTemporaryObjectConstructionContext>(CC);
+ const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);
const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr();
const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
SVal V = UnknownVal();
@@ -274,6 +291,10 @@ std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction(
CallOpts.IsTemporaryCtorOrDtor = true;
return std::make_pair(State, V);
}
+ case ConstructionContext::ArgumentKind: {
+ // Function argument constructors. Not implemented yet.
+ break;
+ }
}
}
// If we couldn't find an existing region to construct into, assume we're