// RUN: %clang_analyze_cc1 -verify %s -analyzer-checker=core

// This file tests ExprEngine::processSwitch.

int switch_simple(int x) {
  // Validate that switch behaves as expected in a very simple situation.
  switch (x) {
    case 1:
      return 13 / x;
    case 0:
      return 14 / x; // expected-warning {{Division by zero}}
    case 2:
      return 15 / x;
    default:
      return 67 / (x - x); // expected-warning {{Division by zero}}
  }
}

int switch_default(int x) {
  // Validate that the default case is evaluated after excluding the other
  // cases -- even if it appears first.
  if (x > 2 || x < 0)
    return 0;
  switch (x) {
    default:
      return 16 / x; // expected-warning {{Division by zero}}
    case 1:
      return 13 / x;
    case 2:
      return 15 / x;
  }
}

int switch_unreachable_default(int x) {
  // Validate that the default case is not evaluated if it is infeasible.
  int zero = 0;
  if (x > 2 || x < 0)
    return 0;
  switch (x) {
    default:
      return 16 / zero; // no-warning
    case 0:
      return 456;
    case 1:
      return 13 / x;
    case 2:
      return 15 / x;
  }
}

enum Color {Red, Green, Blue};

int switch_all_enum_cases_covered(enum Color x) {
  // Validate that the default case is not evaluated if the switch is over an
  // enum value and all enumerators appear as 'case's.
  int zero = 0;
  switch (x) {
    default:
      return 16 / zero; // no-warning
    case Red:
    case Green:
      return 2;
    case Blue:
      return 3;
  }
}

int switch_all_feasible_enum_cases_covered(enum Color x) {
  // Highlight a shortcoming of enum/switch handling: here the 'case's cover
  // all the enumerators that could appear in the symbolic value 'x', but the
  // default is still executed.
  // FIXME: The default branch shouldn't be executed here.
  int zero = 0;

  if (x == Red)
    return 1;
  switch (x) {
    default:
      return 16 / zero; // expected-warning {{Division by zero}}
    case Green:
      return 2;
    case Blue:
      return 3;
  }
}

int switch_no_compound_stmt(int x) {
  // Validate that the engine can follow the switch statement even if there is
  // no compound statement around the cases. (Yes, this is valid, although
  // not very practical.)
  switch (x) case 1: case 0: return 16 / x; // expected-warning {{Division by zero}}

  return 0;
}

void switch_empty(int x) {
  // Validate that the engine does not crash on these empty switches.
  // (These are pretty useless, but the analyzer should still handle them.)

  switch (x) {}

  switch (x)
    ;
}

int switch_with_case_range(int x) {
  // Validate that the GNU case range extension is properly handled.
  switch (x) {
    case 5:
      return 55 / x;
    case 2 ... 4:
      return 3;
    case 0 ... 1:
      return 44 / x; // no-warning: there is no state split between 0 and 1
    default:
      if (x)
        return 8;
      return 45 / x; // no-warning: x cannot be 0 on the default branch
  }
}
