diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp --- a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp @@ -63,6 +63,25 @@ return N && N->ASTNode.get(); } +// Returns true iff Node is a lambda, and thus should not be expanded. Loc is +// the location of the auto type. +bool isDeducedAsLambda(const SelectionTree::Node *Node, SourceLocation Loc) { + // getDeducedType() does a traversal, which we want to avoid in prepare(). + // But at least check this isn't auto x = []{...};, which can't ever be + // expanded. + // (It would be nice if we had an efficient getDeducedType(), instead). + for (const auto *It = Node; It; It = It->Parent) { + if (const auto *DD = It->ASTNode.get()) { + if (DD->getTypeSourceInfo() && + DD->getTypeSourceInfo()->getTypeLoc().getBeginLoc() == Loc) { + if (auto *RD = DD->getType()->getAsRecordDecl()) + return RD->isLambda(); + } + } + } + return false; +} + bool ExpandAutoType::prepare(const Selection& Inputs) { CachedLocation = llvm::None; if (auto *Node = Inputs.ASTSelection.commonAncestor()) { @@ -70,11 +89,13 @@ if (const AutoTypeLoc Result = TypeNode->getAs()) { // Code in apply() does handle 'decltype(auto)' yet. if (!Result.getTypePtr()->isDecltypeAuto() && - !isStructuredBindingType(Node)) + !isStructuredBindingType(Node) && + !isDeducedAsLambda(Node, Result.getBeginLoc())) CachedLocation = Result; } } } + return (bool) CachedLocation; } diff --git a/clang-tools-extra/clangd/test/check-fail.test b/clang-tools-extra/clangd/test/check-fail.test --- a/clang-tools-extra/clangd/test/check-fail.test +++ b/clang-tools-extra/clangd/test/check-fail.test @@ -11,4 +11,5 @@ // CHECK: All checks completed, 2 errors #include "missing.h" -auto x = []{}; +void fun(); +auto x = fun; diff --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp b/clang-tools-extra/clangd/unittests/TweakTests.cpp --- a/clang-tools-extra/clangd/unittests/TweakTests.cpp +++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp @@ -559,8 +559,7 @@ EXPECT_THAT(apply("au^to x = &ns::Func;"), StartsWith("fail: Could not expand type of function pointer")); // lambda types are not replaced - EXPECT_THAT(apply("au^to x = []{};"), - StartsWith("fail: Could not expand type of lambda expression")); + EXPECT_UNAVAILABLE("au^to x = []{};"); // inline namespaces EXPECT_EQ(apply("au^to x = inl_ns::Visible();"), "Visible x = inl_ns::Visible();");