diff options
author | Alex Lorenz <arphaman@gmail.com> | 2017-11-14 23:10:50 +0000 |
---|---|---|
committer | Alex Lorenz <arphaman@gmail.com> | 2017-11-14 23:10:50 +0000 |
commit | 8337f81f68365b2b2f8efb46a45a70fe54545351 (patch) | |
tree | f064f215b10d7d741f530666e253f5e59e99f74b /clang/lib/Tooling/Refactoring/ASTSelection.cpp | |
parent | 57dd59d472d30a57d2c63a9ff5f455db29ee75e1 (diff) | |
download | bcm5719-llvm-8337f81f68365b2b2f8efb46a45a70fe54545351.tar.gz bcm5719-llvm-8337f81f68365b2b2f8efb46a45a70fe54545351.zip |
[refactor][selection] canonicalize decl ref callee to the call expr
We would like to extract the full call when just the callee function is
selected
llvm-svn: 318215
Diffstat (limited to 'clang/lib/Tooling/Refactoring/ASTSelection.cpp')
-rw-r--r-- | clang/lib/Tooling/Refactoring/ASTSelection.cpp | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/clang/lib/Tooling/Refactoring/ASTSelection.cpp b/clang/lib/Tooling/Refactoring/ASTSelection.cpp index ae8a3cb7c58..7123fc32cec 100644 --- a/clang/lib/Tooling/Refactoring/ASTSelection.cpp +++ b/clang/lib/Tooling/Refactoring/ASTSelection.cpp @@ -259,29 +259,64 @@ struct SelectedNodeWithParents { /// when it makes sense to do so. void canonicalize(); }; -} // end anonymous namespace -void SelectedNodeWithParents::canonicalize() { - const Stmt *S = Node.get().Node.get<Stmt>(); - assert(S && "non statement selection!"); - const Stmt *Parent = Parents[Parents.size() - 1].get().Node.get<Stmt>(); - if (!Parent) - return; +enum SelectionCanonicalizationAction { KeepSelection, SelectParent }; + +/// Returns the canonicalization action which should be applied to the +/// selected statement. +SelectionCanonicalizationAction +getSelectionCanonizalizationAction(const Stmt *S, const Stmt *Parent) { // Select the parent expression when: // - The string literal in ObjC string literal is selected, e.g.: // @"test" becomes @"test" // ~~~~~~ ~~~~~~~ if (isa<StringLiteral>(S) && isa<ObjCStringLiteral>(Parent)) - Node = Parents.pop_back_val(); + return SelectParent; // The entire call should be selected when just the member expression - // that refers to the method is selected. + // that refers to the method or the decl ref that refers to the function + // is selected. // f.call(args) becomes f.call(args) // ~~~~ ~~~~~~~~~~~~ - else if (isa<MemberExpr>(S) && isa<CXXMemberCallExpr>(Parent) && - cast<CXXMemberCallExpr>(Parent)->getCallee() == S) - Node = Parents.pop_back_val(); + // func(args) becomes func(args) + // ~~~~ ~~~~~~~~~~ + else if (const auto *CE = dyn_cast<CallExpr>(Parent)) { + if ((isa<MemberExpr>(S) || isa<DeclRefExpr>(S)) && + CE->getCallee()->IgnoreImpCasts() == S) + return SelectParent; + } // FIXME: Syntactic form -> Entire pseudo-object expr. - // FIXME: Callee -> Call. + return KeepSelection; +} + +} // end anonymous namespace + +void SelectedNodeWithParents::canonicalize() { + const Stmt *S = Node.get().Node.get<Stmt>(); + assert(S && "non statement selection!"); + const Stmt *Parent = Parents[Parents.size() - 1].get().Node.get<Stmt>(); + if (!Parent) + return; + + // Look through the implicit casts in the parents. + unsigned ParentIndex = 1; + for (; (ParentIndex + 1) <= Parents.size() && isa<ImplicitCastExpr>(Parent); + ++ParentIndex) { + const Stmt *NewParent = + Parents[Parents.size() - ParentIndex - 1].get().Node.get<Stmt>(); + if (!NewParent) + break; + Parent = NewParent; + } + + switch (getSelectionCanonizalizationAction(S, Parent)) { + case SelectParent: + Node = Parents[Parents.size() - ParentIndex]; + for (; ParentIndex != 0; --ParentIndex) + Parents.pop_back(); + break; + case KeepSelection: + break; + } } /// Finds the set of bottom-most selected AST nodes that are in the selection |