diff options
| author | Artem Dergachev <artem.dergachev@gmail.com> | 2018-03-30 19:21:18 +0000 |
|---|---|---|
| committer | Artem Dergachev <artem.dergachev@gmail.com> | 2018-03-30 19:21:18 +0000 |
| commit | 9d3a7d8b2badf05a52188e2874a1e53c1416e279 (patch) | |
| tree | 692008944c764fdc963025a945d3253da3381820 /clang/lib | |
| parent | dc97172b2fb7452bdd9e841e4b2d5049fbdd9275 (diff) | |
| download | bcm5719-llvm-9d3a7d8b2badf05a52188e2874a1e53c1416e279.tar.gz bcm5719-llvm-9d3a7d8b2badf05a52188e2874a1e53c1416e279.zip | |
[CFG] [analyzer] Avoid modeling C++17 constructors that aren't fully supported.
Not enough work has been done so far to ensure correctness of construction
contexts in the CFG when C++17 copy elision is in effect, so for now we
should drop construction contexts in the CFG and in the analyzer when
they seem different from what we support anyway.
This includes initializations with conditional operators and return values
across multiple stack frames.
Differential Revision: https://reviews.llvm.org/D44854
llvm-svn: 328893
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Analysis/CFG.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 23 |
2 files changed, 26 insertions, 6 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 77770c56f31..0f0556135c2 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -1302,6 +1302,15 @@ void CFGBuilder::findConstructionContexts( } case Stmt::ConditionalOperatorClass: { auto *CO = cast<ConditionalOperator>(Child); + if (!dyn_cast_or_null<MaterializeTemporaryExpr>(Layer->getTriggerStmt())) { + // If the object returned by the conditional operator is not going to be a + // temporary object that needs to be immediately materialized, then + // it must be C++17 with its mandatory copy elision. Do not yet promise + // to support this case. + assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() || + Context->getLangOpts().CPlusPlus17); + break; + } findConstructionContexts(Layer, CO->getLHS()); findConstructionContexts(Layer, CO->getRHS()); break; diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 3bea9465706..18cd4149f09 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -203,13 +203,24 @@ ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE, // TODO: What exactly happens when we are? Does the temporary object live // long enough in the region store in this case? Would checkers think // that this object immediately goes out of scope? - // TODO: We assume that the call site has a temporary object construction - // context. This is no longer true in C++17 or when copy elision is - // performed. We may need to unwrap multiple stack frames here and we - // won't necessarily end up with a temporary at the end. const LocationContext *TempLCtx = LCtx; - if (const LocationContext *CallerLCtx = - LCtx->getCurrentStackFrame()->getParent()) { + const StackFrameContext *SFC = LCtx->getCurrentStackFrame(); + if (const LocationContext *CallerLCtx = SFC->getParent()) { + auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()] + .getAs<CFGCXXRecordTypedCall>(); + if (!RTC) { + // We were unable to find the correct construction context for the + // call in the parent stack frame. This is equivalent to not being + // able to find construction context at all. + CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true; + } else if (!isa<TemporaryObjectConstructionContext>( + RTC->getConstructionContext())) { + // FXIME: The return value is constructed directly into a + // non-temporary due to C++17 mandatory copy elision. This is not + // implemented yet. + assert(getContext().getLangOpts().CPlusPlus17); + CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true; + } TempLCtx = CallerLCtx; } CallOpts.IsTemporaryCtorOrDtor = true; |

