1 //===- Mutations.cpp ------------------------------------------*- C++ -*-=====// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 #include "clang/Tooling/Syntax/Mutations.h" 9 #include "clang/Basic/LLVM.h" 10 #include "clang/Basic/SourceLocation.h" 11 #include "clang/Lex/Token.h" 12 #include "clang/Tooling/Core/Replacement.h" 13 #include "clang/Tooling/Syntax/BuildTree.h" 14 #include "clang/Tooling/Syntax/Nodes.h" 15 #include "clang/Tooling/Syntax/Tokens.h" 16 #include "clang/Tooling/Syntax/Tree.h" 17 #include "llvm/ADT/ArrayRef.h" 18 #include "llvm/ADT/Optional.h" 19 #include "llvm/ADT/STLExtras.h" 20 #include "llvm/Support/Casting.h" 21 #include <cassert> 22 #include <string> 23 24 using namespace clang; 25 26 static syntax::Node *findPrevious(syntax::Node *N) { 27 assert(N); 28 assert(N->getParent()); 29 if (N->getParent()->getFirstChild() == N) 30 return nullptr; 31 for (syntax::Node *C = N->getParent()->getFirstChild(); C != nullptr; 32 C = C->getNextSibling()) { 33 if (C->getNextSibling() == N) 34 return C; 35 } 36 llvm_unreachable("could not find a child node"); 37 } 38 39 // This class has access to the internals of tree nodes. Its sole purpose is to 40 // define helpers that allow implementing the high-level mutation operations. 41 class syntax::MutationsImpl { 42 public: 43 /// Add a new node with a specified role. 44 static void addAfter(syntax::Node *Anchor, syntax::Node *New, NodeRole Role) { 45 assert(Anchor != nullptr); 46 assert(Anchor->Parent != nullptr); 47 assert(New->Parent == nullptr); 48 assert(New->NextSibling == nullptr); 49 assert(New->isDetached()); 50 assert(Role != NodeRole::Detached); 51 52 New->setRole(Role); 53 auto *P = Anchor->getParent(); 54 P->replaceChildRangeLowLevel(Anchor, Anchor->getNextSibling(), New); 55 56 P->assertInvariants(); 57 } 58 59 /// Replace the node, keeping the role. 60 static void replace(syntax::Node *Old, syntax::Node *New) { 61 assert(Old != nullptr); 62 assert(Old->Parent != nullptr); 63 assert(Old->canModify()); 64 assert(New->Parent == nullptr); 65 assert(New->NextSibling == nullptr); 66 assert(New->isDetached()); 67 68 New->Role = Old->Role; 69 auto *P = Old->getParent(); 70 P->replaceChildRangeLowLevel(findPrevious(Old), Old->getNextSibling(), New); 71 72 P->assertInvariants(); 73 } 74 75 /// Completely remove the node from its parent. 76 static void remove(syntax::Node *N) { 77 assert(N != nullptr); 78 assert(N->Parent != nullptr); 79 assert(N->canModify()); 80 81 auto *P = N->getParent(); 82 P->replaceChildRangeLowLevel(findPrevious(N), N->getNextSibling(), 83 /*New=*/nullptr); 84 85 P->assertInvariants(); 86 N->assertInvariants(); 87 } 88 }; 89 90 void syntax::removeStatement(syntax::Arena &A, syntax::Statement *S) { 91 assert(S); 92 assert(S->canModify()); 93 94 if (isa<CompoundStatement>(S->getParent())) { 95 // A child of CompoundStatement can just be safely removed. 96 MutationsImpl::remove(S); 97 return; 98 } 99 // For the rest, we have to replace with an empty statement. 100 if (isa<EmptyStatement>(S)) 101 return; // already an empty statement, nothing to do. 102 103 MutationsImpl::replace(S, createEmptyStatement(A)); 104 } 105