125 lines · cpp
1// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=debug.DumpCFG -std=c++14 -analyzer-config eagerly-assume=false %s > %t 2>&12// RUN: FileCheck --input-file=%t %s3// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=core,debug.ExprInspection -std=c++14 -verify -analyzer-config eagerly-assume=false %s4 5void clang_analyzer_eval(bool);6 7int global;8 9namespace variant_0 {10 11class A {12public:13 ~A() { ++global; }14};15 16class B {17 A a;18};19 20// CHECK: void foo(int)21// CHECK: [B1]22// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], B)23// CHECK-NEXT: 2: B i;24// CHECK-NEXT: 3: operator=25// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, B &(*)(B &&) noexcept)26// CHECK-NEXT: 5: i27// CHECK-NEXT: 6: {} (CXXConstructExpr, [B1.7], [B1.8], B)28// CHECK-NEXT: 7: [B1.6] (BindTemporary)29// CHECK-NEXT: 8: [B1.7]30// CHECK-NEXT: 9: [B1.5] = [B1.8] (OperatorCall)31// CHECK-NEXT: 10: ~B() (Temporary object destructor)32// CHECK-NEXT: 11: [B1.2].~B() (Implicit destructor)33void foo(int) {34 B i;35 i = {};36}37 38void bar() {39 global = 0;40 foo(1);41 clang_analyzer_eval(global == 2); // expected-warning{{TRUE}}42}43 44} // end namespace variant_045 46namespace variant_1 {47 48class A {49public:50 ~A() { ++global; }51};52 53class B {54 A a;55};56 57// CHECK: template<> void foo<int>(int)58// CHECK: [B1]59// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], B)60// CHECK-NEXT: 2: B i;61// CHECK-NEXT: 3: operator=62// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, B &(*)(B &&) noexcept)63// CHECK-NEXT: 5: i64// CHECK-NEXT: 6: {} (CXXConstructExpr, [B1.7], [B1.8], B)65// CHECK-NEXT: 7: [B1.6] (BindTemporary)66// CHECK-NEXT: 8: [B1.7]67// CHECK-NEXT: 9: [B1.5] = [B1.8] (OperatorCall)68// CHECK-NEXT: 10: ~B() (Temporary object destructor)69// CHECK-NEXT: 11: [B1.2].~B() (Implicit destructor)70template <typename T> void foo(T) {71 B i;72 i = {};73}74 75void bar() {76 global = 0;77 foo(1);78 clang_analyzer_eval(global == 2); // expected-warning{{TRUE [debug.ExprInspection]}}79}80 81} // end namespace variant_182 83namespace variant_2 {84// Making field 'a' in class 'B' public turns the class into an aggregate.85// In this case there is no constructor at {} - only an aggregate86// initialization. Aggregate initialization is unsupported for now.87 88class A {89public:90 ~A() { ++global; }91};92 93class B {94public:95 A a;96};97 98// CHECK: template<> void foo<int>(int)99// CHECK: [B1]100// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], B)101// CHECK-NEXT: 2: B i;102// CHECK-NEXT: 3: operator=103// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, B &(*)(B &&) noexcept)104// CHECK-NEXT: 5: i105// CHECK-NEXT: 6: {}106// CHECK-NEXT: 7: {}107// CHECK-NEXT: 8: [B1.7] (BindTemporary)108// CHECK-NEXT: 9: [B1.8]109// CHECK-NEXT: 10: [B1.5] = [B1.9] (OperatorCall)110// CHECK-NEXT: 11: ~B() (Temporary object destructor)111// CHECK-NEXT: 12: [B1.2].~B() (Implicit destructor)112template <typename T> void foo(T) {113 B i;114 i = {};115}116 117void bar() {118 global = 0;119 foo(1);120 // FIXME: Should be TRUE, i.e. we should call (and inline) two destructors.121 clang_analyzer_eval(global == 2); // expected-warning{{UNKNOWN}}122}123 124} // end namespace variant_2125