Implement support for equality comparisons (!=, ==) of member
pointers, by extending the "composite pointer type" logic to include
member pointer types.

Introduce test cases for member pointer comparisons, including those
that involve the builtin operator candidates implemented earlier. 


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79925 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/SemaCXX/composite-pointer-type.cpp b/test/SemaCXX/composite-pointer-type.cpp
index b4a5c88..ebc40c1 100644
--- a/test/SemaCXX/composite-pointer-type.cpp
+++ b/test/SemaCXX/composite-pointer-type.cpp
@@ -25,3 +25,11 @@
   if (d1 == d2) // expected-error{{comparison of distinct}}
     return;
 }
+
+// PR4691
+int ptrcmp1(void *a, int *b) {
+  return a < b;
+}
+int ptrcmp2(long *a, int *b) {
+  return a < b; // expected-error{{distinct}}
+}
\ No newline at end of file
diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp
index 3f4d715..65fbd83 100644
--- a/test/SemaCXX/conditional-expr.cpp
+++ b/test/SemaCXX/conditional-expr.cpp
@@ -170,7 +170,7 @@
     i1 ? &MixedFields::ci : &MixedFieldsDerived::i;
   const volatile int (MixedFields::*mp2) =
     i1 ? &MixedFields::ci : &MixedFields::cvi;
-  i1 ? &MixedFields::ci : &MixedFields::vi; // expected-error {{incompatible operand types}}
+  (void)(i1 ? &MixedFields::ci : &MixedFields::vi);
   // Conversion of primitives does not result in an lvalue.
   &(i1 ? i1 : d1); // expected-error {{address expression must be an lvalue or a function designator}}
 
diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp
index 3b106d5..9e407a1 100644
--- a/test/SemaCXX/member-pointer.cpp
+++ b/test/SemaCXX/member-pointer.cpp
@@ -40,6 +40,14 @@
 
   // Conversion to member of base.
   pdi1 = pdid; // expected-error {{incompatible type assigning 'int struct D::*', expected 'int struct A::*'}}
+  
+  // Comparisons
+  int (A::*pf2)(int, int);
+  int (D::*pf3)(int, int) = 0;
+  bool b1 = (pf == pf2); (void)b1;
+  bool b2 = (pf != pf2); (void)b2;
+  bool b3 = (pf == pf3); (void)b3;
+  bool b4 = (pf != 0); (void)b4;
 }
 
 struct TheBase
diff --git a/test/SemaCXX/overloaded-builtin-operators.cpp b/test/SemaCXX/overloaded-builtin-operators.cpp
index 2a6c24a..a8c94f1 100644
--- a/test/SemaCXX/overloaded-builtin-operators.cpp
+++ b/test/SemaCXX/overloaded-builtin-operators.cpp
@@ -20,11 +20,21 @@
   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) {
+void f(Short s, Long l, Enum1 e1, Enum2 e2, Xpmf pmf) {
   // C++ [over.built]p8
   int i1 = +e1;
   int i2 = -e2;
@@ -37,6 +47,10 @@
   (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));
@@ -53,7 +67,15 @@
   operator volatile long&();
 };
 
-void g(ShortRef sr, LongRef lr) {
+struct XpmfRef {
+  operator pmf&();
+};
+
+struct E2Ref {
+  operator E2&();
+};
+
+void g(ShortRef sr, LongRef lr, E2Ref e2_ref, XpmfRef pmf_ref) {
   // C++ [over.built]p3
   short s1 = sr++;
 
@@ -64,6 +86,14 @@
   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);