// RUN: %clang_cc1 -std=c++98 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s
// RUN: %clang_cc1 -std=c++11 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s
// RUN: %clang_cc1 -std=c++14 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s
// RUN: %clang_cc1 -std=c++17 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s
// RUN: %clang_cc1 -std=c++20 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s

// Check -ffinite-loops option in combination with various standard versions.
// RUN: %clang_cc1 -std=c++98 -ffinite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s
// RUN: %clang_cc1 -std=c++11 -ffinite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s
// RUN: %clang_cc1 -std=c++14 -ffinite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s
// RUN: %clang_cc1 -std=c++17 -ffinite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s
// RUN: %clang_cc1 -std=c++20 -ffinite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s

// Check -fno-finite-loops option in combination with various standard versions.
// RUN: %clang_cc1 -std=c++98 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s
// RUN: %clang_cc1 -std=c++11 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s
// RUN: %clang_cc1 -std=c++14 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s
// RUN: %clang_cc1 -std=c++17 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s
// RUN: %clang_cc1 -std=c++20 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s

int a = 0;
int b = 0;

// CHECK: datalayout

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2f0v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %for.cond
// CHECK:       for.cond:
// CXX98-NOT:    br {{.*}} llvm.loop
// CXX11-NOT:    br {{.*}} llvm.loop
// FINITE-NOT:   br {{.*}} llvm.loop
void f0() {
  for (; ;) ;
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2f1v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %for.cond
// CHECK:       for.cond:
// CHECK-NEXT:    br i1 true, label %for.body, label %for.end
// CHECK:       for.body:
// CXX98-NOT:    br {{.*}}, !llvm.loop
// CXX11-NOT:    br {{.*}} llvm.loop
// FINITE-NOT:   br {{.*}} llvm.loop
// CHECK:       for.end:
// CHECK-NEXT:    ret void
//
void f1() {
  for (; 1;)
    ;
}

// CXX98-NOT:  mustprogress
// CXX11:      mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2f2v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %for.cond
// CHECK:       for.cond:
// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr @b, align 4
// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
// CHECK-NEXT:    br i1 [[CMP]], label %for.body, label %for.end
// CHECK:       for.body:
// CXX98-NOT:    br {{.*}}, !llvm.loop
// CXX11:        br label %for.cond, !llvm.loop [[LOOP3:!.*]]
// FINITE-NEXT:  br label %for.cond, !llvm.loop [[LOOP3:!.*]]
// CHECK:       for.end:
// CHECK-NEXT:    ret void
//
void f2() {
  for (; a == b;)
    ;
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z1Fv(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %for.cond
// CHECK:       for.cond:
// CHECK-NEXT:    br i1 true, label %for.body, label %for.end
// CHECK:       for.body:
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NOT:     br {{.*}}, !llvm.loop
// FINITE-NOT:    br {{.*}}, !llvm.loop
// CHECK:       for.end:
// CHECK-NEXT:    br label %for.cond1
// CHECK:       for.cond1:
// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr @b, align 4
// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
// CHECK-NEXT:    br i1 [[CMP]], label %for.body2, label %for.end3
// CHECK:       for.body2:
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NEXT:    br label %for.cond1, !llvm.loop [[LOOP5:!.*]]
// FINITE-NEXT:   br label %for.cond1, !llvm.loop [[LOOP5:!.*]]
// CHECK:       for.end3:
// CHECK-NEXT:    ret void
//
void F() {
  for (; 1;)
    ;
  for (; a == b;)
    ;
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2F2v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %for.cond
// CHECK:       for.cond:
// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr @b, align 4
// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
// CHECK-NEXT:    br i1 [[CMP]], label %for.body, label %for.end
// CHECK:       for.body:
// CXX98-NOT:     br {{.*}} !llvm.loop
// CXX11-NEXT:    br label %for.cond, !llvm.loop [[LOOP6:!.*]]
// FINITE-NEXT:   br label %for.cond, !llvm.loop [[LOOP6:!.*]]
// CHECK:       for.end:
// CHECK-NEXT:    br label %for.cond1
// CHECK:       for.cond1:
// CHECK-NEXT:    br i1 true, label %for.body2, label %for.end3
// CHECK:       for.body2:
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NOT:     br {{.*}}, !llvm.loop
// FINITE-NOT:    br {{.*}}, !llvm.loop
// CHECK:       for.end3:
// CHECK-NEXT:    ret void
//
void F2() {
  for (; a == b;)
    ;
  for (; 1;)
    ;
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2w1v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %while.body
// CHECK:       while.body:
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NOT:     br {{.*}}, !llvm.loop
// FINITE-NOT:    br {{.*}}, !llvm.loop
//
void w1() {
  while (1)
    ;
}

// CXX98-NOT:  mustprogress
// CXX11:      mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2w2v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %while.cond
// CHECK:       while.cond:
// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr @b, align 4
// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
// CHECK-NEXT:    br i1 [[CMP]], label %while.body, label %while.end
// CHECK:       while.body:
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NEXT:    br label %while.cond, !llvm.loop [[LOOP9:!.*]]
// FINITE-NEXT:   br label %while.cond, !llvm.loop [[LOOP9:!.*]]
// CHECK:       while.end:
// CHECK-NEXT:    ret void
//
void w2() {
  while (a == b)
    ;
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z1Wv(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %while.cond
// CHECK:       while.cond:
// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr @b, align 4
// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
// CHECK-NEXT:    br i1 [[CMP]], label %while.body, label %while.end
// CHECK:       while.body:
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NEXT:    br label %while.cond, !llvm.loop [[LOOP10:!.*]]
// FINITE-NEXT:   br label %while.cond, !llvm.loop [[LOOP10:!.*]]
// CHECK:       while.end:
// CHECK-NEXT:    br label %while.body2
// CHECK:       while.body2:
// CXX98-NOT:    br {{.*}}, !llvm.loop
// CXX11-NOT:    br {{.*}}, !llvm.loop
// FINITE-NOT:   br {{.*}}, !llvm.loop
//
void W() {
  while (a == b)
    ;
  while (1)
    ;
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2W2v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %while.body
// CHECK:       while.body:
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NOT:     br {{.*}}, !llvm.loop
// FINITE-NOT:    br {{.*}}, !llvm.loop
//
void W2() {
  while (1)
    ;
  while (a == b)
    ;
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2d1v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %do.body
// CHECK:       do.body:
// CHECK-NEXT:    br label %do.cond
// CHECK:       do.cond:
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NOT:     br {{.*}}, !llvm.loop
// FINITE-NOT:    br {{.*}}, !llvm.loop
// CHECK:       do.end:
// CHECK-NEXT:    ret void
//
void d1() {
  do
    ;
  while (1);
}

// CXX98-NOT:  mustprogress
// CXX11:      mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2d2v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %do.body
// CHECK:       do.body:
// CHECK-NEXT:    br label %do.cond
// CHECK:       do.cond:
// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr @b, align 4
// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NEXT:    br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP14:!.*]]
// FINITE-NEXT:   br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP14:!.*]]
// CHECK:       do.end:
// CHECK-NEXT:    ret void
//
void d2() {
  do
    ;
  while (a == b);
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z1Dv(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %do.body
// CHECK:       do.body:
// CHECK-NEXT:    br label %do.cond
// CHECK:       do.cond:
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NOT:     br {{.*}}, !llvm.loop
// FINITE-NOT:    br {{.*}}, !llvm.loop
// CHECK:       do.end:
// CHECK-NEXT:    br label %do.body1
// CHECK:       do.body1:
// CHECK-NEXT:    br label %do.cond2
// CHECK:       do.cond2:
// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr @b, align 4
// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NEXT:    br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP16:!.*]]
// FINITE-NEXT:   br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP16:!.*]]
// CHECK:       do.end3:
// CHECK-NEXT:    ret void
//
void D() {
  do
    ;
  while (1);
  do
    ;
  while (a == b);
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2D2v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %do.body
// CHECK:       do.body:
// CHECK-NEXT:    br label %do.cond
// CHECK:       do.cond:
// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr @b, align 4
// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NEXT:    br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP17:!.*]]
// FINITE-NEXT:   br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP17:!.*]]
// CHECK:       do.end:
// CHECK-NEXT:    br label %do.body1
// CHECK:       do.body1:
// CHECK-NEXT:    br label %do.cond2
// CHECK:       do.cond2:
// CXX98-NOT:     br {{.*}}, !llvm.loop
// CXX11-NOT:     br {{.*}}, !llvm.loop
// FINITE-NOT:    br {{.*}}, !llvm.loop
// CHECK:       do.end3:
// CHECK-NEXT:    ret void
//
void D2() {
  do
    ;
  while (a == b);
  do
    ;
  while (1);
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z9compound0v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %for.cond
// CHECK:       for.cond:
// CXX98-NOT:    br {{.*}}, !llvm.loop
// CXX11-NOT:    br {{.*}}, !llvm.loop
// FINITE-NOT:   br {{.*}}, !llvm.loop
void compound0() {
  for (; ;) {}
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z9compound1v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %for.cond
// CHECK:       for.cond:
// CXX98-NOT:    br {{.*}}, llvm.loop
// CXX11-NOT:    br {{.*}}, llvm.loop
// FINITE-NOT:   br {{.*}}, !llvm.loop
void compound1() {
  for (; ;) {/*! */}
}

// CXX98-NOT:  mustprogress
// CXX11-NOT:  mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z9compound2v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %do.body
// CHECK:       do.body:
// CHECK-NEXT:    br label %do.cond
// CHECK:       do.cond:
// CXX98-NOT:    br {{.*}}, !llvm.loop
// CXX11-NOT:    br {{.*}}, !llvm.loop
// FINITE-NOT:   br {{.*}}, !llvm.loop
// CHECK:       do.end:
// CHECK-NEXT:    ret void
//
void compound2() {
  do {} while (1+1);
}

// CXX98-NOT:  mustprogress
// CXX11    :  mustprogress
// FINITE   :  mustprogress
// CHECK-LABEL: @_Z5Falsev(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    br label %do.body
// CHECK:       do.body:
// CHECK-NEXT:    br label %do.end
// CHECK:       do.end:
// CHECK-NEXT:    ret void
//
void False() {
  do {} while (1-1);
}


// CXX11: [[LOOP3]] = distinct !{[[LOOP3]], [[MP:.*]]}
// CXX11: [[MP]] = !{!"llvm.loop.mustprogress"}
// CXX11: [[LOOP5]] = distinct !{[[LOOP5]], [[MP]]}
// CXX11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]}
// CXX11: [[LOOP9]] = distinct !{[[LOOP9]], [[MP]]}
// CXX11: [[LOOP10]] = distinct !{[[LOOP10]], [[MP]]}
// CXX11: [[LOOP14]] = distinct !{[[LOOP14]], [[MP]]}
// CXX11: [[LOOP16]] = distinct !{[[LOOP16]], [[MP]]}
// CXX11: [[LOOP17]] = distinct !{[[LOOP17]], [[MP]]}
