diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-10-06 23:08:05 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-10-06 23:08:05 +0000 |
commit | 4657a992742862639a356352c26b4e88f995b578 (patch) | |
tree | d7ecbd379b5ba67e5fcb6fde593418574500ffcc | |
parent | edee783ed3edcd7fd988b9fb1dc58361a7e8f8a0 (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.cpp | 40 | ||||
-rw-r--r-- | test/SemaCXX/builtin-ptrtomember-overload.cpp | 19 |
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; +} + |