// RUN: %clang_analyze_cc1 %s \
// RUN:   -analyzer-checker=debug.DumpDominators \
// RUN:   -analyzer-checker=debug.DumpPostDominators \
// RUN:   -analyzer-checker=debug.DumpControlDependencies \
// RUN:   2>&1 | FileCheck %s

// Test the DominatorsTree implementation with various control flows
int test1()
{
  int x = 6;
  int y = x/2;
  int z;

  while(y > 0) {
    if(y < x) {
      x = x/y;
      y = y-1;
    }else{
      z = x - y;
    }
    x = x - 1;
    x = x - 1;
  }
  z = x+y;
  z = 3;
  return 0;
}

// [B9 (ENTRY)] -> [B8] -> [B7] -> [B6] -> [B5] -> [B3] -> [B2]
//                          |\       \              /       /
//                          | \       ---> [B4] --->       /
//                          |  <---------------------------
//                          V
//                         [B1] -> [B0 (EXIT)]

// CHECK:      Control dependencies (Node#,Dependency#):
// CHECK-NEXT: (2,7)
// CHECK-NEXT: (3,7)
// CHECK-NEXT: (4,6)
// CHECK-NEXT: (4,7)
// CHECK-NEXT: (5,6)
// CHECK-NEXT: (5,7)
// CHECK-NEXT: (6,7)
// CHECK-NEXT: (7,7)
// CHECK-NEXT: Immediate dominance tree (Node#,IDom#):
// CHECK-NEXT: (0,1)
// CHECK-NEXT: (1,7)
// CHECK-NEXT: (2,3)
// CHECK-NEXT: (3,6)
// CHECK-NEXT: (4,6)
// CHECK-NEXT: (5,6)
// CHECK-NEXT: (6,7)
// CHECK-NEXT: (7,8)
// CHECK-NEXT: (8,9)
// CHECK-NEXT: (9,9)
// CHECK-NEXT: Immediate post dominance tree (Node#,IDom#):
// CHECK-NEXT: (0,0)
// CHECK-NEXT: (1,0)
// CHECK-NEXT: (2,7)
// CHECK-NEXT: (3,2)
// CHECK-NEXT: (4,3)
// CHECK-NEXT: (5,3)
// CHECK-NEXT: (6,3)
// CHECK-NEXT: (7,1)
// CHECK-NEXT: (8,7)
// CHECK-NEXT: (9,8)

int test2()
{
  int x,y,z;

  x = 10; y = 100;
  if(x > 0){
    y = 1;
  }else{
    while(x<=0){
      x++;
      y++;
    }
  }
  z = y;

  return 0;
}

//                                    <-------------
//                                   /              \
//                    -----------> [B4] -> [B3] -> [B2]
//                   /              |
//                  /               V
// [B7 (ENTRY)] -> [B6] -> [B5] -> [B1] -> [B0 (EXIT)]

// CHECK:      Control dependencies (Node#,Dependency#):
// CHECK-NEXT: (2,4)
// CHECK-NEXT: (2,6)
// CHECK-NEXT: (3,4)
// CHECK-NEXT: (3,6)
// CHECK-NEXT: (4,6)
// CHECK-NEXT: (4,4)
// CHECK-NEXT: (5,6)
// CHECK-NEXT: Immediate dominance tree (Node#,IDom#):
// CHECK-NEXT: (0,1)
// CHECK-NEXT: (1,6)
// CHECK-NEXT: (2,3)
// CHECK-NEXT: (3,4)
// CHECK-NEXT: (4,6)
// CHECK-NEXT: (5,6)
// CHECK-NEXT: (6,7)
// CHECK-NEXT: (7,7)
// CHECK-NEXT: Immediate post dominance tree (Node#,IDom#):
// CHECK-NEXT: (0,0)
// CHECK-NEXT: (1,0)
// CHECK-NEXT: (2,4)
// CHECK-NEXT: (3,2)
// CHECK-NEXT: (4,1)
// CHECK-NEXT: (5,1)
// CHECK-NEXT: (6,1)
// CHECK-NEXT: (7,6)

