[clangd] Don't offer to expand auto in structured binding declarations.
authorSam McCall <sam.mccall@gmail.com>
Mon, 19 Oct 2020 14:29:04 +0000 (16:29 +0200)
committerSam McCall <sam.mccall@gmail.com>
Wed, 28 Oct 2020 17:55:23 +0000 (18:55 +0100)
auto must be used for the code to parse.

Differential Revision: https://reviews.llvm.org/D89700

clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
clang-tools-extra/clangd/unittests/TweakTests.cpp

index 4dfaf72..61f68a6 100644 (file)
@@ -53,13 +53,24 @@ REGISTER_TWEAK(ExpandAutoType)
 
 std::string ExpandAutoType::title() const { return "Expand auto type"; }
 
+// Structured bindings must use auto, e.g. `const auto& [a,b,c] = ...;`.
+// Return whether N (an AutoTypeLoc) is such an auto that must not be expanded.
+bool isStructuredBindingType(const SelectionTree::Node *N) {
+  // Walk up the TypeLoc chain, because auto may be qualified.
+  while (N && N->ASTNode.get<TypeLoc>())
+    N = N->Parent;
+  // The relevant type is the only direct type child of a Decomposition.
+  return N && N->ASTNode.get<DecompositionDecl>();
+}
+
 bool ExpandAutoType::prepare(const Selection& Inputs) {
   CachedLocation = llvm::None;
   if (auto *Node = Inputs.ASTSelection.commonAncestor()) {
     if (auto *TypeNode = Node->ASTNode.get<TypeLoc>()) {
       if (const AutoTypeLoc Result = TypeNode->getAs<AutoTypeLoc>()) {
         // Code in apply() does handle 'decltype(auto)' yet.
-        if (!Result.getTypePtr()->isDecltypeAuto())
+        if (!Result.getTypePtr()->isDecltypeAuto() &&
+            !isStructuredBindingType(Node))
           CachedLocation = Result;
       }
     }
index 8488c42..563be79 100644 (file)
@@ -572,6 +572,8 @@ TEST_F(ExpandAutoTypeTest, Test) {
             R"cpp(const char * x = "test";)cpp");
 
   EXPECT_UNAVAILABLE("dec^ltype(au^to) x = 10;");
+  // expanding types in structured bindings is syntactically invalid.
+  EXPECT_UNAVAILABLE("const ^auto &[x,y] = (int[]){1,2};");
 
   // FIXME: Auto-completion in a template requires disabling delayed template
   // parsing.