diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2019-03-21 00:15:07 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2019-03-21 00:15:07 +0000 |
commit | aa40315c69fb667c070293ea94f6caaf4a0a6ec6 (patch) | |
tree | 78b67bc379605102073514154a02c0af3841283e | |
parent | f1d87f8b4c430d72e7ab07e13508336a7841c3e6 (diff) | |
download | bcm5719-llvm-aa40315c69fb667c070293ea94f6caaf4a0a6ec6.tar.gz bcm5719-llvm-aa40315c69fb667c070293ea94f6caaf4a0a6ec6.zip |
[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
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 9 | ||||
-rw-r--r-- | clang/test/Analysis/cfg-rich-constructors.cpp | 20 | ||||
-rw-r--r-- | clang/test/Analysis/initializer.cpp | 18 |
3 files changed, 47 insertions, 0 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index f6b829147b3..6ff72540afe 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -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; } diff --git a/clang/test/Analysis/cfg-rich-constructors.cpp b/clang/test/Analysis/cfg-rich-constructors.cpp index 31c306bbfe9..0125c9bf523 100644 --- a/clang/test/Analysis/cfg-rich-constructors.cpp +++ b/clang/test/Analysis/cfg-rich-constructors.cpp @@ -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 diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index 0cb68c4a978..5853f3aed56 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -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 |