Skip to content

Commit 04f4c4c

Browse files
[clangd] Move function body to out-of-line: unnamed class method incorrect moving
The refactoring !!Move function body to out-of-line!! produces incorrect code for methods of unnamed classes. For this simple example // foo.h struct Foo { struct { void f^oo() {} } Bar; }; the refactoring generates code: // foo.cpp void Foo::(unnamed struct at D:\test\foo.h:2:3)foo() {} Outplace definition for methods of unnamed classes is meaningless. The patch disables it. Reviewed By: kadircet Differential Revision: https://reviews.llvm.org/D143638
1 parent fef08da commit 04f4c4c

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,11 +392,20 @@ class DefineOutline : public Tweak {
392392
if (Source->getTemplateSpecializationInfo())
393393
return false;
394394

395-
// Bail out in templated classes, as it is hard to spell the class name, i.e
396-
// if the template parameter is unnamed.
397395
if (auto *MD = llvm::dyn_cast<CXXMethodDecl>(Source)) {
396+
// Bail out in templated classes, as it is hard to spell the class name,
397+
// i.e if the template parameter is unnamed.
398398
if (MD->getParent()->isTemplated())
399399
return false;
400+
401+
// The refactoring is meaningless for unnamed classes and definitions
402+
// within unnamed namespaces.
403+
for (const DeclContext *DC = MD->getParent(); DC; DC = DC->getParent()) {
404+
if (auto *ND = llvm::dyn_cast<NamedDecl>(DC)) {
405+
if (ND->getDeclName().isEmpty())
406+
return false;
407+
}
408+
}
400409
}
401410

402411
// Note that we don't check whether an implementation file exists or not in

clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,32 @@ TEST_F(DefineOutlineTest, TriggersOnFunctionDecl) {
8484
template <typename> void fo^o() {};
8585
template <> void fo^o<int>() {};
8686
)cpp");
87+
88+
// Not available on methods of unnamed classes.
89+
EXPECT_UNAVAILABLE(R"cpp(
90+
struct Foo {
91+
struct { void b^ar() {} } Bar;
92+
};
93+
)cpp");
94+
95+
// Not available on methods of named classes with unnamed parent in parents
96+
// nesting.
97+
EXPECT_UNAVAILABLE(R"cpp(
98+
struct Foo {
99+
struct {
100+
struct Bar { void b^ar() {} };
101+
} Baz;
102+
};
103+
)cpp");
104+
105+
// Not available on definitions within unnamed namespaces
106+
EXPECT_UNAVAILABLE(R"cpp(
107+
namespace {
108+
struct Foo {
109+
void f^oo() {}
110+
};
111+
} // namespace
112+
)cpp");
87113
}
88114

89115
TEST_F(DefineOutlineTest, FailsWithoutSource) {

0 commit comments

Comments
 (0)