void myFunction1() {
  int i;
  int result = 0;

  for (i = 0;; i = i+1) {

    if (i < 20) result++; // $ Alert[cpp/constant-comparison]
    if (i <= 20) result++; // $ Alert[cpp/constant-comparison]
    if (i > 20) result++; // $ Alert[cpp/constant-comparison]
    if (i >= 20) result++; // $ Alert[cpp/constant-comparison]
    if (i == 20) result++; // $ Alert[cpp/constant-comparison]
    if (i != 20) result++; // $ Alert[cpp/constant-comparison]

    if (i < -1) result++; // $ Alert[cpp/constant-comparison]
    if (i <= -1) result++; // $ Alert[cpp/constant-comparison]
    if (i > -1) result++; // $ Alert[cpp/constant-comparison]
    if (i >= -1) result++; // $ Alert[cpp/constant-comparison]
    if (i == -1) result++; // $ Alert[cpp/constant-comparison]
    if (i != -1) result++; // $ Alert[cpp/constant-comparison]

    if (i < 5) result++;
    if (i <= 5) result++;
    if (i > 5) result++;
    if (i >= 5) result++;
    if (i == 5) result++;
    if (i != 5) result++;

    i = i % 7;
  }
}

void myFunction2() {
  int i;
  int result = 0;

  for (i = 0;; i++) {

    if (i < 20) result++; // $ Alert[cpp/constant-comparison]
    if (i <= 20) result++; // $ Alert[cpp/constant-comparison]
    if (i > 20) result++; // $ Alert[cpp/constant-comparison]
    if (i >= 20) result++; // $ Alert[cpp/constant-comparison]
    if (i == 20) result++; // $ Alert[cpp/constant-comparison]
    if (i != 20) result++; // $ Alert[cpp/constant-comparison]

    if (i < -1) result++; // $ Alert[cpp/constant-comparison]
    if (i <= -1) result++; // $ Alert[cpp/constant-comparison]
    if (i > -1) result++; // $ Alert[cpp/constant-comparison]
    if (i >= -1) result++; // $ Alert[cpp/constant-comparison]
    if (i == -1) result++; // $ Alert[cpp/constant-comparison]
    if (i != -1) result++; // $ Alert[cpp/constant-comparison]

    if (i < 5) result++;
    if (i <= 5) result++;
    if (i > 5) result++;
    if (i >= 5) result++;
    if (i == 5) result++;
    if (i != 5) result++;

    i = i % 7;
  }
}

int myFunction3(int i) {
  if (i < 4) {
    if (i < 5) { // $ Alert[cpp/constant-comparison]
      return 1;
    }
  }
  return 0;
}

int booleans(void* ptr, void* ptr2, int i) {
  if (ptr && (ptr2 || i == 4))
    if (i == 3)
      return i;
  return 0;
}

#define NUM 999
static int ranges(double a, double b) {
  if (a > NUM && b < NUM) // GOOD
    return 1;
  else if (a <= NUM && b < NUM) // GOOD
    return 2;
  else if (a > -NUM && b >= NUM) // GOOD
    return 3;
  else
    return 4;
}



int myFunction4() {
  // No result if both operands are constant.
  if (0 < 1) {
    return 1;
  }
  return 0;
}

// Pointless checks for unsigned values being negative
int unsignedBounds(unsigned int a, unsigned long b, unsigned long long c) {
  if (a < 0) { // $ Alert[cpp/constant-comparison]
    return 1;
  }
  if (b >= 0) { // $ Alert[cpp/unsigned-comparison-zero] // UnsignedGEZero
    if (b > 0 && c < 0) { // $ Alert[cpp/constant-comparison] // Only the test of c is bad here
      return 1;
    }
  }
  return 0;
}

int twoReasons(int a, int b) {
  if (a <= 0 && b > 5) {
    return a < b; // $ Alert[cpp/constant-comparison]
  }
  if (a <= 100 && b > 105) { // BUG [Not detected - this clause is always false]
    return a > b; // $ Alert[cpp/constant-comparison]
  }
  return 0;
}

