int getAnInt();

bool cond();

void test(unsigned x, unsigned y, bool unknown) {
	if(x - y > 0) { } // $ Alert // BAD

	unsigned total = getAnInt();
	unsigned limit = getAnInt();
	while(limit - total > 0) { // $ Alert // BAD
		total += getAnInt();
	}

	if(total <= limit) {
		while(limit - total > 0) { // GOOD
			total += getAnInt();
			if(total > limit) break;
		}
	}

	if(x >= y) {
		bool b = x - y > 0; // GOOD
	}

	if((int)(x - y) >= 0) { } // GOOD. Maybe an overflow happened, but the result is converted to the "likely intended" result before the comparison

	if(unknown) {
		y = x & 0xFF;
	} else {
		y = x;
	}
	bool b1 = x - y > 0; // GOOD

	x = getAnInt();
	y = getAnInt();
	if(y > x) {
		y = x - 1;
	}
	bool b2 = x - y > 0; // GOOD

	int N = getAnInt();
	y = x;
	while(cond()) {
		if(unknown) { y--; }
	}

	if(x - y > 0) { } // GOOD

	x = y;
	while(cond()) {
		if(unknown) break;
		y--;
	}

	if(x - y > 0) { } // GOOD

	y = 0;
	for(int i = 0; i < x; ++i) {
		if(unknown) { ++y; }
	}

	if(x - y > 0) { } // $ SPURIOUS: Alert // GOOD [FALSE POSITIVE]

	x = y;
	while(cond()) {
		if(unknown) { x++; }
	}

	if(x - y > 0) { } // GOOD

	int n = getAnInt();
	if (n > x - y) { n = x - y; }
	if (n > 0) {
  	y += n; // NOTE: `n` is at most `x - y` at this point.
  	if (x - y > 0) {} // $ SPURIOUS: Alert // GOOD [FALSE POSITIVE]
	}
}

void test2() {
	unsigned int a = getAnInt();
	unsigned int b = a;

	if (a - b > 0) { // GOOD (as a = b)
		// ...
	}
}

void test3() {
	unsigned int a = getAnInt();
	unsigned int b = a - 1;

	if (a - b > 0) { // GOOD (as a >= b)
		// ...
	}
}

void test4() {
	unsigned int a = getAnInt();
	unsigned int b = a + 1;

	if (a - b > 0) { // $ Alert // BAD
		// ...
	}
}

void test5() {
	unsigned int b = getAnInt();
	unsigned int a = b;

	if (a - b > 0) { // GOOD (as a = b)
		// ...
	}
}

void test6() {
	unsigned int b = getAnInt();
	unsigned int a = b + 1;

	if (a - b > 0) { // GOOD (as a >= b)
		// ...
	}
}

void test7() {
	unsigned int b = getAnInt();
	unsigned int a = b - 1;

	if (a - b > 0) { // $ Alert // BAD
		// ...
	}
}

void test8() {
	unsigned int a = getAnInt();
	unsigned int b = getAnInt();

	if (a - b > 0) { // $ Alert // BAD
		// ...
	}

	if (a >= b) { // GOOD
		if (a - b > 0) { // GOOD (as a >= b)
			// ...
		}
	} else {
		if (a - b > 0) { // $ Alert // BAD
			// ...
		}
	}

	if (b >= a) { // GOOD
		if (a - b > 0) { // $ Alert // BAD
			// ...
		}
	} else {
		if (a - b > 0) { // GOOD (as a > b)
			// ...
		}
	}

	while (a >= b) { // GOOD
		if (a - b > 0) { // GOOD (as a >= b)
			// ...
		}
	}

	if (a < b) return;

	if (a - b > 0) { // GOOD (as a >= b)
		// ...
	}
}

void test9() {
	unsigned int a = getAnInt();
	unsigned int b = getAnInt();

	if (a < b) {
		b = 0;
	}

	if (a - b > 0) { // $ SPURIOUS: Alert // GOOD (as a >= b) [FALSE POSITIVE]
		// ...
	}
}

