aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-10-06 23:08:05 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-10-06 23:08:05 +0000
commit4657a992742862639a356352c26b4e88f995b578 (patch)
treed7ecbd379b5ba67e5fcb6fde593418574500ffcc
parentedee783ed3edcd7fd988b9fb1dc58361a7e8f8a0 (diff)
Patch to implement C++ [over.built]p11 of overload resolution.
Doug, please review. There is a FIXME in the test case with a question which is unrelated to this patch (that is, error is issued before set of builtins are added to the candidate list). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83429 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaOverload.cpp40
-rw-r--r--test/SemaCXX/builtin-ptrtomember-overload.cpp19
2 files changed, 58 insertions, 1 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 2ce0aabd7d..7a8c6c0b1a 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -3678,7 +3678,45 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
break;
case OO_ArrowStar:
- // FIXME: No support for pointer-to-members yet.
+ // C++ [over.built]p11:
+ // For every quintuple (C1, C2, T, CV1, CV2), where C2 is a class type,
+ // C1 is the same type as C2 or is a derived class of C2, T is an object
+ // type or a function type, and CV1 and CV2 are cv-qualifier-seqs,
+ // there exist candidate operator functions of the form
+ // CV12 T& operator->*(CV1 C1*, CV2 T C2::*);
+ // where CV12 is the union of CV1 and CV2.
+ {
+ for (BuiltinCandidateTypeSet::iterator Ptr =
+ CandidateTypes.pointer_begin();
+ Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+ QualType C1Ty = (*Ptr);
+ QualType C1;
+ if (const PointerType *PointerTy = C1Ty->getAs<PointerType>()) {
+ C1 = PointerTy->getPointeeType();
+ C1 = Context.getCanonicalType(C1).getUnqualifiedType();
+ if (!isa<RecordType>(C1))
+ continue;
+ }
+ for (BuiltinCandidateTypeSet::iterator
+ MemPtr = CandidateTypes.member_pointer_begin(),
+ MemPtrEnd = CandidateTypes.member_pointer_end();
+ MemPtr != MemPtrEnd; ++MemPtr) {
+ const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr);
+ QualType C2 = QualType(mptr->getClass(), 0);
+ C2 = Context.getCanonicalType(C2).getUnqualifiedType();
+ if (C1 != C2 && !IsDerivedFrom(C1, C2))
+ break;
+ QualType ParamTypes[2] = { *Ptr, *MemPtr };
+ // build CV12 T&
+ QualType T = mptr->getPointeeType();
+ unsigned CV1 = (*Ptr).getCVRQualifiers();
+ unsigned CV2 = T.getCVRQualifiers();
+ T = Context.getCVRQualifiedType(T, (CV1 | CV2));
+ QualType ResultTy = Context.getLValueReferenceType(T);
+ AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+ }
+ }
+ }
break;
case OO_Conditional:
diff --git a/test/SemaCXX/builtin-ptrtomember-overload.cpp b/test/SemaCXX/builtin-ptrtomember-overload.cpp
new file mode 100644
index 0000000000..8c6fb39735
--- /dev/null
+++ b/test/SemaCXX/builtin-ptrtomember-overload.cpp
@@ -0,0 +1,19 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+
+struct A {};
+
+struct B {
+ operator A*();
+};
+
+struct C : B {
+
+};
+
+
+void foo(C c, B b, int A::* pmf) {
+ // FIXME. Bug or correct? gcc accepts it. It requires derived-to-base followed by user defined conversion to work.
+ int j = c->*pmf; // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct C'}}
+ int i = b->*pmf;
+}
+