text: // RUN: %clang_cc1 -fsyntax-only -fshow-overloads=best -verify -triple x86_64-linux-gnu %s
  // RUN: %clang_cc1 -fsyntax-only -fshow-overloads=best -verify -triple x86_64-linux-gnu -std=c++98 %s
  // RUN: %clang_cc1 -fsyntax-only -fshow-overloads=best -verify -triple x86_64-linux-gnu -std=c++11 %s
  
  struct yes;
  struct no;
  
  struct Short {
    operator short();
  };
  
  struct Long {
    operator long();
  };
  
  enum E1 { };
  struct Enum1 {
    operator E1();
  };
  
  enum E2 { };
  struct Enum2 {
    operator E2();
  };
  
  
  struct X { 
    void f();
  };
  
  typedef void (X::*pmf)();
  struct Xpmf {
    operator pmf();
  };
  
  yes& islong(long);
  yes& islong(unsigned long); // FIXME: shouldn't be needed
  no& islong(int);
  
  void f(Short s, Long l, Enum1 e1, Enum2 e2, Xpmf pmf) {
    // C++ [over.built]p8
    int i1 = +e1;
    int i2 = -e2;
  
    // C++  [over.built]p10:
    int i3 = ~s;
    bool b1 = !s;
  
    // C++ [over.built]p12
    (void)static_cast<yes&>(islong(s + l));
    (void)static_cast<no&>(islong(s + s));
  
    // C++ [over.built]p16
    (void)(pmf == &X::f);
    (void)(pmf == 0);
    
    // C++ [over.built]p17
    (void)static_cast<yes&>(islong(s % l));
    (void)static_cast<yes&>(islong(l << s));
    (void)static_cast<no&>(islong(s << l));
    (void)static_cast<yes&>(islong(e1 % l));
    // FIXME: should pass (void)static_cast<no&>(islong(e1 % e2));
  }
  
  struct BoolRef {
    operator bool&();
  };
  
  struct ShortRef { // expected-note{{candidate function (the implicit copy assignment operator) not viable}}
  #if __cplusplus >= 201103L // C++11 or later
  // expected-note@-2 {{candidate function (the implicit move assignment operator) not viable}}
  #endif
    operator short&();
  };
  
  struct LongRef {
    operator volatile long&();
  };
  
  struct FloatRef {
    operator float&();
  };
  
  struct XpmfRef { // expected-note{{candidate function (the implicit copy assignment operator) not viable}}
  #if __cplusplus >= 201103L // C++11 or later
  // expected-note@-2 {{candidate function (the implicit move assignment operator) not viable}}
  #endif
    operator pmf&();
  };
  
  struct E2Ref {
    operator E2&();
  };
  
  void g(BoolRef br, ShortRef sr, LongRef lr, FloatRef fr, E2Ref e2_ref, XpmfRef pmf_ref) {
    // C++ [over.built]p3
    short s1 = sr++;
  
    // C++ [over.built]p4
    long l1 = lr--;
  
    // C++ [over.built]p4
    float f1 = fr--;
  
    // C++ [over.built]p4
    bool b2 = br--; // expected-error{{cannot decrement value of type 'BoolRef'}}
  
    // C++ [over.built]p18
    short& sr1 = (sr *= lr);
    volatile long& lr1 = (lr *= sr);
  
    // C++ [over.built]p20:
    E2 e2r2;
    e2r2 = e2_ref;
    
    pmf &pmr = (pmf_ref = &X::f); // expected-error{{no viable overloaded '='}}
    pmf pmr2;
    pmr2 = pmf_ref;
                 
    // C++ [over.built]p22
    short& sr2 = (sr %= lr);
    volatile long& lr2 = (lr <<= sr);
  
    bool b1 = (sr && lr) || (sr || lr);
  }
  
  struct VolatileIntPtr {
    operator int volatile *();
  };
  
  struct ConstIntPtr {
    operator int const *();
  };
  
  struct VolatileIntPtrRef {
    operator int volatile *&();
  };
  
  struct ConstIntPtrRef {
    operator int const *&();
  };
  
  void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip, ShortRef sr,
                      VolatileIntPtrRef vipr, ConstIntPtrRef cipr) {
    const int& cir1 = cip[sr];
    const int& cir2 = sr[cip];
    volatile int& vir1 = vip[sr];
    volatile int& vir2 = sr[vip];
    bool b1 = (vip == cip);
    long p1 = vip - cip;
  
    // C++ [over.built]p5:
    int volatile *vip1 = vipr++;
    int const *cip1 = cipr++;
    int volatile *&vipr1 = ++vipr;
    int const *&cipr1 = --cipr;
  
    // C++ [over.built]p6:
    int volatile &ivr = *vip;
  
    // C++ [over.built]p8:
    int volatile *vip2 = +vip;
    int i1 = +sr;
    int i2 = -sr;
  
    // C++ [over.built]p13:
    int volatile &ivr2 = vip[17];
    int const &icr2 = 17[cip];
  }
  
  // C++ [over.match.open]p4
  
  void test_assign_restrictions(ShortRef& sr) {
    sr = (short)0; // expected-error{{no viable overloaded '='}}
  }
  
  struct Base { };
  struct Derived1 : Base { };
  struct Derived2 : Base { };
  
  template<typename T>
  struct ConvertibleToPtrOf {
    operator T*();
  };
  
  bool test_with_base_ptrs(ConvertibleToPtrOf<Derived1> d1, 
                           ConvertibleToPtrOf<Derived2> d2) {
    return d1 == d2; // expected-error{{invalid operands}}
  }
  
  // DR425
  struct A {
    template< typename T > operator T() const;
  };
  
  void test_dr425(A a) {
    (void)(1.0f * a); // expected-error{{ambiguous}} \
                      // expected-note 4{{candidate}} \
                      // expected-note {{remaining 8 candidates omitted; pass -fshow-overloads=all to show them}}
  }
  
  // pr5432
  enum e {X};
  
  const int a[][2] = {{1}};
  
  int test_pr5432() {
    return a[X][X];
  }
  
  void f() {
    (void)__extension__(A());
  }
  
  namespace PR7319 {
    typedef enum { Enum1, Enum2, Enum3 } MyEnum;
  
    template<typename X> bool operator>(const X &inX1, const X &inX2);
  
    void f() {
      MyEnum e1, e2;
      if (e1 > e2) {}
    }
  }
  
  namespace PR8477 {
    struct Foo {
      operator bool();
      operator const char *();
    };
  
    bool doit() {
      Foo foo;
      long long zero = 0;
      (void)(foo + zero);
      (void)(foo - zero);
      (void)(zero + foo);
      (void)(zero[foo]);
      // FIXME: It would be nice to report fewer candidates here.
      (void)(foo - foo); // expected-error{{use of overloaded operator '-' is ambiguous}} \
      // expected-note 4{{built-in candidate operator-}} \
      // expected-note{{142 candidates omitted}}
      return foo[zero] == zero;
    }
  }
  
  namespace PR7851 {
    struct X {
      operator const void *() const;
      operator void *();
  
      operator const unsigned *() const;
      operator unsigned *();
    };
  
    void f() {
      X x;
      x[0] = 1;
      *x = 0;
      (void)(x - x);
    }
  }
  
  namespace PR12854 {
    enum { size = 1 };
    void plus_equals() {
      int* __restrict py;
      py += size;
    }
  
    struct RestrictInt {
      operator int* __restrict &();
    };
  
    void user_conversions(RestrictInt ri) {
      ++ri;
      --ri;
      ri++;
      ri--;
    }
  }
  
  namespace PR12964 {
    struct X { operator  __int128() const; } x;
    bool a = x == __int128(0);
    bool b = x == 0;
  
    struct Y { operator unsigned __int128() const; } y;
    bool c = y == __int128(0);
    bool d = y == 0;
  
    bool e = x == y;
  }
  