int test3()
{
  int x,y,z;

  x = y = z = 1;
  if(x>0) {
    while(x>=0){
      while(y>=x) {
        x = x-1;
        y = y/2;
      }
    }
  }
  z = y;

  return 0;
}

//                           <- [B2] <-
//                          /          \
// [B8 (ENTRY)] -> [B7] -> [B6] ---> [B5] -> [B4] -> [B3]
//                   \       |         \              /
//                    \      |          <-------------
//                     \      \
//                      --------> [B1] -> [B0 (EXIT)]

// CHECK:      Control dependencies (Node#,Dependency#):
// CHECK-NEXT: (2,6)
// CHECK-NEXT: (2,7)
// CHECK-NEXT: (3,5)
// CHECK-NEXT: (3,6)
// CHECK-NEXT: (3,7)
// CHECK-NEXT: (4,5)
// CHECK-NEXT: (4,6)
// CHECK-NEXT: (4,7)
// CHECK-NEXT: (5,6)
// CHECK-NEXT: (5,5)
// CHECK-NEXT: (5,7)
// CHECK-NEXT: (6,7)
// CHECK-NEXT: (6,6)
// CHECK-NEXT: Immediate dominance tree (Node#,IDom#):
// CHECK-NEXT: (0,1)
// CHECK-NEXT: (1,7)
// CHECK-NEXT: (2,5)
// CHECK-NEXT: (3,4)
// CHECK-NEXT: (4,5)
// CHECK-NEXT: (5,6)
// CHECK-NEXT: (6,7)
// CHECK-NEXT: (7,8)
// CHECK-NEXT: (8,8)
// CHECK-NEXT: Immediate post dominance tree (Node#,IDom#):
// CHECK-NEXT: (0,0)
// CHECK-NEXT: (1,0)
// CHECK-NEXT: (2,6)
// CHECK-NEXT: (3,5)
// CHECK-NEXT: (4,3)
// CHECK-NEXT: (5,2)
// CHECK-NEXT: (6,1)
// CHECK-NEXT: (7,1)
// CHECK-NEXT: (8,7)

int test4()
{
  int y = 3;
  while(y > 0) {
    if(y < 3) {
      while(y>0)
        y ++;
    }else{
      while(y<10)
        y ++;
    }
  }
  return 0;
}

//                               <----------------------------------
//                              /              <-----------------   \
//                             /              /                  \   \
// [B12 (ENTRY)] -> [B11] -> [B10]-> [B9] -> [B8] ---> [B7] -> [B6]  |
//                             |      \        \                     /
//                             |       \        -----> [B2] --------/
//                             |        \      /
//                             |          -> [B5] -> [B4] -> [B3]
//                             |               \              /
//                             |                <------------
//                              \
//                               -> [B1] -> [B0 (EXIT)]

