brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.9 KiB · 7b6fc92 Raw
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