-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clangd] Handle an expanded token range that ends in the eof
token in TokenBuffer::spelledForExpanded()
#78092
Conversation
Based on previous discussion and analysis in #69849 |
@llvm/pr-subscribers-clangd @llvm/pr-subscribers-clang Author: Nathan Ridge (HighCommander4) ChangesSuch ranges can legitimately arise in the case of invalid code, such as a declaration missing an ending brace. Full diff: https://github.com/llvm/llvm-project/pull/78092.diff 3 Files Affected:
diff --git a/clang-tools-extra/clangd/unittests/DumpASTTests.cpp b/clang-tools-extra/clangd/unittests/DumpASTTests.cpp
index d1b8f21b82c65a..304682118c871d 100644
--- a/clang-tools-extra/clangd/unittests/DumpASTTests.cpp
+++ b/clang-tools-extra/clangd/unittests/DumpASTTests.cpp
@@ -186,6 +186,17 @@ TEST(DumpASTTests, Arcana) {
EXPECT_THAT(Node.children.front().arcana, testing::StartsWith("QualType "));
}
+TEST(DumpASTTests, UnbalancedBraces) {
+ // Test that we don't crash while trying to compute a source range for the
+ // node whose ending brace is missing, and also that the source range is
+ // not empty.
+ Annotations Case("/*error-ok*/ $func[[int main() {]]");
+ ParsedAST AST = TestTU::withCode(Case.code()).build();
+ auto Node = dumpAST(DynTypedNode::create(findDecl(AST, "main")),
+ AST.getTokens(), AST.getASTContext());
+ ASSERT_EQ(Node.range, Case.range("func"));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/clang/lib/Tooling/Syntax/Tokens.cpp b/clang/lib/Tooling/Syntax/Tokens.cpp
index 2f28b9cf286a63..8d32c45a4a70cf 100644
--- a/clang/lib/Tooling/Syntax/Tokens.cpp
+++ b/clang/lib/Tooling/Syntax/Tokens.cpp
@@ -401,6 +401,12 @@ std::string TokenBuffer::Mapping::str() const {
std::optional<llvm::ArrayRef<syntax::Token>>
TokenBuffer::spelledForExpanded(llvm::ArrayRef<syntax::Token> Expanded) const {
+ // In cases of invalid code, AST nodes can have source ranges that include
+ // the `eof` token. As there's no spelling for this token, exclude it from
+ // the range.
+ if (!Expanded.empty() && Expanded.back().kind() == tok::eof) {
+ Expanded = Expanded.drop_back();
+ }
// Mapping an empty range is ambiguous in case of empty mappings at either end
// of the range, bail out in that case.
if (Expanded.empty())
diff --git a/clang/unittests/Tooling/Syntax/TokensTest.cpp b/clang/unittests/Tooling/Syntax/TokensTest.cpp
index 0c08318a637c0b..45b2f0de4eabc1 100644
--- a/clang/unittests/Tooling/Syntax/TokensTest.cpp
+++ b/clang/unittests/Tooling/Syntax/TokensTest.cpp
@@ -816,6 +816,18 @@ TEST_F(TokenBufferTest, SpelledByExpanded) {
EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("prev good")), std::nullopt);
}
+TEST_F(TokenBufferTest, NoCrashForEofToken) {
+ recordTokens(R"cpp(
+ int main() {
+ )cpp");
+ // Calling spelledForExpanded() on the entire range of expanded tokens (which
+ // includes the `eof` token at the end) produces the range of all the spelled
+ // tokens (the `eof` is ignored).
+ EXPECT_THAT(
+ Buffer.spelledForExpanded(Buffer.expandedTokens()),
+ ValueIs(SameRange(Buffer.spelledTokens(SourceMgr->getMainFileID()))));
+}
+
TEST_F(TokenBufferTest, ExpandedTokensForRange) {
recordTokens(R"cpp(
#define SIGN(X) X##_washere
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, LGTM! I only have a minor (and optional) suggestion.
…in TokenBuffer::spelledForExpanded() Such ranges can legitimately arise in the case of invalid code, such as a declaration missing an ending brace. Fixes clangd/clangd#1559
26a11f5
to
2544957
Compare
…in TokenBuffer::spelledForExpanded() (llvm#78092) Such ranges can legitimately arise in the case of invalid code, such as a declaration missing an ending brace. Fixes clangd/clangd#1559
Such ranges can legitimately arise in the case of invalid code, such as a declaration missing an ending brace.
Fixes clangd/clangd#1559