int repeatedComparisons(int a) {
  if (a >= 20) {
    return a >= 20; // $ Alert[cpp/constant-comparison]
  }
  if (a <= 3) {
    return a > 3; // $ Alert[cpp/constant-comparison]
  }
  return 0;
}

// Our analysis does not yet catch these non-constant pointless comparisons
int nonConstantComparisons(int a, int b) {
  if (a < b) {
    if (a < b) {
      return 1;
    }
    if (b >= a) {
      return 1;
    }
    if (a <= b) {
      return 1;
    }
  }
  return 0;
}

// Regression test for a false positive
int myFunction7(int count)
{
  int x = 0;
  int y = 0;
  int *thing_ptr = 0;
  const char **z_ptr = 0;
  const char *z = 0;

  enum {
    THING_A = 0,
    THING_B,
    THING_C,
    THING_D,
    THING_E
  } thing = THING_A;

  thing_ptr = &thing;
  thing_ptr = &x;
  thing_ptr = &y;
  z_ptr = &z;

  if (!thing)
    thing = count ? THING_E : THING_B;

  if (z && thing != THING_B)
    return 0;

  if (x && thing != THING_E && thing != THING_C && thing != THING_D)
    return 0;

  if (y && thing != THING_C)
    return 0;

  return 1;
}

int myFunction5(int x) {
  int d, i = 0;
  if (x < 0) {
    return -1;
  }

  while (i < 3) {
    i++;
  }
  d = i;
  if (x < 0) {  // $ Alert[cpp/constant-comparison] // Comparison is always false.
    if (d > -x) {  // Unreachable code.
      return 1;
    }
  }
  return 0;
}

enum my_enum {
	FOO
};

int myFunction6(enum my_enum e) {
	if (e < 0) { // GOOD (suppressed because it's platform-dependent)
		return 1;
	}
	return 0;
}

typedef unsigned long long size_t;

#define SIZE_MAX (~(size_t)0)

void cpp_105_regression_test(size_t s) {
  if (s > SIZE_MAX - 1) { // GOOD
    // ...
  }
  if (s > SIZE_MAX - 2) { // GOOD
    // ...
  }
  if (s > SIZE_MAX - 4) { // GOOD
    // ...
  }
}

unsigned int global_setting;

#define MAYBE_DO(CODE) \
  if (global_setting >= 0) \
    CODE;

void macroExpansionTest() {
  int x;

  MAYBE_DO(x = 1); // GOOD (the problem is in the macro)
  MAYBE_DO(if (global_setting >= 0) {x = 2;}); // $ Alert[cpp/unsigned-comparison-zero] // BAD (the problem is in the invocation)
}

int overeager_wraparound(unsigned int u32bound, unsigned long long u64bound) {
  unsigned int u32idx;
  unsigned long long u64idx;

  for (u32idx = 1; u32idx < u32bound; u32idx++) {
    if (u32idx == 0) // $ MISSING: Alert // BAD [NOT DETECTED]
      return 0;
  }

  for (u64idx = 1; u64idx < u64bound; u64idx++) {
    if (u64idx == 0) // $ MISSING: Alert // BAD [NOT DETECTED]
      return 0;
  }

  return 1;
}

int negative_zero(double dbl) {
  if (dbl >= 0) {
    return dbl >= -dbl; // $ SPURIOUS: Alert[cpp/constant-comparison] // GOOD [FALSE POSITIVE]
  }
  return 0;
}

typedef unsigned char u8;

int widening_cast1(u8 c) {
  if (c == 0) {
    if ((int)c > 0) { // $ Alert[cpp/constant-comparison] // BAD
      return 1;
    }
  }
  return 0;
}

int widening_cast2(u8 c) {
  if (c <= 10)
    return -1;
  else if ((c >= 11) /* BAD */ && (c <= 47)) // $ Alert[cpp/constant-comparison]
    return 0;
  else
    return 1;
}

int unsigned_implicit_conversion(unsigned int ui1) {
  // These two comparisons are supported by the range analysis because the
  // implicit signedness conversion is on the constants (0 and 5), not on the
  // variables (ui1).
  if (ui1 == 0) {
    if (ui1 >= 5) { // $ Alert[cpp/constant-comparison] // BAD
      return 1;
    }
  }
  return 0;
}

int signedness_cast1(u8 c) {
  if ((signed char)c == 0) {
    if (c >= 5) { // $ Alert[cpp/constant-comparison] // BAD
      return 1;
    }
  }
  return 0;
}

int signedness_cast2(signed char c) {
  if ((u8)c == 0) {
    if (c >= 5) { // $ Alert[cpp/constant-comparison] // BAD
      return 1;
    }
  }
  return 0;
}

int nan1(double x) {
  if (x < 0.0) {
    return 100;
  }
  else if (x >= 0.0) { // GOOD [x could be NaN]
    return 200;
  }
  else {
    return 300;
  }
}

int nan2(double x) {
  if (x == x) {
    // If x compares with anything at all, it's not NaN
    if (x < 0.0) {
      return 100;
    }
    else if (x >= 0.0) { // $ Alert[cpp/constant-comparison] // BAD [Always true]
      return 200;
    }
    else {
      return 300;
    }
  }
}

struct info_t {
  int id;
  unsigned long long value;
};

int command(void* p, unsigned int s);

int callCommand(void)
{
  struct info_t info;
  unsigned int tmp = 0;

  info.id = 1;
  info.value = (unsigned long long)& tmp;
  if (command(&info, sizeof(info))) {
    return 0;
  }
  if (tmp == 1)  // tmp could have been modified by the call.
    return 1;
  return 0;
}

void shifts(void)
{
	unsigned int x = 3;

	if (x >> 1 >= 1) {} // $ Alert[cpp/constant-comparison] // always true
	if (x >> 1 >= 2) {} // $ Alert[cpp/constant-comparison] // always false
	if (x >> 1 == 1) {} // always true [NOT DETECTED]
}

void bitwise_ands()
{
	unsigned int x = 0xFF;

	if ((x & 2) >= 1) {}
	if ((x & 2) >= 2) {}
	if ((x & 2) >= 3) {} // $ Alert[cpp/constant-comparison] // always false
}

void unsigned_mult(unsigned int x, unsigned int y) {
  if(x < 13 && y < 35) {
      if(x * y > 1024) {} // $ Alert[cpp/constant-comparison] // always false
      if(x * y < 204) {}
      if(x >= 3 && y >= 2) {
        if(x * y < 5) {} // $ Alert[cpp/constant-comparison] // always false
      }
  }
}

void mult_rounding() {
  unsigned long x, y, xy;
  x = y = 1000000003UL; // 1e9 + 3
  xy = 1000000006000000009UL; // x * y, precisely
  // Even though the range analysis wrongly considers x*y to be xy - 9, there
  // are no PointlessComparison false positives in these tests because alerts
  // are suppressed when ulp() < 1, which roughly means that the number is
  // larger than 2^53.
  if (x * y < xy) {} // always false [NOT DETECTED]
  if (x * y > xy) {} // always false [NOT DETECTED]
}

void mult_overflow() {
  unsigned long x, y;
  // The following two numbers multiply to 2^64 + 1, which is 1 when truncated
  // to 64-bit unsigned.
  x = 274177UL;
  y = 67280421310721UL;
  if (x * y == 1) {} // $ Alert[cpp/constant-comparison] // always true [BUG: reported as always false]

  // This bug appears to be caused by
  // `RangeAnalysisUtils::typeUpperBound(unsigned long)` having a result of
  // 2**64 + 384, making the range analysis think that the multiplication can't
  // overflow. The correct `typeUpperBound` would be 2**64 - 1, but we can't
  // represent that with a QL float or int. We could make `typeUpperBound`
  // exclusive instead of inclusive, but there is no exclusive upper bound for
  // floats.
}
