[cfe-dev] libclang and MemberRefExpr
Douglas Gregor
dgregor at apple.com
Fri May 13 08:56:00 PDT 2011
On May 13, 2011, at 5:13 AM, Erik Verbruggen wrote:
> On 12 May, 2011,at 05:43 PM, Douglas Gregor <dgregor at apple.com> wrote:
>
>>
>> On May 12, 2011, at 5:52 AM, Erik Verbruggen wrote:
>>
>> > Hello,
>> >
>> > When using the visitor functions in libclang, I noticed that for a member-access I get a MemberRefExpr containing a DeclRefExpr. The CXSourceRange for the DeclRefExpr covers the base expression and the CXSourceRange for the MemberRefExpr covers the whole expression. So the question is: how can I get the CXSourceRange covering the id-expression for the member itself? I.e., for "x.y", how can I get the range for "y"?
>>
>> clang_getCursorLocation() will retrieve the location of "y" in the member expression "x.y". So long as the name is a simple identifier, you can just turn that into a range with clang_getRange().
>
> Thanks. I worked around it by getting the tokens for the translation unit, then searching for the identifier, and checking if the cursor for that token was part of the member expression.
>
>> However, if the name isn't a simple identifier ("x.operator[]"), then you can still get the location of the start of the member name ("operator"), but when you ask for the range, you'll only get the range of that one token.
>>
>> Back when we designed libclang, Clang didn't even have the information about where the three tokens of "operator[]" were. Now, we actually have this information via DeclarationNameInfo, so it would make sense to add an API for specifically what you want. Here is a general API that (I think!) could fully solve this problem:
>>
>> CXSourceRange clang_getCursorReferenceNameRange(CXCursor C, unsigned NameFlags, unsigned PieceIndex);
>>
>> where C is a cursor that references something else (e.g., a member reference, declaration reference, type reference, etc.), and returns the source range covering the reference itself. The two "unsigned" values would be for configurability:
>>
>> - NameFlags could be bitset with three independent flags: WantQualifier (to ask it to include the nested-name-specifier, e.g., Foo:: in x.Foo::y, in the range), WantTemplateArgs (to ask it to include the explicit template arguments, e.g., <int> in x.f<int>, in the range), and WantSinglePiece (described below).
>>
>> - WantPiece/PieceIndex is my attempt at handling cases where the name itself isn't contiguous. For example, imagine the expression "a[y]", which ends up referring to an overloaded operator[]. The source range for the full operator name is, effectively, "[y]", since the name has been split into two parts. However, that's not necessarily useful, so WantPiece would indicate that we want a range covering only one piece of the name, where PieceIndex==0 indicates that we want the '[' and PieceIndex==1 indicates that we want the ']'.
>
> So for "operator[]" you would 3 pieces? Or just 1?
Probably just one.
> Also, how would you know that there are no more pieces left? By returning a null-range?
Yes.
>> My real motivation for WantPiece/PieceIndex is Objective-C, where we have identifiers that are split, e.g., [foo aMethod:bar withWibble:wibble]. The method name here is aMethod:withWibble:, and a single source range for that method name just doesn't work.
>
> How many ranges would be returned for a call to "aMethod:withWibble:"? Or to rephrase it different, would the first range include the first colon, or would the colon be a separate range?
Two ranges, IMO: one covering "aMethod:" and the other covering "withWibble:".
> Anyway, sounds like a reasonable interface, so I can give it a go if nobody else is working on it.
Nobody else is working on it. If you're interested in tackling it, that would be wonderful!
- Doug
More information about the cfe-dev
mailing list