[CFG] [analyzer] pr41142: C++17: Skip transparent InitListExprs in constructors.

When searching for construction contexts, i.e. figuring out which statements
define the object that is constructed by each construct-expression, ignore
transparent init-list expressions because they don't add anything to the
context. This allows the Static Analyzer to model construction, destruction,
materialization, lifetime extension correctly in more cases. Also fixes
a crash caused by incorrectly evaluating initial values of variables
initialized with such expressions.

Differential Revision: https://reviews.llvm.org/D59573

llvm-svn: 356634
This commit is contained in:
Artem Dergachev 2019-03-21 00:15:07 +00:00
parent f1d87f8b4c
commit aa40315c69
3 changed files with 47 additions and 0 deletions

View File

@ -1378,6 +1378,15 @@ void CFGBuilder::findConstructionContexts(
findConstructionContexts(Layer, CO->getRHS());
break;
}
case Stmt::InitListExprClass: {
auto *ILE = cast<InitListExpr>(Child);
if (ILE->isTransparent()) {
findConstructionContexts(Layer, ILE->getInit(0));
break;
}
// TODO: Handle other cases. For now, fail to find construction contexts.
break;
}
default:
break;
}

View File

@ -1043,3 +1043,23 @@ void testCrashOnVariadicArgument() {
C c(variadic(0 ? c : 0)); // no-crash
}
} // namespace variadic_function_arguments
// CHECK: void testTransparentInitListExprs()
// CHECK: [B1]
// CHECK-NEXT: 1: getC
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class transparent_init_list_exprs::C (*)(void))
// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.5])
// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4])
// CXX11-NEXT: 4: [B1.3]
// CXX11-NEXT: 5: {[B1.4]} (CXXConstructExpr, [B1.6], class transparent_init_list_exprs::C)
// CXX11-NEXT: 6: transparent_init_list_exprs::C c{getC()};
// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.5])
// CXX17-NEXT: 4: {[B1.3]}
// CXX17-NEXT: 5: transparent_init_list_exprs::C c{getC()};
namespace transparent_init_list_exprs {
class C {};
C getC();
void testTransparentInitListExprs() {
C c{getC()};
}
} // namespace transparent_init_list_exprs

View File

@ -242,4 +242,22 @@ void foo() {
B &&bcr = C({{}}); // no-crash
#endif
}
} // namespace CXX17_aggregate_construction
namespace CXX17_transparent_init_list_exprs {
class A {};
class B: private A {};
B boo();
void foo1() {
B b { boo() }; // no-crash
}
class C: virtual public A {};
C coo();
void foo2() {
C c { coo() }; // no-crash
}
} // namespace CXX17_transparent_init_list_exprs