text: // RUN: %clang_cc1 -std=c++1z -verify %s
  // RUN: %clang_cc1 -std=c++1z -verify %s -DUNDEFINED
  
  #ifdef UNDEFINED
  // "used but not defined" errors don't get produced if we have more interesting
  // errors.
  namespace std_example {
    template <typename T, typename... Rest> void g(T &&p, Rest &&... rs) {
      // use p
      if constexpr(sizeof...(rs) > 0)
        g(rs...);
    }
    void use_g() {
      g(1, 2, 3);
    }
  
    static int x(); // no definition of x required
    int f() {
      if constexpr (true)
        return 0;
      else if (x())
        return x();
      else
        return -x();
    }
  }
  
  namespace odr_use_in_selected_arm {
    static int x(); // expected-warning {{is not defined}}
    int f() {
      if constexpr (false)
        return 0;
      else if (x()) // expected-note {{here}}
        return x();
      else
        return -x();
    }
  }
  #else
  namespace ccce {
    void f() {
      if (5) {}
      if constexpr (5) {} // expected-error {{cannot be narrowed}}
    }
    template<int N> void g() {
      if constexpr (N) {} // expected-error {{cannot be narrowed}}
    }
    template void g<5>(); // expected-note {{instantiation of}}
    void h() {
      if constexpr (4.3) {} // expected-error{{conversion from 'double' to 'bool' is not allowed in a converted constant expression}}
      constexpr void *p = nullptr;
      if constexpr (p) {} // expected-error{{conversion from 'void *const' to 'bool' is not allowed in a converted constant expression}}
    }
  }
  
  namespace generic_lambda {
    // Substituting for T produces a hard error here, even if substituting for
    // the type of x would remove the error.
    template<typename T> void f() {
      [](auto x) {
        if constexpr (sizeof(T) == 1 && sizeof(x) == 1)
          T::error(); // expected-error 2{{'::'}}
      } (0);
    }
  
    template<typename T> void g() {
      [](auto x) {
        if constexpr (sizeof(T) == 1)
          if constexpr (sizeof(x) == 1)
            T::error(); // expected-error {{'::'}}
      } (0);
    }
  
    void use() {
      f<int>(); // expected-note {{instantiation of}}
      f<char>(); // expected-note {{instantiation of}}
      g<int>(); // ok
      g<char>(); // expected-note {{instantiation of}}
    }
  }
  
  namespace potentially_discarded_branch_target {
    void in_switch(int n) {
      switch (n)
        case 4: if constexpr(sizeof(n) == 4) return;
      if constexpr(sizeof(n) == 4)
        switch (n) case 4: return;
      switch (n) {
        if constexpr (sizeof(n) == 4) // expected-note 2{{constexpr if}}
          case 4: return; // expected-error {{cannot jump}}
        else
          default: break; // expected-error {{cannot jump}}
      }
    }
  
    template<typename T>
    void in_switch_tmpl(int n) {
      switch (n) {
        if constexpr (sizeof(T) == 4) // expected-note 2{{constexpr if}}
          case 4: return; // expected-error {{cannot jump}}
        else
          default: break; // expected-error {{cannot jump}}
      }
    }
  
    void goto_scope(int n) {
      goto foo; // expected-error {{cannot jump}}
      if constexpr(sizeof(n) == 4) // expected-note {{constexpr if}}
        foo: return;
  bar:
      if constexpr(sizeof(n) == 4)
        goto bar; // ok
    }
  
    template<typename T>
    void goto_scope(int n) {
      goto foo; // expected-error {{cannot jump}}
      if constexpr(sizeof(n) == 4) // expected-note {{constexpr if}}
        foo: return;
  bar:
      if constexpr(sizeof(n) == 4)
        goto bar; // ok
    }
  
    void goto_redef(int n) {
  a:  if constexpr(sizeof(n) == 4) // expected-error {{redefinition}} expected-note {{constexpr if}}
        a: goto a; // expected-note 2{{previous}}
      else
        a: goto a; // expected-error {{redefinition}} expected-error {{cannot jump}}
    }
  
    void evil_things() {
      goto evil_label; // expected-error {{cannot jump}}
      if constexpr (true || ({evil_label: false;})) {} // expected-note {{constexpr if}}
  
      if constexpr (true) // expected-note {{constexpr if}}
        goto surprise; // expected-error {{cannot jump}}
      else
        surprise: {}
    }
  }
  #endif
  