[cfe-commits] r125714 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaExpr.cpp test/SemaCXX/member-expr.cpp

Douglas Gregor dgregor at apple.com
Wed Feb 16 22:34:41 PST 2011


On Feb 16, 2011, at 10:27 PM, Matt Beaumont-Gay wrote:

> On Wed, Feb 16, 2011 at 19:34, Douglas Gregor <dgregor at apple.com> wrote:
>> 
>> On Feb 16, 2011, at 6:54 PM, Matt Beaumont-Gay wrote:
>> 
>>> Author: matthewbg
>>> Date: Wed Feb 16 20:54:17 2011
>>> New Revision: 125714
>>> 
>>> URL: http://llvm.org/viewvc/llvm-project?rev=125714&view=rev
>>> Log:
>>> Fix PR9025 and add a diagnostic (and sometimes a fixit) for an overloaded
>>> function name used as the base of a member expression. Early feedback from
>>> Chandler Carruth, and code review from Nick Lewycky.
>> 
>> Thanks for working on this. A few comments below...
>> 
>>> Modified:
>>>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>>    cfe/trunk/lib/Sema/SemaExpr.cpp
>>>    cfe/trunk/test/SemaCXX/member-expr.cpp
>>> 
>>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=125714&r1=125713&r2=125714&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
>>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Feb 16 20:54:17 2011
>>> @@ -2364,6 +2364,11 @@
>>> def err_typecheck_member_reference_unknown : Error<
>>>   "cannot refer to member %0 in %1 with '%select{.|->}2'">;
>>> def err_member_reference_needs_call : Error<
>>> +  "base of member reference is an overloaded function; perhaps you meant "
>>> +  "to call %select{it|the 0-argument overload}0?">;
>>> +def note_member_ref_possible_intended_overload : Note<
>>> +  "possibly valid overload here">;
>>> +def err_member_reference_needs_call_zero_arg : Error<
>>>   "base of member reference has function type %0; perhaps you meant to call "
>>>   "this function with '()'?">;
>>> def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
>>> 
>>> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=125714&r1=125713&r2=125714&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb 16 20:54:17 2011
>>> @@ -3995,6 +3995,8 @@
>>> 
>>>   // There's a possible road to recovery for function types.
>>>   const FunctionType *Fun = 0;
>>> +  SourceLocation ParenInsertionLoc =
>>> +      PP.getLocForEndOfToken(BaseExpr->getLocEnd());
>>> 
>>>   if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
>>>     if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) {
>>> @@ -4029,7 +4031,53 @@
>>>   if (Fun || BaseType == Context.OverloadTy) {
>>>     bool TryCall;
>>>     if (BaseType == Context.OverloadTy) {
>>> -      TryCall = true;
>>> +      // Plunder the overload set for something that would make the member
>>> +      // expression valid.
>>> +      const OverloadExpr *Overloads = cast<OverloadExpr>(BaseExpr);
>>> +      UnresolvedSet<4> CandidateOverloads;
>>> +      bool HasZeroArgCandidateOverload = false;
>>> +      for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
>>> +           DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
>>> +        const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it);
>>> +        QualType ResultTy = OverloadDecl->getResultType();
>>> +        if ((!IsArrow && ResultTy->isRecordType()) ||
>>> +            (IsArrow && ResultTy->isPointerType() &&
>>> +             ResultTy->getPointeeType()->isRecordType())) {
>>> +          CandidateOverloads.addDecl(*it);
>>> +          if (OverloadDecl->getNumParams() == 0) {
>>> +            HasZeroArgCandidateOverload = true;
>>> +          }
>> 
>> OverloadDecl->getMinRequiredArguments() == 0 would be better here, since it accounts for parameter packs and default arguments.
> 
> Thanks, I'll submit a patch for this tomorrow.
> 
>> 
>> Overall, it would be great to pull the "find a function that we could call with ()" logic out into a subroutine, because there are probably a number of other places where we'd like to have the same kind of recovery.
> 
> Do you have any suggestions about what interface this subroutine
> should have? As a strawman: UnresolvedSet::iterator
> FindZeroArgCall(const UnresolvedSet& Candidates)

That seems reasonable. It might also be nice, if these are non-static member functions, to check that it looks like we can make the call. For example, of the object argument was "const" but the member function was non-const, we'd end up trying to form a bad call.

	- Doug



More information about the cfe-commits mailing list