452 lines · cpp
1// RUN: %clang_cc1 -fexperimental-lifetime-safety -mllvm -debug-only=LifetimeFacts -Wexperimental-lifetime-safety %s 2>&1 | FileCheck %s2// REQUIRES: asserts3 4struct MyObj {5 int id;6 ~MyObj() {} // Non-trivial destructor7};8 9// Simple Local Variable Address and Return10// CHECK-LABEL: Function: return_local_addr11MyObj* return_local_addr() {12 MyObj x {10};13// CHECK: Block B{{[0-9]+}}:14// CHECK: Issue ([[L_X:[0-9]+]] (Path: x), ToOrigin: [[O_DRE_X:[0-9]+]] (Expr: DeclRefExpr))15// CHECK: OriginFlow (Dest: [[O_ADDR_X:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_X]] (Expr: DeclRefExpr))16 MyObj* p = &x;17// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_ADDR_X]] (Expr: UnaryOperator))18 return p;19// CHECK: Use ([[O_P]] (Decl: p), Read)20// CHECK: OriginFlow (Dest: [[O_RET_VAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_P]] (Decl: p))21// CHECK: Expire ([[L_X]] (Path: x))22// CHECK: OriginEscapes ([[O_RET_VAL]] (Expr: ImplicitCastExpr))23}24 25 26// Pointer Assignment and Return27// CHECK-LABEL: Function: assign_and_return_local_addr28MyObj* assign_and_return_local_addr() {29 MyObj y{20};30// CHECK: Block B{{[0-9]+}}:31// CHECK: Issue ([[L_Y:[0-9]+]] (Path: y), ToOrigin: [[O_DRE_Y:[0-9]+]] (Expr: DeclRefExpr))32// CHECK: OriginFlow (Dest: [[O_ADDR_Y:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_Y]] (Expr: DeclRefExpr))33 MyObj* ptr1 = &y;34// CHECK: OriginFlow (Dest: [[O_PTR1:[0-9]+]] (Decl: ptr1), Src: [[O_ADDR_Y]] (Expr: UnaryOperator))35 MyObj* ptr2 = ptr1;36// CHECK: Use ([[O_PTR1]] (Decl: ptr1), Read)37// CHECK: OriginFlow (Dest: [[O_PTR1_RVAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_PTR1]] (Decl: ptr1))38// CHECK: OriginFlow (Dest: [[O_PTR2:[0-9]+]] (Decl: ptr2), Src: [[O_PTR1_RVAL]] (Expr: ImplicitCastExpr))39 ptr2 = ptr1;40// CHECK: Use ([[O_PTR1]] (Decl: ptr1), Read)41// CHECK: OriginFlow (Dest: [[O_PTR1_RVAL_2:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_PTR1]] (Decl: ptr1))42// CHECK: Use ({{[0-9]+}} (Decl: ptr2), Write)43// CHECK: OriginFlow (Dest: [[O_PTR2]] (Decl: ptr2), Src: [[O_PTR1_RVAL_2]] (Expr: ImplicitCastExpr))44 ptr2 = ptr2; // Self assignment.45// CHECK: Use ([[O_PTR2]] (Decl: ptr2), Read)46// CHECK: OriginFlow (Dest: [[O_PTR2_RVAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_PTR2]] (Decl: ptr2))47// CHECK: Use ([[O_PTR2]] (Decl: ptr2), Write)48// CHECK: OriginFlow (Dest: [[O_PTR2]] (Decl: ptr2), Src: [[O_PTR2_RVAL]] (Expr: ImplicitCastExpr))49 return ptr2;50// CHECK: Use ([[O_PTR2]] (Decl: ptr2), Read)51// CHECK: OriginFlow (Dest: [[O_RET_VAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_PTR2]] (Decl: ptr2))52// CHECK: Expire ([[L_Y]] (Path: y))53// CHECK: OriginEscapes ([[O_RET_VAL]] (Expr: ImplicitCastExpr))54}55 56// Return of Non-Pointer Type57// CHECK-LABEL: Function: return_int_val58int return_int_val() {59 int x = 10;60// CHECK: Block B{{[0-9]+}}:61// CHECK: Issue ([[L_X:[0-9]+]] (Path: x), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr))62// CHECK: Expire ([[L_X:[0-9]+]] (Path: x))63 return x;64}65// CHECK-NEXT: End of Block66 67 68// Loan Expiration (Automatic Variable, C++)69// CHECK-LABEL: Function: loan_expires_cpp70void loan_expires_cpp() {71 MyObj obj{1};72// CHECK: Block B{{[0-9]+}}:73// CHECK: Issue ([[L_OBJ:[0-9]+]] (Path: obj), ToOrigin: [[O_DRE_OBJ:[0-9]+]] (Expr: DeclRefExpr))74// CHECK: OriginFlow (Dest: [[O_ADDR_OBJ:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_OBJ]] (Expr: DeclRefExpr))75 MyObj* pObj = &obj;76// CHECK: OriginFlow (Dest: {{[0-9]+}} (Decl: pObj), Src: [[O_ADDR_OBJ]] (Expr: UnaryOperator))77// CHECK: Expire ([[L_OBJ]] (Path: obj))78}79 80 81// CHECK-LABEL: Function: loan_expires_trivial82void loan_expires_trivial() {83 int trivial_obj = 1;84// CHECK: Block B{{[0-9]+}}:85// CHECK: Issue ([[L_TRIVIAL_OBJ:[0-9]+]] (Path: trivial_obj), ToOrigin: [[O_DRE_TRIVIAL:[0-9]+]] (Expr: DeclRefExpr))86// CHECK: OriginFlow (Dest: [[O_ADDR_TRIVIAL_OBJ:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_TRIVIAL]] (Expr: DeclRefExpr))87 int* pTrivialObj = &trivial_obj;88// CHECK: OriginFlow (Dest: {{[0-9]+}} (Decl: pTrivialObj), Src: [[O_ADDR_TRIVIAL_OBJ]] (Expr: UnaryOperator))89// CHECK: Expire ([[L_TRIVIAL_OBJ:[0-9]+]] (Path: trivial_obj))90// CHECK-NEXT: End of Block91}92 93// Trivial Destructors94// CHECK-LABEL: Function: return_int_pointer95int* return_int_pointer() {96 int* ptr;97// CHECK: Block B{{[0-9]+}}:98 int x = 1;99// CHECK: Issue ([[L_X:[0-9]+]] (Path: x), ToOrigin: [[O_DRE_X:[0-9]+]] (Expr: DeclRefExpr))100// CHECK: OriginFlow (Dest: [[O_ADDR_X:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_X]] (Expr: DeclRefExpr))101 ptr = &x;102// CHECK: Use ([[O_PTR:[0-9]+]] (Decl: ptr), Write)103// CHECK: OriginFlow (Dest: [[O_PTR]] (Decl: ptr), Src: [[O_ADDR_X]] (Expr: UnaryOperator))104// CHECK: Use ([[O_PTR]] (Decl: ptr), Read)105// CHECK: OriginFlow (Dest: [[O_RET_VAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_PTR]] (Decl: ptr))106// CHECK: Expire ([[L_X]] (Path: x))107// CHECK: OriginEscapes ([[O_RET_VAL]] (Expr: ImplicitCastExpr))108 return ptr;109}110// CHECK-NEXT: End of Block111 112// CHECK-LABEL: Function: conditional113void conditional(bool condition) {114 int a = 5;115 int b = 10;116 int* p = nullptr;117 118 if (condition)119// CHECK: Block B{{[0-9]+}}:120// CHECK: Issue ([[L_A:[0-9]+]] (Path: a), ToOrigin: [[O_DRE_A:[0-9]+]] (Expr: DeclRefExpr))121// CHECK: OriginFlow (Dest: [[O_ADDR_A:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_A]] (Expr: DeclRefExpr))122// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_ADDR_A]] (Expr: UnaryOperator))123 p = &a;124 else125// CHECK: Block B{{[0-9]+}}:126// CHECK: Issue ([[L_B:[0-9]+]] (Path: b), ToOrigin: [[O_DRE_B:[0-9]+]] (Expr: DeclRefExpr))127// CHECK: OriginFlow (Dest: [[O_ADDR_B:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_B]] (Expr: DeclRefExpr))128// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_ADDR_B]] (Expr: UnaryOperator))129 p = &b;130// CHECK: Block B{{[0-9]+}}:131 int *q = p;132// CHECK: Use ([[O_P]] (Decl: p), Read)133// CHECK: OriginFlow (Dest: [[O_P_RVAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_P]] (Decl: p))134// CHECK: OriginFlow (Dest: [[O_Q:[0-9]+]] (Decl: q), Src: [[O_P_RVAL]] (Expr: ImplicitCastExpr))135}136 137 138// CHECK-LABEL: Function: pointers_in_a_cycle139void pointers_in_a_cycle(bool condition) {140 MyObj v1{1};141 MyObj v2{1};142 MyObj v3{1};143 144 MyObj* p1 = &v1;145 MyObj* p2 = &v2;146 MyObj* p3 = &v3;147// CHECK: Block B{{[0-9]+}}:148// CHECK: Issue ([[L_V1:[0-9]+]] (Path: v1), ToOrigin: [[O_DRE_V1:[0-9]+]] (Expr: DeclRefExpr))149// CHECK: OriginFlow (Dest: [[O_ADDR_V1:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_V1]] (Expr: DeclRefExpr))150// CHECK: OriginFlow (Dest: [[O_P1:[0-9]+]] (Decl: p1), Src: [[O_ADDR_V1]] (Expr: UnaryOperator))151// CHECK: Issue ([[L_V2:[0-9]+]] (Path: v2), ToOrigin: [[O_DRE_V2:[0-9]+]] (Expr: DeclRefExpr))152// CHECK: OriginFlow (Dest: [[O_ADDR_V2:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_V2]] (Expr: DeclRefExpr))153// CHECK: OriginFlow (Dest: [[O_P2:[0-9]+]] (Decl: p2), Src: [[O_ADDR_V2]] (Expr: UnaryOperator))154// CHECK: Issue ([[L_V3:[0-9]+]] (Path: v3), ToOrigin: [[O_DRE_V3:[0-9]+]] (Expr: DeclRefExpr))155// CHECK: OriginFlow (Dest: [[O_ADDR_V3:[0-g]+]] (Expr: UnaryOperator), Src: [[O_DRE_V3]] (Expr: DeclRefExpr))156// CHECK: OriginFlow (Dest: [[O_P3:[0-9]+]] (Decl: p3), Src: [[O_ADDR_V3]] (Expr: UnaryOperator))157 158 while (condition) {159// CHECK: Block B{{[0-9]+}}:160 MyObj* temp = p1;161// CHECK: Use ([[O_P1]] (Decl: p1), Read)162// CHECK: OriginFlow (Dest: [[O_P1_RVAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_P1]] (Decl: p1))163// CHECK: OriginFlow (Dest: [[O_TEMP:[0-9]+]] (Decl: temp), Src: [[O_P1_RVAL]] (Expr: ImplicitCastExpr))164 p1 = p2;165// CHECK: Use ([[O_P2:[0-9]+]] (Decl: p2), Read)166// CHECK: OriginFlow (Dest: [[O_P2_RVAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_P2]] (Decl: p2))167// CHECK: Use ({{[0-9]+}} (Decl: p1), Write)168// CHECK: OriginFlow (Dest: [[O_P1]] (Decl: p1), Src: [[O_P2_RVAL]] (Expr: ImplicitCastExpr))169 p2 = p3;170// CHECK: Use ([[O_P3:[0-9]+]] (Decl: p3), Read)171// CHECK: OriginFlow (Dest: [[O_P3_RVAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_P3]] (Decl: p3))172// CHECK: Use ({{[0-9]+}} (Decl: p2), Write)173// CHECK: OriginFlow (Dest: [[O_P2]] (Decl: p2), Src: [[O_P3_RVAL]] (Expr: ImplicitCastExpr))174 p3 = temp;175// CHECK: Use ([[O_TEMP]] (Decl: temp), Read)176// CHECK: OriginFlow (Dest: [[O_TEMP_RVAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_TEMP]] (Decl: temp))177// CHECK: Use ({{[0-9]+}} (Decl: p3), Write)178// CHECK: OriginFlow (Dest: [[O_P3]] (Decl: p3), Src: [[O_TEMP_RVAL]] (Expr: ImplicitCastExpr))179 }180}181 182// CHECK-LABEL: Function: overwrite_origin183void overwrite_origin() {184 MyObj s1;185 MyObj s2;186// CHECK: Block B{{[0-9]+}}:187 MyObj* p = &s1;188// CHECK: Issue ([[L_S1:[0-9]+]] (Path: s1), ToOrigin: [[O_DRE_S1:[0-9]+]] (Expr: DeclRefExpr))189// CHECK: OriginFlow (Dest: [[O_ADDR_S1:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_S1]] (Expr: DeclRefExpr))190// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_ADDR_S1]] (Expr: UnaryOperator))191 p = &s2;192// CHECK: Issue ([[L_S2:[0-9]+]] (Path: s2), ToOrigin: [[O_DRE_S2:[0-9]+]] (Expr: DeclRefExpr))193// CHECK: OriginFlow (Dest: [[O_ADDR_S2:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_S2]] (Expr: DeclRefExpr))194// CHECK: Use ({{[0-9]+}} (Decl: p), Write)195// CHECK: OriginFlow (Dest: [[O_P]] (Decl: p), Src: [[O_ADDR_S2]] (Expr: UnaryOperator))196// CHECK: Expire ([[L_S2]] (Path: s2))197// CHECK: Expire ([[L_S1]] (Path: s1))198}199 200// CHECK-LABEL: Function: reassign_to_null201void reassign_to_null() {202 MyObj s1;203// CHECK: Block B{{[0-9]+}}:204 MyObj* p = &s1;205// CHECK: Issue ([[L_S1:[0-9]+]] (Path: s1), ToOrigin: [[O_DRE_S1:[0-9]+]] (Expr: DeclRefExpr))206// CHECK: OriginFlow (Dest: [[O_ADDR_S1:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_S1]] (Expr: DeclRefExpr))207// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_ADDR_S1]] (Expr: UnaryOperator))208 p = nullptr;209// CHECK: OriginFlow (Dest: [[O_NULLPTR_CAST:[0-9]+]] (Expr: ImplicitCastExpr), Src: {{[0-9]+}} (Expr: CXXNullPtrLiteralExpr))210// CHECK: Use ({{[0-9]+}} (Decl: p), Write)211// CHECK: OriginFlow (Dest: [[O_P]] (Decl: p), Src: [[O_NULLPTR_CAST]] (Expr: ImplicitCastExpr))212// CHECK: Expire ([[L_S1]] (Path: s1))213}214// FIXME: Have a better representation for nullptr than just an empty origin. 215// It should be a separate loan and origin kind.216 217 218// CHECK-LABEL: Function: reassign_in_if219void reassign_in_if(bool condition) {220 MyObj s1;221 MyObj s2;222 MyObj* p = &s1;223// CHECK: Block B{{[0-9]+}}:224// CHECK: Issue ([[L_S1:[0-9]+]] (Path: s1), ToOrigin: [[O_DRE_S1:[0-9]+]] (Expr: DeclRefExpr))225// CHECK: OriginFlow (Dest: [[O_ADDR_S1:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_S1]] (Expr: DeclRefExpr))226// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_ADDR_S1]] (Expr: UnaryOperator))227 if (condition) {228// CHECK: Block B{{[0-9]+}}:229 p = &s2;230// CHECK: Issue ([[L_S2:[0-9]+]] (Path: s2), ToOrigin: [[O_DRE_S2:[0-9]+]] (Expr: DeclRefExpr))231// CHECK: OriginFlow (Dest: [[O_ADDR_S2:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_S2]] (Expr: DeclRefExpr))232// CHECK: Use ({{[0-9]+}} (Decl: p), Write)233// CHECK: OriginFlow (Dest: [[O_P]] (Decl: p), Src: [[O_ADDR_S2]] (Expr: UnaryOperator))234 }235// CHECK: Block B{{[0-9]+}}:236// CHECK: Expire ([[L_S2]] (Path: s2))237// CHECK: Expire ([[L_S1]] (Path: s1))238}239 240 241// CHECK-LABEL: Function: assign_in_switch242void assign_in_switch(int mode) {243 MyObj s1;244 MyObj s2;245 MyObj s3;246 MyObj* p = nullptr;247// CHECK: Block B{{[0-9]+}}:248// CHECK: OriginFlow (Dest: [[O_NULLPTR_CAST:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_NULLPTR:[0-9]+]] (Expr: CXXNullPtrLiteralExpr))249// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_NULLPTR_CAST]] (Expr: ImplicitCastExpr))250 switch (mode) {251 case 1:252// CHECK-DAG: Block B{{[0-9]+}}:253 p = &s1;254// CHECK-DAG: Issue ([[L_S1:[0-9]+]] (Path: s1), ToOrigin: [[O_DRE_S1:[0-9]+]] (Expr: DeclRefExpr))255// CHECK-DAG: OriginFlow (Dest: [[O_ADDR_S1:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_S1]] (Expr: DeclRefExpr))256// CHECK-DAG: Use ({{[0-9]+}} (Decl: p), Write)257// CHECK-DAG: OriginFlow (Dest: [[O_P]] (Decl: p), Src: [[O_ADDR_S1]] (Expr: UnaryOperator))258 break;259 case 2:260// CHECK-DAG: Block B{{[0-9]+}}:261 p = &s2;262// CHECK-DAG: Issue ([[L_S2:[0-9]+]] (Path: s2), ToOrigin: [[O_DRE_S2:[0-9]+]] (Expr: DeclRefExpr))263// CHECK-DAG: OriginFlow (Dest: [[O_ADDR_S2:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_S2]] (Expr: DeclRefExpr))264// CHECK-DAG: Use ({{[0-9]+}} (Decl: p), Write)265// CHECK-DAG: OriginFlow (Dest: [[O_P]] (Decl: p), Src: [[O_ADDR_S2]] (Expr: UnaryOperator))266 break;267 default:268// CHECK: Block B{{[0-9]+}}:269 p = &s3;270// CHECK: Issue ([[L_S3:[0-9]+]] (Path: s3), ToOrigin: [[O_DRE_S3:[0-9]+]] (Expr: DeclRefExpr))271// CHECK: OriginFlow (Dest: [[O_ADDR_S3:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_S3]] (Expr: DeclRefExpr))272// CHECK: Use ({{[0-9]+}} (Decl: p), Write)273// CHECK: OriginFlow (Dest: [[O_P]] (Decl: p), Src: [[O_ADDR_S3]] (Expr: UnaryOperator))274 break;275 }276// CHECK: Block B{{[0-9]+}}:277// CHECK-DAG: Expire ([[L_S3]] (Path: s3))278// CHECK-DAG: Expire ([[L_S2]] (Path: s2))279// CHECK-DAG: Expire ([[L_S1]] (Path: s1))280}281 282// CHECK-LABEL: Function: loan_in_loop283void loan_in_loop(bool condition) {284 MyObj* p = nullptr;285// CHECK: Block B{{[0-9]+}}:286// CHECK: OriginFlow (Dest: [[O_NULLPTR_CAST:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_NULLPTR:[0-9]+]] (Expr: CXXNullPtrLiteralExpr))287// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_NULLPTR_CAST]] (Expr: ImplicitCastExpr))288 while (condition) {289 MyObj inner;290// CHECK: Block B{{[0-9]+}}:291 p = &inner;292// CHECK: Issue ([[L_INNER:[0-9]+]] (Path: inner), ToOrigin: [[O_DRE_INNER:[0-9]+]] (Expr: DeclRefExpr))293// CHECK: OriginFlow (Dest: [[O_ADDR_INNER:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_INNER]] (Expr: DeclRefExpr))294// CHECK: Use ({{[0-9]+}} (Decl: p), Write)295// CHECK: OriginFlow (Dest: [[O_P]] (Decl: p), Src: [[O_ADDR_INNER]] (Expr: UnaryOperator))296// CHECK: Expire ([[L_INNER]] (Path: inner))297 }298}299 300// CHECK-LABEL: Function: loop_with_break301void loop_with_break(int count) {302 MyObj s1;303 MyObj s2;304 MyObj* p = &s1;305// CHECK: Block B{{[0-9]+}}:306// CHECK: Issue ([[L_S1:[0-9]+]] (Path: s1), ToOrigin: [[O_DRE_S1:[0-9]+]] (Expr: DeclRefExpr))307// CHECK: OriginFlow (Dest: [[O_ADDR_S1:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_S1]] (Expr: DeclRefExpr))308// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_ADDR_S1]] (Expr: UnaryOperator))309 for (int i = 0; i < count; ++i) {310 if (i == 5) {311// CHECK: Block B{{[0-9]+}}:312 p = &s2;313// CHECK: Issue ([[L_S2:[0-9]+]] (Path: s2), ToOrigin: [[O_DRE_S2:[0-9]+]] (Expr: DeclRefExpr))314// CHECK: OriginFlow (Dest: [[O_ADDR_S2:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_S2]] (Expr: DeclRefExpr))315// CHECK: Use ({{[0-9]+}} (Decl: p), Write)316// CHECK: OriginFlow (Dest: [[O_P]] (Decl: p), Src: [[O_ADDR_S2]] (Expr: UnaryOperator))317 break;318 }319 }320// CHECK: Block B{{[0-9]+}}:321// CHECK: Expire ([[L_S2]] (Path: s2))322// CHECK: Expire ([[L_S1]] (Path: s1))323}324 325// CHECK-LABEL: Function: nested_scopes326void nested_scopes() {327 MyObj* p = nullptr;328// CHECK: Block B{{[0-9]+}}:329// CHECK: OriginFlow (Dest: [[O_NULLPTR_CAST:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_NULLPTR:[0-9]+]] (Expr: CXXNullPtrLiteralExpr))330// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_NULLPTR_CAST]] (Expr: ImplicitCastExpr))331 {332 MyObj outer;333 p = &outer;334// CHECK: Issue ([[L_OUTER:[0-9]+]] (Path: outer), ToOrigin: [[O_DRE_OUTER:[0-9]+]] (Expr: DeclRefExpr))335// CHECK: OriginFlow (Dest: [[O_ADDR_OUTER:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_OUTER]] (Expr: DeclRefExpr))336// CHECK: Use ({{[0-9]+}} (Decl: p), Write)337// CHECK: OriginFlow (Dest: [[O_P]] (Decl: p), Src: [[O_ADDR_OUTER]] (Expr: UnaryOperator))338 {339 MyObj inner;340 p = &inner;341// CHECK: Issue ([[L_INNER:[0-9]+]] (Path: inner), ToOrigin: [[O_DRE_INNER:[0-9]+]] (Expr: DeclRefExpr))342// CHECK: OriginFlow (Dest: [[O_ADDR_INNER:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_INNER]] (Expr: DeclRefExpr))343// CHECK: Use ({{[0-9]+}} (Decl: p), Write)344// CHECK: OriginFlow (Dest: [[O_P]] (Decl: p), Src: [[O_ADDR_INNER]] (Expr: UnaryOperator))345 }346// CHECK: Expire ([[L_INNER]] (Path: inner))347 }348// CHECK: Expire ([[L_OUTER]] (Path: outer))349}350 351// CHECK-LABEL: Function: pointer_indirection352void pointer_indirection() {353 int a;354 int *p = &a;355// CHECK: Block B{{[0-9]+}}:356// CHECK: Issue ([[L_A:[0-9]+]] (Path: a), ToOrigin: [[O_DRE_A:[0-9]+]] (Expr: DeclRefExpr))357// CHECK: OriginFlow (Dest: [[O_ADDR_A:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_A]] (Expr: DeclRefExpr))358// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_ADDR_A]] (Expr: UnaryOperator))359 int **pp = &p;360// Note: No facts are generated for &p because the subexpression is a pointer type,361// which is not yet supported by the origin model. This is expected.362 int *q = *pp;363// CHECK: Use ([[O_PP:[0-9]+]] (Decl: pp), Read)364// CHECK: OriginFlow (Dest: {{[0-9]+}} (Decl: q), Src: {{[0-9]+}} (Expr: ImplicitCastExpr))365}366 367// CHECK-LABEL: Function: ternary_operator368// FIXME: Propagate origins across ConditionalOperator.369void ternary_operator() {370 int a, b;371 int *p;372 p = (a > b) ? &a : &b;373// CHECK: Block B{{[0-9]+}}:374// CHECK: Issue ([[L_A:[0-9]+]] (Path: a), ToOrigin: [[O_DRE_A:[0-9]+]] (Expr: DeclRefExpr))375 376// CHECK: Block B{{[0-9]+}}:377// CHECK: Issue ([[L_B:[0-9]+]] (Path: b), ToOrigin: [[O_DRE_B:[0-9]+]] (Expr: DeclRefExpr))378 379// CHECK: Block B{{[0-9]+}}:380// CHECK: Use ({{[0-9]+}} (Decl: p), Write)381// CHECK: OriginFlow (Dest: {{[0-9]+}} (Decl: p), Src: {{[0-9]+}} (Expr: ConditionalOperator))382}383 384// CHECK-LABEL: Function: test_use_facts385void usePointer(MyObj*);386void test_use_facts() {387 MyObj x;388 MyObj *p;389// CHECK: Block B{{[0-9]+}}:390 p = &x;391// CHECK: Issue ([[L_X:[0-9]+]] (Path: x), ToOrigin: [[O_DRE_X:[0-9]+]] (Expr: DeclRefExpr))392// CHECK: OriginFlow (Dest: [[O_ADDR_X:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_X]] (Expr: DeclRefExpr))393// CHECK: Use ([[O_P:[0-9]+]] (Decl: p), Write)394// CHECK: OriginFlow (Dest: [[O_P]] (Decl: p), Src: [[O_ADDR_X]] (Expr: UnaryOperator))395 (void)*p;396// CHECK: Use ([[O_P]] (Decl: p), Read)397 usePointer(p);398// CHECK: Use ([[O_P]] (Decl: p), Read)399 p->id = 1;400// CHECK: Use ([[O_P]] (Decl: p), Read)401 MyObj* q;402 q = p;403// CHECK: Use ([[O_P]] (Decl: p), Read)404// CHECK: Use ([[O_Q:[0-9]+]] (Decl: q), Write)405 usePointer(q);406// CHECK: Use ([[O_Q]] (Decl: q), Read)407 q->id = 2;408// CHECK: Use ([[O_Q]] (Decl: q), Read)409// CHECK: Expire ([[L_X]] (Path: x))410}411 412// CHECK-LABEL: Function: test_use_lifetimebound_call413MyObj* LifetimeBoundCall(MyObj* x [[clang::lifetimebound]], MyObj* y [[clang::lifetimebound]]);414void test_use_lifetimebound_call() {415 MyObj x, y;416 MyObj *p = &x;417// CHECK: Issue ([[L_X:[0-9]+]] (Path: x), ToOrigin: [[O_DRE_X:[0-9]+]] (Expr: DeclRefExpr))418// CHECK: OriginFlow (Dest: [[O_ADDR_X:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_X]] (Expr: DeclRefExpr))419// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_ADDR_X]] (Expr: UnaryOperator))420 MyObj *q = &y;421// CHECK: Issue ([[L_Y:[0-9]+]] (Path: y), ToOrigin: [[O_DRE_Y:[0-9]+]] (Expr: DeclRefExpr))422// CHECK: OriginFlow (Dest: [[O_ADDR_Y:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_Y]] (Expr: DeclRefExpr))423// CHECK: OriginFlow (Dest: [[O_Q:[0-9]+]] (Decl: q), Src: [[O_ADDR_Y]] (Expr: UnaryOperator))424 MyObj* r = LifetimeBoundCall(p, q);425// CHECK: Use ([[O_P]] (Decl: p), Read)426// CHECK: OriginFlow (Dest: [[O_P_RVAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_P]] (Decl: p))427// CHECK: Use ([[O_Q]] (Decl: q), Read)428// CHECK: OriginFlow (Dest: [[O_Q_RVAL:[0-9]+]] (Expr: ImplicitCastExpr), Src: [[O_Q]] (Decl: q))429// CHECK: OriginFlow (Dest: [[O_CALL_EXPR:[0-9]+]] (Expr: CallExpr), Src: [[O_P_RVAL]] (Expr: ImplicitCastExpr))430// CHECK: OriginFlow (Dest: [[O_CALL_EXPR]] (Expr: CallExpr), Src: [[O_Q_RVAL]] (Expr: ImplicitCastExpr), Merge)431// CHECK: OriginFlow (Dest: [[O_R:[0-9]+]] (Decl: r), Src: [[O_CALL_EXPR]] (Expr: CallExpr))432// CHECK: Expire ([[L_Y]] (Path: y))433// CHECK: Expire ([[L_X]] (Path: x))434}435// CHECK-LABEL: Function: test_conditional_operator436void test_conditional_operator(bool cond) {437 MyObj x, y;438 MyObj *p = cond ? &x : &y;439// CHECK: Block B{{[0-9]+}}:440// CHECK: Issue ([[L_X:[0-9]+]] (Path: x), ToOrigin: [[O_DRE_X:[0-9]+]] (Expr: DeclRefExpr))441// CHECK: OriginFlow (Dest: [[O_ADDR_X:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_X]] (Expr: DeclRefExpr))442// CHECK: Block B{{[0-9]+}}:443// CHECK: Issue ([[L_Y:[0-9]+]] (Path: y), ToOrigin: [[O_DRE_Y:[0-9]+]] (Expr: DeclRefExpr))444// CHECK: OriginFlow (Dest: [[O_ADDR_Y:[0-9]+]] (Expr: UnaryOperator), Src: [[O_DRE_Y]] (Expr: DeclRefExpr))445// CHECK: Block B{{[0-9]+}}:446// CHECK: OriginFlow (Dest: [[O_COND_OP:[0-9]+]] (Expr: ConditionalOperator), Src: [[O_ADDR_X]] (Expr: UnaryOperator))447// CHECK: OriginFlow (Dest: [[O_COND_OP]] (Expr: ConditionalOperator), Src: [[O_ADDR_Y]] (Expr: UnaryOperator), Merge)448// CHECK: OriginFlow (Dest: [[O_P:[0-9]+]] (Decl: p), Src: [[O_COND_OP]] (Expr: ConditionalOperator))449// CHECK: Expire ([[L_Y]] (Path: y))450// CHECK: Expire ([[L_X]] (Path: x))451}452