njames93 updated this revision to Diff 294357. njames93 marked 2 inline comments as done. njames93 added a comment.
Updated function doc Fix potential assertion Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D88297/new/ https://reviews.llvm.org/D88297 Files: clang-tools-extra/clangd/Hover.cpp clang-tools-extra/clangd/unittests/HoverTests.cpp Index: clang-tools-extra/clangd/unittests/HoverTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/HoverTests.cpp +++ clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -698,6 +698,26 @@ HI.Parameters->back().Name = "v"; HI.AccessSpecifier = "public"; }}, + {// Setter (move) + R"cpp( + namespace std { template<typename T> T&& move(T&& t); } + struct X { int Y; void [[^setY]](float v) { Y = std::move(v); } }; + )cpp", + [](HoverInfo &HI) { + HI.Name = "setY"; + HI.Kind = index::SymbolKind::InstanceMethod; + HI.NamespaceScope = ""; + HI.Definition = "void setY(float v)"; + HI.LocalScope = "X::"; + HI.Documentation = "Trivial setter for `Y`."; + HI.Type = "void (float)"; + HI.ReturnType = "void"; + HI.Parameters.emplace(); + HI.Parameters->emplace_back(); + HI.Parameters->back().Type = "float"; + HI.Parameters->back().Name = "v"; + HI.AccessSpecifier = "public"; + }}, {// Field type initializer. R"cpp( struct X { int x = 2; }; @@ -802,8 +822,8 @@ HI.Type = "int"; HI.AccessSpecifier = "public"; }}, - {// No crash on InitListExpr. - R"cpp( + {// No crash on InitListExpr. + R"cpp( struct Foo { int a[10]; }; Index: clang-tools-extra/clangd/Hover.cpp =================================================================== --- clang-tools-extra/clangd/Hover.cpp +++ clang-tools-extra/clangd/Hover.cpp @@ -413,6 +413,8 @@ // If CMD is one of the forms: // void foo(T arg) { FieldName = arg; } // R foo(T arg) { FieldName = arg; return *this; } +// void foo(T arg) { FieldName = std::move(arg); } +// R foo(T arg) { FieldName = std::move(arg); return *this; } // then returns "FieldName" llvm::Optional<StringRef> setterVariableName(const CXXMethodDecl *CMD) { assert(CMD->hasBody()); @@ -455,6 +457,18 @@ } else { return llvm::None; } + + // Detect the case when the item is moved into the field. + if (auto *CE = llvm::dyn_cast<CallExpr>(RHS->IgnoreCasts())) { + if (CE->getNumArgs() != 1) + return llvm::None; + auto *ND = llvm::dyn_cast<NamedDecl>(CE->getCalleeDecl()); + if (!ND || !ND->getIdentifier() || ND->getName() != "move" || + !ND->isInStdNamespace()) + return llvm::None; + RHS = CE->getArg(0); + } + auto *DRE = llvm::dyn_cast<DeclRefExpr>(RHS->IgnoreCasts()); if (!DRE || DRE->getDecl() != Arg) return llvm::None;
Index: clang-tools-extra/clangd/unittests/HoverTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/HoverTests.cpp +++ clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -698,6 +698,26 @@ HI.Parameters->back().Name = "v"; HI.AccessSpecifier = "public"; }}, + {// Setter (move) + R"cpp( + namespace std { template<typename T> T&& move(T&& t); } + struct X { int Y; void [[^setY]](float v) { Y = std::move(v); } }; + )cpp", + [](HoverInfo &HI) { + HI.Name = "setY"; + HI.Kind = index::SymbolKind::InstanceMethod; + HI.NamespaceScope = ""; + HI.Definition = "void setY(float v)"; + HI.LocalScope = "X::"; + HI.Documentation = "Trivial setter for `Y`."; + HI.Type = "void (float)"; + HI.ReturnType = "void"; + HI.Parameters.emplace(); + HI.Parameters->emplace_back(); + HI.Parameters->back().Type = "float"; + HI.Parameters->back().Name = "v"; + HI.AccessSpecifier = "public"; + }}, {// Field type initializer. R"cpp( struct X { int x = 2; }; @@ -802,8 +822,8 @@ HI.Type = "int"; HI.AccessSpecifier = "public"; }}, - {// No crash on InitListExpr. - R"cpp( + {// No crash on InitListExpr. + R"cpp( struct Foo { int a[10]; }; Index: clang-tools-extra/clangd/Hover.cpp =================================================================== --- clang-tools-extra/clangd/Hover.cpp +++ clang-tools-extra/clangd/Hover.cpp @@ -413,6 +413,8 @@ // If CMD is one of the forms: // void foo(T arg) { FieldName = arg; } // R foo(T arg) { FieldName = arg; return *this; } +// void foo(T arg) { FieldName = std::move(arg); } +// R foo(T arg) { FieldName = std::move(arg); return *this; } // then returns "FieldName" llvm::Optional<StringRef> setterVariableName(const CXXMethodDecl *CMD) { assert(CMD->hasBody()); @@ -455,6 +457,18 @@ } else { return llvm::None; } + + // Detect the case when the item is moved into the field. + if (auto *CE = llvm::dyn_cast<CallExpr>(RHS->IgnoreCasts())) { + if (CE->getNumArgs() != 1) + return llvm::None; + auto *ND = llvm::dyn_cast<NamedDecl>(CE->getCalleeDecl()); + if (!ND || !ND->getIdentifier() || ND->getName() != "move" || + !ND->isInStdNamespace()) + return llvm::None; + RHS = CE->getArg(0); + } + auto *DRE = llvm::dyn_cast<DeclRefExpr>(RHS->IgnoreCasts()); if (!DRE || DRE->getDecl() != Arg) return llvm::None;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits