NoQ updated this revision to Diff 198342. NoQ added a comment. No, this is all wrong. We shouldn't unwrap to the parent stack frame here. We should end up exactly in the location context in which the call has happened. But we should still unwrap the block invocation context, as an exception, because it's just a weird location context that goes before the stack frame but still has its corresponding `AnalysisDeclContext` tied to the *callee* stack frame.
These block invocation contexts are used, like, once, to help modeling captures. I should probably try to get rid of them entirely. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D61545/new/ https://reviews.llvm.org/D61545 Files: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp clang/test/Analysis/copy-elision.mm Index: clang/test/Analysis/copy-elision.mm =================================================================== --- /dev/null +++ clang/test/Analysis/copy-elision.mm @@ -0,0 +1,19 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core -fblocks -verify %s + +// expected-no-diagnostics + +namespace block_rvo_crash { +struct A {}; +struct B {}; + +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 Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -196,6 +196,12 @@ // 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);
Index: clang/test/Analysis/copy-elision.mm =================================================================== --- /dev/null +++ clang/test/Analysis/copy-elision.mm @@ -0,0 +1,19 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core -fblocks -verify %s + +// expected-no-diagnostics + +namespace block_rvo_crash { +struct A {}; +struct B {}; + +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 Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -196,6 +196,12 @@ // 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);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits