On Tue, Sep 18, 2012 at 10:23 AM, Argyrios Kyrtzidis <span dir="ltr"><<a href="mailto:kyrtzidis@apple.com" target="_blank">kyrtzidis@apple.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div style="word-wrap:break-word"><div><div><div><div>On Sep 17, 2012, at 4:50 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>> wrote:</div><br><blockquote type="cite">

On Mon, Sep 17, 2012 at 4:04 PM, James Dennett <span dir="ltr"><<a href="mailto:jdennett@google.com" target="_blank">jdennett@google.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">


<div><div>On Mon, Sep 17, 2012 at 3:04 PM, Argyrios Kyrtzidis <<a href="mailto:kyrtzidis@apple.com" target="_blank">kyrtzidis@apple.com</a>> wrote:<br>
><br>
> On Sep 17, 2012, at 2:38 PM, James Dennett <<a href="mailto:jdennett@googlers.com" target="_blank">jdennett@googlers.com</a>> wrote:<br>
><br>
>> On Mon, Sep 17, 2012 at 2:22 PM, Argyrios Kyrtzidis <<a href="mailto:kyrtzidis@apple.com" target="_blank">kyrtzidis@apple.com</a>> wrote:<br>
>>> On Sep 17, 2012, at 12:44 PM, James Dennett <<a href="mailto:jdennett@googlers.com" target="_blank">jdennett@googlers.com</a>> wrote:<br>
>>><br>
>>>> On Mon, Sep 10, 2012 at 7:17 PM, Argyrios Kyrtzidis <<a href="mailto:akyrtzi@gmail.com" target="_blank">akyrtzi@gmail.com</a>> wrote:<br>
>>>>> Author: akirtzidis<br>
>>>>> Date: Mon Sep 10 21:17:21 2012<br>
>>>>> New Revision: 163588<br>
>>>>><br>
>>>>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=163588&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=163588&view=rev</a><br>
>>>>> Log:<br>
>>>>> [libclang] Fix getting a cursor inside an angled #include directive.<br>
>>>>><br>
>>>>> Fixed by pointing the end location of the preprocessed entity for the #include<br>
>>>>> at the closing '>', instead of the start of '<'.<br>
>>>>><br>
>>>>> <a>rdar://11113134</a><br>
>>>>><br>
>>>>> Modified:<br>
>>>>>   cfe/trunk/lib/Lex/PPDirectives.cpp<br>
>>>>>   cfe/trunk/test/Index/c-index-getCursor-pp.c<br>
>>>>><br>
>>>>> Modified: cfe/trunk/lib/Lex/PPDirectives.cpp<br>
>>>>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=163588&r1=163587&r2=163588&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=163588&r1=163587&r2=163588&view=diff</a><br>



>>>>> ==============================================================================<br>
>>>>> --- cfe/trunk/lib/Lex/PPDirectives.cpp (original)<br>
>>>>> +++ cfe/trunk/lib/Lex/PPDirectives.cpp Mon Sep 10 21:17:21 2012<br>
>>>>> @@ -1296,6 +1296,9 @@<br>
>>>>>  case tok::string_literal:<br>
>>>>>    Filename = getSpelling(FilenameTok, FilenameBuffer);<br>
>>>>>    End = FilenameTok.getLocation();<br>
>>>>> +    // For an angled include, point the end location at the closing '>'.<br>
>>>>> +    if (<a href="http://FilenameTok.is" target="_blank">FilenameTok.is</a>(tok::angle_string_literal))<br>
>>>>> +      End = End.getLocWithOffset(Filename.size()-1);<br>
>>>>>    CharEnd = End.getLocWithOffset(Filename.size());<br>
>>>>>    break;<br>
>>>>><br>
>>>>><br>
>>>>> Modified: cfe/trunk/test/Index/c-index-getCursor-pp.c<br>
>>>>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/c-index-getCursor-pp.c?rev=163588&r1=163587&r2=163588&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/c-index-getCursor-pp.c?rev=163588&r1=163587&r2=163588&view=diff</a><br>



>>>>> ==============================================================================<br>
>>>>> --- cfe/trunk/test/Index/c-index-getCursor-pp.c (original)<br>
>>>>> +++ cfe/trunk/test/Index/c-index-getCursor-pp.c Mon Sep 10 21:17:21 2012<br>
>>>>> @@ -15,6 +15,8 @@<br>
>>>>><br>
>>>>> const char *fname = __FILE__;<br>
>>>>><br>
>>>>> +#include <a.h><br>
>>>>> +<br>
>>>>> // RUN: c-index-test -cursor-at=%s:1:11 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-1 %s<br>
>>>>> // CHECK-1: macro definition=OBSCURE<br>
>>>>> // RUN: c-index-test -cursor-at=%s:2:14 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-2 %s<br>
>>>>> @@ -31,6 +33,8 @@<br>
>>>>> // CHECK-7: macro expansion=B:12:9<br>
>>>>> // RUN: c-index-test -cursor-at=%s:16:25 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-8 %s<br>
>>>>> // CHECK-8: macro expansion=__FILE__<br>
>>>>> +// RUN: c-index-test -cursor-at=%s:18:12 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-9 %s<br>
>>>>> +// CHECK-9: inclusion directive=a.h<br>
>>>>><br>
>>>>> // Same tests, but with "editing" optimizations<br>
>>>>> // RUN: env CINDEXTEST_EDITING=1 c-index-test -cursor-at=%s:1:11 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-1 %s<br>
>>>><br>
>>>> This change broke clients that implement<br>
>>>> PPCallbacks::InclusionDirective, which now receive the location of the<br>
>>>> closing '>' rather than the location of the token that they're<br>
>>>> expecting based on the spec:<br>
>>>> /// \param EndLoc The location of the last token within the<br>
>>>> inclusion<br>
>>>> /// directive.<br>
>>>> The last (preprocessing) token is the whole of <filename>, of type<br>
>>>> tok::angle_string_literal.<br>
>>>><br>
>>>> Could we consider reverting this change and finding an alternative way<br>
>>>> to fix libclang without breaking/changing the lower-level interface?<br>
>>><br>
>>> Hi James,<br>
>>><br>
>>> This is not a high-level libclang issue.<br>
>><br>
>> Apologies, I was going by the change description "[libclang] Fix<br>
>> getting a cursor inside an angled #include directive.", and that the<br>
>> only tests I saw included were for libclang.  (That does suggests that<br>
>> we're missing tests for this in the appropriate place.)<br>
><br>
> You're right, a preprocessing record unit test is also needed.<br>
><br>
>><br>
>>> The preprocessing record needs to know the '>' location and depends on the PPCallbacks::InclusionDirective callback. Previously this callback did not provide a way to reliably get at that location.<br>



>><br>
>> I'm not sure about that -- it provided a way to get there, but it was<br>
>> necessary to skip over the filename.<br>
><br>
> If the include filename was formed via a macro expansion then you had an EndLoc pointing at '>'. So this was the situation:<br>
><br>
> No macro expansions involved: EndLoc points at '<'<br>
> With macro expansion: EndLoc points at '>'.<br>
><br>
> The receiver had no easy way to know which case it was. With the change it always pointed at '>'.<br>
<br>
</div></div>Checking which character is at the EndLoc isn't so hard, but I take your point.<br>
<div><br>
>> With your change a similar trick<br>
>> is required for code wanting to get to the filename, but only for<br>
>> #include <filename>, not for #include "filename".  (Why are the two<br>
>> cases different?  Currently the callback returns the location of the<br>
>> opening quote for the #include "name" case, and the closing one for<br>
>> #include <name>.  The asymmetry seems strange.)<br>
><br>
> There's an asymmetry due to how lexing would behave if you pointed at the beginning of the filename, for example:<br>
><br>
> #include "filename"<br>
> If you point at the opening quote and start lexing you will get the tok::string_literal token, the same that the preprocessor saw. Then you can get at the character range of the whole filename input by checking the token size.<br>



><br>
> #include <filename><br>
> if you point at the opening '<' and start lexing you will get a tok::less token, you need to get into the special "parsing include directive" mode to receive a tok::angle_string_literal token.<br>



> So just pointing at '<' will not allow you to easily lex and get the character range of the filename input.<br>
<br>
</div>I was assuming that you'd lex correctly, which means being in the<br>
right mode to lex an include directive in this case.  I don't think it<br>
matters that if you lex incorrectly that you'll get the wrong results.<br>
<div><br>
>>> I believe we still need to modify the bahavior of the InclusionDirective callback and focus the discussion there.<br>
>>><br>
>>> How about reverting the EndLoc adjustment but have the InclusionDirective also pass the FilenameTok token so that receivers of the callback can have more information for the inclusion directive (then the preprocessing record can do the adjustment itself).<br>



>><br>
>> That sounds good to me -- though I'm not sure if we need to pass<br>
>> EndLoc if we pass the FilenameTok (possibly for cases where the<br>
>> filename comes from macro expansion? I'm not all that familiar with<br>
>> this code).<br>
><br>
> Yes, the EndLoc is necessary because if there are macro expansions involved then the FilenameTok token will be a tok::less for '<'.<br>
<br>
</div>This is going to be "fun" to document thoroughly enough for clients to<br>
be written based on the spec alone -- but then the quirky lexing rules<br>
for this context are what they are, and Clang can't (and shouldn't)<br>
completely hide them.</blockquote><div><br></div><div>In terms of getting something which is easy to explain, how about we pass FilenameTok, as described above, and we also pass the location of the terminating > or " *character* as EndLoc? Would that cover all the use cases?</div>

</div></blockquote><div><br></div></div></div><div>Not sure about pointing at the character, pointing at '>' is pointing at something that can be lexed raw as a token, while pointing at the ending quote is not.</div>

</div></div></blockquote><div><br></div><div>You can't lex the ending character as a token in the angle_string_literal case either. For instance, we accept (with a warning):</div><div><div><br></div><div>#include <iostream>></div>
<div><br></div><div>If you try to lex the '>' as a token, you'll get '>>'. But I don't see why it would be useful to lex from that position, so I don't think this matters.</div></div><div>
 </div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div>How about a minor change to your suggestion and pass the end location of the directive character range (just after the > or "); this is already calculated as the CharEnd variable.</div>
</div></div></blockquote><div><br></div><div>Yes, I think that's an improvement. I had incorrectly recalled that a CharRange included both the start and end character. Since it actually excludes its end character (unlike a TokenRange!), this seems like the more useful option. On reflection, I think my preferred option would be to ditch FilenameTok and pass a CharSourceRange for the included entity to the InclusionCallback.</div>
</div>