[cfe-commits] [patch] Better diagnostics in for-range expressions.

Sam Panzer panzer at google.com
Mon Aug 20 17:54:09 PDT 2012


Fixed, and finally committed as r162248.


On Mon, Aug 20, 2012 at 4:37 PM, Richard Smith <richard at metafoo.co.uk>wrote:

> Couple of tiny things, then LGTM:
>
> +    *CallExpr = FinishOverloadedCallExpr(*this, S, Fn, Fn, Loc, &Range, 1,
> +                                         Loc, 0, CandidateSet, &Best,
> +                                         OverloadResult,
> +                                         /*AllowTypoCorrection=*/false);
> +    if (CallExpr->isInvalid() || OverloadResult == OR_Deleted) {
>
> The second condition would be clearer as OverloadResult != OR_Success.
>
> +      ForRangeStatus RangeStatus =
> +          BuildNonArrayForRange(*this, S, BeginRangeRef.get(),
> +                                EndRangeRef.get(), RangeType,
> +                                BeginVar, EndVar, ColonLoc, &CandidateSet,
> +                                &BeginExpr, &EndExpr, &BEFFailure);
> +
> +      // If building the range failed, try dereferencing the range
> expression
> +      // unless a diagnostic was issued or the end function is
> problematic.
> +      if (RangeStatus != FRS_Success) {
>
> This 'if' is now redundant; all the code within it is conditioned within
> 'if (RangeStatus == FRS_NoViableFunction)'. I suggest you change this to
> check for FRS_NoViableFunction and remove the newly-redundant inner checks.
>
> On Mon, Aug 20, 2012 at 3:43 PM, Sam Panzer <panzer at google.com> wrote:
>
>> New patch is ~10% smaller!
>>
>>
>> On Thu, Aug 16, 2012 at 3:14 PM, Richard Smith <richard at metafoo.co.uk>wrote:
>>
>>> On Thu, Aug 16, 2012 at 2:56 PM, Sam Panzer <panzer at google.com> wrote:
>>>
>>>> Here's the next update for this patch.
>>>>
>>>>
>>>> On Wed, Aug 15, 2012 at 4:29 PM, Richard Smith <richard at metafoo.co.uk>wrote:
>>>>
>>> [...]
>>>
>>>>  > +  if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) {
>>>>
>>>> > +    // - if _RangeT is a class type, the unqualified-ids begin and
>>>>> end are
>>>>> > +    //   looked up in the scope of class _RangeT as if by class
>>>>> member access
>>>>> > +    //   lookup (3.4.5), and if either (or both) finds at least one
>>>>> > +    //   declaration, begin-expr and end-expr are __range.begin()
>>>>> and
>>>>> > +    //   __range.end(), respectively;
>>>>> > +    SemaRef.LookupQualifiedName(BeginMemberLookup, D);
>>>>> > +    SemaRef.LookupQualifiedName(EndMemberLookup, D);
>>>>> > +
>>>>> > +    if (BeginMemberLookup.empty() != EndMemberLookup.empty()) {
>>>>> > +      *BEF = BeginMemberLookup.empty() ? Sema::BEF_end :
>>>>> Sema::BEF_begin;
>>>>> > +      return Sema::FRS_BeginEndMismatch;
>>>>>
>>>>> Can you just issue the diagnostic directly here? I don't think we
>>>>> should attempt recovery in this case. (My "If there's a viable begin() but
>>>>> lookup for end() fails" comment was intended to apply to this case too.)
>>>>>
>>>>>
>>>> Yes, though this means that I have two "diagnostic emitted" error
>>>> codes: one which needs the type and which of begin/end failed to be noted,
>>>> and a second which needs no extra diagnostics.
>>>>
>>>
>>> I think previously I suggested that you should emit note_for_range_type
>>> directly in BuildForRangeBeginEndCall; that still seems like the best way
>>> to address this. I would also suggest that you don't emit the note in the
>>> case where FinishForRangeVarDecl fails, since in that case we've already
>>> emitted a diagnostic explaining what we're doing.
>>>
>>>
>>
>> This wasn't possible before introducing SFINAETrap, though it simplifies
>> the code now as you suggest. After a little adjusting, I moved
>> NoteForRangeBeginEndFunction and FinishForRangeVarDecl back out of Sema.
>>
>>
>>
>>>  > +    }
>>>>> > +  } else {
>>>>> > +    // - otherwise, begin-expr and end-expr are begin(__range) and
>>>>> > +    //   end(__range), respectively, where begin and end are looked
>>>>> up with
>>>>> > +    //   argument-dependent lookup (3.4.2). For the purposes of
>>>>> this name
>>>>> > +    //   lookup, namespace std is an associated namespace.
>>>>> > +
>>>>> > +  }
>>>>> > +
>>>>>  > +  *BEF = Sema::BEF_begin;
>>>>> > +  Sema::ForRangeStatus RangeStatus =
>>>>> > +      SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc,
>>>>> BeginVar,
>>>>> > +                                        Sema::BEF_begin,
>>>>> BeginNameInfo,
>>>>> > +                                        BeginMemberLookup,
>>>>> CandidateSet,
>>>>> > +                                        BeginRange, BeginExpr);
>>>>> > +  if (RangeStatus != Sema::FRS_Success)
>>>>> > +    return RangeStatus;
>>>>> > +
>>>>> > +  *BEF = Sema::BEF_end;
>>>>> > +  RangeStatus =
>>>>> > +      SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc,
>>>>> EndVar,
>>>>> > +                                        Sema::BEF_end, EndNameInfo,
>>>>> > +                                        EndMemberLookup,
>>>>> CandidateSet,
>>>>> > +                                        EndRange, EndExpr);
>>>>> > +  return RangeStatus;
>>>>> > +}
>>>>> > +
>>>>> > +/// Speculatively attempt to dereference an invalid range
>>>>> expression.
>>>>> > +/// This function will not emit diagnostics, but returns StmtError
>>>>> if
>>>>> > +/// an error occurs.
>>>>> > +static StmtResult RetryWithDereferencedRange(Sema &SemaRef, Scope
>>>>> *S,
>>>>>
>>>>> Please include something about ForRange in this function name.
>>>>>
>>>>
>>>> How about RebuildForRangeWithDereference?
>>>>
>>>
>>> SGTM
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120820/3cae9bfd/attachment.html>


More information about the cfe-commits mailing list