void test10() {
	unsigned int a = getAnInt();
	unsigned int b = getAnInt();

	if (a < b) {
		a = b;
	}

	if (a - b > 0) { // GOOD (as a >= b)
		// ...
	}
}

void test11() {
	unsigned int a = getAnInt();
	unsigned int b = getAnInt();

	if (a < b) return;

	b = getAnInt();

	if (a - b > 0) { // $ Alert // BAD
		// ...
	}
}

void test12() {
	unsigned int a = getAnInt();
	unsigned int b = getAnInt();
	unsigned int c;

	if ((b <= c) && (c <= a)) {
		if (a - b > 0) { // GOOD (as b <= a)
			// ...
		}
	}

	if (b <= c) {
		if (c <= a) {
			if (a - b > 0) { // GOOD (as b <= a)
				// ...
			}
		}
	}
}

int test13() {
	unsigned int a = getAnInt();
	unsigned int b = getAnInt();

	if (b != 0) {
		return 0;
	} // b = 0

	return (a - b > 0); // GOOD (as b = 0)
}

int test14() {
	unsigned int a = getAnInt();
	unsigned int b = getAnInt();

	if (!b) {
		return 0;
	} // b != 0

	return (a - b > 0); // $ Alert // BAD
}

struct Numbers
{
	unsigned int a, b;
};

int test15(Numbers *n) {

	if (!n) {
		return 0;
	}

	return (n->a - n->b > 0); // $ Alert // BAD
}

int test16() {
	unsigned int a = getAnInt();
	unsigned int b = getAnInt();

	if (!b) {
		return 0;
	} else {
		return (a - b > 0); // $ Alert // BAD
	}
}

int test17() {
	unsigned int a = getAnInt();
	unsigned int b = getAnInt();

	if (b == 0) {
		return 0;
	} // b != 0

	return (a - b > 0); // $ Alert // BAD
}

int test18() {
	unsigned int a = getAnInt();
	unsigned int b = getAnInt();

	if (b) {
		return 0;
	} // b == 0

	return (a - b > 0); // GOOD (as b = 0)
}

typedef unsigned int uint32_t;
typedef long long int64_t;
uint32_t get_limit();
uint32_t get_data();

void test19() {
	// from the doc:
	uint32_t limit = get_limit();
	uint32_t total = 0;

	while (limit - total > 0) { // $ Alert // BAD: if `total` is greater than `limit` this will underflow and continue executing the loop.
		total += get_data();
	}

	while (total < limit) { // GOOD: never underflows here because there is no arithmetic.
		total += get_data();
	}

	while ((int64_t)limit - total > 0) { // GOOD: never underflows here because the result always fits in an `int64_t`.
		total += get_data();
	}
}

void test20(int a, bool b, unsigned long c)
{
  int x = 0;

  if(b) {
    x = (a - c) / 2;
  } else {
    x = a - c;
  }

  if (a - c - x > 0) // GOOD
  {
  }
}

uint32_t get_uint32();
int64_t get_int64();

void test21(unsigned long a)
{
  {
    int b = a & get_int64();
    if (a - b > 0) { } // GOOD
  }

  {
  int b = a - get_uint32();
  if(a - b > 0) { } // GOOD
  }

  {
    int64_t c = get_int64();
    if(c <= 0) {
      int64_t b = (int64_t)a + c;
      if(a - b > 0) { } // GOOD
    }
    int64_t b = (int64_t)a + c;
    if(a - b > 0) { } // $ Alert // BAD
  }

  {
    unsigned c = get_uint32();
    if(c >= 1) {
      int b = a / c;
      if(a - b > 0) { } // GOOD
    }
  }

  {
    int b = a >> get_uint32();
    if(a - b > 0) { } // GOOD
  }
}
