// RUN: %clang_cc1 -std=c++0x -analyze -analyzer-checker=core -analyzer-inline-call -analyzer-store region -verify %s

// test to see if nullptr is detected as a null pointer
void foo1(void) {
  char  *np = nullptr;
  *np = 0;  // expected-warning{{Dereference of null pointer}}
}

// check if comparing nullptr to nullptr is detected properly
void foo2(void) {
  char *np1 = nullptr;
  char *np2 = np1;
  char c;
  if (np1 == np2)
    np1 = &c;
  *np1 = 0;  // no-warning
}

// invoving a nullptr in a more complex operation should be cause a warning
void foo3(void) {
  struct foo {
    int a, f;
  };
  char *np = nullptr;
  // casting a nullptr to anything should be caught eventually
  int *ip = &(((struct foo *)np)->f);
  *ip = 0;  // expected-warning{{Dereference of null pointer}}
  // should be error here too, but analysis gets stopped
//  *np = 0;
}

#ifdef TEST_THIS
// check to determine if the correct function is picked
// which was the whole point of the nullptr to begin with
// FIXME: disabled for now until inline-call works again
struct A {
  int x;
  A(int a) { x = a; }
  A(int *ip) { x = 1; }
  int getx() const { return x; }
};

void f1() {
  A x((int *)0);
  if (x.getx() == 0) {
    int *p = 0;
    *p = 3;  // warning
  } else {
    int *p = 0;
    *p = 3;  // no-warning
  }
}

void f2() {
  A x(nullptr);
  if (x.getx() == 1) {
    int *p = 0;
    *p = 3;  // warning
  } else {
    int *p = 0;
    *p = 3;  // no-warning
  }
}
#endif

