summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp6
-rw-r--r--clang/test/Analysis/copy-elision.mm18
2 files changed, 24 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index aaab01f98c2..62699fb3186 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -196,6 +196,12 @@ std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction(
// able to find construction context at all.
break;
}
+ if (isa<BlockInvocationContext>(CallerLCtx)) {
+ // Unwrap block invocation contexts. They're mostly part of
+ // the current stack frame.
+ CallerLCtx = CallerLCtx->getParent();
+ assert(!isa<BlockInvocationContext>(CallerLCtx));
+ }
return prepareForObjectConstruction(
cast<Expr>(SFC->getCallSite()), State, CallerLCtx,
RTC->getConstructionContext(), CallOpts);
diff --git a/clang/test/Analysis/copy-elision.mm b/clang/test/Analysis/copy-elision.mm
new file mode 100644
index 00000000000..fa9435f599f
--- /dev/null
+++ b/clang/test/Analysis/copy-elision.mm
@@ -0,0 +1,18 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -fblocks -verify %s
+
+// expected-no-diagnostics
+
+namespace block_rvo_crash {
+struct A {};
+
+A getA();
+void use(A a) {}
+
+void foo() {
+ // This used to crash when finding construction context for getA()
+ // (which is use()'s argument due to RVO).
+ use(^{
+ return getA(); // no-crash
+ }());
+}
+} // namespace block_rvo_crash
OpenPOWER on IntegriCloud