Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp =================================================================== --- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp +++ clang-tools-extra/trunk/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; } Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp =================================================================== --- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp +++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp @@ -255,6 +255,23 @@ struct $Class[[Tmpl]] {$TemplateParameter[[T]] $Field[[x]] = 0;}; extern template struct $Class[[Tmpl]]; template struct $Class[[Tmpl]]; + )cpp", + // This test is to guard against highlightings disappearing when using + // conversion operators as their behaviour in the clang AST differ from + // other CXXMethodDecls. + 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);