This is an archive of the discontinued LLVM Phabricator instance.

ExtractFunction: support extracting expressions and selected part of it
Needs ReviewPublic

Authored by KKoovalsky on Dec 23 2022, 3:58 AM.

Details

Reviewers
sammccall
Summary

This is mainly insipred by ExtractVariable's ParsedBinaryOperator,
tweaked a little to collect references within the selected area.

On the side:
This is my first PR to the LLVM (and clangd) - I wanted to see how it
goes for the future, to contribute even more, as I am a C++ fan and I
love open-source, plus recently, I really like to automate stuff when
coding!

Getting back to the implemented functionality:
it upports extraction of expressions to a function or method:

  • int x{[[a + b + c]]},
  • int x{a + [[b + c]] + d};

Handles:

  • Binary operators.
  • Operator overloads, which resemble binary operators, e.g. struct S{ S& operator+(const S&); }
  • Infers return type of the expression basing on the operation return type; refs and const-refs are properly inferred as well.
  • Collects parameters from the selected area. Skips global variables and members. (Uses already-in-place DeclInfoMap containing info about the declarations within the enclosing function).
  • Handles deeply nested arguments within function calls, and collects them as the extracted function parameters.

Known limitations:

  • Macros within the selected area; the selected area is treated as the expr would be selected to the most-LHS entity; effectively: int x{a + [[SOME_MACRO(A) + b]] + c} becomes: int x{[[a + SOME_MACRO(A) + b]] + c} This is known limitation of ExtractVariable, thus nothing new here.
  • Does not make the method 'const' if the selected members are not mutated, in case the enclosing method is non-const.

PS. This contribution is a little messy, since it was hard to support
partially selected expressions, because the code already-in-place used
the term "root statement", which assumes that the entire statement is
selected. With this PR this assumption will be broken.
Yet, adding this feature taught me a lot, and I understand the code
structure better. I would like to boil down all the details of
implementing the Extract Function feature as a whole.

Diff Detail

Event Timeline

KKoovalsky created this revision.Dec 23 2022, 3:58 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 23 2022, 3:58 AM
KKoovalsky requested review of this revision.Dec 23 2022, 3:58 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 23 2022, 3:58 AM
nridge added a subscriber: nridge.Dec 26 2022, 1:06 AM

Linking to potentially relevant issue on file: https://github.com/clangd/clangd/issues/1254

Hey! I can see that the build: https://reviews.llvm.org/harbormaster/build/311598/ failed, but I am not sure whether this is related to my change. Could someone take a look?

Hey! I can see that the build: https://reviews.llvm.org/harbormaster/build/311598/ failed, but I am not sure whether this is related to my change. Could someone take a look?

I can reproduce the failures locally with the patch applied. To do so, run:

<build>/bin/llvm-lit <src>/clang-tools-extra/clangd/test/check.test

and similarly for check-fail.test and check-lines.test.

You can read more about how these tests work at https://llvm.org/docs/CommandGuide/lit.html.

By the way, I also got linker errors when trying to build this patch in a shared-libs build. Resolved by adding clangASTMatchers to clang_target_link_libraries in clang-tools-extra/clangd/tool/CMakeLists.txt.

I can reproduce the failures locally with the patch applied.

(The failures seem to have to do with ExtractFunction segfaulting when invoked at a particular location in the code in check.test.)

  1. Fixed lit fail: dereferencing a null pointer when calling ignoreImplicit() on CommonAncestor being nullptr - fixed with sanitization of CommonAncestor being nullptr.
  2. Fixed link error: missing ASTMatchers lib.+
  1. Fixed lit fail: dereferencing a null pointer when calling ignoreImplicit() on CommonAncestor being nullptr - fixed with sanitization of CommonAncestor being nullptr.
  2. Fixed link error: missing ASTMatchers lib.

Fixed nullptr dereferencing and missing ASTMatchers lib linking

  1. Fixed lit fail: dereferencing a null pointer when calling ignoreImplicit() on CommonAncestor being nullptr - fixed with sanitization of CommonAncestor being nullptr.
  2. Fixed link error: missing ASTMatchers lib.

@nridge I have fixed the issues. Thank you for supporting.