[cfe-commits] r83429 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/SemaCXX/builtin-ptrtomember-overload.cpp

Douglas Gregor dgregor at apple.com
Wed Oct 7 09:01:13 PDT 2009


On Oct 6, 2009, at 4:08 PM, Fariborz Jahanian wrote:

> Author: fjahanian
> Date: Tue Oct  6 18:08:05 2009
> New Revision: 83429
>
> URL: http://llvm.org/viewvc/llvm-project?rev=83429&view=rev
> Log:
> 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).

Very nice. Some comments below.

>   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();

For both CV1 and CV2, we should get the canonical type (of *Ptr and T)  
before getting the CV qualifiers. Otherwise, we won't see qualifiers  
applied within a typedef.

> +          T = Context.getCVRQualifiedType(T, (CV1 | CV2));
> +          QualType ResultTy = Context.getLValueReferenceType(T);
> +          AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2,  
> CandidateSet);
> +        }
> +      }
> +    }
>     break;

>   case OO_Conditional:
>
> Added: cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload.cpp?rev=83429&view=auto
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload.cpp (added)
> +++ cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload.cpp Tue Oct   
> 6 18:08:05 2009
> @@ -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'}}

GCC is correct. I'm guessing it's because of this FIXME in  
BuiltinCandidateTypeSet::AddTypesConvertedFrom:

       // FIXME: Visit conversion functions in the base classes, too.

so, we're not seeing the conversion function B::operator A*() when we  
look for user-defined conversions from C.

Thanks, Fariborz!

	- Doug



More information about the cfe-commits mailing list