[PATCH] D71880: [clangd] Implement Decl canonicalization rules for rename

Haojian Wu via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 12 00:13:49 PST 2020


hokein added a comment.

don't dig into details, first round of comments.

I think the scope is a bit ambiguous, my reading is that it 1) removes old clang-rename API usage *and* 2) fixes some existing bugs. I would suggest just scoping it on 1).



================
Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:251
+const NamedDecl *canonicalRenameDecl(const FieldDecl *D) {
+  // This is a hacky way to do something like
+  // CXXMethodDecl::getINstantiatedFromMemberFunction for the field because
----------------
yeah, this is quite tricky. I'd suggest to defer it to a separate patch. 

The behavior you described in https://github.com/clangd/clangd/issues/582 makes sense to me.

Another missing case is about static class members, they are `VarDecl` in the AST. 


================
Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:283
+    const auto *Definition = RD->getDefinition();
+    Candidate = Definition ? Definition : RD->getMostRecentDecl();
+  }
----------------
I'm not sure the motivation of the change,  the same as line 244.


================
Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:299
+  if (const auto *Field = dyn_cast<FieldDecl>(Candidate))
+    return canonicalRenameDecl(Field);
+  return Candidate;
----------------
Looks like we're missing the `VarDecl` case (looks like a regression). I think we should probably add tests from https://github.com/llvm/llvm-project/commit/1e32df2f91f1aa1f8cd400ce50a621578fa0534e to clangd rename test.


================
Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:300
+    return canonicalRenameDecl(Field);
+  return Candidate;
+}
----------------
we're comparing Decl pointers to check whether they point to the same symbol, I think we should use `Candidate->getCanonicalDecl()` here.

thinking of a case, in the AST, we have two `Decl*`s, one points to the forward decl, the other one points to the definition. but they points to the same symbol.

```
class Foo; // forward decl, this is the canonical decl.

class Foo {
};
```



================
Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:307
   trace::Span Tracer("FindOccurrencesWithinFile");
-  // If the cursor is at the underlying CXXRecordDecl of the
-  // ClassTemplateDecl, ND will be the CXXRecordDecl. In this case, we need to
-  // get the primary template manually.
-  // getUSRsForDeclaration will find other related symbols, e.g. virtual and its
-  // overriddens, primary template and all explicit specializations.
-  // FIXME: Get rid of the remaining tooling APIs.
-  const auto *RenameDecl =
-      ND.getDescribedTemplate() ? ND.getDescribedTemplate() : &ND;
-  std::vector<std::string> RenameUSRs =
-      tooling::getUSRsForDeclaration(RenameDecl, AST.getASTContext());
-  llvm::DenseSet<SymbolID> TargetIDs;
-  for (auto &USR : RenameUSRs)
-    TargetIDs.insert(SymbolID(USR));
+  const auto *RenameDecl = canonicalRenameDecl(&ND);
 
----------------
since we call `canonicalRenameDecl` in `locateDeclAt`, I think `ND` is already canonical, right?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71880/new/

https://reviews.llvm.org/D71880



More information about the cfe-commits mailing list