return N && N->ASTNode.get<DecompositionDecl>();
}
+// 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<DeclaratorDecl>()) {
+ 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()) {
if (const AutoTypeLoc Result = TypeNode->getAs<AutoTypeLoc>()) {
// 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;
}
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();");