diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -52,6 +52,10 @@ // When calling the destructor manually like: AAA::~A(); The ~ is a // MemberExpr. Other methods should still be highlighted though. return true; + if (isa(MD)) + // The MemberLoc is invalid for C++ conversion operators. We do not + // attempt to add tokens with invalid locations. + return true; addToken(ME->getMemberLoc(), MD); return true; } diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -255,6 +255,20 @@ struct $Class[[Tmpl]] {$TemplateParameter[[T]] $Field[[x]] = 0;}; extern template struct $Class[[Tmpl]]; template struct $Class[[Tmpl]]; + )cpp", + R"cpp( + class $Class[[Foo]] {}; + struct $Class[[Bar]] { + explicit operator $Class[[Foo]]*() const; + explicit operator int() const; + operator $Class[[Foo]](); + }; + void $Function[[f]]() { + $Class[[Bar]] $Variable[[B]]; + $Class[[Foo]] $Variable[[F]] = $Variable[[B]]; + $Class[[Foo]] *$Variable[[FP]] = ($Class[[Foo]]*)$Variable[[B]]; + int $Variable[[I]] = (int)$Variable[[B]]; + } )cpp"}; for (const auto &TestCase : TestCases) { checkHighlightings(TestCase);