[PATCH] D40841: [analyzer] Fix a crash on C++17 AST for non-trivial construction into a trivial brace initializer.
Artem Dergachev via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 5 09:08:13 PST 2017
NoQ created this revision.
Herald added subscribers: cfe-commits, rnkovacs.
Yet another situation where we cannot easily guess, by looking at the CFG, the target region for C++ constructor call.
Consider the following brace initialization:
struct A {
A();
};
struct B : public A {
int x;
};
void foo() {
B b = {};
}
AST in C++14:
`-VarDecl 0x7ff07884eab8 <col:3, col:10> col:5 b 'struct B' cinit
`-CXXConstructExpr 0x7ff07887a940 <col:9, col:10> 'struct B' 'void (void) noexcept(false)' list zeroing
AST in C++17:
`-VarDecl 0x7fb1cf012b18 <col:3, col:10> col:5 b 'struct B' cinit
`-InitListExpr 0x7fb1cf012f38 <col:9, col:10> 'struct B'
|-CXXConstructExpr 0x7fb1cf012fd0 <col:10> 'struct A' 'void (void)' list
`-ImplicitValueInitExpr 0x7fb1cf013000 <<invalid sloc>> 'int'
CFG in C++14:
[B1]
1: {} (CXXConstructExpr, struct B)
2: B b = {};
CFG in C++17:
[B1]
1: {} (CXXConstructExpr, struct A)
2: /*implicit*/(int)0
3: {}
4: B b = {};
So, essentially, in C++17 we don't have the trivial constructor call for `B` present anywhere at all, neither in AST, nor in CFG.
This causes a crash in the analyzer because he tries to find the target region for `CK_NonVirtualBase` constructor of `A` by looking at the parent stack frame, expecting to find the derived class constructor (for `B`) here, and then taking a base region within its this-object.
This fix is a quick-and-dirty suppression for the crash. It follows the tradition of "when unsure, make up a temporary and construct into that, then discard the result" - which is wrong, but at least it gets some invalidation done.
In our example it would be correct to construct into `base{A, b}`. There can also be situations when such initializer-list is instead lifetime-extended by a `const&` or `&&` reference (see the tests), so in this case we'd need to construct into a respective sub-region of the temporary (but not into the temporary itself, of course).
Finally, from the perspective of checker development, i believe it would be useful to actually revive the constructor call, so that PreCall/PostCall event occured.
Repository:
rC Clang
https://reviews.llvm.org/D40841
Files:
lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
test/Analysis/initializer.cpp
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D40841.125544.patch
Type: text/x-patch
Size: 4131 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171205/8867e3c2/attachment.bin>
More information about the cfe-commits
mailing list