// CHECK:      Control dependencies (Node#,Dependency#):
// CHECK-NEXT: (2,10)
// CHECK-NEXT: (3,5)
// CHECK-NEXT: (3,9)
// CHECK-NEXT: (3,10)
// CHECK-NEXT: (4,5)
// CHECK-NEXT: (4,9)
// CHECK-NEXT: (4,10)
// CHECK-NEXT: (5,9)
// CHECK-NEXT: (5,5)
// CHECK-NEXT: (5,10)
// CHECK-NEXT: (6,8)
// CHECK-NEXT: (6,9)
// CHECK-NEXT: (6,10)
// CHECK-NEXT: (7,8)
// CHECK-NEXT: (7,9)
// CHECK-NEXT: (7,10)
// CHECK-NEXT: (8,9)
// CHECK-NEXT: (8,8)
// CHECK-NEXT: (8,10)
// CHECK-NEXT: (9,10)
// CHECK-NEXT: (10,10)
// CHECK-NEXT: Immediate dominance tree (Node#,IDom#):
// CHECK-NEXT: (0,1)
// CHECK-NEXT: (1,10)
// CHECK-NEXT: (2,9)
// CHECK-NEXT: (3,4)
// CHECK-NEXT: (4,5)
// CHECK-NEXT: (5,9)
// CHECK-NEXT: (6,7)
// CHECK-NEXT: (7,8)
// CHECK-NEXT: (8,9)
// CHECK-NEXT: (9,10)
// CHECK-NEXT: (10,11)
// CHECK-NEXT: (11,12)
// CHECK-NEXT: (12,12)
// CHECK-NEXT: Immediate post dominance tree (Node#,IDom#):
// CHECK-NEXT: (0,0)
// CHECK-NEXT: (1,0)
// CHECK-NEXT: (2,10)
// CHECK-NEXT: (3,5)
// CHECK-NEXT: (4,3)
// CHECK-NEXT: (5,2)
// CHECK-NEXT: (6,8)
// CHECK-NEXT: (7,6)
// CHECK-NEXT: (8,2)
// CHECK-NEXT: (9,2)
// CHECK-NEXT: (10,1)
// CHECK-NEXT: (11,10)
// CHECK-NEXT: (12,11)

int test5()
{
  int x,y,z,a,b,c;
  x = 1;
  y = 2;
  z = 3;
  a = 4;
  b = 5;
  c = 6;
  if ( x < 10 ) {
     if ( y < 10 ) {
        if ( z < 10 ) {
           x = 4;
        } else {
           x = 5;
        }
        a = 10;
     } else {
       x = 6;
     }
     b = 10;
  } else {
    x = 7;
  }
  c = 11;
  return 0;
}

//                                                    [B0 (EXIT)] <--
//                                                                   \
// [B11 (ENTY)] -> [B10] -> [B9] -> [B8] -> [B7] -> [B5] -> [B3] -> [B1]
//                            |       |       |      /       /       /
//                            |       |       V     /       /       /
//                            |       V     [B6] -->       /       /
//                            V     [B4] ----------------->       /
//                          [B2]--------------------------------->

// CHECK:      Control dependencies (Node#,Dependency#):
// CHECK-NEXT: (2,10)
// CHECK-NEXT: (3,10)
// CHECK-NEXT: (4,9)
// CHECK-NEXT: (4,10)
// CHECK-NEXT: (5,9)
// CHECK-NEXT: (5,10)
// CHECK-NEXT: (6,8)
// CHECK-NEXT: (6,9)
// CHECK-NEXT: (6,10)
// CHECK-NEXT: (7,8)
// CHECK-NEXT: (7,9)
// CHECK-NEXT: (7,10)
// CHECK-NEXT: (8,9)
// CHECK-NEXT: (8,10)
// CHECK-NEXT: (9,10)
// CHECK-NEXT: Immediate dominance tree (Node#,IDom#):
// CHECK-NEXT: (0,1)
// CHECK-NEXT: (1,10)
// CHECK-NEXT: (2,10)
// CHECK-NEXT: (3,9)
// CHECK-NEXT: (4,9)
// CHECK-NEXT: (5,8)
// CHECK-NEXT: (6,8)
// CHECK-NEXT: (7,8)
// CHECK-NEXT: (8,9)
// CHECK-NEXT: (9,10)
// CHECK-NEXT: (10,11)
// CHECK-NEXT: (11,11)
// CHECK-NEXT: Immediate post dominance tree (Node#,IDom#):
// CHECK-NEXT: (0,0)
// CHECK-NEXT: (1,0)
// CHECK-NEXT: (2,1)
// CHECK-NEXT: (3,1)
// CHECK-NEXT: (4,3)
// CHECK-NEXT: (5,3)
// CHECK-NEXT: (6,5)
// CHECK-NEXT: (7,5)
// CHECK-NEXT: (8,5)
// CHECK-NEXT: (9,3)
// CHECK-NEXT: (10,1)
// CHECK-NEXT: (11,10)
