This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Fix selection on multi-dimensional array.
ClosedPublic

Authored by hokein on Dec 23 2021, 6:15 AM.

Diff Detail

Event Timeline

hokein created this revision.Dec 23 2021, 6:15 AM
hokein requested review of this revision.Dec 23 2021, 6:15 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 23 2021, 6:15 AM

Ooh, this is messy indeed. Thanks for digging!

clang-tools-extra/clangd/Selection.cpp
526

I don't think this is a complete solution: won't the inner ArrayTypeLoc still end up owning both sets of brackets?

I think maybe a better solution is making getSourceRange(ArrayTypeLoc) return only ATL.getBracketRange(), and then modify canSafelySkipNode to to avoid pruning based on this small range.

This is vaguely similar to how DeclTypeLoc works today (though in that case the reduced range is the one reported by the AST).

527

ConstantArrayType isn't the only kind of array, see the other subclasses of ArrayType

hokein added inline comments.Jan 3 2022, 2:12 AM
clang-tools-extra/clangd/Selection.cpp
526

won't the inner ArrayTypeLoc still end up owning both sets of brackets?

yes, unfortunately, the inner ATL still owns both sets of brackets, that means go-to-def (etc) won't work on an overloaded subscript operator [], I don't have a better solution to fix that. I guess it is ok to live with that as it might be a rare case in practice.

I think maybe a better solution is making getSourceRange(ArrayTypeLoc) return only ATL.getBracketRange(), and then modify canSafelySkipNode to to avoid pruning based on this small range.

yeah, indeed I tried this approach before coming up the current approach, and I didn't find a satisfied solution (BracketRange is not enough, otherwise we will lose the array type int).

// int array[Size][100];
// ~~~      [-2 -]~~~~~  ConstantArrayTypeLoc int[Size][100]
// [1]            [-3-]  |-ConstantArrayTypeLoc int[100]

Ideally, the inner ATL should own tokens int ([1]) and tokens [100] ([3]). And in the canSafelySkipNode, we want to skip the inner ATL if the cursor is in the source range of array[Size], it seems quite tricky to get the source range (the range of int [1] in particular). Of course we could use some lexer hacks or call ATL.getElementLoc() recursively until we hit a non-array type loc (it can easily go up to O(n^2) for super-multi-dimensional arrays).

527

oh, right. There are three others, we could do similar for them. Will do that if we agree on the current approach.

hokein updated this revision to Diff 397233.Jan 4 2022, 2:21 AM

refine the patch based on D116536, and one more test.

sammccall accepted this revision.Jan 4 2022, 2:39 AM
This revision is now accepted and ready to land.Jan 4 2022, 2:39 AM
This revision was automatically updated to reflect the committed changes.